From 6054d7e6533d549d57dfc645ac1f5420fd224915 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Thu, 19 Apr 2018 14:23:30 -0700 Subject: [PATCH 01/69] Refactor copy and add Refactor copy and add Add/copy pass integration tests --- pkg/commands/add.go | 72 ++++++++++++++-------------------------- pkg/commands/copy.go | 69 ++++++++++++++++---------------------- pkg/util/command_util.go | 17 +++++----- pkg/util/fs_util.go | 56 +++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 95 deletions(-) diff --git a/pkg/commands/add.go b/pkg/commands/add.go index f6aee688c3..c124661c3a 100644 --- a/pkg/commands/add.go +++ b/pkg/commands/add.go @@ -54,59 +54,50 @@ func (a *AddCommand) ExecuteCommand(config *manifest.Schema2Config) error { } dest = resolvedEnvs[len(resolvedEnvs)-1] // Get a map of [src]:[files rooted at src] - srcMap, err := util.ResolveSources(resolvedEnvs, a.buildcontext) + srcs, err = util.ResolveSources(resolvedEnvs, a.buildcontext) if err != nil { return err } + var unresolvedSrcs []string // If any of the sources are local tar archives: // 1. Unpack them to the specified destination // 2. Remove it as a source that needs to be copied over // If any of the sources is a remote file URL: // 1. Download and copy it to the specified dest // 2. Remove it as a source that needs to be copied - for src, files := range srcMap { - for _, file := range files { - // If file is a local tar archive, then we unpack it to dest - filePath := filepath.Join(a.buildcontext, file) - isFilenameSource, err := isFilenameSource(srcMap, file) - if err != nil { + for _, src := range srcs { + fullPath := filepath.Join(a.buildcontext, src) + if util.IsSrcRemoteFileURL(src) { + urlDest := util.URLDestinationFilepath(src, dest, config.WorkingDir) + logrus.Infof("Adding remote URL %s to %s", src, urlDest) + if err := util.DownloadFileToDest(src, urlDest); err != nil { + return err + } + a.snapshotFiles = append(a.snapshotFiles, urlDest) + } else if util.IsFileLocalTarArchive(fullPath) { + logrus.Infof("Unpacking local tar archive %s to %s", src, dest) + if err := util.UnpackLocalTarArchive(fullPath, dest); err != nil { return err } - if util.IsSrcRemoteFileURL(file) { - urlDest := util.URLDestinationFilepath(file, dest, config.WorkingDir) - logrus.Infof("Adding remote URL %s to %s", file, urlDest) - if err := util.DownloadFileToDest(file, urlDest); err != nil { - return err - } - a.snapshotFiles = append(a.snapshotFiles, urlDest) - delete(srcMap, src) - } else if isFilenameSource && util.IsFileLocalTarArchive(filePath) { - logrus.Infof("Unpacking local tar archive %s to %s", file, dest) - if err := util.UnpackLocalTarArchive(filePath, dest); err != nil { - return err - } - // Add the unpacked files to the snapshotter - filesAdded, err := util.Files(dest) - if err != nil { - return err - } - logrus.Debugf("Added %v from local tar archive %s", filesAdded, file) - a.snapshotFiles = append(a.snapshotFiles, filesAdded...) - delete(srcMap, src) + // Add the unpacked files to the snapshotter + filesAdded, err := util.Files(dest) + if err != nil { + return err } + logrus.Debugf("Added %v from local tar archive %s", filesAdded, src) + a.snapshotFiles = append(a.snapshotFiles, filesAdded...) + } else { + unresolvedSrcs = append(unresolvedSrcs, src) } } // With the remaining "normal" sources, create and execute a standard copy command - if len(srcMap) == 0 { + if len(unresolvedSrcs) == 0 { return nil } - var regularSrcs []string - for src := range srcMap { - regularSrcs = append(regularSrcs, src) - } + copyCmd := CopyCommand{ cmd: &instructions.CopyCommand{ - SourcesAndDest: append(regularSrcs, dest), + SourcesAndDest: append(unresolvedSrcs, dest), }, buildcontext: a.buildcontext, } @@ -117,19 +108,6 @@ func (a *AddCommand) ExecuteCommand(config *manifest.Schema2Config) error { return nil } -func isFilenameSource(srcMap map[string][]string, fileName string) (bool, error) { - for src := range srcMap { - matched, err := filepath.Match(src, fileName) - if err != nil { - return false, err - } - if matched || (src == fileName) { - return true, nil - } - } - return false, nil -} - // FilesToSnapshot should return an empty array if still nil; no files were changed func (a *AddCommand) FilesToSnapshot() []string { return a.snapshotFiles diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 845e7dfcd4..5cdcd55ce0 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -17,14 +17,13 @@ limitations under the License. package commands import ( - "os" - "path/filepath" - "strings" - "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/sirupsen/logrus" + "os" + "path/filepath" + "strings" ) type CopyCommand struct { @@ -47,51 +46,41 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { } dest = resolvedEnvs[len(resolvedEnvs)-1] // Get a map of [src]:[files rooted at src] - srcMap, err := util.ResolveSources(resolvedEnvs, c.buildcontext) + srcs, err = util.ResolveSources(resolvedEnvs, c.buildcontext) if err != nil { return err } - // For each source, iterate through each file within and copy it over - for src, files := range srcMap { - for _, file := range files { - fi, err := os.Lstat(filepath.Join(c.buildcontext, file)) - if err != nil { + // For each source, iterate through and copy it over + for _, src := range srcs { + fullPath := filepath.Join(c.buildcontext, src) + fi, err := os.Lstat(fullPath) + if err != nil { + return err + } + destPath, err := util.DestinationFilepath(src, src, dest, config.WorkingDir, c.buildcontext) + if err != nil { + return err + } + if fi.IsDir() { + if err := util.CopyDir(fullPath, dest); err != nil { return err } - destPath, err := util.DestinationFilepath(file, src, dest, config.WorkingDir, c.buildcontext) + copiedFiles, err := util.Files(dest) if err != nil { return err } - // If source file is a directory, we want to create a directory ... - if fi.IsDir() { - logrus.Infof("Creating directory %s", destPath) - if err := os.MkdirAll(destPath, fi.Mode()); err != nil { - return err - } - } else if fi.Mode()&os.ModeSymlink != 0 { - // If file is a symlink, we want to create the same relative symlink - link, err := os.Readlink(filepath.Join(c.buildcontext, file)) - if err != nil { - return err - } - linkDst := filepath.Join(destPath, link) - if err := os.Symlink(linkDst, destPath); err != nil { - logrus.Errorf("unable to symlink %s to %s", linkDst, destPath) - return err - } - } else { - // ... Else, we want to copy over a file - logrus.Infof("Copying file %s to %s", file, destPath) - srcFile, err := os.Open(filepath.Join(c.buildcontext, file)) - if err != nil { - return err - } - defer srcFile.Close() - if err := util.CreateFile(destPath, srcFile, fi.Mode()); err != nil { - return err - } + c.snapshotFiles = append(c.snapshotFiles, copiedFiles...) + } else if fi.Mode()&os.ModeSymlink != 0 { + // If file is a symlink, we want to create the same relative symlink + if err := util.CopySymlink(fullPath, destPath); err != nil { + return err + } + c.snapshotFiles = append(c.snapshotFiles, destPath) + } else { + // ... Else, we want to copy over a file + if err := util.CopyFile(fullPath, destPath); err != nil { + return err } - // Append the destination file to the list of files that should be snapshotted later c.snapshotFiles = append(c.snapshotFiles, destPath) } } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index e74745796c..251b96980e 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -84,7 +84,7 @@ func ContainsWildcards(paths []string) bool { // ResolveSources resolves the given sources if the sources contains wildcards // It returns a map of [src]:[files rooted at src] -func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) (map[string][]string, error) { +func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) ([]string, error) { srcs := srcsAndDest[:len(srcsAndDest)-1] // If sources contain wildcards, we first need to resolve them to actual paths if ContainsWildcards(srcs) { @@ -99,13 +99,8 @@ func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) (map[s } logrus.Debugf("Resolved sources to %v", srcs) } - // Now, get a map of [src]:[files rooted at src] - srcMap, err := SourcesToFilesMap(srcs, root) - if err != nil { - return nil, err - } // Check to make sure the sources are valid - return srcMap, IsSrcsValid(srcsAndDest, srcMap) + return srcs, IsSrcsValid(srcsAndDest, srcs, root) } // matchSources returns a list of sources that match wildcards @@ -206,10 +201,16 @@ func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) } // IsSrcsValid returns an error if the sources provided are invalid, or nil otherwise -func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, srcMap map[string][]string) error { +func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSrcs []string, root string) error { srcs := srcsAndDest[:len(srcsAndDest)-1] dest := srcsAndDest[len(srcsAndDest)-1] + // Now, get a map of [src]:[files rooted at src] + srcMap, err := SourcesToFilesMap(resolvedSrcs, root) + if err != nil { + return err + } + totalFiles := 0 for _, files := range srcMap { totalFiles += len(files) diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index e2d5f588fd..60631adce0 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -210,3 +210,59 @@ func DownloadFileToDest(rawurl, dest string) error { } return os.Chtimes(dest, mTime, mTime) } + +// CopyDir copies the file or directory at src to dest +func CopyDir(src, dest string) error { + files, err := RelativeFiles("", src) + if err != nil { + return err + } + for _, file := range files { + fullPath := filepath.Join(src, file) + fi, err := os.Stat(fullPath) + if err != nil { + return err + } + destPath := filepath.Join(dest, file) + if fi.IsDir() { + logrus.Infof("Creating directory %s", destPath) + if err := os.MkdirAll(destPath, fi.Mode()); err != nil { + return err + } + } else if fi.Mode()&os.ModeSymlink != 0 { + // If file is a symlink, we want to create the same relative symlink + if err := CopySymlink(fullPath, destPath); err != nil { + return err + } + } else { + // ... Else, we want to copy over a file + if err := CopyFile(fullPath, destPath); err != nil { + return err + } + } + } + return nil +} + +func CopySymlink(src, dest string) error { + link, err := os.Readlink(src) + if err != nil { + return err + } + linkDst := filepath.Join(dest, link) + return os.Symlink(linkDst, dest) +} + +func CopyFile(src, dest string) error { + fi, err := os.Stat(src) + if err != nil { + return err + } + logrus.Infof("Copying file %s to %s", src, dest) + srcFile, err := os.Open(src) + if err != nil { + return err + } + defer srcFile.Close() + return CreateFile(dest, srcFile, fi.Mode()) +} From be38696c7d18b6ee5721412e0feddd5f88ac6c61 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Thu, 19 Apr 2018 17:26:32 -0700 Subject: [PATCH 02/69] Updated unit tests after refactor --- pkg/commands/add.go | 5 +- pkg/commands/copy.go | 4 +- pkg/util/command_util.go | 80 +++++--------- pkg/util/command_util_test.go | 190 +++++++++++----------------------- pkg/util/fs_util.go | 2 + 5 files changed, 93 insertions(+), 188 deletions(-) diff --git a/pkg/commands/add.go b/pkg/commands/add.go index c124661c3a..2ce4a090f8 100644 --- a/pkg/commands/add.go +++ b/pkg/commands/add.go @@ -53,7 +53,7 @@ func (a *AddCommand) ExecuteCommand(config *manifest.Schema2Config) error { return err } dest = resolvedEnvs[len(resolvedEnvs)-1] - // Get a map of [src]:[files rooted at src] + // Resolve wildcards and get a list of resolved sources srcs, err = util.ResolveSources(resolvedEnvs, a.buildcontext) if err != nil { return err @@ -61,10 +61,9 @@ func (a *AddCommand) ExecuteCommand(config *manifest.Schema2Config) error { var unresolvedSrcs []string // If any of the sources are local tar archives: // 1. Unpack them to the specified destination - // 2. Remove it as a source that needs to be copied over // If any of the sources is a remote file URL: // 1. Download and copy it to the specified dest - // 2. Remove it as a source that needs to be copied + // Else, add to the list of unresolved sources for _, src := range srcs { fullPath := filepath.Join(a.buildcontext, src) if util.IsSrcRemoteFileURL(src) { diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 5cdcd55ce0..bded4bf99c 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -45,7 +45,7 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { return err } dest = resolvedEnvs[len(resolvedEnvs)-1] - // Get a map of [src]:[files rooted at src] + // Resolve wildcards and get a list of resolved sources srcs, err = util.ResolveSources(resolvedEnvs, c.buildcontext) if err != nil { return err @@ -57,7 +57,7 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { if err != nil { return err } - destPath, err := util.DestinationFilepath(src, src, dest, config.WorkingDir, c.buildcontext) + destPath, err := util.DestinationFilepath(src, dest, config.WorkingDir) if err != nil { return err } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 251b96980e..20efd19a37 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -83,7 +83,7 @@ func ContainsWildcards(paths []string) bool { } // ResolveSources resolves the given sources if the sources contains wildcards -// It returns a map of [src]:[files rooted at src] +// It returns a list of resolved sources func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) ([]string, error) { srcs := srcsAndDest[:len(srcsAndDest)-1] // If sources contain wildcards, we first need to resolve them to actual paths @@ -136,24 +136,9 @@ func IsDestDir(path string) bool { // If source is a dir: // Assume dest is also a dir, and copy to dest/relpath // If dest is not an absolute filepath, add /cwd to the beginning -func DestinationFilepath(filename, srcName, dest, cwd, buildcontext string) (string, error) { - fi, err := os.Lstat(filepath.Join(buildcontext, filename)) - if err != nil { - return "", err - } - src, err := os.Lstat(filepath.Join(buildcontext, srcName)) - if err != nil { - return "", err - } - if src.IsDir() || IsDestDir(dest) { - relPath, err := filepath.Rel(srcName, filename) - if err != nil { - return "", err - } - if relPath == "." && !fi.IsDir() { - relPath = filepath.Base(filename) - } - destPath := filepath.Join(dest, relPath) +func DestinationFilepath(src, dest, cwd string) (string, error) { + if IsDestDir(dest) { + destPath := filepath.Join(dest, filepath.Base(src)) if filepath.IsAbs(dest) { return destPath, nil } @@ -182,51 +167,42 @@ func URLDestinationFilepath(rawurl, dest, cwd string) string { return destPath } -// SourcesToFilesMap returns a map of [src]:[files rooted at source] -func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) { - srcMap := make(map[string][]string) - for _, src := range srcs { +func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSources []string, root string) error { + srcs := srcsAndDest[:len(srcsAndDest)-1] + dest := srcsAndDest[len(srcsAndDest)-1] + + if !ContainsWildcards(srcs) { + if len(srcs) > 1 && !IsDestDir(dest) { + return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'") + } + } + + if len(resolvedSources) == 1 { + fi, err := os.Stat(filepath.Join(root, resolvedSources[0])) + if err != nil { + return err + } + if fi.IsDir() { + return nil + } + } + + totalFiles := 0 + for _, src := range resolvedSources { if IsSrcRemoteFileURL(src) { - srcMap[src] = []string{src} + totalFiles++ continue } src = filepath.Clean(src) files, err := RelativeFiles(src, root) if err != nil { - return nil, err + return err } - srcMap[src] = files - } - return srcMap, nil -} - -// IsSrcsValid returns an error if the sources provided are invalid, or nil otherwise -func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSrcs []string, root string) error { - srcs := srcsAndDest[:len(srcsAndDest)-1] - dest := srcsAndDest[len(srcsAndDest)-1] - - // Now, get a map of [src]:[files rooted at src] - srcMap, err := SourcesToFilesMap(resolvedSrcs, root) - if err != nil { - return err - } - - totalFiles := 0 - for _, files := range srcMap { totalFiles += len(files) } if totalFiles == 0 { return errors.New("copy failed: no source files specified") } - - if !ContainsWildcards(srcs) { - // If multiple sources and destination isn't a directory, return an error - if len(srcs) > 1 && !IsDestDir(dest) { - return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'") - } - return nil - } - // If there are wildcards, and the destination is a file, there must be exactly one file to copy over, // Otherwise, return an error if !IsDestDir(dest) && totalFiles > 1 { diff --git a/pkg/util/command_util_test.go b/pkg/util/command_util_test.go index 242a1a3057..478a4d349a 100644 --- a/pkg/util/command_util_test.go +++ b/pkg/util/command_util_test.go @@ -110,93 +110,61 @@ func Test_EnvReplacement(t *testing.T) { var buildContextPath = "../../integration_tests/" var destinationFilepathTests = []struct { - srcName string - filename string + src string dest string cwd string - buildcontext string expectedFilepath string }{ { - srcName: "context/foo", - filename: "context/foo", + src: "context/foo", dest: "/foo", cwd: "/", expectedFilepath: "/foo", }, { - srcName: "context/foo", - filename: "context/foo", + src: "context/foo", dest: "/foodir/", cwd: "/", expectedFilepath: "/foodir/foo", }, { - srcName: "context/foo", - filename: "./context/foo", + src: "context/foo", cwd: "/", dest: "foo", expectedFilepath: "/foo", }, { - srcName: "context/bar/", - filename: "context/bar/bam/bat", + src: "context/bar/", cwd: "/", dest: "pkg/", - expectedFilepath: "/pkg/bam/bat", + expectedFilepath: "/pkg/bar", }, { - srcName: "context/bar/", - filename: "context/bar/bam/bat", + src: "context/bar/", cwd: "/newdir", dest: "pkg/", - expectedFilepath: "/newdir/pkg/bam/bat", + expectedFilepath: "/newdir/pkg/bar", }, { - srcName: "./context/empty", - filename: "context/empty", + src: "./context/empty", cwd: "/", dest: "/empty", expectedFilepath: "/empty", }, { - srcName: "./context/empty", - filename: "context/empty", + src: "./context/empty", cwd: "/dir", dest: "/empty", expectedFilepath: "/empty", }, { - srcName: "./", - filename: "./", + src: "./", cwd: "/", dest: "/dir", expectedFilepath: "/dir", }, { - srcName: "./", - filename: "context/foo", - cwd: "/", - dest: "/dir", - expectedFilepath: "/dir/context/foo", - }, - { - srcName: ".", - filename: "context/bar", - cwd: "/", - dest: "/dir", - expectedFilepath: "/dir/context/bar", - }, - { - srcName: ".", - filename: "context/bar", - cwd: "/", - dest: "/dir", - expectedFilepath: "/dir/context/bar", - }, - { - srcName: "context/foo", - filename: "context/foo", + src: "context/foo", cwd: "/test", dest: ".", expectedFilepath: "/test/foo", @@ -205,7 +173,7 @@ var destinationFilepathTests = []struct { func Test_DestinationFilepath(t *testing.T) { for _, test := range destinationFilepathTests { - actualFilepath, err := DestinationFilepath(test.filename, test.srcName, test.dest, test.cwd, buildContextPath) + actualFilepath, err := DestinationFilepath(test.src, test.dest, test.cwd) testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFilepath, actualFilepath) } } @@ -278,141 +246,111 @@ func Test_MatchSources(t *testing.T) { } var isSrcValidTests = []struct { - srcsAndDest []string - files map[string][]string - shouldErr bool + srcsAndDest []string + resolvedSources []string + shouldErr bool }{ { srcsAndDest: []string{ - "src1", - "src2", + "context/foo", + "context/bar", "dest", }, - files: map[string][]string{ - "src1": { - "file1", - }, - "src2:": { - "file2", - }, + resolvedSources: []string{ + "context/foo", + "context/bar", }, shouldErr: true, }, { srcsAndDest: []string{ - "src1", - "src2", + "context/foo", + "context/bar", "dest/", }, - files: map[string][]string{ - "src1": { - "file1", - }, - "src2:": { - "file2", - }, + resolvedSources: []string{ + "context/foo", + "context/bar", }, shouldErr: false, }, { srcsAndDest: []string{ - "src2/", + "context/bar/bam", "dest", }, - files: map[string][]string{ - "src1": { - "file1", - }, - "src2:": { - "file2", - }, + resolvedSources: []string{ + "context/bar/bam", }, shouldErr: false, }, { srcsAndDest: []string{ - "src2", + "context/foo", "dest", }, - files: map[string][]string{ - "src1": { - "file1", - }, - "src2:": { - "file2", - }, + resolvedSources: []string{ + "context/foo", }, shouldErr: false, }, { srcsAndDest: []string{ - "src2", - "src*", + "context/foo", + "context/b*", "dest/", }, - files: map[string][]string{ - "src1": { - "file1", - }, - "src2:": { - "file2", - }, + resolvedSources: []string{ + "context/foo", + "context/bar", }, shouldErr: false, }, { srcsAndDest: []string{ - "src2", - "src*", + "context/foo", + "context/b*", "dest", }, - files: map[string][]string{ - "src2": { - "src2/a", - "src2/b", - }, - "src*": {}, + resolvedSources: []string{ + "context/foo", + "context/bar", }, shouldErr: true, }, { srcsAndDest: []string{ - "src2", - "src*", + "context/foo", + "context/doesntexist*", "dest", }, - files: map[string][]string{ - "src2": { - "src2/a", - }, - "src*": {}, + resolvedSources: []string{ + "context/foo", }, shouldErr: false, }, { srcsAndDest: []string{ - "src2", - "src*", + "context/", "dest", }, - files: map[string][]string{ - "src2": {}, - "src*": {}, + resolvedSources: []string{ + "context/", }, - shouldErr: true, + shouldErr: false, }, } func Test_IsSrcsValid(t *testing.T) { for _, test := range isSrcValidTests { - err := IsSrcsValid(test.srcsAndDest, test.files) + err := IsSrcsValid(test.srcsAndDest, test.resolvedSources, buildContextPath) testutil.CheckError(t, test.shouldErr, err) } } var testResolveSources = []struct { - srcsAndDest []string - expectedMap map[string][]string + srcsAndDest []string + expectedList []string }{ { srcsAndDest: []string{ @@ -421,28 +359,18 @@ var testResolveSources = []struct { testUrl, "dest/", }, - expectedMap: map[string][]string{ - "context/foo": { - "context/foo", - }, - "context/bar": { - "context/bar", - "context/bar/bam", - "context/bar/bam/bat", - "context/bar/bat", - "context/bar/baz", - }, - testUrl: { - testUrl, - }, + expectedList: []string{ + "context/foo", + "context/bar", + testUrl, }, }, } func Test_ResolveSources(t *testing.T) { for _, test := range testResolveSources { - actualMap, err := ResolveSources(test.srcsAndDest, buildContextPath) - testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedMap, actualMap) + actualList, err := ResolveSources(test.srcsAndDest, buildContextPath) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedList, actualList) } } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 60631adce0..f5c96b80b1 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -244,6 +244,7 @@ func CopyDir(src, dest string) error { return nil } +// CopySymlink copies the symlink at src to dest func CopySymlink(src, dest string) error { link, err := os.Readlink(src) if err != nil { @@ -253,6 +254,7 @@ func CopySymlink(src, dest string) error { return os.Symlink(linkDst, dest) } +// CopyFile copies the file at src to dest func CopyFile(src, dest string) error { fi, err := os.Stat(src) if err != nil { From 6b3473e4c304861d13c7d6fbd3ff02a07e925169 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Apr 2018 10:26:41 +0200 Subject: [PATCH 03/69] Use kaniko with docker config.json password --- deploy/Dockerfile | 4 +--- files/docker-credential-pass | Bin 0 -> 2529418 bytes 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100755 files/docker-credential-pass diff --git a/deploy/Dockerfile b/deploy/Dockerfile index a1b920c5de..74d94533d5 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -17,9 +17,7 @@ FROM scratch ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ -ADD files/docker-credential-gcr /usr/local/bin/ -ADD files/config.json /root/.docker/ -RUN ["docker-credential-gcr", "config", "--token-source=env"] +ADD files/docker-credential-pass /usr/local/bin/ ENV HOME /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs diff --git a/files/docker-credential-pass b/files/docker-credential-pass new file mode 100755 index 0000000000000000000000000000000000000000..525169cad569d77775e1de954ee437fa8d805799 GIT binary patch literal 2529418 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 z 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

)RB$96m!EB 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%0A`ZsCLOfxaZ5 z?g>$G$y((;a;bDVmzXZJoQd4nan z9xj|{A|EV+YR_*6I50$0#+t|)$ZhB@0tEwdW`EJ3di}dl^KFhJMq|cFW zB7R>ycUkI58?BsdJ;*^1v_{z+vZ!L<;FJVQ$u%7&K`O_gN1oPqk#HndPo1WdHlTJC z^f1hD@t3H7_cL~`j8$VgMV3)nq({I2PI4>~Qxf3i$BJaV@-r^|H<^Jmnb|*84|`)SkgNn!jr0=;V1Ng%d9QLczb(}^TbcMsEUguEr;|Tdf+BH!$nDk zxl%vE6|L4gJLuT@`tytkz4%FtH3fQ;jZ3HqKlS_&U7SxqXUTD@NRk}*`5bv;&z|t2 za%POStcIw2qH)3{&h!)9hqMp3AqM2VkSZ~Q26*WGJanZV-60+vY0@zm0Q^{!EP|1q zU74P7(}Z`Ua-=Y^V;o~z4PL#0Qv5fiAi}(7*IJk^yBZ5NGVr}mN+M@S2pq^JIz$}8 zJdM{q%mdo2&*<6HL-)!=5#3IwX1zcaHq z)FK`2%FXz)&@fU#rN2Q7kjIc}3r3F8Sk~u5wt$-BApx`>r~K{zu^}6fisNs z4KXK}xab55e24-Inb1#q_YeyAV$>9U(y;CZU`x~qGCaBXMK1opy0~Xg$L|fEd6YAa z(g9#h=)H>8#n4{dg!g37VLdHWr!UqMHsE;C=>+3gt?#E)nC`}zPcx~uQaX<~09rXJ zrqHR9-4KP$8X~X}*4e<#iI`GYn5w3Cl8A_az%S4PL3oR8Y?v$oYj??-`=OfOZZc;` zTpCP#dffqu?HwxMvXlf2h0^Ay^ba=U_Xy>>m8ErW=8BhgQjDojd%o02hELex$I3Hi zikB(WZ4RMJO?aOPi8-xo7jg$fT- zsBmP=z8%k_QKgs#tgY)eVhkkTAK7zoi4pj?de`J!_)Ea5rt6Ui>t%0#sb<4L_$2YS zxcJ0&Q7!Ry$Iw&9v3B9?U83HF(1Y1 zA027%#pRpHsoprTQ4MmZPYw@5?0rDMz8uSs5)qve^h=XVNQXdXHkb+r#>-Dn6a=$# zWiL01TCw)#M?nxjS6n@gSSoR0bqlh96!4aAufBdKWjJD~liIwhUH=ted`p!)g* z_>aRF$R@j!kmS3VQfJY*$9DW7m0atGv4>gYpIMZWXqfiP?mJGWS;Z}q(**k-&>!rU zZ}mBi51zX?GMSHghT5ZPB|_6q7Y}*R5h%xi6cTTu~^hA4ez?L(A2% zQPIJzaPkrqyEJr`is+tghpuJ^GOd{Nr$`x!?4WU@_^w0_vat`J1X+E=-5;dGIy*6mWE1l_b3;~93$Fsm~gBSptx~5 z7PJQ~zRS={HK@@WB-qG{)mQMztfxPe;Lq($RgjaupJ<5+JCnq(eWm+-6dHUl&IE11 ziwm{`8D5wT=;{5lgdXUR?8nte3;h=5kLq7%9v@&mOWnxWVS6)sC+`fGDD;xCc4)j zHB~F1w_*YyB4Sam7U7Z`9#hZu+yE{@$T$E`iE=aCoI$sxg(DchjVt7;4>0KA!TrOd zrgnvxzFLD%JAK)8FM@5gu0zkP1uz58_zdv3;^VSsMHYU77KLhO<-aHk{S#8q0B{4! z*IgXRH3)2_k%hRVL*FAB9X|uhmDo=I@o6x}tt=oI&W_vAH)_q?3R95+z;y?}bl7ZCAhU-EkY5_f1u@?MY=PXYchoq>c zch@F;pdB(3p}`Jd<|m!0MdFjlu!zG8Rb$3}Nc<|&y7^l&)2wUmY;1RXUSwbZ+acgU z#zupwD#jlsrdYvl;4v>UBQXrJ9-G0Ry95=6h6@KSh7u;leW4fkF2ix!EAAAF2Q(HoI9+EjKxt?k}A8otN5UE33U8Rrvro52wA zUU6D3!f!YPiGl@3{t~6MubCQmCZ)hb)S059yHtoMu}N>e`FNIsuZhnkBiy~@BBLw{ z`XgF+*txf-w&?sCQ~M&pynN8`cGPX*lX^Ntr*A(L_&tRNo*`16HjC6Tm}hv6K;v?-4CR-T}%h zDqy~H^5g_;A^Hkz9nGe(HeW45QntmjDiyp76C1LG0M3IYn4JE~=7^+uRPDEv=9Q= z^C>MDK^%-+`IZ(yi(h{W5Qu;HEk9~QBm+kG_a7r?zVl<^+FA&6k&pR+wK*;z?df`S zA(&eG&X?8a3Nw62z>Hg!87;Po7hjt7^lXX)BuB+r6#K)78Wc|e$y4HG* z0&%IpjxbbIF7RA$_7SfddXnt!7f~7E4J)f)M?{tm%Fg2CUkryH#`&z*7U~s8gx^9) zC8l`z%ZH)p8+}`db!Y?G%{&ZPJ#nY}wg+_)C_M<$mg@rM6Ts;JW37o4%0F23SUkq2 zzPz74E}eZZotTgYlqd;i5Lyd@V=WR(kBL`!Kror{$kX6!{Wuk4)nV0hs1Tkw1BRvm z!giUOpdeN`4Vvo_?pRwm@Fwv(tm#yLJbQ-cUw9|cZo z3J6ID=^}0j5`_p~?m*e4EY=N)NaVPO zs0zkKx)<{pf}?2`b056Rr4sSaoQc>BFtI0j>o(GL zBi0D{K73R2?Q>O$eRNk)HXmvvR1qpo@mEp_3ta29+Zw-5}G?B20m}J?@m>%5f)TIZWn|Q0d%VI;@nxt@&}Ot~ehHzQwH3*YlRv$4uN#7p4iL7d2T| z5jV{W3svlqm~aMz82d0gmmgW|!sw|(kGYQO`A2m0nTq!teTguAflH+X8+qf;e53F& zWMDt4c)s!T4NpCtVc%zymUUvU4u7fMrzUib!nrB1RNLlSmx`0Qf$1lV<#Kw!g^QTq zOeR-~U(@9JN}ku=33|{r>`kN5reUEVl$d2HtH4aHm#E^$(#5T{_=pa1>qRWt?u=Rb z8q!*U+4P9loc_s?zNak;H&hsSGAu$T+_WJ zcFYG;#tJput+Smbyv)#v(t^Lh)B*+@9iGEtb^OifO$i#>OVcWI{JuW=*V+rKO zt{hFuil&|$L)^`JDe{$dVyL^BaZDg|@MoAiSI-xQKRrA?Md$V2GRh4}Xl}6p3b+n| z4P>eDW16PWB-l;;o144&}egsj%&d=9c5{ybI_KdElcs1Ogz)ZRABb!IgwT{Wj%MOLL0W`YXpMHDFYCOnC^v&pDpS}yV5>mP#u)Wr| z1>YOTLJ#?+XnWpf>(GdBh7rXn^XG(zC&uw7>6PGT;Q%%WSXFX+SnVjQ$eOgc{~wP8 zi*c!JAx-rmH&VByWe?H!F|H!{CV}rkDDJ8X27LeJxo|I zGy*})Ak6q`de>HOb7Nd#^Q>xew|7b3c6sYgRA(@z^wG5tJ)r1MG4LzotJAi?VG^e< z{Q$#GXuYU1NsKR>K(AYSwhcYo2Zi`{S@&zFKG5L;|GKv=L%ea=VU`yl#R%O(Y-^n< zL&N_AX2AMf!I^;oAfduyNiDjJQD3p7%BSx-GB#1dP&AAN=ILs^7Pd42rCb2#d`6Ad zgz`(uS0A`y%eBo6Xg*z`f4EoXnh`rmb0^L;u{)#qTEeW|IDa_$Y6z<}wz_Pgskaw^l)V zldmG%WSN|fIqTOuiWo3N8A#GUvEMnLeQdk#3$zGbcbo8;pvlY01*8PsYnD}rV-Qa} z^KBr1a?5%aMwTx0@HLh^*NIg@jwWKF@ITbO}r6U)@-G$X`v^cTrLO||aDbI(WFJaXOvl{R@1+t9P; zJ!nQ?tvh4ty?9wx=>M&@3BKS{{DxI#6w4))W@f9IQN10nXu1Ej-&5^U=x0g`#M7Ox zKSK|U(zS?`Gsptp!8_F~{U0P-pB~^yJ!fHTt+mmmJ_k}oiJr6{mIr*kwn=_%qupO$ ze}N0n=tJwB&GIoXYPX#Fk9AG*>s`9gYk`P%b~%_eAH&+-3FK_>QBt%rd4T?%_w`!bg~Fprub*-L?1 z(w>0d8C&iIY0WDceQ&8S>>lyvuwVrUp;q&d)-4>#*MBS1dIN`b?oQcQGMY%M$bViT59508(`{lzn)BFx&eU5QH%Ufjp$1}bNH4#I_t&;94ccTeg_^k&KM6ispwoI?UCmhQfZ|kVm z_hv(q!%7v#J)n!S#rKuYdMnazBk;_Zkf8N_PhzEC%?QM?eRCHqrf@7KeB;$O5gj6O zn3R6_<)sIw3W}kfQZY-8=)DKkpQjCx2+TTi;#g#pmXSdfVfeJ~w}DMRg)hfrKR`?V zINMGW!7RM$zwNKt)FzsqU~l`sTg~=c;2RgEI`v*)anwa$oLjLXONWZihk(Ms`+rz_ z6EHc8;(vVdz6&fMIJ%f@CXj=K07DXz5OPeGWm%SG^D+#}5;nVofPexn z3MiKha*C*fAeS5?w+Awa+}DWm6%lom`^>MZK2`np?BT5c=bz`v&O6heuCA`GuCA^= z-u<4@2Rcl5ez5Di!5P7a!6tNIfuiw;2Ry;y02)m|Hhb^RRV2hy_>2S3R66>?O?R0% zg{ns9q1aFzE0<`|%#IHH(Q4x|QnM@t!`KIFnRXlbu(Vm8!=}qWa**zH{kCv5*QwfDr2!=-edkiZ{@bNM}Cyr})zX|#3a zU0H58JjfF7mOw}7=HEgT-llV(e8h3PUFd`a|2>vYJ(3mPN*4B~1xLRp<E=&@75VmoyRmEbls@&u1q*e&!Fz2;IHcqdV-sRrCH+=(@mxM>0E8 zL^E?}({0o$@6c8&y3BfucY?iXB&WB=M?0;W{H^BQg02sm=-B;{A2i)DL3WgLLrn~C z4&JAqiJALXeL%m2cLjGd?EY0R5RQfv{_SS68S>laO?OTR*SMQ*GY{rb{E!-gPO+{% zjb_xr!E|{Qy=R=aCLQo`xHIeB#x!JndG)0xH}R7TPPY=R zZvJLZB}FQ{`3jo-p4#-w3Bj`y-f6mP0-2e8-*0aFImLO8yz|UA{xAFi8OZ&@duRb* zJ38<|%h2J46cBiw-W`4+t^7X{Or?w$}n+)o#?2PKN?_e;jeSZ18!Uta-UPd0ueBhvCLoG}C1q#chJEKmIX$ z6;u9B_bUA%T%Ycur&igFPo1vFT;F^`H_hp3-JEW2JCLq$q)mBbI_bRMW*^h_gr~@) zm~M~0r+IR?CN0`e`V|3a8H;A?yyJ}SclbD5>k9cwa-?g=X0M)17ZH;*sF(4ofn2-0 z1hhP~M(M}XuCp8X29GIp9ms%9eS-xxaMk#y*1q(u6q(~QFyPOGrFX0 z&U+lG5xxdKsPr^1xndFTh@VVmg|^1fe1wkPym={y_~dyq#S!UBy*ggj0bS+`s#3d3E!>v_WyFcZ!EM z|7sbnIq{VI75+Ttk?`}|{+SLpZcSVJ9_E`dd0)V`6l4Qs`)0Q>b-9tW4AHPi?>|4Yes{1GXNWG`|^s`gt;fpSf;6z2yBfG!I(yiktilZhhC*aRoA2QJhk4H;?VhGPW<))9UOjp8 zqtT^PmWZ}AKY8ht$>-8WRjNntNBjmCiZ!lo?%;m7IUU!h$n4{^bV}Q(r!;SL>D;F; zZKgXv$=z?>h`J}e3xH0g(shJ1O?glY-a-n#l%vS|tfnoURO-x+4{JW-(#eM%Pp5S! zH~;Oj$yZW{g~~hOBYs=M|F@h?_waQi_mEahBbBD3`I|T0JAvj;v{R5YU_q*Rw9!Bd>(`-WJ__>=EH-<=yk!qAJPy_4a>%+JmDkijdW`=b^i|&)I~0h z!tGCO{yUlfvzwo#yzT#?cplm0=jpdi==|*r+KCs1BIv4mb?@*cJ23^|AM`svmkKu1< z{GpC;{Ej+Yei%+#-E`jsTClvEF5Dq8P7LoO@BF?A^!*n4PTyW7mzUm$_6PFzXmFx! zKL8Wl`HXpne z|EC|qU1;WZ{kaR9YYWv^O}`U7N8Vz%auHqiL?grSMjRR zxZw)Ym9MiOOs0%xy0kV&FQBG{7`h$q(%>mFNp#HZ?O?hD^|zymTri1Bc$I2${Vx^< zv* zpoLG;CA}|8u_meaNm26 ztir~tqXmfx6OxHUVm18>6BGKApIWPVjbxD6lzx+c$+Ubd#8+Z+o=cxy zm!8)2PrLMk>(Vo0ls{4NSxrCQ<)7P<59YTF%)k$Zt12$?aJgQtaBf-4z;svNOiNl2 z>pI*lc``a#O+VbFQ+WffxP;-#vsdcty>;wobLQdC@3 zxJ-~fEg;+xEV%p%`I~DQAQ2h9@OjXEr4GMj1m5HneF1pCU3!DV93O_OHo#f=nGHd& z;OTc)u!_s?3Z~)X65`nKm5qS!ufv}_0&n`B*#!7C6ZqFMFijpTJ*(*(yL7ayr57}P zto~Be^bKA91$Fex4f0nt-RjpeaBN-v0dg1UA-O4?cM zURQ9Td^uRuIbr#VTOi*Nb@`4NGoQ&l@kQkOp_i{W_!;Nx4Js&uS+n|#_J-CbO z(;h4uS)bOeQT{I+eriic@NLF-gsBOx-nDIjyV%2#k34~aQPAb=^3Zm`ZRGe|C{I@3 zlBTck(dh_&E9I>sq_t;xd(b&K03o(#ZQ&(SUfV*3w~;lczX9pS%(#8hUq-&ikxlGi zA5^A~q&3Uvr*;G`wkK1m!LMbKy`)<7m&PX6fg2#=NlLG{6Y~Ah(Vt5CE_O4wm~-TU zw0uxg(-+s^R&HTuz;QWd5S2E@;qvcDrBHvS9z9_hvb3~FO{wu(#ic9Q* zd|wOk1M62i1%o(adm#3+9mTf?8TpaM2}(LtHOty9y*uc9pmdo|6kH_b2c(o%UV0DU z=KJjy+`~A!JQyDZd<@A46+}r?1&rUO$Hl!s=Q@v0SGb1o-9;O}rO}BO<1h0S;9-T) z-=biS>mRcT%l}G>`|jHK-ZHSPWnLhbWnNHZUgm`}1AP9xNj@$0N_?9qMH`=)sc9j! zqtj;|cg11Jv)Ykr%0J_?FfA?Lzm1yhC7R(77`iy zH8@8;j>Q*9EA~4ob3ykpPhPp;8V2XWX4kAv4#mTOkL@1IYkxPs*m#|o58P%6{A(Fl zEDx5R()7(;`Vx6EIi@xJYLBmca24~F4_^ILL|J)gyH{ z@D<6$`niCN%TFC)*FK6n#^L6+^e$zxz2wHtaCSDk2=uggqKEHBC(`r*k4{f;q?6n3 z`g=`rYq@?#`VdZ*cFqMyOS|xJPR(-=XEAvtmZXKkb*}!L595L8Gi8`g2;--;6!=XX zp6mazRE+Ji;VR33%LsM!<6Ll{RnL{5$^!Sa!!f;Xp%)zB#Om;g<-i~8mEReh$N0{G z#&7x{rHT{^-kBE}9(1UjgBoPN}f1%6O! z!TQ1TA(=4bshi9&x=}Z9E1g{=yBw|*x_MgDGz~F+Yb${Nrbo9g5J#hLE`g11Ap-8p zo*X)Z+eCrFxvqLnZlxUXpVNss_xr9eFNTv2BRj!af2^DY{9=!OPdHWh?qPdAh1B3M z<39G6T2~_9v32=oYQC$HZ_&tn#eU?=c=@`+eI#Euw75G+$N5YSwE^UNaLt7L<8hQu z>Pfv8hP%;#0EIAo`3&Iq_S&N(+(F9epf_<_2_}cc*}&gaC%4@M-xVIOpRbRQU->-b z`(Q0$i}ZuW_weh&*Sv7He$wkrhx2z4^6loyftC@aoGAFY!JR!zTnzlrPz;sB_D2T2 z-Zny8y-SMw$vQDVQ^Rl_Zjh-#VFcam)u6lF(dF@u<^$RxOhL7y-R0@f8C;BCNi`^uO=N=q znY@Q?2Hks`3e~1_Uhdg+{&c8s2ye+E>i~XJ`dL!UMXcWDZ{1i1MY|XBmLw4mFKx0`C~_T z^eXqIIXUrT`3qbw=wV!ran|mI`_qEB(Zl6s`jgKaQI??LTOR=aK_5RLNcKL7i>!#; z@QDY3zuv1?56}0>UWfa->N)zQhk(D$rytNr1ImuR$s>9gc;DXiKps7vUOiKf0Jp;9 zBNv>&baSlPI!wF%HS}xXj{@og{Wev9{$SYv4=%2H8Qyj{TB3p zFTbLF`q&Sh($dG`F@CI`+1~+Q_VB%Z4DSs(2yVF4qrm;b!{q}3ihfx6RmJV<_~-dL zbr+V$59Nb=vvjO?kAd!ajxPB_Jm3-ozTTA-cb&tre#$(uuKa8T^afo2=J9B4>OVZw zJdpYmBrsd)RG$RC-{E;ax3=`VrQmxhNB(JcC(g-I%u$wx$4Qec9X{X6J`Z{YZ(O6R zng!hDDW?{nwy@q`E<&t_0`S*14UO;hzmlzk( ztk|_*_HV$=MKRRB$&aJv(_zH5M_F;xJzO7ILc>`*CtnA>R~?Sar9R5xDN?uLdY1S* z@Qud1jN%qMx^qc!r#J?z{F35M_UhdmenAA*J80H9wr{QfK>2?E@8N&}8zK5EXPmu0q{pr+5C^?(R&gD zdpr5N$*rn5^DhL)4U%S5JietrOw0GU{a7B$nP86N7pjJCoJf5Hd`fb0`ODmCk$r5RCh6~m)u1!bgdb!+#&L9(xcFOL0r}7LEqqF>To(rsrEfh~%1YFwo)NXu9KkYHh3@J;z`k{m^taYh}H z)8qC`t_|F2&dyJz3SA^M(e*U)vSNI3UEn7=JlV@|8`u*Wo}=J)s<@N?dca?y{87Ds zz>k(5t&j9wTzVu=mR{2IZ@ctBOo6pa`qRjtasDRHllMXsgkP8OvP*{7E~$JM`3|f| z)}MwpK>k~u+$la0&XWA}N%ew(G`VIr0)D3nV2Jggo2LpCzoTyD#;L-_!2R9vHMONb z{FKP4KYVr#qZfS+oU_ZJMlJ6>4MkF7AMQTYLF>f>*d6Jz_z65K1$7R=x~;$;p%L z7&#JTYshPh<2E}2_c@Pl6tpug;xM4`@A%jW_;noK8xOzZ%&C)4X=mWic6jDP)@O3T zEirxLJG~3=Imb8Yfy_rZ+B@B~YguszI2@0g`#T1VUUFB^gH>kx%y9#k48+bN2 zG5%9~1OHuDPqyF3G2uSa8rL7oiaXZFi3ROjpTcl^dVxa{5ine8HgHdRbo(F@`Niyg;vnFrIvmDHt9M4zU-s;EclfU8 zM|b#;GeCxKJrwkAY63yF*X?1@#1(I62UR<;wQKD#;Ln*5<9mY_7~ZR^1maBg(l|mt z>1YzKV-^-5|G(<;-z(tY4*3vs)a(CcM?>rD`rF~4bA`uuE__JzD;I7k_00vBJ2_i@ zlS`3r2XB1t)3|J3@Yo1^It%=qPg#B2T23Df*IAcYrH4&aqDH^i4gB-UFUvEBd3lZl zPF4@Y7mfqIy{7_dEK*Dg0>kq7#t*grm2B0ww!Nf1@{gkbFSU z@R^f=KiHE;K6ssLmk%Do$0?M_^t5;i@bP-}0ai0Lb!+!Y@nvi2>C5Tlv)i;J5Mc`QTAu)b}rv1>nx~%RfQN=kDzKXHju~ zaX7X!4>GWyXHLfF(5awzgI8{M@O#E}_sd^il8WP@>C=F3^W++Zf7W`9oL8340Dir? ze!Hvab2oPkm4oq9J`4CWo&GPQ8PUI)lf_{-HTN*NWzGfuDpyaoLp_YoQ&)52dEz|a zmQMf>`uh&!a@4-`_eh~_d_>;{zSpZ~dvGZu+v%n;$A|UX+WEkL#luG$0Ewi1B5{6r z+Xb6Q%h!4V@@?koOMWcuc^6&t%jI>2@5JSqzGS|SeBW^Op4+lA=p50{tBT7{@az4Q z)L6%F8a3kf&0Ye!PkQ($+)~?@wqU4zH@lg>4EVd9zuVSw)?kk5pEaoCB0cZ|3je}A zP+HLBoVW`4(=I=^_Zy5}9Bxm;ua;->O8*G>V?6%)g1Z^t7wjh=62|XiXU>yz=?3IG zv@YM%$hW_Ih-L57_A&mFHzMDwp8n=^BSS7c$~BDP6D8o+^YnmT{Vwv$2hTdaF?{mp zz@P8&)rJT_n}lnI^^elczz;fpcpXgxY{3Uyk%ctvapQXHZNR_j^n~?Gg0EfdjwyNP zpS0c%{Ii}u=EL=s|1+3=K70yaMPT`GKl4Mc^I0A&>Xj z@vZ@7-1sQ}7WsNSKJx5I4)f<*e+OJFXSSCGk@Euii&iz)#N?8E6#3?_V{%{CGCN!< z+Ev&8Q_keV04)uakcVcK=o8TF+Qr#0{=S? z--&&Ao!)i6xz{hry$3dDh(Ky&fvm*09(k}q_dB^Wz@?`bNYWhE1I@jj{sgFNC zXI=!IrMcW^|%i)ojwkW4%f@dOQ8E7N0;a8GT-TixOf9% zydGD1d3<=QU!@BCa~}Pb*gvrHa3XB-FZ~I)yFHv2H>1{-Fr<@z^a}6`9G?882I=Hq{u^)yI{M36 z7KJwn{Y7C!pU@m@ujD^~kKFi5dKMlo{kAWB+u=4Erhsi#~{q`;3 z4w(QT>u(QsFZBdhGQ5YTzcbyqQhFQsU;6lPqVU~=cxv79AlI2GTRoz8k>B4Bk_%T! z{#r`*U4=ua)|;4YYPGeFWSun&SFKVY`$ch5wXs zEs`)&B&-|#Xu^JyVY#Ev`;VqOMKt?URb0En1xNCu)t_#Ql9Y8_yK}tr4^n;?{3Q-| zx_V{T0RA{fkK;S!5o-r9{wj)l%;C7bzvJp}kbdn>>Y7=*52t&G+$kNlV4B$n_XYSB{l`_&N>_! zP{MJ)uy!ab?$|mxT?RS*Brf0Zt($}HVRiTifL{^gjgO%%fS>O8AUjU>ez+a4D((S? zTR`)ni<$09s+Z%plp3x6;#cLpu!OVA(HDXLgGV>VaeC4NV#D>f%$C4)I2`ebnMmC@ zS5{oNkE5A84V;2AeQMnb^n5?CQyuS4?#H~t=Tv-<_vY$X*arDlI{NJI2)_RyhWAsf zFdfJ7659g*H-~4x;$hc8tsQEL^Vi>3lD)Hbu=dSt2YPWFt*zzi!Em8y_)}4H- z+XLV4$|t#TKOSbMvR?x3TOKZd3RftfW393BYop*aJ|mr%b%*<|;R`!}?yXKA+gffI z45tgfHw<#*T)Mi+A-yB;KXZJL{~=-0oGeTj-J0Sq3jl;YyHCh=$VwT0H@ZWupu58H z!SOBb$gq@#OY92V+g|y-!4n2^^-AmpTx{3-TK*^+K7~KY!G;Ahx)sHr>F9Dh9OLMk zUS@X(-FRJ|aWvT`1*U%H{#rxZ_*T<=e|PkQ*ZI-PukHc5cer#~ucnrzSZi>qhb!(0 z-2FaI0#(3SdC^|L#c_W+bVUEGeX5#%mq(|cMiM*zvAAY=lf?7{4*Kw ztscdFfP3GyBdr6`1cBVX@Gknz;l2voYF9qT@n3ZEHa?4!fV(9CQ2ea$7||noi41+# zw_|oP@RvHed`{`xB1pEOCZ9waxP2V1Po9jww5E5vbY4fwGMzr3PDycThZ~e9E2pOE zC%W_?&ySWKO#vTMZ4lmF2E$Tu@U#+HG$mVfq#mq`Qsvp=AfFzKL%uTBI0PhL6QI2X~) z%b#ie-SCy^z!yDy7yN}TKL0cvAI$)M3s>L1mbX@5ELAnXivP3k(~v6e*lKKzHh9ew|R1oH&!jd2hQxgv5H)L{?$4=WwCat&IX-UuiTu( zk?QSP@?hX5x%$(5dAT$HuD@m!cc4eF2j|gjzCqJ4FaCXqmhaK+Co^T^mGN0o-1j}4 z*)x)+8{eZ0=*{+UE02%qnLd{lx2D5QlP6c6rl(yx#kpu4v+ssW9*Xi#boHG<^SrN0 zGb}njmh;dY;BNQmbz+^plQur2jb3Iha2I&EF5tQr(Qk&UDeiiQBY%MOmhCY05GRk~ zJkUGZ;dmS%o5{w3{u#aGVdKLU#)+$q6PKMozH%$$#HAO2-egoS!RzI`Fr?LW^(`oF zp=-CPG%voH1xUv+yzytD@)v+0+x2d`_<@1l;WYZJx9gcBfM4a6pXYNT zusAOc=~F=WP>*gO%?pQ*SH*GS68)eDZw&i;`p8+K zZXj06ZNgcfx7`T{*ZAUNhb1Jy;&^S3|H*#-VAcp+>KxEZHyLhfOE!E$lb2)H(fn?dIw zej~W0^vZaXbL9fyQXog=E|VwYtETCV#=F)FL8lQeQk)-$jo7~*<|kDZ7wa|og=AOK z%BS&{x(MZtg|m8Q6}P>sC)v&R*lrJLdNu%n`$s3H5uNlRKBu6j2et2`+*>?7h{BB6 ziHH~8hv`A-65#Lm@HsiRg^p$QDO?7ezaO*rXzupCJZo~}M(gFkJyb_e?YVbxg7KTU z0{Ejnd_H)O3Fk*UZyyzb|F)AC`?F*!$xv~y#Q05I3EV|>I0X85-=URXRGh!AnbZB! zys6##ztK%y1-dsmy6m@n+u0Xu*Q(-%&xfttnx?N2#O>OrV*_#I-0l^yJis zg9v>bJ{`_y@;c!E;OI|n>7>X83#v0rPB6N)9|2czIJQGC2`=XyD6#rSHv(U0Uui*u z-8O$+FZC1PepDwX2^8^`57$l=#a&*96UFKyYvkG~`YGr&*V*frg-^OY(+SMvU$_bQ z4P(0UWc4m;`i=nr+^-@XPelYZX2%fE8w1X<+Fb*>ll3;yE0t%KHzrna4X55N$YpR4Jpo#S9AyeVtIC-?8&ow zKj>ZN^*?$=spwxX_gk%x)4vCS-@uhWPoB*GC~Er09=$vVdf4t2@o|WJP^%K{*-EGQ zFzEXIwGS8Y*fxjYOwQLQ-k|;s7Ryg;|A+ZYso#L!k&aKYr{ef>n0SVpuMH{g43FR5 z;6oH~mjM3S3Ja-5-H28*0sO_|)%#zo-uXF7UMM zWq3$Cktja~{Lj}0A>IeRD10g842!~xr2Q6Q|HLBQ2Dm8rgQQ}Y$0C}s@S$qjip8|8 z{R+>5Zam-NaRB2GBv0NowF3PWiJM%q&mrHmikoE-m#^x1*Qhwsb5eI&WycTO%te+Mp}|C8M!1Cv&| zMz5l{I1W$kLW)84SW+jKH$d-o#}~`_`=WE?J5emK4#7N}4%K1%O^ z{uz!w`gvDaU7umic^ZKE3VJ+v|C ze$CUbF2wb_WI0w9#`vgg`rr95JC@!IxKdMGzpijoX%31TiT?80Robphf8+DrwJ#!H zr^8tXsrj= zJRB&P7p@}qhsh(k2k5uEb|-!3c2UQ`eKmssaWlzwnpNG>>Mk>Uf zt&OwMUcl|>%I%gXOD}5rUM{^?o~(VUn!bj|PZX56oJc%4y+@NGS5jlkSKAxq#`EyD zmbX@g1Ja;xt&)iGTdUffoJ=nhUq!xuI)2zMBKt-4M|0$8c!+Hbt;9z*kk}qKCNE^-uN4S?{HSr4c{_wgiyBcg$DUcW8}B; zDw_UX$1nLeVs>RY2L>Y@>v1$0{F*yt>AbrC+dOu@{cJMUH=vn!x{l z9_~rSXoHx1tMh=5_ss<-b4kW;_AsPJj^AZ1Q^U8!PEVDUaqwkwt{e`$KM(0817`Ce z!=)CD4;MAS8J}gv`SbtoU*I+F8PDd(`NLJkVV4rtZF_lLBaMn$ z`K|4sx3LO@_u0HM5MI6}Q>2H?X5hie>nz}>IeAh4rugV^eJUz$l7|~@eXKf8daY-p z++#d?eKLCSvgmX-A1f;En@s?6e{QEYWN~%c!&{}Fwj<;u02?P;&jbCt!Z=?~I8X3B z;a4R;9}Ljub9!4lANhul>n5+%caZ*D$2a+zGGO-w-}2h4rnu*vf4PkIL6n-UL~F0g zrJ%Qyr-uccz=^ec^i$xnjt`FGlH#TDgVnF1xV@b`*w1=`3+9!1`b+IW z4PkVXCD8qfqf6~TeucGz;WCOVIvmGOXo8~xGhA()xS^X+F1g_HkL{%PzlHq6RQ#N% zDegK~AHIL&a;`~)FnUB*jlRfG5K;J$o=Gh9mns^|xp*_m+gIswd3>Ks#jLVad9ImRkZby&i!LofcCoFHOzh`a(z55(4 z_!U1I|Eb%N92=~x&_CSE*Uc7> z#(zG3WBu03$^H`fAJ@fYUKRVhG+ZF|YN>beqSZ6`E97ej+a%xMNPe{Rf~Jqe1f-M?lXL9>;6HHu@wukQ8J}m7nY?Nb0{3N) zZg&_8AKfZjCSi0_4+HiMzis{NZJ(Fwl5#Uxe0m$>@g*px{lzSZc>ic+o$M_lg z9r7hY%g5)n|HSmWBYoZV0AT;_hl634(4&X^+8}83k~QGfU7-F1PtW*EX?od} z$NEeS#qmc^PiJd-Rq?NR_3y<63B7u~T(2zN#TVL8Pm+;O|FV|F{y^nF;O`!fUT1iy z=uIc@Lmf804ZQ{Yc8=freU7G&WyRg$^q1GsUJ$yA$iL?$G8wEE(HcLMVR}+{7xZI2 z;(bQcpL8HFTupKQ`on1Zk+ScBUe58$^hmzL=vBvw%f1hKk2-qXkI$5TOzxYDW3_$& z+|?c~!u<>p*VyV&Rb0)(_24eo9vX(6J*#{OdN+9O)P;5DE`L9V=~dxl;A1^u`QHZl zdwOMjM5}>+!Q-PF_q}%e{AScMxy!@l`TW0jJS#srVX7cjdHhCLD2;-%om#nmH535< zfQRo1K4H1``1d~;zu6|>{q@u?1jf49)iyrTYXJ8tk8Xr@iC6@&8!66>H`Xb;oFdZ)=hqv&((p~vM;I8ZM{zySLljQ=BYM#rf;P{(CU2-Aam!<&B7k@mJIIKBph-=lzxSxsR_gvT+JrB@)p_cv|iJwYHWE z2K5C^^zbPeU@jOui78w#2o1hq@MxoCQyX-T2GrP<|%%znk}+s9cSHc_-li;4bEDlehPxJ)iBe6U1optSSKGW?Ee&N`5`Vj2_ z{4eVGfIz6P#N+XvzzsSauOH4~y0XFF$}cI-Uq8+T_cAWW*TSgST=}hggKivOW__S; z$tO*zEc1s-iu=&3SC?$uB*(vl;a#E}T_WY!KP!C&^!x0|&yCp3$vM0^Q^FcOEw=qU-vz;i7$kgEfTxmW$WbejBc)xYry#jzc|U z>fq#C{Tk?<;c#58GkXpfO$H9DR46wWq(|^q87HnaJwAFviFtYP#jiEO^(!`hP7W}8t65`6%_YF*M1z2qj7-x z6NQVMf7?18^giR&ryKqpy$pL~eKIq~SD%vN{B_rEUJp=tPE@{%2Y_B9eH@wz+*tj< z>_~DJaKG~E-Gh6+diZ*w;dZ2|_@|wnY-_oFFuZ{V0^!u?mJbHqFF3ottYv=i50>YA za%AamP-E(owA^Y2_}ezd4?JIeVIaI@EymKr5j0gjsyNQ$6s5^O9Ofk?4<$fxb@>&G6H@#ho^hr`k8!N_#}-E!{wC80e_^E zEBogMjL^?=1Dw^b^#stn#+BdJa_wN4mH~<$_EsJynmkVg{v%gD-&05ZZkRq*dx7)! zZFXRXXvYkymW>O=lYraamCyH&lY;Pgw+v!lPCO`iC+Et^$oESxUr*R2Z1;paE7$Qj zGSm-zi_bd`&zVY399&mY&eitr0?h3z8?5jdLxt8b#^YoL?RdLwt*YW`)>*!wq{N`(+ z0Jejl41~{#)%#?C92u1GmX=?+6!?$VkMZ;x#~YY5z2EUQX~0_tDUih9WomWnAcfZW z8^W4|db}Q`VErH;T)<=vU{(1{TnA&_Gc+zL;fcD_4F5qwEKB4D19T>HO*NqfAL1-kJt4nKkbj;jQin3 z$#ly%n~$4b*M5Th@%_@gf8=%=li0C244I4={V9I)k7a9s$9~y0spdo=eYl3?1Nm)0VKnvZU=6W!{L2KSe}T_#TFFT z=iwsny`DxdaR=zNd$^ppzs~wsq_~vBEt4msGorH$3JL(ODb*cY2_w<33`oiX~j)Ju~M#ozQE`WHNcrXs)}3F(L>zb=+rcQ zf0s`0U7-2y@Oq~20{@FWT%N}%1sc7g;{17v+{;IPE-8HM=iUu^{=BOX5eZoa9O3WW z1N^UD`P^>Tk7&2ly}*qnXVd$v;%c7Wcj`Q}Gn_>F4-TwenfpK&f1wY2@78cR6%}`n z$ETdLQp0WZviF0M&nKT47(q{Q=Q(;j?-SF(%iC@rXzK%@7q3I3M_GB1rZ?JWT~r*X zp`I&8sb@`bjr@bw2SI5poV7=!IR8FNxhR&$y@ItyJWduK0^LWPTv#7uaLDs^Bo((C zS2GU-zoxV2jK7fWsJw38^v(KB_7UJWaP;TNlkr>7^cfz#h}XF}0C#uH??laC`8DX_ z?@0YIx~bm)Q6GQ1hUs=w^qsw73h%}D0A+p)`~i+nvOg5(9HB>wJI2HL@%)MUd-8Xn zccxdbZn+1%ejF%13LO59tdG&FDXx(n&HNse8sSQcyWQ1;+wmgT;3miDG0Gms?Vt)l2cV`^f`%(7?iz<%U-)}O~mx9}I>Wb#e4v5!mQN?<_CGd@~h1^z!yzr$}$XzAatW##miesafx zCCFgoSnFSbS2)p63&7ITnjY_m>#s{MXu7{|tuN?x{%_(n&_4>r5`7w<`e(Kb=zwJ9 zM2Z`WkAkM(7}KeXN3{M8CeaVmyqB@#i!l?KK8R{oto@?TGI`eQCz<(hwlSeKBAvhM!|KDg3J5^ z<^Igk<9XQ`Zd|l-6aNG*jt{l9+%*^j4Oboo_tC&eT;X3M>3y_nBraVW1$W9wT;kur zJ>u%o*YeRxBXO0{a4SaQivJmf-m;On=*>}Z_r`*msQjeg8U?pH7L4JNZ;ytH1!K7C zsJK`#hAX`@8ogLBhAX@~8ZH)$;WF=yhKmJbxYYZj;bOrUt~M$z7L4J_AB;wCwG)it zhCUn>=LBQ8>_?;GoL~&s`thhZCm6#eJ{c9~1Y@|$=r|`B!xdMLO3w+#>`IiFCK~oB zr}x-#V(A4s(rcQ2r^_GQ!H-st(gg6=?Cc)zJAabL zzrN!LXXTUw;6Cl>AcAY@6-{5qrNiU2^s1(B)PwC!fv?XwI`Hr;J*DZNcj<@8 zlclFMefAmvvtquCSx%|1h{1r{#-KC#Um!4b)`Nz_aR!z5hw+tLvmp`lN zTRHmhI30ft@|QI|K95LFInlEGiBEyQ%^iI>GM1jw^hs{MMTcj+{Mq%9f2{r!HApXL z`WIdKS$VSZOPc;kT>i&?`K8aG{0&|H1$Fr=4bp3xzLo1=^indSVCAP;K!1BjA0E1; zXEc2Wm)=!ZenHbim%d+J`jDoNBjuUE@p49YRV)@F|&6b|o0QpZ<0a5=e@S~+yH$?gwar;Zi+|r{>kp4#vv{L>j z_|eicTO$3lj=w|Y$y+pl6K?akm3e?9PbyT@sO6k(#CIcYm~Q>!|`Yt>qT1AQ}Qd%|LVt|tft5D8_E1-S-le5B7I#)2k}8mPilHR zPGbkK@sZJV^a8Fo`xCSuCJll{r=+;C^s=hyW7*xrcHnb6$LG=VWb|7#{X~}@h+|~w zB~2e*zSX0u>9D4#N1oz;X{Bd$TDJ!u&90mo@?`00O&_k8mY&u0;p3z6QPA|Mjy}bK zM~T~46gS}E6WgmVf#1Cxu2-I{ydh1$(xr18kk%QY1}^TN-T`#(@o=(k$NLB+ zl8pqToA@&DWASIWg5vreU7A0i#N97Xn?d8aW@1OsJKV>S|EAS-{W+_+g+7kjaX7B5 zxUu-N_Db)Bawj=@h@d$BHGM2PhD+=WI^B*A)l=fedFr%rJtM_6qE}Pg`93|^tvnex z7e5ncLDC4I(oz!HN*iPy`th8@t4{a^m=@Hw4Ooa>gqeBxF0(lpU2|J9)9?; z{+`|q^!$Cax!`+DFc)`dv(x+3-s7WJR9vHWZr$g<)3g3jQrvKV*5q5& z^b36c`Tomc?OXT?%6rA(cwOK~wC|FU?Hhd+_(t}iqPRx(pmh@H^||s{U#Q?=`chKd zck6KIC%(R9_8p)6DvHA_ko7c>t(Ydi%-29C9@m&J+5t9!OJ=0TwYt#-!#WiY&#D3$WmsMONdgTW6OpjChqujCd zIHT!}`fEjTjqGwX73IBG*Ip!F?HAVm(KO)xREPVqwCg;tU9;22C%3ZV8p$m+V|?@q zifcr#s<^S_XYG(Z0Ofwg)%Rq1GI< z2>EAbfzFF{xN}AR6ozvBs`bF}$!kb)jpS8R+*tCmdPK8PZoNF{P!#ohT78;sxSHa| zqGxi84g$TgujuJrFZK)d5>;2<Tz~4|u_bfMV8-JOjfJ1a!#(!yX zYtN#lk7d`5PO1ZRj&bD$o&0EYhBUole^*??{(dydYt)}Aio4eF#c~t^m%OB@5-s~){vaEtUOfBdQ`u2Fq6U7**fz9q#qs&DJDpy%s%E=UW1G)r{$t)#fI z^w;X!+6{X5d-aWQuO{E4;O6~_+()6#_&G#-B`SNQ@bz0)$fvFtm-QnnQ z+(tGe_Ri;Ad^nwgGPaIcRs07YKF1daaQtSbe8_P>e&-pNWqegnKsj%Ee6=HAd)P+X z0hKX_KN0xvd-xu_ccCYEM_8(>ci|-9&-3tI;TlAkPB6=xeZa8kP4Z;m{di0tzbK2= z3rG)VS$&I&>vii)e6H?F#-uYC93RxztRRR4ItcIz3yALa10T~4;G_mfi3aP3o6+*J<8@2@)5>8*4e(`yzOIUvW=)V0FKBg}#8Ib*Lec2f&intDuE`~NKIks; z+S}q#@b=`~Rc^UTW|G!3`VR8_ujjT*Z_3|A{(W4zEGOzOET@0P{V#Fh_;BfqfWxXG z^icPWQ}8g>my+WA{=)aQkUU< z*e@sd`YD>kb(6C6C)&Jj`I8r;ym(&&=coO|l!s(be>Fd?+Rzv13gx$UOkaZh@%y0J zU%!aK?ElkW$(SPz7XxScvX>%Xlh+Qtyic8~D5FPjMxM#$q*)Z!e$i#f7x9nukNti* zZ!^r^RTUTecWys_o8K;(%Rz4}oXM%IxH*nrKKFSW^VlbyiEk63XW5#}Z}`&wZ1qiD zfpV_vGQR0PJ`v5ra8R-?44?R%3W*?A-^$w4CBv_fP3%X6_fALDzV5tmaUI}>udAD0 zl{Nj*Iyz$5w+G*9^1ZF6}Q~k9lpP16R~gI;Y9ibWvfqSeb9Z<<0Btj z$Fj@Q>arVOT0i~YaVFPf61abP<+q2wmGaxMf4-fMV-Bxhq6PWx_4u&&%(AOu^vjAX zd+pwVef}LdX51m&q(fh%Wc4g;0QzS-`lNq+K?LbH?}N8?Nq!!yoAZ`m&Zf2CL7NaZaT0rUB$_ni7UJxXqjd~-d1R?0f%O6u(K_#Y{56njRaMf`r* zs^ac*^k`hi_{7%{6Zdp*mxONeC~boBf9~P+MYM8Z&piD-+7!6cbmIb_f4*xlT-n4l z?-~@7Li?ew##ep85&b|_=Jar585`+`Uqc4ge-qn*?wX$5a(I764%ZO7w;b%pq;j*M zGp?P!g#7Wn7p}f?%$%F+6Ut)st?dZ>cU*nhu6~0_%RQ2Y8`=pte?4`j$Z=(!?bN24 zKe01#pL6ukl13+`>G?RFI2subDJpJwJjCi*)$}+X%Y2KX^kY;Y+m?>s+g4}=U;g`h z<)S}!vn4|pDFS~HBi9w2k8hXC2hmkKIa~S8?gn~g*G^QvzK0}cfP@&NMV2SZUvS3V zhFFt-MlZD|=uLKh6w|}~6aC`<_M>vR%S&DfLe$AMYu_%cn8dR1H=@ymGKiz2c5S(I^P`7 z7r4^{=+MJ)LWdqe=bHoM%n%)uXEYmh?$P?PzmvoLGdVuKtm@(HNb5nsf6d90-~aMC zDg;Qg+tIu!V=`$%E_foo+j$| zlBOTy(pewKTOv(3kbW~ zZCHBiu}EJPr}y)t>1#>TpY+=a^YxzaduT55<@vT#a`NMO^H2}yuIu>Xe*8DA`y6U>kR(L&`#eUPLS`#|NM2TPIhdSk$I9z>57}U zHhy6HPSyYBUS%)Ljr0s3`llmd( zHHzC86nCAY$MNcp$#>iwiiu`#o13SD)w}(CKjX;q%=Gj%d%S;(p+8 z%pV!}VeMJC7xWt8Qf1)IaP;Pq9i^@`j9#e$&iZTmSD?3sXNU4wH(@`4yagHa^qDO+ z3hvkPGxs6?&)38cEYG~$@5VDD@zvc2<@SC&6yM&*ho+q_-{f8ZhU%}!_!#hz*YcCU zM){94Tlwr4&Jc4kFT7aVaUSpcEopo&5ns<_@Oc3|CZKZym0U8SQ7>JpDcO1n6yDXIG~)ZmA3~ z`WIJWEya!ROK}0zQpAIoiiKYa`C0jyr$F~+S3Zy5Co$a|%_5yWO+F3WI=-IBNGxx; zqQ>eG-7vbTXMq2fqswuSU$O;p{SyeiLvZX>(b`W$eL)+>h; z*N9$iob)o!qufU8pB2TO?#U;I{oXlRcXIKB>j ziW`eg>Lt*z{x{bCi=yK8ar~eL#!q#ebh0m_yuBSA%sh-vQPangkKs~P(5a96ksn2I zGqQ6|&#Q|2yr+*n!H*f&}Iyd8xl6|K(nJ-N!SsTi%W}ydRd|06va$@i;{NR_&xHAF-1C2XMb$)A(Y4{y4GE zixK}_jM&iPaGFSCF?&Vi=Ccs_<0tY#)`h-MODQAPuB~r@z8_!g;Jg2n5365IaX)tT zcajW0%D$n9Opxf-)tF7hgL5Xl)J*fV{)r0Xx2N#9&F>ta zofem4{73Ht-^l({6t~dPrTt*!o~irj^s)5=(0j$kgh#U&9|PCp!eX3GzSU^qBQ! z$0lk1AS)lVLgeD;Lm?#acdxuQ+_2deCa8I}VU54S8oS<6Uxb2 z^6ED`JYLwHEpEYVz75c=lN3_G$LDY9JuZm(F2efrBFt(R@k{RF`~Q<$Azza#hwar2 zDW@Ix)3={Mt!MotwKeeU6Y)P;|04i?O(fd!b0SjQb!*`VmN(r>da^W-_kb-1bQkI! zED`z?=jhf!@pgxQPtN;?C0L>=xi!Eu;E&7QLd$z6cIwyu2XM?K_cxbn-2^XC=aqs%KZyMo^L z9KE?TpP{a;1zUY;io3|eb@RI>hv9~H13iEI?iuBrPI7nPe7{QWE62~SzC+{0CHFwa zGd=!tydp*RkLCxiKNJ;rpTn^|r;g61jMj=w-qt?Ro}l}?(eUJ`567qX0{-_Nz6bH6 zp1E8~4+f1*H9fgE@Y?*;57Lri<)<|LxjK562qn-Xrb(Htof7+iUL*Mz8sMz_#8*Hs ze%~j**J&&1*NgZC6)FJ3*S-q;J5HY&zk}k7Bk}tJe}KbNd>{9OXZg6a^;4sto(%l! zo;V=o%lzDWI^q$9EU* zTkqoV_HcZ8Kj8oF_~3ij#X8mTZS+g~|8MjwQ~x)7Z5r_P_UT)!SDmBDJvrll<3Di# z@PnRwvRJRkdf^i1ClqD^KVJC{&HCTyCuak{r^iow@KdgD`)Kve90dGZUVC+69^2*X znYCBuVBp`b!^n7tO&tonZ?8wYZ?CMlMs&?y z73P4hiqY9COCQqocs(X)XOUQXVlMI@>*R#@En0e{>GR|C!~FaeOJ3f7gBdoSEvv+GiJ*P`mKPa<{5~ARy=CV?TVzVA_Q} zc3pV&OBc4vc7=zaK#FTKY0aSDXja3)TP&_RE@lE+&&*%(qoz?*n=-Pu6x->{F_25V z?!|F9GSFC(p}&}KSih+#KI8TKZunu{qmB2eV?qBt=g0DV;1j9dV)ypWn4eS+@cz0_ zH{z{2-6q}h_-|bSeBHj|@MxjmhV#2^ZT&T_(TUg}|TZ%|9+03@;b|`=UX9Lx*?()_)5Z z122o2M2GI@k*mioy?6=I_eJrP-Y-v9URBfmeeSleOh(Ima1Iw~{W!V|^nU5+@p{O` z&d)eqe{a1UxW`-Z1J5JAF&G{u6H$8DSt>*it2bgv(8CYymudEJle7{g9c&Muwxnz9 zmw(yA%le>~AIw%hlD`KZyF2~jefckPnY~NouSBzT>nZONZK~Wh$Vz zhiiBCD`Z^jmbgpz941lsmuKmgf9P@Kzu3!f?=P2$v+n!UP^O#UTU@2}3FMcTQ4&vl zzf3>NpL(LcfC0fUz})(D_K%v+=~Z9L3nzt_i_~5?DfoaX&?lJ!(JyQ7p{J3re*Po< zzb8vr!=;}A&g#kY%U%+lvf-+koL(LNTLG#f7YFW~05@+sa-aT)v?%RN$@KW_BVD`15p-i^}7uchLBGCVCc zx!3*;O8z{h5B2M#k(J>1%YBDg*i`vQzKMKBr)A&-NwM!4O@G?8C$Goz=)oHUXo5u_ zI!%-nDwAXDJD@w&YoA{12h#2Fe7RA)AEodv@V`;MxP2n*--rf?=e+)&c@Ma=oFCNI za>-zL&N|EqJ@A_!`2kCq^eL8=KE=nO&kK=Gkq^NiD3<+_LH*7v?2?_rh|W=r-8QHdx~}OisI%-^8boZ@qec&r~+UUVHeZs2J7Ybo-^>9-dJiu{g-J z)gP#PYqxdwHn|zflgk{52bNQeNO>9Oy~Tb{X$tTiuD$$d5)RbpYu2^RXNjj&c+TaDHx8aq;;CmU}#K zS$Tz-ptru`pAN0jKT99d^v}BVL*>c%DQUXD53Y+}G&8LJnOP{Ok=%>p#MKn%w|9P& z_RbuLa@!sMEC-tPsA5<>%8G0AaI&9DaW-DJ&IY|7Hv!1~XL^{G{xcoNZKj9&%kVv& z^fqpf4Dxk)^mDx9TIpN=${Y&Zx4r(gINS*SK*(Mb1Z(_M=K=r4I{d!C!w+4IWB7}C z+AwRLmY-aRd>gua?Dw55b{U6+qNC-@a{MIIvj}G=bgdU}Ig1vHkuW*79s#=WW})YK zE?MhodR0=~CQcq`NuyKI^i5qqpnYn=f2{h>f2u7;d7F9l=)n8EJ18>3%y%3mf92Sb z%a_a|-%eh>Ha+*=7B)-9He?YFjj!~P$mjb-{<@mAOIdM;IeW(EDmE6nS@4(TV@Jd7 zYpMhE<2Vzy%j;-_sjm9Y9u$rS{&*)xI)}~Yq{&v&bY;5fRiYC(e;vOw+(r25~^rUh38qEm_WuX><#Ud&RXApYLA6Ksn~kAAj=tLDUVpXL)pccztPj`Nsjb ztw*;58=~cXyVf49J-}V<=<&EAk*t2!!AbgiRdGjn?VSxPG) zpm%^*zqasHsb3rWvsyp12bopC>vWCAM~oDf9%=d)9Di8Bu=F8K-@v8A(ph>*({)=3 z(Z|jROD}8sdM^KLd9w71rf=cWm)51%G<`FdzF3~j9whZeLh<}?S<5|x8kxCgFnE?F zc+cPpYe;LCOaXFP;plSQh$h#=#-+02zSIPu%;RM~7=;hZ=oHaK{7&qy|JF_i{o5UV zwl}gAG3xxMbO!L(*Wsry_jP#VKl=^fuk`T#{mO<*o;i|k4*Le`=87q~|A>4M@K&8HLRf!msyh~k#q&EAs_8r_Knqo2MU^lx|L8}HYAUF5ScyxR4A!zZo;{x=>!Jy?6};V_C0 z$4-wbil6H6quyC%-uTx+{f@8SsZfg;KecN>XRPriaqWLkPip$`d6&^| z)%0~;eb8dozG+Q=ya@oFr_2d2ka_x?;2CCk4#i&Gc%Aw&`0?ZEdJjE0_;g%h4s^oC zvy$Q~%|^ei<%imxemEEot;w0_;YiiINy=y87L=25dfL`<<6u}6MZIwlJICo$!pHP^ zs;Z*Zt8yFizv=4D?RYVlmOH}!k|?abDz^jwkcaQZ`wsaY(Kz062XGfU9F4O*OfZsd z>_#trCvg6JH==pG;ihW-s^SJbJrPO-q(PqHee!`X)I;c}>1I{pex1Dw<;C}@ENe;g zLdz8T@WwHdPx)@(PjuzVd-2}k476*OS`l{3@acPjKdBxsCT28zxeR=}!?Pa~yvFqD za|Hd?`+)b`%iX_0GfXwxuDx3C2mU744&;x}yq*Qd`@960B`L_3k{=8X+j^&nq68H(90^{r_(Ef`n*I|*-!>*K*dnk^m;#3{PA9nv=|@RS3&2* zH9&~%`|NN_vG23d9cN=-((K^3%*<@Ic5z&<`a1HP-r4%2wSVgGT2D`(x^aF%wm+EO z8a{dhcz=IkWc`BNy5ac3KY;hg<47Y)@hOp*-|Rnu|DuyyR-R_-_aRL$dGeSQo+mS( zS<+)>g-7C>goE@qX|GxIm)n^CS$)!Pp}a@%GtC#-j}>@c2;@5@li`zZ1OJdGuPzxE zy0CgIljK>68?`Hh;79V|6A{Lz2j@zH3_MC58>pwVpHB2#77~i-WhO)m22C-)v%+Uc-ypf!TCeO{ zz!lW6aDSq0Pd`|jDbvIG!s0E1!Grh#TP5f_#kK^%+k%LM$+h}<(EIh;ak(^azHcpt z)5D8Ij}g`{N-5wkcXDlO`D7s6x|#9x@Sce3lYv00PoJ+Kzm=ES5&5@w`w;k?#ZQIn z_Hbd7)z|Qa-GKM~`Unft5m`STwq|k(hR^H{{C>Wk1Z45pK;HshxTc0L?g6~Nf4dEK zvW?@qrnlBkwLO9V4#Y)ztM|SUC%(NN+6%ZpIvkBl5;lu?x!c*_Xm8+-_4v&SyIKFZ zxZ}6F5Aa)h_IEKFcd=|^L9)XqC*cQwo-XkXCpj=^^{Xfzs}P8<@r%lIm~nJl_XXX* z`1RBK;LsvSFgd5b_P^nilYxJxu0O0TdNM1#hWZ84jec!^eBarP8$3VTQ?zkm@R-3J z|EU?kPx0g);dpg~O`*|pZhfO49RR$4uSg#DA-UL6k$y79%I7r0wDl1|BQDB z9!~`sE;$#tV;qkA7scCE0iApm7xx3+_auIwu1AnyY0_wC?kr#FFwj5HlW#s)CQKhD zf7|6Rzbc-Q=2s*ZAm4C*&g^1R)35gEM!5ISmVMCdV*F+6kJQlkDlY{6C9Yj~Khm#7 z-t8_w&L9lppDaFD=D)zu)pYDYb)mzi5qk zTq-UDey-OZyaQ~wJxFAMOM3N}{UW3c3n9@Q^J07?mjgec4lg3g`|AUSPqhL6uH%FK zg(E%6NHBS(js*TfkG|U|1b1ID%UNntRnxz6JMwMdtd@c#TSkBxMBy*fuYG&vTI0e-T_k6rM{d+CuH z>sPr8zuf8S$@8m2SnfLVBEiu=7Wh7=$2`9OQ}kHQc+@dVrrd8bALR^J8+) zt^nTm-}`Xi7~g#A?ro|mZoMY($Nt|UIXOOsJ|7W&7LBqWK9L9gZ9IOuAkQv7hfHn+ z5A)8Rww?(546nYO*wEIAvz(pS9oUJt4NO%z7EVGw|6H=&udntLmejYZR6!eOOn$XK z(7E#e@%H9{aaCpi_+!HIDk6n~sDK7V5h!8yOb|8QTj&x<%hFPk$;?eM?QG1FHf#+F zB7zcRQA8y!EP_Z_6cLrM%c2AU6+{gRA_7`O1w`ccdCqe0nLGDn+Sm8@?H|pY&*wSM zdCtDxb6k7*dsi_KUDLXoTm9X7H-3_ozuIUojuxZ5xmfT0hU-D=?^Y$^W+Q(6>i)U@ z*3}L2vrd=#Bd$F>zZUIsfv?+;tXICeKOqrsADZj+nX+D^UGm4b^hqh-W$4ezjLC@w zpIrTTaN-Op-)6`cWc{nNN4FbOXG-~->e5GELU?rRgQDCV&HEuz%uUy^vn8;`O($-@ z`GaphNXqB2C4ZsH|1IZ8cc(j_;&ryiSiCIyp)!_wcyHo4@kew}ijcJYpFaU{eJDt5 zPS?rG@u7ZhL5X27EPaY3*7YlNzO?J-%1)k_4a@U)!$m|w%gy?{l>1(toEYB>^CFd& zn^JO9b#mu(*!;bKD>r_D)c2erx4z|Gw*Y8;V;4%ff7Z!8+9-F?R?1y0<*qXH75EM^ zRq%AUU0>Kbxh+cWJ9YZbZO}LVMXB%6I=L@#x)jh~y6G}{iIg+f>k2$L@!R($Dfe)l zz6*sutlPT!+AfuHSJ%mXxFSDK}lG z@5c@LW?d%b{$R+hZ@Ilej>fl6-?Wmm>C^4u)Yqgw^SotQ-UA`7+mfu;zKwrfBDWds z&w9}?^Mv#qoLdh*~^+HZG?DcZ=t*z77t>jd4$Z*91j?|~)Gp^*!aZyIz6p=CKv)az-t7Z7> zT|05^P0a7hm_T^CzRYSM!xIsX)hJ2k1Y(S()Lb%Tk5SJm#GzzgpN0jRd=M@^1650wcMDJYqqaF>pH2g!%eSY@k`s+t@tZlp2wLeNIcFA zh!0IjeRtH!qouRRPi>?8`1RYSzjT9?f3VITF%GMBKQ}B=1vxB}vnpScbNHHO2zK`nW z=MSa5w)7rXye&PZn)u(+grD`JnZpk?;k%pgr6&BC;%)JpY{GA8qJP$pXD$yR#oNN~ zQ@pJ{k2m3`6>qE0q1&W=Hhxs`Hv1-;@Y9O7l`oo{Ise<5@Lf&#KE>PYA5*-ozD_jZ zr<(9vn((u3pE>>^#oO%fYvO;j2|wP1pKQWUH{t1ynd8^igzr+kt-mfQ-qv4FDBhNS z(@pqUcg}2oNb$Dv)2(=0_@hnui6;EC;;r@Tu9@v`Yr=Om;rkSCi{F^yZRs=7gr91{ zZ?W*YznpcqjDNHKa!kpcQP*G27c)6*Jh6>rO*=_WiqAmeBA-)7-;d(ox% zX6?nKlDpY$FL)nBEYOLY%-!+zgEOc1xZ-W;G1bKXmL~kHpUxb9s0rWQgfBJW$C~gH zinp~F(~7sX7i~Y2@w260cN2b8@wWbRT=BN@G}%P|7RB4zi_k;Tej8s>ysf>MY{Ji) znmK*Cn(!sX+tO#O2|v+ zep>Oi^rgpUE{|=Bw}s!Wcw2ig)`Xu@ysf=x`-Qa6#+MXtvv0f!Kc#qE`fO>!&-$gb z&*neWgzr|o&Hhov+uDoqCj4X*e%iw8_JV#ThFt`)z!e;%()*Pw}?$INC)2 zgyL=O#g-;~=t*h6tvwiR!cQsQ7JvH9%;^(Sye)mYoA9M3{8$ryLh&~HrxkC@ANs9~ zpN(&8!gpDC-Cp!5zFB)Qt>l`u7vsN^_S({WQt`I**wV!Rtm&Echnn!+P54q1eyj;U z(S)B;ysf>Ur)2zW?M0X3ZRuBP!jCK7nm>xSmAC08`e*%K+HY$wx|{H0inp~F(@pr$ zA7uEp^yzEDk15`kJ`+v&sV4lECj6|YXSTmf@wWWwYr>B<;m0k!ZZ9Sk->kjpdPc^h zS$jc$lybK8Zd1H1Kf9awFE!!En(z}%_^BrRmL~kHXJ?LoNb$DzqEGR*_F`P|w)C57 z!qcB-wy#a`w({7ecw6`-#oOA8i6;CO#oOA8uIHrvHhxU;Hv1-<@LLpbE5Eb;JahVm zn(*CC_>$sn_Kz#xmOqnC_~|A*Jul)GQ? z^iL_?)?Uo|tF+(7cPrl39*j5PwBz-j+V&inrN6)x`gnCj6|w$@tsC4>jStoA9M3{8$ryLh-ixJ*{|K z{cd}?N%?HTk1F1lKI4kFm7mEb`nM?FR)0f(m-gHElHzUkd$I{X>mM_xPgfJZqhCy*MuLn@OnHjuJ~r-fwotqoulslC*LDGPoI}? z?|&RuavKe~pnJC4UX}VLTsb~ZE-$*l2U706OjAm3(_5q+Ci|_UM_n6Yt z{V%Ea_Es&A@4V!N&L^~H)#qM(S-%u>zY}cxj|9B$$_#(UH~Q1*H~kiA!DcrexQ|an zV;G0az56cvTBMw37r!Haics9&`T=|oEW_9F2<;%{-(h@zw!Za`LVkVg3dr;KDK~3x z?so@WJ4t^}yY}#RAL6^+0$;a_&zJCZt@r*x=i{>{4PxZl5oc9Z(e^vUsyy-L4M#|b4jYS@wE?<9TS>xO1aeSbE}LqFda%I|!< z1<506H~h9eBv4<@&SH7-nyfy@Kc(dU=7!Jd_DPXooNlVPxZm4Py;JIaXglda-Y>@Q zbl_sK)=~90A^-BtO@R6P9G$=8drAL$y5A%6ceo!G@);?g33|_bav$mMXNH|s`5ttY zzth+88GEmkGw(yt_r00l%edpb_bGc^y+?~*nxAaKPb>Z+*MG}}{8QUA+9vgz--Qmy z_gMz`GjW~1x;#woE9K4a)y2Ck5_a=<>irVbvRvfq`$xKCCzRG^788mc@BM(xba{U%<{gcnox4*x%TrtSSXp&yIUT*;u6@!uv>hH zgL>I|70gftLfhM&l=7oSI_i7hTU!uKpZrv(l)tF1ejP3AmvM88)?YeI%3o>f7vH~? zTbFw3z5e23Qa=7RFZ~v^-YC*U@!i!4t>NvsT%6F7a-&bjt8}02k^Y`{{o!2|eo~pANdLX~Bfc{}zU4*3 zp+0;(UQw4C6d=~PKb*48`)O zM>McizV}C$S8d1C_oe)l+m7)48Q&GvW=-o$s5R1umLI=O${%3l+fZw_NZBD-FNSd4 zkDDG-w@dlYy6M5+E#rm(3A^8i_1z(XHdjvGxT4d4RPnF4JdfWWbM?4#cS=2fFyuS`Zgz=*PswwHpNvNhsFo(EUppPXBgN z;q24UAGIDP^5X=)Ukn`(S|`{3$zMzPFBolzZNg zbMLX@22J5wZ{HuJ{MoKN=Mz4Jm$2LZZc%doW2Apcjyv@|exeK0cF;3Y!KAB~=kK_u z0^>K4Ut)IU#cxu{54iGd#}RHvpzRI)QR+4CvpNap;{6EB!WPjf%Kw;>yUUm#XT*J4 z{NOf50{lnZOOO$Fn6eY2Q2fC_2LFo}Ix_OYb#Z}!%gD1*u} z`PtVxSN`RTDOE+(_IJG@{hj36!`}~liw&=u>sUJdC;ubmcXs<1p4Z9wML*ByIA8xF z{)k)db-iDv?4R212=VI!Za2dp7qK`j3_GaULt5 zQ#zJM>vLxxi`E($t<$wTBmLKng9li!z_$zGkEr}|5fMqK^R3&F{>*!t#JxDO7?W&W z;9)?@edVn>{kdMAE#kAL^&mNZlJ{1wX`Ls`Uc(P4;Z`_#i`*Jn>equcz*rj?wzZrIQF*7@{Jm!-ZR zxca#M<0dK8e=HZf56OS8ln3<;rM1J-Mos)AJ}Xugbg4t6Sc;D7iO`bkX+@ zVmyb?aqT0wLDCcn@e{4UR3$Fj_9pu(^h_Cda+l%f`N%>P;d9*LG!uPcnU2#|c)TgEV4X!-b z$AuytWd*F)KX#6ke^ccHx6dVguQ2TAK7;>hd&bU{@(H8-W#l?khKreBe(JN^CO_*u zDgSA=9Pqn1KNIEW=+-gBLx!O9Vf+Fqe}~aNcB^qsw|K2%?(A;9FEA#5s?DtrAOb?A4!`Tm zQZC`z-9P(^&8;Vih+eT-Ux(|a`{-p-zQY|q^w0k0=GLE!PWhXgF*B^s*U8JJ{GCQV z7351h1%B>8$4}cccBPbmk82N?%Ns{&10 zgI?eAT7dkuQr>(oXuW!`VST@woo;`%$=mmbx<%x*U0t_I|Lcr-UVm#$6ytt12H+&r^5c_I{vB?)=ke7u zLcY(CcjIx7lz+j}a7ydHcK4-w*YBj<$!@#C>%T{d z`niPfALQqeQSbQA67h#`1@*>(lTS(i&$#&}@^@b`K*K{f!qOjac2iWR)5J5{=%Oh=T2M*9#DH84gg#uk@x2@5MShrG+{6pzKuMTz`G4 zM4RsviE|U2;G)#33xbtL9lz3BmWhxS8SxV<9qbR|T>djC|A>iJS&UrE@`d!Wyl7PK zFQHpw@lT0AGLx&i1n#HeGr7GCuja-N<8_f{Wt`SnRVg#<^gEJ*a_&LgsiT{!Q?sx6t@X+zGzqH%@y7HrM-8T8| zw{4qz+fLgizeUNL_v5?iC5oRY2JU=~c9#0TVZ?V>#&;O~vAe!Iq2&HjCnxe@SeE}` zo~F3+(`A{I-(q^X2wm&zFnmJWSxGI!9uYt@ZP%`ZL_5O<#qDP9yUbbbJX7{ zCEv^*T|UQlmHOAa`f+{=B~vyN-a0DnCgsd_)J^YzcusDk{OIg$)8DoGw#m~T+a^D` zjq;=K+&2APdv2RNy=&X#C$~~w_d}!amipi3mIKi(xaD?C@#g+;pL)N$kNXuV?#hSu zlKRYdhK5>x%>`>nwC+P#Lq*}8qrw~ATgsd3IPQB~7_KVy?l^yRA1OcJ+KYW{EF;aG z&CeVxa?govQF7-P{d7*fOPZ7GQ)1tkw~s}w%3*8aoTKdN{*d%{h&%qn`zx&ni}Arg%d{IIH~l{><;7+obj&`ji$;aMOJ{BIO*TKO9oi9ey3jUyizCQr;Uc*YC5t;VU_Fzp^Y} zt|)Wq*XcbPm-@zy@CW28zXNjHU_fqg4TwH^V68G~j!Lh#4(b2%MtS9jv-nun*FT0%dzDKck@99gSP~ObDel^Fn3VgY8xP)3mFw6mc&6y9@3TH8 zwT;DD6evewX)9GINxYTQopGqxj8sxTYrCh0NEA?%qTxsrB>f1`W z(mbgz=jLbd`{L6|?lxDB>lr#?uGbj<_{;hDe5rTJkT*BJ<|w?hK+2u!<~!@XO6t9_ zQSX+8QhuYWm+!~LI+h0T(^U5i=~|Hdx0*+&vC=sAbx58r6&Bi;y>W} z@2~Se)x&c(c3)-4{HemJ z4`YW*z0K^Lb%c~_X6K}mYo@Pjnbc>V=P>U{*6BE{z}5VOMMsC zmDlgf^7@0u@;bV5>*7t_Qts(KAT}QXA34QS#UD zb`t0QF{9qo%*Y8_M!pT1Y5kZOEx4$d&1G6fMWl3p6FNrf^ZJY4*$dRTY(ZaGV(t&#rkb=Ot;XP>*db-wV3A3b8h>DpSul?i2W+ zgUWVyJTQ@w^1m?hC&L@sN>H~4V~&)2rz^Kw{L=h{h1cb9O7SDEfA<`iI7Ox9x(8%9 z=NNLs{N0DYyehffjPg=$!Lk9j+vtaNyFEwgp&_aFI#(~Zn@d=}u3y#i6Wb`?mzDZA zzFh{u=g<#tT`fi$hqu1+RviJIUeh%xzlUqjD)CFF0}V?) zgxpt-LZ?c(Rqp%(?@Y@lGgrxD;H$Wjy6Ycfo29(@4)~CKzh#Jbk9Gb{j!L=b-SF`~ zw%jMp@iOMotzpVUo``ynE1N!o(`%Edf z%xwqx{E+-EslWAVUiX2I7aD%71&atTgy5x;Xs(p2$<39;I(e&E`1+PInco`(4JAlKYpN z@4QcOkcgN5ZUnsof2AP?)hEaYs82vsAPU4`Dqd4p$?y(x`(^GA$A!<g zf7^Hecm8$ylx~s!Gp?OjXA);qHlfw`zAv3tau2$4Tn|oUJ4+eyfBm}B#1Ew2{oHtQ z{gmg**2r_$ZpAzusiN(f{;~9@l<9;2h7rye;b-UE(y%W}p^Bj+JxZOOw*<1M^y+g{iy6pybqruHl z{Men6|Fat&#{a6H{XA>qCzOqTcJwYOZ=UZG@4WfONjg4VcT4$|u70E=hGDusYq>Ec z_Yp(xByX9*EzeU*E@#LM2eg-6_sDR!cAiG}O8Kw3dU+nSxgmchl$?3~Pj3LB6uRl& z_YX6S`l9 zccm-G^JTPW7&oVl_)RN09UmP(ZTGAPq@IIaJvs49^IeKR)aB*KU+WuHylF?lcz96H zgF+9=a1MN{RK(-z<6Grn-{a*1=kcwl?day?92H*QW76N&jz{}`A?3~e9$imROdIM+ z+b^a3fIDs!=aNT63yM?781smluls|s$EEyhJ9_c>@#fY{E9=IO1B6HXkVhMEGNC4! zQ|tbSx$BQNE70ab$U6PTo|55CxOQS*E5C18(0YalbOA3jVO}fRd+o35Y3c85!{0LL zZ<#o*H+S|j>2I0vH%F!W)E}k4b#8ma=k{LU0Qz{|AV+JSeW5=|`MZs9*0kOt3|k{7 zxNA^Ld0e%MeIKvFq35N)&${W!=g2tO=kj^7YlQ*;y$bla7&(CH(F}}XQ9g0Te<8@W zNv%Xot*vwyg`wI&WS{BX1Ax!gZu{O7v(tCYDA78>31{;JgXDP=$RH+r0p zWyZtjD16pyQtpSY9QS`BqXXxuQ%e4xI(ZT6K>6{1N&T-F^0}5Vwm2saW++_SGyeM4 z*`wpx_iriR=j!M7YGFfrH5nkM(gTyU#kA-wQlDm?zxNLGjjru!u-Klhruy3lv(=$m ze|x%^KO|F3Z*a=$&%x=klW_{wY$|u~kdrGp<;o$YRHf41jsNCsi!V=6rG1IeM6tQs zQ$Cd~v}X(1YNl9l?zowb1y-&hz`WC*$_=K<<A_-eKA$SlI_;`t z2UF>4wpgH1!&9~bN&32h43txOr&P=qs!qArDWv*y2d-}c)n*`#_6vO(%}Y@A97NqUdkI#e-8OqDi;T`Ij5YeI`k!w`wb*w?HvQo zfccN^(#(LL`HN*>p8u>Wzgv=*tE(>=ZJ^a!<9KEey^ZsX7(9-(Zo=M>(bC#o-FQWWf2;Zp`OScF=RNrkR8;DWPJfq8H|@`@mMEaAI!uf^y^?I(Mj7c_6!TXpqQ|!JJc|@B6R{Jz*dN*>a_tFJ@|}uc>N^c3A3}BpR3f4In#^N;}I? z+i1CgrgLZ+d#lCXO77@-H^1QmT+mZ{YOL8z@3>kk*ANU0|RYXTT}18Yww+ zi-B^KIBFt}NqX8wg(FFP66P7jrKF#ukuX5iu7x>NMOq6`l)YFenlcL?ovE4r0Vff0 zViB}csc5G&K-U?H26IrJo0~(!N53?1G_3Qo)%ivACiJF(JNZ&|Bws;t(1(_JM!Fe? zqEbv3O30}S9b*WfSx!4NVjzR*`NcxDT+E@VrLP-ADw8QAfV9&)?4;>IgF!Xm2Aa0i zV<*zC%RN&dl%|LQz$9R_+JN9LRm=HQWdog352td-rgE6RQ4bGpOl@%JCkN-z3A zddG@7V+QA!(bPK>H(>60^60_xwLGl@E?bX*0W$+bbe3jfArx)nA6@S>`nML14#*}*%hQKedUhg>O0*b&vc#wLM1ye>#y`5$P$JqQ`jLUaf?THJmVu{ic@ZccI~b+1%(p1oG?H&s#%Ioe-&CV>NmJjv6xHeoK&G!qR$vO`n&l< zPI^Ng%^KZk5GdO^_n$Ce(SG$*(K@I>&&q)T^d$6-BR%8tJt+B*sX8k#NU6}F2Itm+ zOm;Y*8qB6?$Y2raY_&4Ci~&uB&Nqnu8k(aj`c=Bwhl)n?NdwGF*$TboD9@x#8vKv} z_G|D614OewAX2tufcaY0;hx$Z@_fZ0MXeQH?le$t$%+HL^Lv+bN>u2t28Y318ilDJ zsn|PM9H>` zNYAZp8m8YHAVMrxYo()77#!snaL+Vrm1j?_Eb!ipGfYVX&lWPyriJBlu}r-NT*+nA zj)XsDz{v7!M&aKv@ZzvjMw)MwK7M5|KvPu-ziGfI2gUM;#P?tAnJN08+y*+rz%toP zu{y*9-4jjJNo7QqU2K3zFU(YO4&7>iC5#iR^N<}F$}HvR(sLG;c01ZLMU13H2uYx- z^NGZCyTX5|-($k{%(;dp^kSkoh~ECYCJ~}X;S|HX>JZw`Os~jA`j2pb1O%PWI)zl}u# z7g9MEdBYIlNlH(4P;@jOJk~R;zn0Bq)cBrO7{ox?aZch5Xk}RL67YwLUbyB&NZ=$VAr!Zco=L`-W()6~qo(%wo=^z8Z1gqM6QX)p(esB}O znhEmgM})&Omdgw#(?2+zLK@#`U}a|@=cKFL{m}CUj*e7T;#tRgRw1t_WVq91%)+?@ ztv0}cjTsa}+GIfRhXPw!c?5mcL^+?hL#4a?=rY9Lq38WD3+HPz8=sM>%GhpXd2eN7 zwwfM7ZZ0qdP`-FP4S0hAqa^o?Mn}ivn_iTDOfB2FdU6}j!?hAUYzWFVEA*j0ne9`aMVkhl zYX5L=qtKy-kg8VP>iATZ3@M{IRRb8G@U@0;sn(Aoi9%B>s4=5Y_|JxLs*+dAeM0Z+ z_hQ1>Jy2DI{l_h_(YQ7PQNXG@QH*I(WKv)Ju~(8Mk5^wzcokrWD@as)NjsapG-I! z4t4kqy2&RLNkqaizeUgagyNA{B{uEP?r<-$o zmiubfb%sd$V6mT9X4_-*iy$~oZv?>!+HXjWhq?8odD_M81&`6v02;foj!-;ApR-X3 zy2VCy(9B|OYA_z5D*}lAd^SuE1rrf^)gZ94 zX)KPGXul1f&2^FNq?HEM+dG`86nl9<(~Az8PHyDT_c2`@$fQPu%yo@2X`Zk3DoG*q zv>{X|_Nx6BqYvIA=NZU5E*QGx0sU__z0B<^jJmKOrnbc@%d?dV2CJAyU>KBl)R^p< z|G&cNamtvGuRdy-3h0FV_EfC2&&A+_PLjWSFtn*v>5Fjbs2&KBMc5IVlP$I%!<%Ad zy4MxP%Hq=&*`qLT<*8O-dxFn}D;H5ae!5y^J20rC~^}o@;8?Z~!j$&sPYgrjel>V!Dgk$t+ z)}Z!-4-_+tN_*pEv{_@}15ld3niT_nhumkq_|4u_9 zK~Mj88ahIhDF0WnNOsVt|2qxgNC*A;zf=+Jp!Ujt6_0Q%OsD^ER2X&qVfg3Pr(9l9 z>@F7vv7A+*e*)~U4FE?OUEvI31~ZJ!;Z%m&s+xfh*)}bzVU=}>iEAHnd#GYkOAEuO zQ<>ETUbN#qX!^R9KB`u5=wX*OOcBi-{Tq}ty=Mr$vjq3883t-Y=4OUd=-z3CNh)wv zvA8HzrV*1`l*OcbRT0~O^feQQ?6M-(PVR9*BPE|_P>kIwY>u3fFN2ERhc$sTV-=X3 zIdrIt8ajFbx(&ekO0m%HHK*YyeGatSim3T&d%23)`W)>N`-=CNa`pP$48XPr&UEBp zQn9SMyPY>0>g&C&E+~1{Z~8eBe(FV$Pu*f)^^^w6iwr99H8as+dSV6|QyzNTCV#-5 z_HYP8&6)UEgw{9k*yyOb@l-ps;|)>;6!&G^$zx~!X8~-!UwM7qBvoUM(ZfRBm>)D^ zk3c*crnL?H5SHLiZ$L%rJ3YMV)Xgh%H(Dgh^TitG?;B{9v&!t9Smw7A3Q& zK}Kv>Bw`|R7}IPF7Klc)z*P`%OR|UocX^`3yFr=7>`!+2)de*?cQWFPis|i;ll7J* zj$Wh_10AVQf85C=GjyD0VzF3%IOW7L2`AzVU_SIo!C*ofjVBY)j{Xc?u8~9}p3HQh z?Y|d@#eBmYe_h%66ss>I6OCcyia-ylEJ-h7XegS#`MDy7$@F>nsZUU^UUYOO>5c|| zsG869qz0TGY-Vn0U@MAwͽ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

$QPy+2dCNI&uAxtd#z9Vuu{w~Q+A z(xRKVBqN16x1M4#H3g#*H_e=4TqOy%tyGe4AIUM*#XHXZ)gMLG!S?HB1E3N5e9C^ zI`~Ob;1*cHigt>L=)io`1+W#rRTcJ9wQ_*|@?dyalW`sm7xtOyA!-GZGq&up& z!7vFzcDd5>kOqn}@a0w%9>=KHS7^z!ip)|KAQWyV0 zZMA*0zrus{Pc^aEU{p}AST)?J3dGMCGLJpXu`DE1ZAfDV*lmAQ?qf92R~gNezN(2N zLX|qABETQ;r;v#GrV|lFN#p^2&Htp5fE-3LMGjm`+Ri6UWbp?`XZ=|bV;ebn8?l(% zM{dNdgkE=%FIbW+QUoi;AAwvU@tfO%3$e$cDFeB)lX)Jx(CZLmzytq z=hx5)g=V#}!LqEd1n#d#?#Cdqr?RYBd)GZa-G0UJaWlp2s2=B)kBoc>cJ6N;{U{z7UE@GgvYy2&;T-3+|xzpQ!R})2aNVfUl*QD zl|D8+o7&f_5{IW#DJYRGICL;IIuBD_l%^Y8EKPW$6Q{p{!_5#JYlRGnI`XqdQM8Ay z>O^0j-HlL!HmMzE#n>rLPH;WTmYa}=lq^a4f+h9z^ChgDZ-X5Q&GuGwSF1-Gb!hQ+P^~jZ2VyI5k+=m{j zCd^*_d5=+nQjP?{RFBZzO647!chUMH#s9QD1qhoSp|(&NY?l)+#K<+lNn%RgK3p5! zv6(rX2tK&lr=3hHMuv~EYIRQr=_H=JQGgJpQ%)Sa4OL`us$M(QEBZ`Hr^!&lBFnQ9 zLL0V02B_)TDjjVN+jymyRKWF{D?Cqa1%5V+k=4(N+V+%3={k$CD($X@wl2-9)|?h- zSC(nPq$MK3+&?GFIbTW+Zku9j2yQrVZ%sHmwFuHWH6QQ9_&c}KyG`VBRXYymvZtDn z#EGz>5*JIooi?E$7c-PbNBDLL7YNp(9FQM)nyR7RBOf>*hCoz;d2UKf9$X34<$EP> z0dXx71l(eOp|lKUU*n)mJ)n;ltx-d|*wPc4g$#Jk8R7;OveMl2H{o zAN&~A!x6qeZA|>Y=V?nHT!UM5BKH{@iFi9QVe@wEj;h*zLMQ4zux-!5J$%bpX=J#E&hkWg)Ya#- z&Q2Z+bWEssKqhTASVyVDKMIJFt+&Ekhi1UY3){81@@`CTcWTgnNaQVXOb{ke@=cFb zGvt_#)Kjv(qFIM&+ru$ck%q~)mq?@cEk2q8^1V8gf^+mj!&{v;?_h$(LYBbir7w8u zt^ksEm85uBgS`yaApkvgY!-HM4sCjlrUA5Nl~zZ67c$7hbCNvg zjgQW~$aX{u-t|Hk@*R{X@AHtOYa|xm-ZM}cqQ}BO^v4Z}qh@oqxy4OEv?b`Ic{{%I zksf6N_;XfkWx{C@zXOGjYdBNaGpT2zOiK%|{vcfMaCNjoLxDPVjEvQ~-Q{D;3SU#a zBWSa&s|4el3Glgejn+uaFU#I1;mRzig-I~&K*^`k7;4ARaFhf5vyDvM$OvsF*qa7h zN*fwD+}-6KzT0I2klD2=!HGkk-95(oA~; zs;CN}C#-J`uy3H-ZCGEHulXPY_m?`o_5n>lm0tk4PeR(68TI`c*cxilqE+H#aHD@M8JT6vi$_mPrsmVG@# zqXW?dGQRB0xL&%vUgBofGbo+*Qtx&s8m;TwIFKUUw&t2>=82B$(IMYSuyFIn7FmH= zENo>*JGG}&1_q*Okb1`^Rd<~c(4l+hP}Hqy3>{wVuaMj}qA5UqadV4OoPfuYk#{r$ zO26Flx2Gu0pSsjJ(7M~UI88dls8hmmvw@TrVh%|{5FSd4Zp~r_$LMXqYLo-*KPeAc zT94(GUt@tf|ATHD_)^aonowE=?&KgZincqMuG*op$@~<#XYC_1aL0Z?mzYBlBx(b> z!XMOifN)w=y{BA06pe%4GtW}Gt|xBT6lofs@0k*xZwE8@)iHMkTA*B;u(xbrCM{N= zp&%Xq02BAysm%P%l`trk3VK_2Dcyt;TB_yhh?}Ael#tdNl97`7f^ggGw9OwPIVvP6 zV=-YyX=7=b(JVoL&1XXp+3a!MhcPH<;>fu;JsE&Z^8tQxQS)UT3-oJ7nT6& zI|Eu=(#2D}txC$Hm9d1U~()VU~4Kw8t@U2!H9~KK1;&yN@VR6<H6 z??;PmS-qfxULmH{wECtd5 zTe|*-{b#TiSR1YPs5N?l!ewgVAF<{5`o-w9V^b-I9vx$&!<8rxUJAp?6OIoK z`z<=L2}#ttX#zb@7}^NBJLPzGH%%QCf&G?Clm?{QU+74cYKThJ+%*lsogMYlR^(S? zRxvo}h?9fi5jfY8rgp#(1-rqg*u@w#AHgVWr> zjc|GK7@b(*oHqnHUBlGHl&SCwHDaES2$QHLD2bLPwbK2C5VR_3iOwk~XtuICKWu^lrm=*B`7V}A~q~^i{?PAPrD`kfa1%Cea#W~p4m9JJCBl}bpPX>2) zAQ?x5Qa%XLsk#p=qcZ@Loq;I%RB@bS0f`TCZva_=evrML`_*NngrOoFUB5F#*8+`0 zj_Y2d?L6kksAF>bbA0SV4N{g?f}yD0q!aW7axF}_ejrroip82d^fC#0-%h8CM(_Jg z_?OzDN;R5AnFGg_XX=dTSmAtKFBtb*Ye^JzP=1w2*pzyww@e)Vqh6%0(U8N!m*Ihsq$5#QBm=~2s)YSAZ-_5L-_sW*1=@DHSxcLMD<&DUGAH0+;5Es zCPu*r1)6HE*Tlaty@@c%d9>@oBrO_Rx}1=tt7xhC4ME-!emjQRj_XjgU}*4hS9nuU z)_a}lL@KU)zcu(U#N8l~4=>&sq8m?WzK>Gr>K*fFF>e~A4-Rt9@a`RTr9mbMJMIb+ z`kfOEytO*kYl1X5)`=kLQl>^7%I6>J!j;fX(iiGiv@vH;WpE7Cz4$LQc2t*3J&aGM zy}xvepMIh)#(&a8>R~LguA)FG^fZBAW-SF}%`sCt^*V-0+EY^0?^rTDSjdu7w_}o1 z(y6QEBqa4bmP+xG?e?LL#{gt9r_&l%X7tq6a!!4pC1qP{qrK(6ZaQ~NkNVLgOtkxs zT5#UTXNf5{L)+%lENTi`wYc8crflD=_fkCcbdEoAXx5u&)Qu$Em7j+TreoZG(C`j8 z558^J-lzn;XMb7U22I9_B*XOwt^?0#o>kifJgc}O4n(OfvH3(3fL-yGhHMYX>mqJ| zqi|WbkQ?+4ar<(bwvGaUaiXK3hbj5!2oDH~VBp-ZDkHHj3Zb@5+>Mm6ie676+?pkt z|Snu9_SvkDABY@7)I{V?)eML9zs0(?Nn99Jn<|;830n|Bn5I({4tS zXDn`OWO+eIV}?)3KB|fBWC}JxaPtehJ*!+>#YUf(ke!#>q6x^m?he&#LqMA{w%)(4 z%k1G(A2eIo39QQvQ|7s~yjmOUp7y*V)3$FY1F_60tMb${I14g+vw>S3L%TRY*5OPE z1g`m}5*j4EY1~XbwyYk8OS)nq+=kmJ3XUdF?!dRyLNM~`_miNpp$riHI)6AoV)sIz zRe+6ryG2l`9WsnybcCLg5`*PQ2B(ywMdu;$r}0Q<93;Q3q~me3aj#ki09{1IEpis6 zp8XxwCfj$g|64X+dD(qLREH<}r45bcXaZ3A?4n{!m5D9YgQ&M0szm)^Rfq9TLh)6-g zY-$wAy7kJ zw^l}KqY{(Of!X{1CY5RH54EmSAo~>T+!{?09DS%F&XLCqX0?O&X*CyeV zK_S#F!GjH6ZJlObZe?bB@LS(%P+77uo6$bi_x)LES)|e6mOMwvU7u24MeY@rppsnR z?r%dgS=j@wXs7#2*F;4~Hu~QxVO68SAim?R;}@y_l*UHu^tvm_k-4|^K_J61IgET9 z;Ah>Xwak0&>V2e-CV)V9(f6{Ikay~iN+^5BJ+|Xu7*C*Ta2yW!B^}XmILseC%3tgr zrEr`-dQ^eJaXzI2CLH8*L!$bpF}~V4-E1>9+M@{JFrVId8nr`1v%!d6hVbDqzv5n` zn+x-t>YkztNBR}qoI4&2;=2zV7%AHct#HJTFAyRe_{&IP^2)*k^u&@V4MT1kssAT7 z2WC`h_!N%UNj-jy{$3qUI9=dFI7D~4z=v>*4leN}9Hui<(p!_hY4rUDr7?PxduKVA zKy&z(Ebgadzq4*s7#JEtH}%T8MJUnjtKrF@Y!(LhyL-X#nIra5=EQ^bj@U=J(97>%4eyT#<_GNP zlAj#NURtU4@ifNCX&bx~hNCXpzl;{~lz&3Y2>J(&%c2rK{_K(3d{ipf52@Me=TZ(- zIxXAcs{uxUd=CGfQ@_=}SL2)Oo9YJ;>8&*8%B*37*S$2AN9PxT`L-Cgc0`L~*db2=acNt~wIPFR``rT9d#S&Q za)7%w25aNe1#4J9Cjj=@bWreWMACTW$t4|kBVwBY+G|#*2Gp(sr1ZHeMGB`3CINHJ z%K72y!@@-GTt{FpkIN?jeDqN#NTANzWC4zvKVA1S4(M%TbRYG53lb-!GY$L~6`M(9bRd!aZe1ehY$ibF?j6m@J#A676o}=BmK)J#j zRXC6dhb~Dn9H!H`5YXse+Y&8TNT}KAXqwh#`VFY@Vhsyb1%Wfp(E1T94bN%RsRHpa zZ~msAXxwR^Tp5JuG`!SXNHPO9xlF?a+FNAtw|vk6X&BV^RjRg39ES6puKB}2UbzDC zAc}8ZJ$7ywK9njvUEW z>UPV~DxEZs=D^ik&s6SYw)`?mvjSfbu~@tGg>Gog)%OE(DrJvD_AAhKCe>3vP6ZID`^i zPO>H3qNe$OV&!;fIO(;Rh#v(9`}1Q^bAUL$Ras!DUwR*v2DO84xu(N*bk*}D%Kgfh zCr7j7xGvRtzvt(Li5YrSs5~-oj4VL7iRMuJ0o#p@1~3XNx~X_Z@+kSuc@bia43&@Q zl@GHhS=#{~GF3Lu{=)q}3iGTx8Rsu@2+men=b@#v65YiTE86M2(qsB&RMEw_9s+d+G6CI3)d>G>+lzAOsFPoTb=St z#AWUy+yLi{SLNPK(@p#YbP1#7Gxvl(yb*6W>{9~Zd((kw6Ax>c?nl7pFl{8^=J8N@d>oA;4{E>BG$0E*L!JW; zp}psS+ikxV>ytGlHS;1$ezT-z&Q6E=W9r;>4~O54Lg~~~SU+91&X~H3AXU3!>N7Mo zF;PQ@WE)@EVwNRsuISqw^_i@!#&&gxPqEHInC(vu)zYd_seauFof0s4M+>C(DJGb5$@iO)>gYA*P8W&*46%=kby9$_zz8M$1i6SUu_JS2RH#Z?w3Tj&_8aUQJ6l{wRZ`iDLh zizlz8fmpk-d&h#cWnU9s&Y&iO>PefoukT!qZ8Zk+{HvIYa4L>k5?%Ps_7Ua5?Ij15 zYuOvuRWPyRyXl0UG}U?n%dCjFn=+rU?ddP~(3xvs|CiFp_PM17qainOERDByt|wtJ z>UXUDuA(e@l?B@I_7WIxy?XdWFKZ*%l;W>UI{0zxg=GmQZxU(j(ZH_VwGz?Aj=xLs zmu^j=W@<88bB~!%+e+5Oigwxh7>%RofdLaW@U&s$2s~}fY$|-jjs%=fF{pvNbTXk4 zcU%MP6T5q(Dww)UnTyM}xYnq19`2TfXwb=h`jEdaui?TJ0TCCz!rbnHRa_MwDqJ-KPe*vWXi} z$mfvF4X{0NFeG=nQM8#uiL=JEWFHT>k7!d&`WvCj5K#$bRvuAphRO?@MbKKjDl*H7 z6v^LTh*JxOD&|eM`8Ybwo4PwKis0j($NsnZk=yukVB_=34({I5)}mtqziUZU>#p*f zL7_iis?%L1bguASbWxq|qK+VjRwaqjUSpoyy%1AaHBR14^?wYM{Mf=%2uC1cU&=J{VPb8jLJ)&H&+8 z^C9_Nn-b@fuMj`s#-wv7eV;2~G}#7PjtxqKA^ic`FnZ|Rq0!0!kITCcP~?*X)>FpS z5NWVb8S0Z)rD;RR!*6!uTN$aUN1oTI#HLuNg~1TD*0jyljcX1L3?FE3?;9KH>4-|; z=N9ElP|}=IERc|`2h%9?(`P{@)Qg(F?LC-7h8v!(3e`2@dws%!ptMHh`fE0l746P) zrvS0)Y2ZENMIo+D6fKZnMa={4XgVsm zH7c!g%RL!Q6a(}xF>srUSscp_I=a?r;c@u8L>#0+gKzsiFW=fPM4bTqa}3xbxdrlU zu+fVhzxSR9YtLZ8ul-Kpmo97>DEExgy(@>xyJ&0UaPN6?vOEXGU%V8^nUS8uBkeLG zr8!Vqdi?cr=Xx^|JX0Et3v9l$HcBt=@+2xnO0~0)u}`KuI|~Ik?M(03;GmpU+Fn@s zLtKwB%x+Y}k1QrgSDa>UUIJRW(i$nzDJsF9BYdOENHhnIU-25{{IIc2`=E_&|ITf= zm6TF>phlcG*h6X}R&9UxHNjFZrK0>qkXo_4;Z{MrGvZ6}r7IA5MXaoe}2;_09n zZY?ErO2sbjaC51CkZqme22=eY+jc3YumJXOJME2Qoy=ZY=!D`k?xhV%q6;g$ z^a3~~%>_w#(w8-QrC<3bJz+_jrqgdd9~MF!AeE-mJBDMa*uzRQ>K{`3aoJB@B{ROX z4*RwG4|?58$Rp_}lQ9M{OpM>ywx&Smii#e=!_(e8sgX<}>=#&q}BYC{_$ zlnIpak&~({i4x^d^#7zoU`kmnzYd^!=pgrA(JTr-?saP1%;h=mi0Fm>H4;JV^0yGB zbDKh}d_)Ecoxs0qQt2G1(0!a#iT@frDLudmv4w8k{XqUfRgrPih?J8YM39JzCI{hH zNW!L1n&%N*u-9FcK&iov7UiSW;gL~yXGhVFhESDY{Y@*$YxF6VpRS>C`-YFJuOC~wF~c@3ONu&q=9dh@oOzKHa2jh257M!{C7*R$Mt~tcvrlLOYTaX*Y6Pn@0J$>r?e;{AiO(!8vn)uSZaTzb+nVYo$EU z>(HXNICk!bze^g3*Mu!@e^CzQ3-jP;Q%n&LCQ$^!4&ZnQAYqtA z455GJ!zaUZ(FwZy(97y4%qMRzJoWQvU+HH2tj+cPotZJcB<>Uu)Nq|u^L@IsL5fl#>r67co4+U{VX`25yoqjio9XG zMmJS(1>O*ZJB*4hi(;=sP;O>$)OG++@TEN&C+ijf3cW1Z-w{J`mtoLG0H#I}mzros zx>|~i)Y-)KE_?HqT4zdAfznYq7RoO$N#m`owuUeKBz9 ze(XDLAW;^wbX1c>qNln1SC`}? z&oqBm85%8*^mX@?_sTE?z4jcCKK@xCQpZH5T(W*4Q={u1DJ2+ca=3Bf7Z7{Y3)7^h zs^h>1Au}NUU1dVtxRGdTRdt}TZg3WOcYa=llWvfDUA0fw4bzN+YAjAU#iuNw8>C^# zSkLI*?t{E}I+_C$7kxqNj>o@Cj$aE8E03;{qJ!bEc}V5XcRC(>r@H{T3$XwGC6)CO zxspvnBB?)<86OZw_FM3hotGhZ$s3^sqjPswPVYH(I?)f49n$g!GMAd3IAeNnts?i%cjt=(0M&?U~{Ssup!9ajsL`o!DOxK+(0CwDCyBPN_i@cP{7jMU&v{gX_`q$y!j#ylHUFadP|;I^Nts%+Rzlhx)DM@1qUh@17;Jay=m zs`S9fFqxVR{>d?oZiCgzoH$K%`UJXG)A$tzP{%D$n) z9nmagdf?AgNk>V^c9+fopH?CG*xh8ylZL-(c<69>WVGT4j05-?zdVTq2I*Q+*|E_D z)T`6cEo?~+@+w}(6DZvITd}Qg`dZnKtkt1v5uFPgHc2~2Iqp~E|-opgiZ$~a* zE=Up=K(?zcfI882&Qybx^_&t50yj8I)jZj~WNK=c+4G#8+3zOHkaS#;RwDIC z&o8HAPq=W6uHv?<({BirP7{`8}4I8&(%UcQlf!$%1_Xxfy4{mc+!N zE2?pe@?*U$)%o@>qnG6wTAg&IO1A8i<8e1CdtA+wxj9Bju{qL#S6t zhrTJ^HB)0vV6J-}Pa^)G>cNVN7@hHYAqlqo6d`K%XX<2{NZn_u%aW3p99IQv2oP@J z)ewM%-|5~Hnu6TB9;5P8#hlIh|H0+nG^zho8Se~U0&p#yGtW_G-IgHNhSG?}Y>VPl zF}EOznCI8#s3e8Nwr2%%^E8ODvPWHGClfngceWgLn>8px)Fg>WwMdrt&eU~+eIv9= zB*7x7H)rU4-cUHI4iiN;bFNLu2`4_i{8xW zVgv4fWR0-|6(3uzs;(cd(lvlgz`v4|J#d(+RQ1CP(e~h=afM-witlO5-lF#EuuRKD zww)-)Y4%NZO)GaYQ$2^m|FT{|SW@r3Jqx_s zs(o;*HoB3{IwN=Q1}(+sM07V(mR2ySm!ttRRo2o%a?vz^qU!_PhKVYmzIjF(WGWj$ zTsDhRr#zu~X;@gR--+eE%yKLuQ$(T>MYj1iI!Aqn&M38+{})fCUa9E4lCLy z*m_`>SbH=FY5r-OO69lWQD~&bOXq~uySYwQ9Z5!=Ath6|WXWzn8d-YKQMv7ClomAo zn2#+P_nDZF+-E*ALsAhymkE{aq5D6nmFb2>=UiPAOA7AHYZLV$dC1$ny}4Ovuj`cu zjA0%D9*wFff7y=aIA8c`eU#^LWRY+jg^xZ(D?xmGm$|$KUbj&rbThT%KwXL9DmC!@TL&!;GW&8_!K; zsMg&lXJGwcj=Da~9VM|*6}7V~1JM)!|8!m|u&J$)q_TA=I^Pw(AO0?h+nRwSdqKwv zFIDDH_PzU>Gt#Ju?&_{O^pzeqX#;Gz(6pnUD9`e7`xtPE1 z*2tRzUR6-0TQ|~#gI*b9(XdHF!Hm2*MZR3!X9n_g`V_kDA@0USA0?lm+YdCp1q*R#3O6 zCg3Nf>Px%A{SP$5R>##k_PG@T&ja+qJ%;AUj)q01i} zNRI+FW~f&Pzcx1wtlP@Xcx}`}5rV{{vnc)KzGf(m92%oYK-!7oPd(TSrcpRbW3b&4 zk#?c@CH>7{lJThX6vU0Qzi||=Rhq%5{iP_E4Q(8SZ@IV`h#Fc72s`R&6u$IODu_gE zKCnmuF;6`Xgu4cTlo3Z9I9_qYtvlYs?!~mmj+fLajUpOy6!#9N%7E6ajUq(`OpSJ- z{Lh-==qz9YN6tRXq3oY)ss&6S(M*{6avA}^=Wn_#T*D%NZ;pGp_;zyTcOXmL2iHec z7qe3j9+E)7kam&>w&ai{Hg6Y?*^(X0rjes zS{(=2FON3oELpESz^d({as4iN?RpLXFS%5Kj`UOT>t_VAqjd|K*-=DWNd`9!SC2)L zKsxJ6m6uN8aBFfMxz#hJ@_2<(!=9Wr7$a}kl~XG6Qhy#IZ01KZ;ypIy)zqNhrepPb zGCA1#K&di4O9;W%hhAEp4CaDrBN7C}q8?F!e`Uwl(Jng6wnvP;1o`iNwd!HH%=?jC z@BFMY>@3^*lH;n#EJsAdN^s>0w+~A3PKJ6dS@FrIL|japJWiAY#f|@>lx1s>kNWEA z+LV2R{)Xo4OTZd zY{jz~VRah|Ky+@PTb6`*(I24CdY*zG-tO^-eDSru2O>Nc`$ za8%1}f$TK`O_DG-8d56(c~*I6`^rCtbIYkmFK>gNdf$R~HxMWCJXQlMtINs!q69ws)|C`ZBQ`%-(F zi)Op&cd%00q=hh97i8o>@Kdc4meZh1eb~D|s+%yaG6Q;(FKba?(A8-cC+#v@!cn70 zt2~w#y|~zcHH{D=&o2p2PBL#sWrdCI|;baSDyq};uAv?pmn_FB%m^%4z?3; z_kZn4fOU|0Kz;UPK$`Oc*z=B`1U^Zra846|yYO`<0hYC@Ll)pY`t>IPR~!_8ivZ01 z>q!81n9lzx;BQU_u=px)98Ee-XYsdg+A`^^n|T9=>0F@#e*6t5K^1h`i53#08DPEc zjlguzY6ksL(^*P%U$H*2nK*k_?T98pYX6&+qz~|d@q!QV{BR*dcRC|h3;M>`jLmPgkr9lUfrJ*HhryqzNGY*^qe$td6R(GFbKp{QS@+L|GL@Z*hEGi@!^< z3rATUO`!BM-l|eA9A!<^h0+(^uy~ZUQ5Qb7p8xN}p@fAs45~{6R3sj@Gc58BIQ_zJ9z-hpM?Zxy+iFJ{mFvlgsI;mq<4=2;tdAH6E}YR>zj>S zH#UWAx4aXS{r9$&I7($#j!h%erSDQU^~$l^F_5CDzsMR(+wIY|k{7BBY#bnudv`t9 zuUi0fi}fCTi0GfLQM9x1GXQ$&zpG9g^VS^Dt*B1|=fHoQ5FUb!Do~#Ap83&qyqIc7*viof zoZlKAThKjk$0XWfEC|TadmV>YzE3%gA;WfzQi|=6Gb^{Z^Zr%3`qy1&#lAu;e;lY^ zkD=R+#KrJ!*t5Xg@cxil2^XYIE3{Y- z37hBw&@)>A^fr;kqx3uzfO&fhaN0km^Cx=|rvUTW7U0s_lNZ-rR5AmcpPn$Dv`^fn z0%<2<{ z(|asBf%Nni5cS}Ax_t!KS#$yHa0{SmJ-)9&w_y!1Z)yQf=g-r5bRFvyaDLJluio5j zF-A{fHo@1Uz;l3K@qvbQPcb3w>XVqUwR{V)T9Z2@8a||+ z)C{dVpuLrPr)V5>KiZgn+6mW$QYnHK1{$1i^}^FF4l|(jo5nO7R$_A_;rlP554t)# z6@PtjnCxnsqj9KN1j<=0pfz`xw!5eVsEbbqB&o9soadhmymRRA%LIVle!_r^HU*Tg zG)7xwZ3pL9X952E#zYo$hSl4v-z87$meGftZ9NEoQ*3LIWa6h;^T1#CH=tvOS~~%L zUSlFQAoH$1B|w+ql$@=Ix`1_?Ve$aL4pl5BL=Vtsfm-{py5$%;f^?(SG)Sju?eLNm zi`2(~{Tid8QDO3ylC(&@4j1A2B+x$I0%}??QIE=(6V3qZr!8Qn#q4#M61dL+>z*G` z4L6oP&E3^ux`EflX<+^5$-&fcbq;X%ym@}pN()!(G!VqBIUp`?0ogk;KNhY-mcX?L ztUWDYrbQ8Tm@azl0@$k?gEs66)1ucjA{xR@g2vaI&{}8+n@&%RW)@@~c}v6EJqdAa zV+JIcErR$ZjhQ$Z!E7BD6oQR|;F}r~ZdkD`SPzG_Q-JHC$5h|Hs_Bz{hnJ_v2TxB#R_~@^X|y%SH;pHbIdc$1#CY zC5~MubrLl;iA%`OTCG;n#?tP3cjXr(Q3~a60>7d{OAY_DRZF36C?K9OkAet~nm}8% z;gRyH_(33qmw1~{%Ktm(%*;9W?!DTTwC?|xPm8>B&;8DvbLPyMne(_Q2D_?ZpyZtP zG1`k7gG!JC4E3^P$d%}V=k!i7hqokiT9P*!(d&@sJHtFad3tz--QPK8^3Bu5Onu-5 z=Fs-hM6;!%DsJj1d)J<+3)#V7>#IQJjw`p`6z4+vpzJ^PGSsd*Amirw5F|N|0}OPe z4!}6)(FZi1<0J#Uu@1nvLGJ@vw{e=0KF|O}&u5%vxGy#U);Nsw4D>`DfN>6^Uvu^r zg9q7y@?U2`t2HRjTl67a@;Ak3SJi=9tBYhQiJ^+gkWpi|$hDEa*r5clz`r?}O^kQ3 zqy(_fTfFNTX7_M1TeS|gMxFJN7--eUqUNT$Uuyx1U){l2>+8Ub^Q--edroyP!)>nv zww7fy9(6whmFobEb6`Sp!sTL^HzmVGHBXb4wcw4v#kdbA<7?m7!ZXem<2+FZUai6B zJgtwjo#4NV*@-$p$<1PmL!@nh&&62z;Uw^}{ z6*KtcX2-iI+(>DDJ#kdUc8*G4D~aeVrJ)kQtB6C%4tXyV$n1t>PCATysZK$M!ibWB?Twf zNiOa^D&j7C=&p}(GIij^%{dN_{Kg`q+*=1)oZqNu#%Y{ll>6&Ii?d&fWO&X+>^BxV^K75 z3sVeqRULqFZlTuK^9lPH>y|n&onaTty>`7~8i#OzQC?ODTAYWaXg0Yz#W0^rhKuT% zI)rh_)iAuIRp%J}NuNsWrzP(Uh;lLt(ZLLUKbcXCN-uR|Kpbn6N*!Rff1S*}5vf$= z57%>sSv{Q0GO+^})emy#=NWX>Ly7&Sqjga*^5r`iWPKfAi<(Gv)Me z;lD1*Q;%?YmD!3zw0y&Lim^8*^U(3(OuOf^iWznm_nh)c27jY65x>m?u4DhMZ52ICFwJlus{=M}){n|- z_VUg#*yDA8#<}QGP`fdJ!Or++Y31Ywh%iO-x40(NnpzYoO2D_sU z&^Y%!+6uBcfZ^_~12)c!kHR`r@zpkIb$_)Y)e}9tk-dG22oWCD!1kdfCX2|!| z0qy1nG1qSQsTe=w{m(Mk*Xsa{bI79d+8|(o(boNIqP9d8bI~9mmW#v!z04%H2(zVb zu}ENORHw*%-kHoVW+*H*Bv?d(?X+WfR=Ce4HgO{&gQytrYCD+Y<;k2AJGUMcqBx+F{z>Nv$wr zOEArN=l{DX0tEqQJ+gu$jiC^WqZK&h8Y0n zC4k^z+bZ4s*9DN(ur(bSf~A#!UIx3q4$zum20%@i(a&Ia)B#%4R07n78AV3Bw?U|0 zm@&nW_csXIgc&mo_D~(5HNy$*k2T)-yVduQt%@!i;&w zd!i29nqdYS!3#5j&spVJ!+#gEQf_WY2r~d}!i*GyZLI^erauQz8)oz~+AEV$ql#I7 zm?2yw%$Q;(pIU_3ioy)X(5TKF^EvzTiGw+2D6A;V2uonXj1+TECri=rFau)1|1C1d z*ClgK?A&@(h{B9%#{O6`4;}OMU{aVd$5@Zofmx3c)-Yp%0nhkCqC%*!bplf~$7t&t zhe{zqFT-8mAXvieXRLBE=881J3o|B}#p{z#Cf?{^wDonM){Hl(AvoaZWxVU_z^xf@ z5Uz_j`Wf<$I-u)n2o5=lj5nQ(8#VRyh8$FZP|P7bK9|fZ#?e}S%s~Q3&@s5N)UKZW>jI_tqnE+1uLHC$ zldJ(qKO^4JKx7K^81CK%!cw>}#d!BO3YS1<80_I>(3R@*JPV;;98^IAq6a{0z!fB`?Jz!W4L`j1AfcYwt_ zL;v}IitP`v;5bBC)*pvlzR`eJ%X!q8ES~Cuz zhTu44it+BR1Gi=zLbxstnPJF>>VU4R?>G*bW4z#NiJBHQ_w~jhRDn<&B0R20<`v^~ zEk6z+0VEFTW1g90-fAK18mGpMEHc{b8igux$TS0fpbp@gaR{}87l+I;=I86ct{I0A zwuwXL8Ew`7NmL|l;F_);q1rg4gW;}AhK=fH{c(u0kvOEExx8`_ZYx>>@i-aJQ;Lldf~+( zeaz#QWM0dU3`oyIamWC3IdHnTh2xM(X7l>f$4=vrY3A|1WL~NXZfdEu9J>+`h5JKiSB*l1J z>%gt)-xyqqL;4x*jyh0l#vz1i;*cVv-CGB0O?yG8HV&C$xceIg>%}26jQLQbuuU8? z$7qk&fm$;Tp@!f%WP$O{_?C!JLRpOA~F*aBHcQJES zGY+A4@ZyjZV{Wbk+f5b;>mh_~;*dT@%hZ8d(|;sX8;2Ab?(dUfqxxBY9HML_4w+#t z-(G~g4Sh{H4f=u#PtnCrjU=}u5TbLg$(_ScSoae z3AD&yuS*79nO=Bt$TahKUox-d$04NWp*UogxqSX~aSO*G^UUUFr;nY+A;EX-P*}r% z7n`=+)KV)B*{~7EGZ^vD6qy2%#~T)i5RYlbzV*8@phG-35>cM@M(#M z*U%i3OfleWGH}%N*Bg_VDujX(Ve->tW-%Vv@`Dm1fkY+2_pOe0^IvB#t4%?DBi4A8 zy$rXjVXzXH3^3x6I*@C|C8jC7z+{p^Utb5fn>`W&69aA{lWB(gSRJr6oj(I>Lz6ki zd(saQ4NX){>kmyFABjymn9X&Iuv<}V;Qp;Ca-&uDklfm)w|)(EA@koPtcnxa9* zyT6gR6i&=A;6n`qCe%4b`*AXAq6w(4AH66g_@Pz7HT*YbvRHnUV)Q)}rlgq7=F`S5 z9H;a#pIc5NKMhm{n8|@;W;)>Frke6tE|c9IzSwn=vEEpPx%G3rUZR+>p9OH3?9fj$ z(#PsRjB^h>DecWsjPrOMcyXS*hi6>)1;#n!M^WQgUE??d0a~MX*fF1Br1@mTsJUCj zG53THdE|nA{*M#2D#qrWSsNu z)!OsAry1>ib)eQTg~r{UWt^|qffqLidQw_Hdx3%0{UlKzqFT48pB-f&4t6i&=N93! zR0q47mr;%)vv_ARs~8nus%IU~+_==U!uY3&ZQ2Nz+LHjzT?aF}Jeg@?N7m33a-#bf zHj@mmBe(_}dCx_Lxwj6u8s<~o<|)Ryzaf}t(isMNs3CyHrDdeYSB^+<3k-Aa&k_}F zxqa@r#wkYMoXllOuCb@LA)mO9@o#B7pRhALzzhzY4o2z)Pcr)Jley@Kai-r(*O$%b zvG5@WNx}@K1`CBT_cez@DgEeJ>LqvLgAUWo>inOJK2VPR_?MQkp=jyMQ_OTao;fG@ zRhXCrzgPF$HePuQiB6j!Rn==5lp*adTn{L$r9(&Lh1^tt-DaBY-pOl^k8 zD?PZralEpw=U^#U$@Zs*hNwQmVaF3vpM3Tp*+hH}y*40dlM%APKda=DdGC}BAUyRV?f?OmH5w_-*m;pi;Ia(uSwdQ+RGmeV6o z*-GP_POn|?&%HF_vT1zok>%Li%<_b*b-=>7aU6k}$mcSJA$&QGU%#kLs#O>pdQrAi zpoad)-CY9EQY>XNgxTlX-l+W!_uJEuh~BVFjpQn(Q&U~BoeHCx&!j8appWIh_$;Z186)1XirSgbfQl#%J}YA?+8NK48n7Jn zGONE4mf>1QAVVX=01O@qX86@-o+DD*ae-FwlmLcf1cMhuPX|nOyy|)S;~CRMD`|#* zr;goL*V?^{)ca7-%hJ9>q+Yb*9_%8`NsYm9z2|acgkg=e&eC|W3A#azygv}M-#9-O zwN@`>f)u|v7Y|^@b$eIhK--@QNM*fsv{;Q{ns(7~MFFjk6A>;E` zcXxg9gdO@VMKkk&IPIDK{KUABk4MO4Z%}&1BNuzv-0aW^sf7@j+V7~QmqHWB7E;^+ zol?S`%9eK3Lp;lsX%!viJ=1U?TVh51)Q7l~nA4OR5E)$<1;g3Wx}IBUj=p&!pADwD zy&m{YX}3X{iM=5<*b`%ArFz~hJV-8>&V^=SA$S&u}S=%U!tO|N9Jif%wH0ztzm=(_HR>*z&C~Ce)bDQD`mfv#l#L zlP^I(CaGLGSI7sm4EKe2SZV$`akr19M}m2Vnn=aftd$41I)R#%h!fOwZZOG6vllIf zD2_>MDO;hcJC$k8mQ4Sx?fUY0es^pyQtu51f;-p6_$|g!+tVf8(RvVl^MZG=J3d?} zAq`+#SEj1gv}HLq!-dS8v_-Ynh=8Fs8$@K-#WD!*_jQX5Wl>&lDkzJh4!Ch>WF2*~ zvUpARg=OpLQrXz)T^lj|+e)QE39Z2r9KTp3sbmjT9(-V9j6Cv$t%H-QbqP|$bxJV9 z+~4v{kz&z4G0pE)(KP?saPvbadLylGHDC-W17`DDqw1J=G;8tVzJf zP|8`D_+XZWdCgiDs0=I?HibE1 z)cW(LVGrjxGHjg=Oz&NT>afpXv=YUPF%r>GS{7e&jxhp37j z`jX$hsKRv|lk_p8o3@C`Eeh_(4h~x@cV1HEwi~~ypP9@(cQIy5b5J7n+KO)rjb#r7 z!Xo>8X-K$m{bLix2fbBWCAQE0`LjHJ#Y6Iju;@lAsiqu-7n$z`FIcRqI~I+h4Gr*8mGM zd!qyF?~*KRHLH z|8MF#@fEi2a7=orzBE|&xG9~;L+Of{)Vw)0G&a&DGgY*AsTGm7jPJ$Kbbe?oYu6OZ z!7NMm);%KOfu39?JxKkD;6ZXxEtYCK6;{xr8~Lmej8I|mKu7jT={6&nEm;<*YhTPW zsjz22trG$NT3__+sCy`Hx)zKm9mf^UqPE)BFq4-vBz|uix9n=P@eH@ncL%klbgH)1 zub!)I^c^=n zvgzJqRpd=ZcdE!&5c#-A-j_YBJZHjm>i|*fc>)?6GwT)1bw8IdPliYvdWkj{rkPp# zkuc3vYTly_l5I040sxOyJ>VF5!F!-S8D5yWE5<1U{n%ZuqbqJ`-Q^U&Vuv`&9`~r$ zj{tEdO6=Zfs(7NBZmKz3O*d6NSxq+`IOoyPC1i%E1!2rpZ;4DkCde@8s<*bm_`zci zCNk*iGN7$P*`iH&IcMDtLs<9irNTH3!CBVgO|NBbMzqy*pN2CSCpTKJ)0-*d{7`ru zWN5>FC>ZeDQD@XR#`f_bLi|4Fo_n2)sj57q4GcY>S?>w-vK$<$d$QV4J*94eZ-;E< zh<}m!zUoh<6{7P2*P~s>u|#30bcY6etwwAwI!05WmS$>lozMywJ+5hpZUDCUTqY0) zKuZwaipS~K0UkC(O|k5M`TE#8$PDHTwGT6%E0^I~0xFp1_uqbO88}0QejE4C@Y|pG z2kFuDFeaPp%zg$`=LdIbb=ZjjalyGZmWY)UkWYDJW3eW^q*|`q7{{X?DQ(pbZ%%ns zH~RhAlLle;mBhuLRDqzrgEyZNStdkpDy=oyaJ&vpX?L1p9FR^;9Qd8VjTp>v+kNuw z(uT+x9bo?r62H&OSHgX_OM{?4;L%-M_)AuP{k)3!_4B-eTJ+B zAr7sO4X*^ zJj2SlV<{gr8!qMCaOGNL6N2EqmcjP-aYM9}3I#JE^s6ar$&BX4j90ivX{}MdV+9h- zV?1gMqG!;DbEUFDc2<_98O^4Prn>zs#Y-O$X$*)b3WZYO;{<83d`*S9ziD{)C?%pNS%A3{EJ#&-$Bi6beaCxAFo)YZZgi%qvak`k188D_p8kl` zwM@qBm}mILiQunV3{4bGAwTtE);s*g3KOn`Yz7I|m)t3ZR(IbO!wyfk^gsWEa9Nr`Qs%X_y0$^GB2BX>AN{0=w0x_i;w{4}S!w22iZA^W zOCzR9p;u~}ET4J7{}-wC|FC`1`qb{pW!fiO(GIR)_ncI81x8ARuF=1X8!79_usp94 zxiB=1ré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%0AismWo=@r)<@$@9r%g{& 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�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 Date: Fri, 20 Apr 2018 13:36:34 +0200 Subject: [PATCH 04/69] Add cat to the container To run with jenkins kubernetes plugin --- deploy/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 74d94533d5..6937c9d99e 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -14,10 +14,14 @@ # Builds the static Go image to execute in a Kubernetes job +FROM alpine + FROM scratch ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ ADD files/docker-credential-pass /usr/local/bin/ +COPY --from=0 /bin/cat /usr/local/bin/ +COPY --from=0 /bin/busybox /usr/local/bin/ ENV HOME /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs From e546795e0396fe57c71d2909552c36feb7c82a0b Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Apr 2018 13:45:04 +0200 Subject: [PATCH 05/69] Use full alpine image --- deploy/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 6937c9d99e..d723256424 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -16,12 +16,9 @@ FROM alpine -FROM scratch ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ ADD files/docker-credential-pass /usr/local/bin/ -COPY --from=0 /bin/cat /usr/local/bin/ -COPY --from=0 /bin/busybox /usr/local/bin/ ENV HOME /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs From ad7f299a44de86bea1ff2d9a8e26806b3c4694cb Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Apr 2018 13:49:03 +0200 Subject: [PATCH 06/69] Use the correct path --- deploy/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index d723256424..484e75cb8f 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -20,6 +20,6 @@ ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ ADD files/docker-credential-pass /usr/local/bin/ ENV HOME /root -ENV PATH /usr/local/bin +ENV PATH /bin:/usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs ENTRYPOINT ["/kaniko/executor"] From 425491641ef85b52264a3d8268d7c6a618a21f89 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Apr 2018 14:35:35 +0200 Subject: [PATCH 07/69] Add support for insecure docker registry Using --insecure-skip-tls-verify --- cmd/executor/cmd/root.go | 4 +++- deploy/Dockerfile | 6 +++++- pkg/executor/executor.go | 4 ++-- pkg/image/image.go | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 7a648fb1d2..6449e551d4 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -37,6 +37,7 @@ var ( srcContext string snapshotMode string bucket string + dockerInsecureSkipTLSVerify bool logLevel string force bool ) @@ -47,6 +48,7 @@ func init() { RootCmd.PersistentFlags().StringVarP(&bucket, "bucket", "b", "", "Name of the GCS bucket from which to access build context as tarball.") RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)") RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting") + RootCmd.PersistentFlags().BoolVarP(&dockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic") RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container") } @@ -70,7 +72,7 @@ var RootCmd = &cobra.Command{ } logrus.Warn("kaniko is being run outside of a container. This can have dangerous effects on your system") } - if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode); err != nil { + if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil { logrus.Error(err) os.Exit(1) } diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 484e75cb8f..1b4cc583d0 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -14,12 +14,16 @@ # Builds the static Go image to execute in a Kubernetes job +# need to have `cat` FROM alpine +# need to have `nohup` +RUN apk add --no-cache coreutils + ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ ADD files/docker-credential-pass /usr/local/bin/ ENV HOME /root -ENV PATH /bin:/usr/local/bin +ENV PATH /bin:/usr/bin:/usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs ENTRYPOINT ["/kaniko/executor"] diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index ee7c87e452..ab9eacd53f 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -32,7 +32,7 @@ import ( "github.com/sirupsen/logrus" ) -func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string) error { +func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool) error { // Parse dockerfile and unpack base image to root d, err := ioutil.ReadFile(dockerfilePath) if err != nil { @@ -113,7 +113,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string) error if err := setDefaultEnv(); err != nil { return err } - return image.PushImage(sourceImage, destination) + return image.PushImage(sourceImage, destination, dockerInsecureSkipTLSVerify) } func getHasher(snapshotMode string) (func(string) (string, error), error) { diff --git a/pkg/image/image.go b/pkg/image/image.go index 52035ef693..72058b8d46 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -48,7 +48,7 @@ func NewSourceImage(srcImg string) (*img.MutableSource, error) { } // PushImage pushes the final image -func PushImage(ms *img.MutableSource, destImg string) error { +func PushImage(ms *img.MutableSource, destImg string, dockerInsecureSkipTLSVerify bool) error { srcRef := &img.ProxyReference{ ImageReference: nil, Src: ms, @@ -66,6 +66,7 @@ func PushImage(ms *img.MutableSource, destImg string) error { opts := ©.Options{ DestinationCtx: &types.SystemContext{ DockerRegistryUserAgent: fmt.Sprintf("kaniko/executor-%s", version.Version()), + DockerInsecureSkipTLSVerify: dockerInsecureSkipTLSVerify, }, } return copy.Image(policyContext, destRef, srcRef, opts) From 856265ee3091dfb7072de130cad120ca59315e9f Mon Sep 17 00:00:00 2001 From: Nick Kubala Date: Fri, 20 Apr 2018 09:51:44 -0700 Subject: [PATCH 08/69] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8084161d9b..d6c707b5da 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Similar tools include: * [img](https://github.com/genuinetools/img) * [orca-build](https://github.com/cyphar/orca-build) * [buildah](https://github.com/projectatomic/buildah) -* [FTL](https://github.com/GoogleContainerTools/runtimes-common/tree/master/ftl) +* [FTL](https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/ftl) * [Bazel rules_docker](https://github.com/bazelbuild/rules_docker) All of these tools build container images with different approaches. From ae59204727a22ba9971170438bce568c68891dfb Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 20 Apr 2018 10:42:16 -0700 Subject: [PATCH 09/69] Updated vendor for changes to container-diff --- Gopkg.lock | 26 +- .../container-diff/LICENSE | 202 --------- .../container-diff/cmd/util/output/output.go | 0 .../pkg/image/mutable_source.go | 5 +- .../pkg/util/image_prep_utils.go | 2 +- .../prometheus/common/expfmt/decode.go | 4 +- .../prometheus/common/expfmt/text_parse.go | 4 +- .../prometheus/common/model/silence.go | 4 +- .../prometheus/common/model/value.go | 4 +- vendor/golang.org/x/net/http/httpguts/guts.go | 50 +++ vendor/golang.org/x/net/http2/server.go | 50 +-- vendor/golang.org/x/net/http2/transport.go | 3 + vendor/golang.org/x/oauth2/internal/token.go | 2 + vendor/golang.org/x/sys/unix/mkpost.go | 13 +- vendor/golang.org/x/sys/unix/syscall_linux.go | 41 +- .../golang.org/x/sys/unix/syscall_openbsd.go | 4 +- .../x/sys/unix/zerrors_linux_386.go | 135 ++++++ .../x/sys/unix/zerrors_linux_amd64.go | 135 ++++++ .../x/sys/unix/zerrors_linux_arm.go | 135 ++++++ .../x/sys/unix/zerrors_linux_arm64.go | 135 ++++++ .../x/sys/unix/zerrors_linux_mips.go | 135 ++++++ .../x/sys/unix/zerrors_linux_mips64.go | 135 ++++++ .../x/sys/unix/zerrors_linux_mips64le.go | 135 ++++++ .../x/sys/unix/zerrors_linux_mipsle.go | 135 ++++++ .../x/sys/unix/zerrors_linux_ppc64.go | 135 ++++++ .../x/sys/unix/zerrors_linux_ppc64le.go | 135 ++++++ .../x/sys/unix/zerrors_linux_s390x.go | 135 ++++++ .../x/sys/unix/zsyscall_linux_386.go | 11 + .../x/sys/unix/zsyscall_linux_amd64.go | 11 + .../x/sys/unix/zsyscall_linux_arm.go | 11 + .../x/sys/unix/zsyscall_linux_arm64.go | 11 + .../x/sys/unix/zsyscall_linux_mips.go | 11 + .../x/sys/unix/zsyscall_linux_mips64.go | 11 + .../x/sys/unix/zsyscall_linux_mips64le.go | 11 + .../x/sys/unix/zsyscall_linux_mipsle.go | 11 + .../x/sys/unix/zsyscall_linux_ppc64.go | 11 + .../x/sys/unix/zsyscall_linux_ppc64le.go | 11 + .../x/sys/unix/zsyscall_linux_s390x.go | 11 + .../x/sys/unix/zsyscall_openbsd_386.go | 21 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 21 + .../x/sys/unix/zsyscall_openbsd_arm.go | 21 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 409 +++++++++++++++-- .../x/sys/unix/ztypes_linux_amd64.go | 376 +++++++++++++++- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 411 ++++++++++++++++-- .../x/sys/unix/ztypes_linux_arm64.go | 378 +++++++++++++++- .../x/sys/unix/ztypes_linux_mips.go | 373 +++++++++++++++- .../x/sys/unix/ztypes_linux_mips64.go | 374 +++++++++++++++- .../x/sys/unix/ztypes_linux_mips64le.go | 374 +++++++++++++++- .../x/sys/unix/ztypes_linux_mipsle.go | 373 +++++++++++++++- .../x/sys/unix/ztypes_linux_ppc64.go | 384 +++++++++++++++- .../x/sys/unix/ztypes_linux_ppc64le.go | 384 +++++++++++++++- .../x/sys/unix/ztypes_linux_s390x.go | 354 ++++++++++++++- 52 files changed, 5810 insertions(+), 463 deletions(-) delete mode 100644 vendor/github.com/GoogleCloudPlatform/container-diff/LICENSE rename vendor/github.com/{GoogleCloudPlatform => GoogleContainerTools}/container-diff/cmd/util/output/output.go (100%) create mode 100644 vendor/golang.org/x/net/http/httpguts/guts.go diff --git a/Gopkg.lock b/Gopkg.lock index f10ecacc3d..257a9383ed 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -21,20 +21,15 @@ revision = "b26d9c308763d68093482582cea63d69be07a0f0" version = "v0.3.0" -[[projects]] - name = "github.com/GoogleCloudPlatform/container-diff" - packages = ["cmd/util/output"] - revision = "9eb30146e04ed241c8d5be4e0b9383efaa60a395" - version = "v0.9.0" - [[projects]] branch = "master" name = "github.com/GoogleContainerTools/container-diff" packages = [ + "cmd/util/output", "pkg/image", "pkg/util" ] - revision = "859166bbd7810e3c3fc072f1c33ad57b9f4acbd0" + revision = "564361979f3124dd3e6d8bbec027279539c8e08b" source = "github.com/GoogleContainerTools/container-diff" [[projects]] @@ -63,7 +58,7 @@ branch = "master" name = "github.com/containerd/continuity" packages = ["pathdriver"] - revision = "3e8f2ea4b190484acb976a5b378d373429639a1a" + revision = "c6cef34830231743494fe2969284df7b82cc0ad0" [[projects]] name = "github.com/containers/image" @@ -403,7 +398,7 @@ "internal/bitbucket.org/ww/goautoneg", "model" ] - revision = "38c53a9f4bfcd932d1b00bfc65e256a7fba6b37a" + revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6" [[projects]] branch = "master" @@ -488,7 +483,7 @@ "openpgp/s2k", "ssh/terminal" ] - revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e" + revision = "e73bf333ef8920dbb52ad18d4bd38ad9d9bc76d7" [[projects]] branch = "master" @@ -496,6 +491,7 @@ packages = [ "context", "context/ctxhttp", + "http/httpguts", "http2", "http2/hpack", "idna", @@ -505,7 +501,7 @@ "proxy", "trace" ] - revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41" + revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23" [[projects]] branch = "master" @@ -517,7 +513,7 @@ "jws", "jwt" ] - revision = "921ae394b9430ed4fb549668d7b087601bd60a81" + revision = "6881fee410a5daf86371371f9ad451b95e168b71" [[projects]] branch = "master" @@ -526,7 +522,7 @@ "unix", "windows" ] - revision = "3b87a42e500a6dc65dae1a55d0b641295971163e" + revision = "79b0c6888797020a994db17c8510466c72fe75d9" [[projects]] name = "golang.org/x/text" @@ -563,7 +559,7 @@ "storage/v1", "transport/http" ] - revision = "dde16f2e838706995ab9946df55f5dc7c5564cc6" + revision = "b08f8989af4899034b9816f5291a5bbb1bd576bb" [[projects]] name = "google.golang.org/appengine" @@ -591,7 +587,7 @@ "googleapis/rpc/code", "googleapis/rpc/status" ] - revision = "51d0944304c3cbce4afe9e5247e21100037bff78" + revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" [[projects]] name = "google.golang.org/grpc" diff --git a/vendor/github.com/GoogleCloudPlatform/container-diff/LICENSE b/vendor/github.com/GoogleCloudPlatform/container-diff/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/github.com/GoogleCloudPlatform/container-diff/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/GoogleCloudPlatform/container-diff/cmd/util/output/output.go b/vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go similarity index 100% rename from vendor/github.com/GoogleCloudPlatform/container-diff/cmd/util/output/output.go rename to vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go index 5e1cce25ea..8dd8c3e231 100644 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go +++ b/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go @@ -92,7 +92,10 @@ func MutableSourceFromScratch() (*MutableSource, error) { }, extraBlobs: make(map[string][]byte), cfg: config, - mfst: &manifest.Schema2{}, + mfst: &manifest.Schema2{ + SchemaVersion: 2, + MediaType: manifest.DockerV2Schema2MediaType, + }, } return ms, nil } diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go index cf4b5ad50b..47cff2e1dd 100644 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go +++ b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go @@ -26,7 +26,7 @@ import ( "sort" "strings" - "github.com/GoogleCloudPlatform/container-diff/cmd/util/output" + "github.com/GoogleContainerTools/container-diff/cmd/util/output" "github.com/containers/image/docker" "github.com/containers/image/manifest" "github.com/containers/image/pkg/compression" diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index a7a42d5ef4..c092723e84 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -164,9 +164,9 @@ func (sd *SampleDecoder) Decode(s *model.Vector) error { } // ExtractSamples builds a slice of samples from the provided metric -// families. If an error occurs during sample extraction, it continues to +// families. If an error occurrs during sample extraction, it continues to // extract from the remaining metric families. The returned error is the last -// error that has occured. +// error that has occurred. func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) { var ( all model.Vector diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go index 54bcfde294..b86290afa3 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_parse.go +++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go @@ -556,8 +556,8 @@ func (p *TextParser) readTokenUntilWhitespace() { // byte considered is the byte already read (now in p.currentByte). The first // newline byte encountered is still copied into p.currentByte, but not into // p.currentToken. If recognizeEscapeSequence is true, two escape sequences are -// recognized: '\\' tranlates into '\', and '\n' into a line-feed character. All -// other escape sequences are invalid and cause an error. +// recognized: '\\' translates into '\', and '\n' into a line-feed character. +// All other escape sequences are invalid and cause an error. func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) { p.currentToken.Reset() escaped := false diff --git a/vendor/github.com/prometheus/common/model/silence.go b/vendor/github.com/prometheus/common/model/silence.go index 7538e29977..bb99889d2c 100644 --- a/vendor/github.com/prometheus/common/model/silence.go +++ b/vendor/github.com/prometheus/common/model/silence.go @@ -59,8 +59,8 @@ func (m *Matcher) Validate() error { return nil } -// Silence defines the representation of a silence definiton -// in the Prometheus eco-system. +// Silence defines the representation of a silence definition in the Prometheus +// eco-system. type Silence struct { ID uint64 `json:"id,omitempty"` diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go index c9ed3ffd82..c9d8fb1a28 100644 --- a/vendor/github.com/prometheus/common/model/value.go +++ b/vendor/github.com/prometheus/common/model/value.go @@ -100,7 +100,7 @@ func (s *SamplePair) UnmarshalJSON(b []byte) error { } // Equal returns true if this SamplePair and o have equal Values and equal -// Timestamps. The sematics of Value equality is defined by SampleValue.Equal. +// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. func (s *SamplePair) Equal(o *SamplePair) bool { return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) } @@ -117,7 +117,7 @@ type Sample struct { } // Equal compares first the metrics, then the timestamp, then the value. The -// sematics of value equality is defined by SampleValue.Equal. +// semantics of value equality is defined by SampleValue.Equal. func (s *Sample) Equal(o *Sample) bool { if s == o { return true diff --git a/vendor/golang.org/x/net/http/httpguts/guts.go b/vendor/golang.org/x/net/http/httpguts/guts.go new file mode 100644 index 0000000000..e6cd0ced39 --- /dev/null +++ b/vendor/golang.org/x/net/http/httpguts/guts.go @@ -0,0 +1,50 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package httpguts provides functions implementing various details +// of the HTTP specification. +// +// This package is shared by the standard library (which vendors it) +// and x/net/http2. It comes with no API stability promise. +package httpguts + +import ( + "net/textproto" + "strings" +) + +// ValidTrailerHeader reports whether name is a valid header field name to appear +// in trailers. +// See RFC 7230, Section 4.1.2 +func ValidTrailerHeader(name string) bool { + name = textproto.CanonicalMIMEHeaderKey(name) + if strings.HasPrefix(name, "If-") || badTrailer[name] { + return false + } + return true +} + +var badTrailer = map[string]bool{ + "Authorization": true, + "Cache-Control": true, + "Connection": true, + "Content-Encoding": true, + "Content-Length": true, + "Content-Range": true, + "Content-Type": true, + "Expect": true, + "Host": true, + "Keep-Alive": true, + "Max-Forwards": true, + "Pragma": true, + "Proxy-Authenticate": true, + "Proxy-Authorization": true, + "Proxy-Connection": true, + "Range": true, + "Realm": true, + "Te": true, + "Trailer": true, + "Transfer-Encoding": true, + "Www-Authenticate": true, +} diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 39ed755a86..72f65c8f7b 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -46,6 +46,7 @@ import ( "sync" "time" + "golang.org/x/net/http/httpguts" "golang.org/x/net/http2/hpack" ) @@ -1817,7 +1818,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error { if st.trailer != nil { for _, hf := range f.RegularFields() { key := sc.canonicalHeader(hf.Name) - if !ValidTrailerHeader(key) { + if !httpguts.ValidTrailerHeader(key) { // TODO: send more details to the peer somehow. But http2 has // no way to send debug data at a stream level. Discuss with // HTTP folk. @@ -2284,7 +2285,7 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) != // written in the trailers at the end of the response. func (rws *responseWriterState) declareTrailer(k string) { k = http.CanonicalHeaderKey(k) - if !ValidTrailerHeader(k) { + if !httpguts.ValidTrailerHeader(k) { // Forbidden by RFC 7230, section 4.1.2. rws.conn.logf("ignoring invalid trailer %q", k) return @@ -2323,7 +2324,15 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { } _, hasContentType := rws.snapHeader["Content-Type"] if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 { - ctype = http.DetectContentType(p) + if cto := rws.snapHeader.Get("X-Content-Type-Options"); strings.EqualFold("nosniff", cto) { + // nosniff is an explicit directive not to guess a content-type. + // Content-sniffing is no less susceptible to polyglot attacks via + // hosted content when done on the server. + ctype = "application/octet-stream" + rws.conn.logf("http2: WriteHeader called with X-Content-Type-Options:nosniff but no Content-Type") + } else { + ctype = http.DetectContentType(p) + } } var date string if _, ok := rws.snapHeader["Date"]; !ok { @@ -2838,41 +2847,6 @@ func new400Handler(err error) http.HandlerFunc { } } -// ValidTrailerHeader reports whether name is a valid header field name to appear -// in trailers. -// See: http://tools.ietf.org/html/rfc7230#section-4.1.2 -func ValidTrailerHeader(name string) bool { - name = http.CanonicalHeaderKey(name) - if strings.HasPrefix(name, "If-") || badTrailer[name] { - return false - } - return true -} - -var badTrailer = map[string]bool{ - "Authorization": true, - "Cache-Control": true, - "Connection": true, - "Content-Encoding": true, - "Content-Length": true, - "Content-Range": true, - "Content-Type": true, - "Expect": true, - "Host": true, - "Keep-Alive": true, - "Max-Forwards": true, - "Pragma": true, - "Proxy-Authenticate": true, - "Proxy-Authorization": true, - "Proxy-Connection": true, - "Range": true, - "Realm": true, - "Te": true, - "Trailer": true, - "Transfer-Encoding": true, - "Www-Authenticate": true, -} - // h1ServerKeepAlivesDisabled reports whether hs has its keep-alives // disabled. See comments on h1ServerShutdownChan above for why // the code is written this way. diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index e6b321f4bb..da91d19dd4 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -951,6 +951,9 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error { for { cc.lastActive = time.Now() if cc.closed || !cc.canTakeNewRequestLocked() { + if waitingForConn != nil { + close(waitingForConn) + } return errClientConnUnusable } if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) { diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go index ce3f27e028..30fb315d13 100644 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -126,6 +126,8 @@ var brokenAuthHeaderProviders = []string{ "https://api.sipgate.com/v1/authorization/oauth", "https://api.medium.com/v1/tokens", "https://log.finalsurge.com/oauth/token", + "https://multisport.todaysplan.com.au/rest/oauth/access_token", + "https://whats.todaysplan.com.au/rest/oauth/access_token", } // brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints. diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go index 23590bda36..c28e42b009 100644 --- a/vendor/golang.org/x/sys/unix/mkpost.go +++ b/vendor/golang.org/x/sys/unix/mkpost.go @@ -42,6 +42,10 @@ func main() { log.Fatal(err) } + // Intentionally export __val fields in Fsid and Sigset_t + valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`) + b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}")) + // If we have empty Ptrace structs, we should delete them. Only s390x emits // nonempty Ptrace structs. ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`) @@ -69,12 +73,9 @@ func main() { removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) - // We refuse to export private fields on s390x - if goarch == "s390x" && goos == "linux" { - // Remove padding, hidden, or unused fields - removeFieldsRegex = regexp.MustCompile(`\bX_\S+`) - b = removeFieldsRegex.ReplaceAll(b, []byte("_")) - } + // Remove padding, hidden, or unused fields + removeFieldsRegex = regexp.MustCompile(`\bX_\S+`) + b = removeFieldsRegex.ReplaceAll(b, []byte("_")) // Remove the first line of warning from cgo b = b[bytes.IndexByte(b, '\n')+1:] diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index a24ba5fbcf..04f38c53ee 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -944,15 +944,17 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } var dummy byte if len(oob) > 0 { - var sockType int - sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) - if err != nil { - return - } - // receive at least one normal byte - if sockType != SOCK_DGRAM && len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + if len(p) == 0 { + var sockType int + sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) + if err != nil { + return + } + // receive at least one normal byte + if sockType != SOCK_DGRAM { + iov.Base = &dummy + iov.SetLen(1) + } } msg.Control = &oob[0] msg.SetControllen(len(oob)) @@ -996,15 +998,17 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) } var dummy byte if len(oob) > 0 { - var sockType int - sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) - if err != nil { - return 0, err - } - // send at least one normal byte - if sockType != SOCK_DGRAM && len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + if len(p) == 0 { + var sockType int + sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) + if err != nil { + return 0, err + } + // send at least one normal byte + if sockType != SOCK_DGRAM { + iov.Base = &dummy + iov.SetLen(1) + } } msg.Control = &oob[0] msg.SetControllen(len(oob)) @@ -1260,6 +1264,7 @@ func Getpgrp() (pid int) { //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) +//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT //sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 387e1cfcf9..614fcf0494 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -222,6 +222,7 @@ func Uname(uname *Utsname) error { //sysnb Getppid() (ppid int) //sys Getpriority(which int, who int) (prio int, err error) //sysnb Getrlimit(which int, lim *Rlimit) (err error) +//sysnb Getrtable() (rtable int, err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) //sysnb Gettimeofday(tv *Timeval) (err error) @@ -259,6 +260,7 @@ func Uname(uname *Utsname) error { //sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setrlimit(which int, lim *Rlimit) (err error) +//sysnb Setrtable(rtable int) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) @@ -307,7 +309,6 @@ func Uname(uname *Utsname) error { // getlogin // getresgid // getresuid -// getrtable // getthrid // ktrace // lfs_bmapv @@ -343,7 +344,6 @@ func Uname(uname *Utsname) error { // semop // setgroups // setitimer -// setrtable // setsockopt // shmat // shmctl diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 68de61b8c3..51454e1e1c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1560,6 +1601,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -1944,6 +1999,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index a5748ae9e9..c3bad0caf4 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1561,6 +1602,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -1945,6 +2000,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 6d9fc7e943..8218df140c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1568,6 +1609,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -1952,6 +2007,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 0253ba34fd..5ce50c5c5e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -447,6 +447,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -545,6 +546,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1551,6 +1592,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -1935,6 +1990,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 4cef12d8e7..6cfe618733 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1562,6 +1603,20 @@ const ( SIOCSPGRP = 0x80047308 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x1 @@ -1949,6 +2004,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 4782b3efb6..bad6332a69 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1562,6 +1603,20 @@ const ( SIOCSPGRP = 0x80047308 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x1 @@ -1949,6 +2004,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 86eb3063cd..af30fde793 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1562,6 +1603,20 @@ const ( SIOCSPGRP = 0x80047308 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x1 @@ -1949,6 +2004,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 2168ece949..db3baed92f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1562,6 +1603,20 @@ const ( SIOCSPGRP = 0x80047308 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x1 @@ -1949,6 +2004,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 18e48b4f2b..2d74bd48fa 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x4000 IBSHIFT = 0x10 ICANON = 0x100 @@ -1618,6 +1659,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -2006,6 +2061,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index c069f8fabc..822f94ba21 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x4000 IBSHIFT = 0x10 ICANON = 0x100 @@ -1618,6 +1659,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -2006,6 +2061,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index e3f0e27e27..beb9aa3158 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -446,6 +446,7 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EXABYTE_ENABLE_NEST = 0xf0 EXTA = 0xe EXTB = 0xf EXTPROC = 0x10000 @@ -543,6 +544,46 @@ const ( GENL_UNS_ADMIN_PERM = 0x10 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 + HDIO_DRIVE_CMD = 0x31f + HDIO_DRIVE_CMD_AEB = 0x31e + HDIO_DRIVE_CMD_HDR_SIZE = 0x4 + HDIO_DRIVE_HOB_HDR_SIZE = 0x8 + HDIO_DRIVE_RESET = 0x31c + HDIO_DRIVE_TASK = 0x31e + HDIO_DRIVE_TASKFILE = 0x31d + HDIO_DRIVE_TASK_HDR_SIZE = 0x8 + HDIO_GETGEO = 0x301 + HDIO_GET_32BIT = 0x309 + HDIO_GET_ACOUSTIC = 0x30f + HDIO_GET_ADDRESS = 0x310 + HDIO_GET_BUSSTATE = 0x31a + HDIO_GET_DMA = 0x30b + HDIO_GET_IDENTITY = 0x30d + HDIO_GET_KEEPSETTINGS = 0x308 + HDIO_GET_MULTCOUNT = 0x304 + HDIO_GET_NICE = 0x30c + HDIO_GET_NOWERR = 0x30a + HDIO_GET_QDMA = 0x305 + HDIO_GET_UNMASKINTR = 0x302 + HDIO_GET_WCACHE = 0x30e + HDIO_OBSOLETE_IDENTITY = 0x307 + HDIO_SCAN_HWIF = 0x328 + HDIO_SET_32BIT = 0x324 + HDIO_SET_ACOUSTIC = 0x32c + HDIO_SET_ADDRESS = 0x32f + HDIO_SET_BUSSTATE = 0x32d + HDIO_SET_DMA = 0x326 + HDIO_SET_KEEPSETTINGS = 0x323 + HDIO_SET_MULTCOUNT = 0x321 + HDIO_SET_NICE = 0x329 + HDIO_SET_NOWERR = 0x325 + HDIO_SET_PIO_MODE = 0x327 + HDIO_SET_QDMA = 0x32e + HDIO_SET_UNMASKINTR = 0x322 + HDIO_SET_WCACHE = 0x32b + HDIO_SET_XFER = 0x306 + HDIO_TRISTATE_HWIF = 0x31b + HDIO_UNREGISTER_HWIF = 0x32a HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 @@ -1622,6 +1663,20 @@ const ( SIOCSPGRP = 0x8902 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SMART_AUTOSAVE = 0xd2 + SMART_AUTO_OFFLINE = 0xdb + SMART_DISABLE = 0xd9 + SMART_ENABLE = 0xd8 + SMART_HCYL_PASS = 0xc2 + SMART_IMMEDIATE_OFFLINE = 0xd4 + SMART_LCYL_PASS = 0x4f + SMART_READ_LOG_SECTOR = 0xd5 + SMART_READ_THRESHOLDS = 0xd1 + SMART_READ_VALUES = 0xd0 + SMART_SAVE = 0xd3 + SMART_STATUS = 0xda + SMART_WRITE_LOG_SECTOR = 0xd6 + SMART_WRITE_THRESHOLDS = 0xd7 SOCK_CLOEXEC = 0x80000 SOCK_DCCP = 0x6 SOCK_DGRAM = 0x2 @@ -2006,6 +2061,86 @@ const ( WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 WEXITED = 0x4 + WIN_ACKMEDIACHANGE = 0xdb + WIN_CHECKPOWERMODE1 = 0xe5 + WIN_CHECKPOWERMODE2 = 0x98 + WIN_DEVICE_RESET = 0x8 + WIN_DIAGNOSE = 0x90 + WIN_DOORLOCK = 0xde + WIN_DOORUNLOCK = 0xdf + WIN_DOWNLOAD_MICROCODE = 0x92 + WIN_FLUSH_CACHE = 0xe7 + WIN_FLUSH_CACHE_EXT = 0xea + WIN_FORMAT = 0x50 + WIN_GETMEDIASTATUS = 0xda + WIN_IDENTIFY = 0xec + WIN_IDENTIFY_DMA = 0xee + WIN_IDLEIMMEDIATE = 0xe1 + WIN_INIT = 0x60 + WIN_MEDIAEJECT = 0xed + WIN_MULTREAD = 0xc4 + WIN_MULTREAD_EXT = 0x29 + WIN_MULTWRITE = 0xc5 + WIN_MULTWRITE_EXT = 0x39 + WIN_NOP = 0x0 + WIN_PACKETCMD = 0xa0 + WIN_PIDENTIFY = 0xa1 + WIN_POSTBOOT = 0xdc + WIN_PREBOOT = 0xdd + WIN_QUEUED_SERVICE = 0xa2 + WIN_READ = 0x20 + WIN_READDMA = 0xc8 + WIN_READDMA_EXT = 0x25 + WIN_READDMA_ONCE = 0xc9 + WIN_READDMA_QUEUED = 0xc7 + WIN_READDMA_QUEUED_EXT = 0x26 + WIN_READ_BUFFER = 0xe4 + WIN_READ_EXT = 0x24 + WIN_READ_LONG = 0x22 + WIN_READ_LONG_ONCE = 0x23 + WIN_READ_NATIVE_MAX = 0xf8 + WIN_READ_NATIVE_MAX_EXT = 0x27 + WIN_READ_ONCE = 0x21 + WIN_RECAL = 0x10 + WIN_RESTORE = 0x10 + WIN_SECURITY_DISABLE = 0xf6 + WIN_SECURITY_ERASE_PREPARE = 0xf3 + WIN_SECURITY_ERASE_UNIT = 0xf4 + WIN_SECURITY_FREEZE_LOCK = 0xf5 + WIN_SECURITY_SET_PASS = 0xf1 + WIN_SECURITY_UNLOCK = 0xf2 + WIN_SEEK = 0x70 + WIN_SETFEATURES = 0xef + WIN_SETIDLE1 = 0xe3 + WIN_SETIDLE2 = 0x97 + WIN_SETMULT = 0xc6 + WIN_SET_MAX = 0xf9 + WIN_SET_MAX_EXT = 0x37 + WIN_SLEEPNOW1 = 0xe6 + WIN_SLEEPNOW2 = 0x99 + WIN_SMART = 0xb0 + WIN_SPECIFY = 0x91 + WIN_SRST = 0x8 + WIN_STANDBY = 0xe2 + WIN_STANDBY2 = 0x96 + WIN_STANDBYNOW1 = 0xe0 + WIN_STANDBYNOW2 = 0x94 + WIN_VERIFY = 0x40 + WIN_VERIFY_EXT = 0x42 + WIN_VERIFY_ONCE = 0x41 + WIN_WRITE = 0x30 + WIN_WRITEDMA = 0xca + WIN_WRITEDMA_EXT = 0x35 + WIN_WRITEDMA_ONCE = 0xcb + WIN_WRITEDMA_QUEUED = 0xcc + WIN_WRITEDMA_QUEUED_EXT = 0x36 + WIN_WRITE_BUFFER = 0xe8 + WIN_WRITE_EXT = 0x34 + WIN_WRITE_LONG = 0x32 + WIN_WRITE_LONG_ONCE = 0x33 + WIN_WRITE_ONCE = 0x31 + WIN_WRITE_SAME = 0xe9 + WIN_WRITE_VERIFY = 0x3c WNOHANG = 0x1 WNOTHREAD = 0x20000000 WNOWAIT = 0x1000000 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index ef9602c1eb..433becfd02 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 63054b3585..34c5be0fe5 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 8b10ee1445..f91b56c217 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 8c9e26a0a1..52d7595250 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 8dc2b58f58..bfd415b34d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index e8beef850c..b989d0f282 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 899e4403a9..1f8d14cacc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 7a477cbdea..93c1dc2317 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index 9dc4c7d6d4..3bb9a20992 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index f0d1ee125c..56116623d6 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index c443baf63f..9696a0199d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -995,6 +995,17 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PivotRoot(newroot string, putold string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(newroot) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 5c09c07587..49b3b5e8a4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -780,6 +780,17 @@ func Getrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getrtable() (rtable int, err error) { + r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -1254,6 +1265,16 @@ func Setrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setrtable(rtable int) (err error) { + _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 54ccc935d4..c4c7d8540c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -780,6 +780,17 @@ func Getrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getrtable() (rtable int, err error) { + r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -1254,6 +1265,16 @@ func Setrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setrtable(rtable int) (err error) { + _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 59258b0a45..210285b0ba 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -780,6 +780,17 @@ func Getrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getrtable() (rtable int, err error) { + r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -1254,6 +1265,16 @@ func Setrlimit(which int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setrtable(rtable int) (err error) { + _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 3c56b20762..a805313f2c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -96,24 +96,24 @@ type Rlimit struct { type _Gid_t uint32 type Stat_t struct { - Dev uint64 - X__pad1 uint16 - _ [2]byte - X__st_ino uint32 - Mode uint32 - Nlink uint32 - Uid uint32 - Gid uint32 - Rdev uint64 - X__pad2 uint16 - _ [2]byte - Size int64 - Blksize int32 - Blocks int64 - Atim Timespec - Mtim Timespec - Ctim Timespec - Ino uint64 + Dev uint64 + _ uint16 + _ [2]byte + _ uint32 + Mode uint32 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev uint64 + _ uint16 + _ [2]byte + Size int64 + Blksize int32 + Blocks int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Ino uint64 } type Statfs_t struct { @@ -132,9 +132,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -171,7 +171,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -583,12 +583,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -683,7 +683,7 @@ type Sysinfo_t struct { Totalhigh uint32 Freehigh uint32 Unit uint32 - X_f [8]int8 + _ [8]int8 } type Utsname struct { @@ -739,7 +739,7 @@ const ( ) type Sigset_t struct { - X__val [32]uint32 + Val [32]uint32 } const RNDGETENTCNT = 0x80045200 @@ -895,3 +895,352 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [122]int8 + _ uint32 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint32 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 92f1c8fe4d..98aa92371b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -105,7 +105,7 @@ type Stat_t struct { Mode uint32 Uid uint32 Gid uint32 - X__pad0 int32 + _ int32 Rdev uint64 Size int64 Blksize int64 @@ -132,9 +132,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -171,7 +171,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -587,12 +587,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -698,7 +698,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]int8 + _ [0]int8 _ [4]byte } @@ -757,7 +757,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x80045200 @@ -913,3 +913,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]int8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index cee5459ac1..ead8f252ec 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -96,25 +96,25 @@ type Rlimit struct { type _Gid_t uint32 type Stat_t struct { - Dev uint64 - X__pad1 uint16 - _ [2]byte - X__st_ino uint32 - Mode uint32 - Nlink uint32 - Uid uint32 - Gid uint32 - Rdev uint64 - X__pad2 uint16 - _ [6]byte - Size int64 - Blksize int32 - _ [4]byte - Blocks int64 - Atim Timespec - Mtim Timespec - Ctim Timespec - Ino uint64 + Dev uint64 + _ uint16 + _ [2]byte + _ uint32 + Mode uint32 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev uint64 + _ uint16 + _ [6]byte + Size int64 + Blksize int32 + _ [4]byte + Blocks int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Ino uint64 } type Statfs_t struct { @@ -134,9 +134,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -173,7 +173,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -587,12 +587,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -671,7 +671,7 @@ type Sysinfo_t struct { Totalhigh uint32 Freehigh uint32 Unit uint32 - X_f [8]uint8 + _ [8]uint8 } type Utsname struct { @@ -728,7 +728,7 @@ const ( ) type Sigset_t struct { - X__val [32]uint32 + Val [32]uint32 } const RNDGETENTCNT = 0x80045200 @@ -884,3 +884,352 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [122]uint8 + _ uint32 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint32 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 5ce7cfe835..8c32c3bff0 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -106,10 +106,10 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev uint64 - X__pad1 uint64 + _ uint64 Size int64 Blksize int32 - X__pad2 int32 + _ int32 Blocks int64 Atim Timespec Mtim Timespec @@ -133,9 +133,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -588,12 +588,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -676,7 +676,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]int8 + _ [0]int8 _ [4]byte } @@ -736,7 +736,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x80045200 @@ -892,3 +892,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]int8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 2860b3e284..af291d948b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -133,9 +133,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -586,12 +586,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -676,7 +676,7 @@ type Sysinfo_t struct { Totalhigh uint32 Freehigh uint32 Unit uint32 - X_f [8]int8 + _ [8]int8 } type Utsname struct { @@ -733,7 +733,7 @@ const ( ) type Sigset_t struct { - X__val [32]uint32 + Val [32]uint32 } const RNDGETENTCNT = 0x40045200 @@ -889,3 +889,352 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x8000000000000000 + CBitFieldMaskBit1 = 0x4000000000000000 + CBitFieldMaskBit2 = 0x2000000000000000 + CBitFieldMaskBit3 = 0x1000000000000000 + CBitFieldMaskBit4 = 0x800000000000000 + CBitFieldMaskBit5 = 0x400000000000000 + CBitFieldMaskBit6 = 0x200000000000000 + CBitFieldMaskBit7 = 0x100000000000000 + CBitFieldMaskBit8 = 0x80000000000000 + CBitFieldMaskBit9 = 0x40000000000000 + CBitFieldMaskBit10 = 0x20000000000000 + CBitFieldMaskBit11 = 0x10000000000000 + CBitFieldMaskBit12 = 0x8000000000000 + CBitFieldMaskBit13 = 0x4000000000000 + CBitFieldMaskBit14 = 0x2000000000000 + CBitFieldMaskBit15 = 0x1000000000000 + CBitFieldMaskBit16 = 0x800000000000 + CBitFieldMaskBit17 = 0x400000000000 + CBitFieldMaskBit18 = 0x200000000000 + CBitFieldMaskBit19 = 0x100000000000 + CBitFieldMaskBit20 = 0x80000000000 + CBitFieldMaskBit21 = 0x40000000000 + CBitFieldMaskBit22 = 0x20000000000 + CBitFieldMaskBit23 = 0x10000000000 + CBitFieldMaskBit24 = 0x8000000000 + CBitFieldMaskBit25 = 0x4000000000 + CBitFieldMaskBit26 = 0x2000000000 + CBitFieldMaskBit27 = 0x1000000000 + CBitFieldMaskBit28 = 0x800000000 + CBitFieldMaskBit29 = 0x400000000 + CBitFieldMaskBit30 = 0x200000000 + CBitFieldMaskBit31 = 0x100000000 + CBitFieldMaskBit32 = 0x80000000 + CBitFieldMaskBit33 = 0x40000000 + CBitFieldMaskBit34 = 0x20000000 + CBitFieldMaskBit35 = 0x10000000 + CBitFieldMaskBit36 = 0x8000000 + CBitFieldMaskBit37 = 0x4000000 + CBitFieldMaskBit38 = 0x2000000 + CBitFieldMaskBit39 = 0x1000000 + CBitFieldMaskBit40 = 0x800000 + CBitFieldMaskBit41 = 0x400000 + CBitFieldMaskBit42 = 0x200000 + CBitFieldMaskBit43 = 0x100000 + CBitFieldMaskBit44 = 0x80000 + CBitFieldMaskBit45 = 0x40000 + CBitFieldMaskBit46 = 0x20000 + CBitFieldMaskBit47 = 0x10000 + CBitFieldMaskBit48 = 0x8000 + CBitFieldMaskBit49 = 0x4000 + CBitFieldMaskBit50 = 0x2000 + CBitFieldMaskBit51 = 0x1000 + CBitFieldMaskBit52 = 0x800 + CBitFieldMaskBit53 = 0x400 + CBitFieldMaskBit54 = 0x200 + CBitFieldMaskBit55 = 0x100 + CBitFieldMaskBit56 = 0x80 + CBitFieldMaskBit57 = 0x40 + CBitFieldMaskBit58 = 0x20 + CBitFieldMaskBit59 = 0x10 + CBitFieldMaskBit60 = 0x8 + CBitFieldMaskBit61 = 0x4 + CBitFieldMaskBit62 = 0x2 + CBitFieldMaskBit63 = 0x1 +) + +type SockaddrStorage struct { + Family uint16 + _ [122]int8 + _ uint32 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint32 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 17b881cab2..324ee16fcf 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -133,9 +133,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -588,12 +588,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -679,7 +679,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]int8 + _ [0]int8 _ [4]byte } @@ -738,7 +738,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x40045200 @@ -894,3 +894,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x8000000000000000 + CBitFieldMaskBit1 = 0x4000000000000000 + CBitFieldMaskBit2 = 0x2000000000000000 + CBitFieldMaskBit3 = 0x1000000000000000 + CBitFieldMaskBit4 = 0x800000000000000 + CBitFieldMaskBit5 = 0x400000000000000 + CBitFieldMaskBit6 = 0x200000000000000 + CBitFieldMaskBit7 = 0x100000000000000 + CBitFieldMaskBit8 = 0x80000000000000 + CBitFieldMaskBit9 = 0x40000000000000 + CBitFieldMaskBit10 = 0x20000000000000 + CBitFieldMaskBit11 = 0x10000000000000 + CBitFieldMaskBit12 = 0x8000000000000 + CBitFieldMaskBit13 = 0x4000000000000 + CBitFieldMaskBit14 = 0x2000000000000 + CBitFieldMaskBit15 = 0x1000000000000 + CBitFieldMaskBit16 = 0x800000000000 + CBitFieldMaskBit17 = 0x400000000000 + CBitFieldMaskBit18 = 0x200000000000 + CBitFieldMaskBit19 = 0x100000000000 + CBitFieldMaskBit20 = 0x80000000000 + CBitFieldMaskBit21 = 0x40000000000 + CBitFieldMaskBit22 = 0x20000000000 + CBitFieldMaskBit23 = 0x10000000000 + CBitFieldMaskBit24 = 0x8000000000 + CBitFieldMaskBit25 = 0x4000000000 + CBitFieldMaskBit26 = 0x2000000000 + CBitFieldMaskBit27 = 0x1000000000 + CBitFieldMaskBit28 = 0x800000000 + CBitFieldMaskBit29 = 0x400000000 + CBitFieldMaskBit30 = 0x200000000 + CBitFieldMaskBit31 = 0x100000000 + CBitFieldMaskBit32 = 0x80000000 + CBitFieldMaskBit33 = 0x40000000 + CBitFieldMaskBit34 = 0x20000000 + CBitFieldMaskBit35 = 0x10000000 + CBitFieldMaskBit36 = 0x8000000 + CBitFieldMaskBit37 = 0x4000000 + CBitFieldMaskBit38 = 0x2000000 + CBitFieldMaskBit39 = 0x1000000 + CBitFieldMaskBit40 = 0x800000 + CBitFieldMaskBit41 = 0x400000 + CBitFieldMaskBit42 = 0x200000 + CBitFieldMaskBit43 = 0x100000 + CBitFieldMaskBit44 = 0x80000 + CBitFieldMaskBit45 = 0x40000 + CBitFieldMaskBit46 = 0x20000 + CBitFieldMaskBit47 = 0x10000 + CBitFieldMaskBit48 = 0x8000 + CBitFieldMaskBit49 = 0x4000 + CBitFieldMaskBit50 = 0x2000 + CBitFieldMaskBit51 = 0x1000 + CBitFieldMaskBit52 = 0x800 + CBitFieldMaskBit53 = 0x400 + CBitFieldMaskBit54 = 0x200 + CBitFieldMaskBit55 = 0x100 + CBitFieldMaskBit56 = 0x80 + CBitFieldMaskBit57 = 0x40 + CBitFieldMaskBit58 = 0x20 + CBitFieldMaskBit59 = 0x10 + CBitFieldMaskBit60 = 0x8 + CBitFieldMaskBit61 = 0x4 + CBitFieldMaskBit62 = 0x2 + CBitFieldMaskBit63 = 0x1 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]int8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index ec802dc892..08849df80a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -133,9 +133,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -588,12 +588,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -679,7 +679,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]int8 + _ [0]int8 _ [4]byte } @@ -738,7 +738,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x40045200 @@ -894,3 +894,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]int8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 4a99648510..3682beb6ce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -133,9 +133,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -586,12 +586,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -676,7 +676,7 @@ type Sysinfo_t struct { Totalhigh uint32 Freehigh uint32 Unit uint32 - X_f [8]int8 + _ [8]int8 } type Utsname struct { @@ -733,7 +733,7 @@ const ( ) type Sigset_t struct { - X__val [32]uint32 + Val [32]uint32 } const RNDGETENTCNT = 0x40045200 @@ -889,3 +889,352 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [122]int8 + _ uint32 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint32 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 63a0dbe94e..bfa39ec9ce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -105,7 +105,7 @@ type Stat_t struct { Mode uint32 Uid uint32 Gid uint32 - X__pad2 int32 + _ int32 Rdev uint64 Size int64 Blksize int64 @@ -134,9 +134,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -173,7 +173,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -589,12 +589,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -686,7 +686,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]uint8 + _ [0]uint8 _ [4]byte } @@ -709,10 +709,10 @@ type Ustat_t struct { } type EpollEvent struct { - Events uint32 - X_padFd int32 - Fd int32 - Pad int32 + Events uint32 + _ int32 + Fd int32 + Pad int32 } const ( @@ -746,7 +746,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x40045200 @@ -902,3 +902,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x8000000000000000 + CBitFieldMaskBit1 = 0x4000000000000000 + CBitFieldMaskBit2 = 0x2000000000000000 + CBitFieldMaskBit3 = 0x1000000000000000 + CBitFieldMaskBit4 = 0x800000000000000 + CBitFieldMaskBit5 = 0x400000000000000 + CBitFieldMaskBit6 = 0x200000000000000 + CBitFieldMaskBit7 = 0x100000000000000 + CBitFieldMaskBit8 = 0x80000000000000 + CBitFieldMaskBit9 = 0x40000000000000 + CBitFieldMaskBit10 = 0x20000000000000 + CBitFieldMaskBit11 = 0x10000000000000 + CBitFieldMaskBit12 = 0x8000000000000 + CBitFieldMaskBit13 = 0x4000000000000 + CBitFieldMaskBit14 = 0x2000000000000 + CBitFieldMaskBit15 = 0x1000000000000 + CBitFieldMaskBit16 = 0x800000000000 + CBitFieldMaskBit17 = 0x400000000000 + CBitFieldMaskBit18 = 0x200000000000 + CBitFieldMaskBit19 = 0x100000000000 + CBitFieldMaskBit20 = 0x80000000000 + CBitFieldMaskBit21 = 0x40000000000 + CBitFieldMaskBit22 = 0x20000000000 + CBitFieldMaskBit23 = 0x10000000000 + CBitFieldMaskBit24 = 0x8000000000 + CBitFieldMaskBit25 = 0x4000000000 + CBitFieldMaskBit26 = 0x2000000000 + CBitFieldMaskBit27 = 0x1000000000 + CBitFieldMaskBit28 = 0x800000000 + CBitFieldMaskBit29 = 0x400000000 + CBitFieldMaskBit30 = 0x200000000 + CBitFieldMaskBit31 = 0x100000000 + CBitFieldMaskBit32 = 0x80000000 + CBitFieldMaskBit33 = 0x40000000 + CBitFieldMaskBit34 = 0x20000000 + CBitFieldMaskBit35 = 0x10000000 + CBitFieldMaskBit36 = 0x8000000 + CBitFieldMaskBit37 = 0x4000000 + CBitFieldMaskBit38 = 0x2000000 + CBitFieldMaskBit39 = 0x1000000 + CBitFieldMaskBit40 = 0x800000 + CBitFieldMaskBit41 = 0x400000 + CBitFieldMaskBit42 = 0x200000 + CBitFieldMaskBit43 = 0x100000 + CBitFieldMaskBit44 = 0x80000 + CBitFieldMaskBit45 = 0x40000 + CBitFieldMaskBit46 = 0x20000 + CBitFieldMaskBit47 = 0x10000 + CBitFieldMaskBit48 = 0x8000 + CBitFieldMaskBit49 = 0x4000 + CBitFieldMaskBit50 = 0x2000 + CBitFieldMaskBit51 = 0x1000 + CBitFieldMaskBit52 = 0x800 + CBitFieldMaskBit53 = 0x400 + CBitFieldMaskBit54 = 0x200 + CBitFieldMaskBit55 = 0x100 + CBitFieldMaskBit56 = 0x80 + CBitFieldMaskBit57 = 0x40 + CBitFieldMaskBit58 = 0x20 + CBitFieldMaskBit59 = 0x10 + CBitFieldMaskBit60 = 0x8 + CBitFieldMaskBit61 = 0x4 + CBitFieldMaskBit62 = 0x2 + CBitFieldMaskBit63 = 0x1 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]uint8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index f20a63591b..72eab3d832 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -105,7 +105,7 @@ type Stat_t struct { Mode uint32 Uid uint32 Gid uint32 - X__pad2 int32 + _ int32 Rdev uint64 Size int64 Blksize int64 @@ -134,9 +134,9 @@ type Statfs_t struct { } type StatxTimestamp struct { - Sec int64 - Nsec uint32 - X__reserved int32 + Sec int64 + Nsec uint32 + _ int32 } type Statx_t struct { @@ -173,7 +173,7 @@ type Dirent struct { } type Fsid struct { - X__val [2]int32 + Val [2]int32 } type Flock_t struct { @@ -589,12 +589,12 @@ type RtAttr struct { } type IfInfomsg struct { - Family uint8 - X__ifi_pad uint8 - Type uint16 - Index int32 - Flags uint32 - Change uint32 + Family uint8 + _ uint8 + Type uint16 + Index int32 + Flags uint32 + Change uint32 } type IfAddrmsg struct { @@ -686,7 +686,7 @@ type Sysinfo_t struct { Totalhigh uint64 Freehigh uint64 Unit uint32 - X_f [0]uint8 + _ [0]uint8 _ [4]byte } @@ -709,10 +709,10 @@ type Ustat_t struct { } type EpollEvent struct { - Events uint32 - X_padFd int32 - Fd int32 - Pad int32 + Events uint32 + _ int32 + Fd int32 + Pad int32 } const ( @@ -746,7 +746,7 @@ const ( ) type Sigset_t struct { - X__val [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x40045200 @@ -902,3 +902,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]uint8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 30dc10582f..c7935b760b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -172,7 +172,7 @@ type Dirent struct { } type Fsid struct { - _ [2]int32 + Val [2]int32 } type Flock_t struct { @@ -763,7 +763,7 @@ const ( ) type Sigset_t struct { - _ [16]uint64 + Val [16]uint64 } const RNDGETENTCNT = 0x80045200 @@ -919,3 +919,353 @@ const ( BDADDR_LE_PUBLIC = 0x1 BDADDR_LE_RANDOM = 0x2 ) + +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + _ uint32 +} + +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ [948]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +const ( + PerfBitDisabled uint64 = CBitFieldMaskBit0 + PerfBitInherit = CBitFieldMaskBit1 + PerfBitPinned = CBitFieldMaskBit2 + PerfBitExclusive = CBitFieldMaskBit3 + PerfBitExcludeUser = CBitFieldMaskBit4 + PerfBitExcludeKernel = CBitFieldMaskBit5 + PerfBitExcludeHv = CBitFieldMaskBit6 + PerfBitExcludeIdle = CBitFieldMaskBit7 + PerfBitMmap = CBitFieldMaskBit8 + PerfBitComm = CBitFieldMaskBit9 + PerfBitFreq = CBitFieldMaskBit10 + PerfBitInheritStat = CBitFieldMaskBit11 + PerfBitEnableOnExec = CBitFieldMaskBit12 + PerfBitTask = CBitFieldMaskBit13 + PerfBitWatermark = CBitFieldMaskBit14 + PerfBitPreciseIPBit1 = CBitFieldMaskBit15 + PerfBitPreciseIPBit2 = CBitFieldMaskBit16 + PerfBitMmapData = CBitFieldMaskBit17 + PerfBitSampleIDAll = CBitFieldMaskBit18 + PerfBitExcludeHost = CBitFieldMaskBit19 + PerfBitExcludeGuest = CBitFieldMaskBit20 + PerfBitExcludeCallchainKernel = CBitFieldMaskBit21 + PerfBitExcludeCallchainUser = CBitFieldMaskBit22 + PerfBitMmap2 = CBitFieldMaskBit23 + PerfBitCommExec = CBitFieldMaskBit24 + PerfBitUseClockID = CBitFieldMaskBit25 + PerfBitContextSwitch = CBitFieldMaskBit26 +) + +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 +) + +const ( + CBitFieldMaskBit0 = 0x8000000000000000 + CBitFieldMaskBit1 = 0x4000000000000000 + CBitFieldMaskBit2 = 0x2000000000000000 + CBitFieldMaskBit3 = 0x1000000000000000 + CBitFieldMaskBit4 = 0x800000000000000 + CBitFieldMaskBit5 = 0x400000000000000 + CBitFieldMaskBit6 = 0x200000000000000 + CBitFieldMaskBit7 = 0x100000000000000 + CBitFieldMaskBit8 = 0x80000000000000 + CBitFieldMaskBit9 = 0x40000000000000 + CBitFieldMaskBit10 = 0x20000000000000 + CBitFieldMaskBit11 = 0x10000000000000 + CBitFieldMaskBit12 = 0x8000000000000 + CBitFieldMaskBit13 = 0x4000000000000 + CBitFieldMaskBit14 = 0x2000000000000 + CBitFieldMaskBit15 = 0x1000000000000 + CBitFieldMaskBit16 = 0x800000000000 + CBitFieldMaskBit17 = 0x400000000000 + CBitFieldMaskBit18 = 0x200000000000 + CBitFieldMaskBit19 = 0x100000000000 + CBitFieldMaskBit20 = 0x80000000000 + CBitFieldMaskBit21 = 0x40000000000 + CBitFieldMaskBit22 = 0x20000000000 + CBitFieldMaskBit23 = 0x10000000000 + CBitFieldMaskBit24 = 0x8000000000 + CBitFieldMaskBit25 = 0x4000000000 + CBitFieldMaskBit26 = 0x2000000000 + CBitFieldMaskBit27 = 0x1000000000 + CBitFieldMaskBit28 = 0x800000000 + CBitFieldMaskBit29 = 0x400000000 + CBitFieldMaskBit30 = 0x200000000 + CBitFieldMaskBit31 = 0x100000000 + CBitFieldMaskBit32 = 0x80000000 + CBitFieldMaskBit33 = 0x40000000 + CBitFieldMaskBit34 = 0x20000000 + CBitFieldMaskBit35 = 0x10000000 + CBitFieldMaskBit36 = 0x8000000 + CBitFieldMaskBit37 = 0x4000000 + CBitFieldMaskBit38 = 0x2000000 + CBitFieldMaskBit39 = 0x1000000 + CBitFieldMaskBit40 = 0x800000 + CBitFieldMaskBit41 = 0x400000 + CBitFieldMaskBit42 = 0x200000 + CBitFieldMaskBit43 = 0x100000 + CBitFieldMaskBit44 = 0x80000 + CBitFieldMaskBit45 = 0x40000 + CBitFieldMaskBit46 = 0x20000 + CBitFieldMaskBit47 = 0x10000 + CBitFieldMaskBit48 = 0x8000 + CBitFieldMaskBit49 = 0x4000 + CBitFieldMaskBit50 = 0x2000 + CBitFieldMaskBit51 = 0x1000 + CBitFieldMaskBit52 = 0x800 + CBitFieldMaskBit53 = 0x400 + CBitFieldMaskBit54 = 0x200 + CBitFieldMaskBit55 = 0x100 + CBitFieldMaskBit56 = 0x80 + CBitFieldMaskBit57 = 0x40 + CBitFieldMaskBit58 = 0x20 + CBitFieldMaskBit59 = 0x10 + CBitFieldMaskBit60 = 0x8 + CBitFieldMaskBit61 = 0x4 + CBitFieldMaskBit62 = 0x2 + CBitFieldMaskBit63 = 0x1 +) + +type SockaddrStorage struct { + Family uint16 + _ [118]int8 + _ uint64 +} + +type TCPMD5Sig struct { + Addr SockaddrStorage + Flags uint8 + Prefixlen uint8 + Keylen uint16 + _ uint32 + Key [80]uint8 +} + +type HDDriveCmdHdr struct { + Command uint8 + Number uint8 + Feature uint8 + Count uint8 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + _ [4]byte + Start uint64 +} + +type HDDriveID struct { + Config uint16 + Cyls uint16 + Reserved2 uint16 + Heads uint16 + Track_bytes uint16 + Sector_bytes uint16 + Sectors uint16 + Vendor0 uint16 + Vendor1 uint16 + Vendor2 uint16 + Serial_no [20]uint8 + Buf_type uint16 + Buf_size uint16 + Ecc_bytes uint16 + Fw_rev [8]uint8 + Model [40]uint8 + Max_multsect uint8 + Vendor3 uint8 + Dword_io uint16 + Vendor4 uint8 + Capability uint8 + Reserved50 uint16 + Vendor5 uint8 + TPIO uint8 + Vendor6 uint8 + TDMA uint8 + Field_valid uint16 + Cur_cyls uint16 + Cur_heads uint16 + Cur_sectors uint16 + Cur_capacity0 uint16 + Cur_capacity1 uint16 + Multsect uint8 + Multsect_valid uint8 + Lba_capacity uint32 + Dma_1word uint16 + Dma_mword uint16 + Eide_pio_modes uint16 + Eide_dma_min uint16 + Eide_dma_time uint16 + Eide_pio uint16 + Eide_pio_iordy uint16 + Words69_70 [2]uint16 + Words71_74 [4]uint16 + Queue_depth uint16 + Words76_79 [4]uint16 + Major_rev_num uint16 + Minor_rev_num uint16 + Command_set_1 uint16 + Command_set_2 uint16 + Cfsse uint16 + Cfs_enable_1 uint16 + Cfs_enable_2 uint16 + Csf_default uint16 + Dma_ultra uint16 + Trseuc uint16 + TrsEuc uint16 + CurAPMvalues uint16 + Mprc uint16 + Hw_config uint16 + Acoustic uint16 + Msrqs uint16 + Sxfert uint16 + Sal uint16 + Spg uint32 + Lba_capacity_2 uint64 + Words104_125 [22]uint16 + Last_lun uint16 + Word127 uint16 + Dlf uint16 + Csfo uint16 + Words130_155 [26]uint16 + Word156 uint16 + Words157_159 [3]uint16 + Cfa_power uint16 + Words161_175 [15]uint16 + Words176_205 [30]uint16 + Words206_254 [49]uint16 + Integrity_word uint16 +} From 08ce2a0724a6a2eb9a8ea0c1f2d45d6ade6bfda0 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Apr 2018 19:47:06 +0200 Subject: [PATCH 10/69] Add support for insecure docker registry (#131) * Add support for insecure docker registry Using --insecure-skip-tls-verify Fixes #110 * Apply formatting --- cmd/executor/cmd/root.go | 18 ++++++++++-------- pkg/executor/executor.go | 4 ++-- pkg/image/image.go | 5 +++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 7a648fb1d2..2c8e9b69aa 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -32,13 +32,14 @@ import ( ) var ( - dockerfilePath string - destination string - srcContext string - snapshotMode string - bucket string - logLevel string - force bool + dockerfilePath string + destination string + srcContext string + snapshotMode string + bucket string + dockerInsecureSkipTLSVerify bool + logLevel string + force bool ) func init() { @@ -47,6 +48,7 @@ func init() { RootCmd.PersistentFlags().StringVarP(&bucket, "bucket", "b", "", "Name of the GCS bucket from which to access build context as tarball.") RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)") RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting") + RootCmd.PersistentFlags().BoolVarP(&dockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic") RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container") } @@ -70,7 +72,7 @@ var RootCmd = &cobra.Command{ } logrus.Warn("kaniko is being run outside of a container. This can have dangerous effects on your system") } - if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode); err != nil { + if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil { logrus.Error(err) os.Exit(1) } diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index ee7c87e452..ab9eacd53f 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -32,7 +32,7 @@ import ( "github.com/sirupsen/logrus" ) -func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string) error { +func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool) error { // Parse dockerfile and unpack base image to root d, err := ioutil.ReadFile(dockerfilePath) if err != nil { @@ -113,7 +113,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string) error if err := setDefaultEnv(); err != nil { return err } - return image.PushImage(sourceImage, destination) + return image.PushImage(sourceImage, destination, dockerInsecureSkipTLSVerify) } func getHasher(snapshotMode string) (func(string) (string, error), error) { diff --git a/pkg/image/image.go b/pkg/image/image.go index 52035ef693..6309f30970 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -48,7 +48,7 @@ func NewSourceImage(srcImg string) (*img.MutableSource, error) { } // PushImage pushes the final image -func PushImage(ms *img.MutableSource, destImg string) error { +func PushImage(ms *img.MutableSource, destImg string, dockerInsecureSkipTLSVerify bool) error { srcRef := &img.ProxyReference{ ImageReference: nil, Src: ms, @@ -65,7 +65,8 @@ func PushImage(ms *img.MutableSource, destImg string) error { opts := ©.Options{ DestinationCtx: &types.SystemContext{ - DockerRegistryUserAgent: fmt.Sprintf("kaniko/executor-%s", version.Version()), + DockerRegistryUserAgent: fmt.Sprintf("kaniko/executor-%s", version.Version()), + DockerInsecureSkipTLSVerify: dockerInsecureSkipTLSVerify, }, } return copy.Image(policyContext, destRef, srcRef, opts) From 5a8034226c7066fbb3523c385837573b9a0890d3 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Sat, 21 Apr 2018 08:59:42 +0200 Subject: [PATCH 11/69] Remove docker-credential-pass It's not really needed to use config.json credentials --- deploy/Dockerfile | 1 - files/docker-credential-pass | Bin 2529418 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 100755 files/docker-credential-pass diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 74d94533d5..b251cd4112 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -17,7 +17,6 @@ FROM scratch ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ -ADD files/docker-credential-pass /usr/local/bin/ ENV HOME /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs diff --git a/files/docker-credential-pass b/files/docker-credential-pass deleted file mode 100755 index 525169cad569d77775e1de954ee437fa8d805799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2529418 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 z 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

)RB$96m!EB zB1)RW+)?E?R7y&OOi2e_6eD5mP~{)6(i(o)kWkrCm3=-nt07%m^h>2DBfa+tWq=ph zzaC_WTZzqrjiO*fqRH+%U}e z%?dyA>JV2reoJKdO|yf5-_C>I&JhB}Z_fl=nlCn*A~wv%+U+6QT^E3L?bwN~D_-0!l)+f_^dN&{)hk`OWBY`_j8zW?%)i97 zVt&|~FjjqiQD;{DWOA5QaVEi`uqu8G>BaHlRp`Z*O#ixNMwpxT4OM6y+OpcUw`)W0 zQ+hJ;S~!Do&8#4U)kBosVq?KwU4zE=4wY}rbZ!8SI)qcdbz|hI-M|h9%&&Dw{xodO zSe@_w)3v*^ru2W$Whtpnv^aY(z}%|WDd0qJIKtVJV*3F7sMb5c8hlcqJS#!2EFtT zHYFaqgn!-I_J&p{!!l88FZUxWiPi5~QuLvw4^dw}4-N0so@*QNxZH3CxrvM3qYPg% zkHoE1k5b2(dw<4zE?Em`QwBsGRmT-Oyq*X+WS=_0@ZjLcvyFETD`c4iev{BCxAJ_NO}U z%T}T=heU_u6Gow+_HSoho4$5 z{DKQ8m$}U+2_*fEpE(NUnA!=mhT5v&i_{quH#!+_uSgu9S3Ygi_n=RPYkjS5!s=}F)4-e_x0if*#E50s z;i}pjXwUoD^Oa1k7!@^A;y4!!>G?M?>uCjr_Iy zLTo^wA6C2-(8*zq3m2kwMYZ7+W3^IHT^1PKnV6ci1?g+kt}@f~jG#{42O<60pE5$q zhm0Uf~g|^Du$Iwhlr!4sV7KeEL)NM1?+bW?6=XeAK+W^Qs0Oj zKEBJ?@14}gX_orXcv@}hQqLH5je z*)v#nk$g_T5OKyZNcOX5Jb?t7FuSc&2XSfE&$K&3ce!}a7c`Mpk?b{~v;mdUZvgA# zyTy~ImW043vh1j$>laQ~FluPCZr_bdZ&fmMl$FkGCJ9B=xA@}(M*GTR}?Rs94RkeIv+PRQX<+X%ZlDtG(?H@kFlzWtk$f(4SLf#80K$rF}=Gy-BE)uMRBV-kQQ10x{BK7Rp(r3km98X+z zr^JXV+dRmC_+2x;BD*y{`JL^de3_mXa# z5s4s75NeE`s>o(R6|IENXO_NBTPS{6a6A{#1(NejMe&NsPm~wWuYP!RVrBV|x68TB zu1DLSbqlgZP^gYP|G4rWmmRbsvV&A2HeG02XJ|nK(YC5IkzR$8@N_t*On$0T&1j zz)eu}MYX$u-8$PUw~LlZ&PX4!Q6hB|Q0f>8@FF{$V*5R6A%-jniZgj=o6azQ|H*Ec zpNt-A`@nyEC~eN=xswL!(*EbsU!Cm*6BAnCri4+95fj zPkCZ(y#CYe%L#f9fY22-DCDrZTf+sQ#1>B5Z0cs8p-WiC zwBC!+dxf@u=?Gye=d=R2^h52auzibXEk_K=t(eOb@+^F(?L~j*+r(-^m$W?zL*6_t zWWx;sHUFew+2~|pxHAP+CV!c|;&UPS&ft~n7vzCtU?^uS7KW=h>SMbyHK-KDQfjR- zZ98AuRwP2Vq~1Ub{15*@HSh8d_4f>)Q>`nhhSJKpjLoG3@V+kN4&TuQ~Ojpu<8@rZtR{-X?beIEsI1C1NWcgRB!g;Q) zyEcakf%VeW*xbbUU9Rte6pssTM z?{gz~9>;Rs6qxj5oDRoyln(Fc*7TEq&WouVQ z24Jo$mN~FJHiW2XojM=@b6s(t1KT?cW?iusUzz_?hthyBb$_rct{2%kVJh6KKhzcH zIoMMMh4{%Fti_M3E9iju@yT90Vr8N*h7B!kSjR0AscNU-KRY>;Yj07gr{(frW}!T_ zpNn1UY+pHl9-dkB8*1xf%w6<5T@uOv215t~s!kXYRdDUoG!Um-j?#&?tG`F@x@;C@ z6X%RgZk=sWKF&$N)EcOt;%}n$ms_@8xG{11`sY2TLbS{xfr2fjIJdy93rS}Uz0y6c~0@^RPhmhGpU`qoqhs;?HED>hS zT!H;10CTMQ&lW4~gY83=8V64ez#MDd;lRdptMnAW{8_>r1S`4E_JSrZZD?3Baaa1S zB(8oLG?bs{yl>d=9i4eb58#*m-70O^8frq0aNC~JY%8CR7FT2Ub@k?b7lNb&)_-W8 zpP#N5aULI?S8~A!j`M0mvMh}3BR$ZKO~A*KoD@qRu)$ZMVhTv&h^3(ln1)v-p2=Og zb>LUsH=ca7PVmL+CLZhNzV+O67-X3E8cs7Cjm9t=j8~!%lX>2 zoO7;%5%u;0D>^w0rFNM5Jnk=gMz}>@{5I6So+{vbH5`(5W!ir^f~;H@%0N4_{Fj3a zg+{lp7$_+ByfEEpXqJC>0OpwF=glOo5DsZNAs&!sam@(-rw+BNyVZ0aMfiW}k|`!@ zq>#ghUe<{BHAWuQ|0Uckt6u%-pW7vGVcU)V3ogeiVT6s6-wDN^b;;psOWh|O6kwhj zq?eXYdm-V6SYKn^X$OOrN`9@7Oty=$1uGH-e8UCIQ zyW7H=dHXCtP8Hm2D_ttgnBuM*r8fPxd9Kc&2h(#{e{WakuHEYFtq)$AR`3ZMdDn0%{;@y^jctXx)Fp zuxN|L{R)t0$f*g+CIB!~!)~hd@pBzV{>`$(+c2Zpc7;FDUbTB@mL2j&I=iowu2)dG zzFb&2p-P*0xNxp#ux)FjYkHp>YWx9e{9kZ-aUnN|1oL$pPdHXx;|au0`%{KCvjVaH z5i}6Uqs1!dA9sH3sNhI!TiqWX9AXQ%oPq4vf#~nla8G?TPO|m2;qz?6g-o@Z%`iLg zteB^{`=sQGfS#0$(^cXjGZogYk=Z^eZ`;{~LOx6z6WZj^;F3AquTqIcYRho{C64rk zfTQC^z^EWgRMVIg^GI{T08O_Zv%73$f5blUM=LTC@JAQ=y(d=aG~Zej`TiGnd2!@E zZL7D6z1-jP?6y8ZEV+a^_XsQp3T?KmcWixX;eJ@ma0~r(aBk~U9FkRXPDM4N8Jn7( z3N|$jM}K{=60e;~8qv-T)w*T0Hl8?xJ?Do&JpXdM8_78V`_5a%b?>QCA zi83s(?e_2e!|k6mg1(2G3i!qr%kdwUIC<#G;B>Nm=epC$_TU$0YOm5~LDwrhd<}7- zZ4Y;v&UTg0VEq=OLt(hoQRGFIz+V|Q)KX5aYE9(ccPI2lE9*xbJgtY0k<%-;1R@kb z+4l>A+q;ePVFhrP$nccszcP`FypxergECMB-(^daNSVoPAX7*|+jjbKOeOl)$&`sO zOl2D0--`^P0Nt83m|uTN3!?Nc#kSuOp!R9D0^6su*%!e+Piaw}jU$`}cn z0B(5Hs!oO77sfVs0O+rN2>b3!3Deii5ir^E_duqeaO-#(#T3WBm_!$Z&o&bcHDR%+ zadSb!bZ4~75lzQR4dv*G#a+D$y z-v|=v#P~{C;^STzV0uYMUsB!2EX*D zhKykIEFsf2x%18lPRqw&+r@jr2(q3F487f0GK)4o&h*$DwDLV82DEqA+(hSHeL+dn z)Pf-;b?s~~c$NMv^Ny`5Oa7AM)hh~yjbcrt@flL1^G3Fh%*Szx$Fq_5xOa7|f-q!= zyS6;q!pMChBicWNYQy$;1&=+itO=>E@J=0Hf&Ihx8#QF51H3D|I|MqKdvM2=MxQ<= z#}-=lQNfAjLsyh`cH7{zFLv^u=GV~ zfzp+qQDH&esD}SU8~(MOmW_TgI`Mf$;)C+U%8JA~DyhBAi&U1nz#Ssc!Twn6LPyy} z?$8xRRYze;)c3gUS>T!PBDj4=FWTSG=0Hsx&uTNPMyN{i%yd09Z-?l-=PeSqq~Wz_ z!%}8&(Rnj1p>9(h>(wNrf#dD0o49-#JkpD2?$ca~R(9cF+0O~G->W(uj2<&+l3i#9 zpWI_-bgw-@icf}T-=mztWCB^DDNmucl76A_UnAM;W(aUAoGLhaY_>TAn$9ZF$&YBE znu75|7LDWQfU@Y*M~@j-hPWRzD$&B>DE7SnxH68!o6*29JT5VDOguqg#Sjidk;1ns z(d;v=a6HzOr%kS{rA1T*fljaV4t?-QZJ)hd;Vg{n4iD4V5U8!a$O@^Tvl zM@Xjdj3>{i)CRg&8Dipzqv_{<9jhh&bw71`NB2{Rk=6{;7;t>R1x+Ux4B-fYXycRc zh$e^gt;d5*CC{&&LuJvYSH!hd`eu8J|8_k=UXcMy8EKLYMMWrisY$cXqVpOGq}>pr zJT($Zi8`G7b8|CkJNb`QxrXHPwhyD|L2Ly+`*04ETv9uri47K3YoJc1EnLj&0{`sa zu~N#YyHDGDQjcchIFqLTy46CWFQMgq3(_PpMErb&(q;OS|MImw_YvtDDA0@ag6`}$ zI+JZ;btLGI{ZIMU3XrCs=pKJNwyk95^z3gD)y25($!lt|Zjh2t9D}_o7{uvJ2(*5& zhT?!Q3_5xG=w}^*#dz<~=F}DjuZCvZ>Wku5l~sQA->4%Q8MIw!xV16#eneHR8Im@t zmN5PSx$D;C1 z=Kmsu)_y8wr7h1ypRN#V5rH|*eDqE>m9shOE-oiOJl0>qFcqmY1-kcI|%Q5=ygwCmw(vg^lj=9TuJsehrFrtc#C_- zGk8AlR4k`@o@wLfWtjYUMd zm+dI3QFtMGmvR70v_T`lXm7U)M*KQGG8(QNDjl+~7QqRFUs7|h&Ol*(zIsT7cMfa$ zZ-dY2WZ#lqvp=eZ<85||CtlNz)F4OgtLfr6oMjr}QXnNI zP9w~6V3WeLEEA?*02a~+;~m@)?}myqM%@!Q{|txLH@k<>+KtxuEq_!C!DD_b^a(ds zmj5^Vn_8~Ar8De zJef0Q+KdKp_$C0`{T{3Qwy**>CRThlh%(!9bH1K`F~CKuyE5JV0Q&#B)4tyMlTaJ- zgB7UB?QYqj<+s? zw>Z!E{aRwG7RbdQk8X@@wmog^)r7Z1u*pGhGn>%IJU`CGo5BbwOFN%wCT9VxU=})~ z6d6%?cmk_P7kbmFHg9&tL~gQTU>ZL=TueM@old6GB7zWL!C(eQxrue#n<*IbK(PJS zI(oz{m)ID17UhZg>NAnqu87z@n{xoXUO5d}(>^jHvy_N2SIxR--(|FS8N`B2 zw(Lu(^*X4!X^MEv7{l=dR2B1qVE~fmF3#r$=^U>l7E$2=x8yD8_})eSRb6L&rveH! zm6>^q)qp?9f@83w>t|RBBu@4tT6br!Jf>KomsncYdE?b*bM8WGvzkNxt0768-54#^ zN6{nmH!4hcC!*-}dGbCm8!*?rD{2=xj;2v1mbXKDwNF;V{U-aN@M#|#$r7vD?m(gR z2=CZ3VSI76gYQcR{e;e-*`3-u>6f$>E|3QrS*OBN~_ZFFSk zzS;zs>Y`Hq%Y-)JgJH@QtvQKFLtcF3_hhavaWb7as|B-)RCqm6nn$!{AJ!laa{KK~ zI|t(j^QQ?q3<2G6HESJhpZNPt65UKXo~M1j#Y=chYv?6Z1+v&9I*)4G66R}YyVf%Q z*)*Q*4&xQUIK3$rV8g{l`xQ4eg+!%G4GP}_JGXR zfV7-j$&XTU+h6VRZXQ$IZqe@lG>3NXo9X8+{X17xbh00Xd@N|+m28>;dxRZjc!D*f zesiy@S*oO^^D%Y=41jcQBAYw2_TQHDo_=v4z0K8>c-ws$3HYze?{Ztk z8)3IWKb8NHXXQVz-4B-^oqnC8f06V{q4Wy^8ksf2O!C^JhBiy+qhf!oA$_c0ShT>b z3^*rjWgJ*6V?|cRZ94?UO50+_oKY$&f#&?=U(Sj^T-3kpQRvZjmwo9CVXe~%PuUuQ z(x+#b1*&wW$I;uOw~ANjv=xF$X2Qx*Ytw_OH?hMc)SI_bhr7#AME@_#w|!6I%#QNU zOP7C3=kgE#k@8OmfA}k-%af7a)1@r717*`5LY|@t)g1k$W2h%KR!^XCZY)8`&3}^?|EVgGF=(pS|2ZDLL3i_S@!Pfiy#6=Y`)qrU*6V%=NFFRK)Nkw^ zo!OTpCUX6v$#)S&^YVMQu2Et;As_bSAA5|0ClR4aXP>f13Rd;7`qG5v=J=y;u0VfdqldaRFJt)RC{b@kbP5(D=nWoc4z% zINq&(rf>Dcl;r|z{}G73T?^}=R%M{{1XMpkU6l{iI*Ejtza)j)xn`DOJuVzRX1N9k z>zy6eHamn`hY0Jfj;x=**R?nPB`U1pD>9#MXSQ-2Kq>zAuARNRwe!;Hnci4w{2)f*c^gPrsK_Ya_;QKMtuT{+>@QQ*|bcF zNFkdGal8eu8XClXPZ*lg?P>0FqlLfuA{&SH&Z5~rX790Hxz?>$4w2HD_65C(tUee7 zmbzbCuOwVkhwDv|$Dcl7EhO$W4QEhQ_?v!+VV>Dv$|TwMM9mvoHXRiovNXPYvjS0L zpmY7RY6|426dz5X3>(d+xQB*|7zovsa6p&A(ZBIH%S97{&0P-3 zc;XpBRwU{Ka{ZN1wAxv;VdYI%4Qyv`Hq71FW(-sYZXhm zkM`aXOvTCOKTrf3t%Vz>7R3CUUel3HHm1oZ!-p#I8qA(PbLb{(V*ky1;r(6#5{Y_8 z&L`|Au}VG7{_kT^%*r|5xEyB8@i%OzBrDMs*2Xj(G|lTGT#~spMe1HAH~vMV1nl}U z^%{1CL%D`>9o33#%2fNcG+Z+Br|^+u7WR>Qttpt+`C{YL;eh!||HJOrr+z@6oFpT;yM2ws zB%8F|n~5MtF7RM-#D#6Q4^}tNY9dKXoZo2%n9N;NAwOP|QoY>E9muQzu#78rk2Dwbn1exsa=Vb09%*v@=sf+5G`4=0Y zX)(Wsz8)TBrq%%Z@5K!LWh4pxMVi31*6CG$UhWI-`>Npkb?&=f^#|yh4Csvx)DJ+9 zaiDtDUu)gkj!YXfna*~ZvWB|)zm_IT=C&Vb_$zf$T@L>W|2%#Te?6!G;Xlab&nHRv z-=zGlb$ZpGm;3#m*1lNq{WSMoulfVDFax^6fffaz_*eB^ulj4P8{UzrB$Me+E>k?n z^px~kGWRrxzfu>~Rq`+R&#K~A4y-yos5b%PRM}n>_DdkpgKu`?|RiAT-%YUDU<2FJw%^5vw}?8%mm};by3|M{>^s$ z!wx50Yju=!)sZ$peAtVDAjeIIdB{^0glptzX*&HJOFv63y4+K_KA=h2tRr3i;3Y2u z-IPyp2A~K1*-I>V0hRhq$8Z-W>g%^lCd8As=V+b2p=aXeoZpG}aaGX$^IwP*p#vhaZ28(^i)IGIdH;|DbkmUkd zEzQ`elwCt04-4cE2BJYb_YU42a^G=^jUh*Blb{YsLuJreo(4&MAa6|~9Mtht=G&ZZ z-)_l#J1hMyncFv0^A(xTS?SN2D$mJ$dr-!Erz(%md>h;C+rF7^L(<=pxrrg^#%`ba z{EDp*hg;Id^&Uou)aB`KHb$<@q#u?}Pv*XQtn|J*_sPuXEf}``DeD<@X7PmK7~UVy z0@pF#F#Zurr}<_~brqR~mIoVZ2;}4|OtQ~&S=u{xSMlA+%iDFJ(1zvl!TNx|Kj5)B zVn2?6sy?6PnaQWIoxu`3$DQu}OwQc-d30V~A%$BcOR^VdO=DvOOB0OkkvWAT3~n?3 z`lG}J!m3_DfxjMOrs-n)38hc|H?7+XJEEI?ey|iu{TC%_-*B~WxR?9kJm!X+SnsC8 zOwnaldb>IkfQ9oTxr8Hm`PSmCY?^{RoViq<%z}+uefw zMcy!mDyHp4P*3fxdGfyBLD0vL?ymlcJG#+R7|C}}#{I6a^; z#u=^otrSi3RAQlR>L7q=S=-GW{q8?;dGsiRU?wS?;5T?qt6kB? z*EQIK)NuMT0YB|zC@_EIwvDC(kaVqR+!z3nQ%8upkWO#VB}X8_-ibN3sj2_3?XBZ` z>(Mr#bk4Gu%K~xP2i3oyy_HjB!q}m;G)7;-Jg&D(tndAEWaL4kJQ36}4?#fKU5S27 zI+oO2h|ca&_B<7@@{r{i0zNdjisfA5NR_+)&;kJrdR%av_0+iH8a}!cUx-g2 z#Gxg99Y!>dXoquJ6tnQ%DLOL#oTWVHuH~6nyKi>3Si8N9W=63)1Bx+a606f`!5n)! z6Hwuu-^M96P}rMY2t8+1R=J1epVxnc$=2`2c=G1uW293}gCIBl?P~)5UQ}{H_PExP zF|-zeZ;GEM`;$N?%0*>plTac)eo@J|EP&3!oGST^p3c#CD#T^*jLKy#*=;@+l;IGx9F+m<6I`y*W)(Uas#Wml`$sgb<|fa-HmkLypt0h={jNh5jLi^ zF?ETgJ2_j{R7XP=@VV`S`1xi{RsVv*OMd|wpYC^DJWYs48Qa-G@a=Ygkfc4_f2@Z`kSNEKM{dD-G3_ch=!5OgUo7sh@~G2(+@@IhvD{+ zjNFKO#<6WOVBna@Wx5oVZ9zq-J|4zEPd1U26;Up9r`4sN*V+PIx;MT`Jz|S;~Q^*yvS;~K7h-}bIniTb0#e%Mn}i* z$n;^Fc8LXBKFT%cR&If%m?r{NwJ&}E)n|fNqE^Suf}rashYuo+QJ;U|MCBu@817&q;NX>=cxvH(e5&i_;N#FQOD>vMi~^?q5-fbI|r=z2dB&t+!E}^LPd=vkN}SP#5dl>lomX{1-Ikuw###fZieY#~ujR@F>SN?G z8Qi+FD=S8KQyvTFAbZ01jweSPQsGV0%%j3f$kMAI{Bdk~qSwZF`yxOlzDHM8YlfHUrm=eSa!=I{ z$~ci*VF`v@tu0)cnsknEdTaE{Ay03vdh0oGBWB{{Q%%kT6qC2q6@f7G4F9*maX~qv z0CHqwKEXFS-8xueZ4K5@GfSp5BIyQpNyAL*P(L_kanM%99KS6pIS=)DzUVSubb%u~ zXw+IVMQKdEn)J&bkF(qpkO*IE38*nYWH$YElx8QZ6c^FBo6MrtlDNLHUg5q}>dQN% z@TF2;;)%=Y9d{C83HM;SURY=5cse%e%}Ibf;ku#Tx`BOHqd6y{-c}0}6>o0r@|`1> zev2Hw$pv>Y%=v?nl_xBtS8wyk;&s(!bmKB2;Kw#qj$KrGK@Sr{?}Q2BQKU-KMU=)k zr~Ldya$CW(F~FD(z)h)nXj=c_ldZGvaX)kIr}J#E@3$c%m3B-eEB?nWbH-2Cb%)ZX zU8ltYJpg8OI?}(&?lp;I?=D_*{XfN6aL6+5^!a=@l3Pn%w{gAj7R~aKk&l;j<+Kwn zH5N-oYQo1m>_M;ihowI?hPPzxrBA!LPY|O75}R^^xuo1qpvR@fG2EFoKsndLD5rqk zw~=S0cz|?M294ip9P6IZ|HVm0<_WCNq<#s^59u$94=U_F*Nd2DF>GylK*NFSSsJu| zfI?SY>St43xA-6-i;^?K=ZO_f>80gqqiNe!{3F{amRwV$SOy5E{dkliSDZ z*KACWcFa|>vhuQ`_45SZ+M<`t^q?x9=m&eN%MM!U_|EBKot)$t3f>>y0gqQLd22=i zeI6_~z>Bu5Cu{2m6px*cCI+>$TjKxQ`X=|9KGHXpruf&W8`JtGcdYwj+hXo_UjlBF zSzrff-RgABYKPoQrYpFby7-%FqQ4(EJ>flT^ZVjW)#t(MoZ?5EB^t$`Ccf=mSD1%U z8?QnsFp6B~3{LnUn;E}*GeT$d2)^yWgz{_Y7q-`pC!hMTUbpj|3x--crE`E|EQC2< z`O0-ri3Ndo{`OerTVE*@rwJ@Dl!1=b+n~o`&q!*2Qznsl10a~j4ZjR~5Up@w*rQ*l z8n3)cOrWU}^5XyLN&{YJd;X zAJS_6-UD*%cWzl_yno{ciLp_WS>ns4Ou9XEEGx>3Nv)0W%Y}k`6-J; z%q$(lQ;DAPdC)I|gQOWW{DmLM*33*`B2?OTQ+NC5agnu?KWQ8GU~P@n$>>P;(jI61 z_>V16BO_<*LLZPkoav!6@JwwVW6AObfR0J04L;c+rYTY7pq{oeV?>#Bvi&{{M@ifI z%q8PZa~}3FG~|l0ZvKvPt%7v6_o<*td%3lbyYU^2wdm9FG2>7dyJ(+I2zW+ zK=Qc~qg~<4-W;b9-gef<0?0*V^vdXTZjk_Dj#CMbno3AsL1^rTXnmD^I&0-d`M-wa zAB#2|PEv3p2F9!I9CoK(Tt*F-#p2$TD2T1`gdVG>@H-_s@3OJcc~_3zVQWd#Wn)Q= z#fM;}DZ0da)K&V7(?gr1^-HCr6MZpl0Gqbe5kUtR+Zi~?nj+YF810ugZq4?p8}5gE zJjkJwoGm>L!Mt0v$QAb7O zRoEdg*f|6$cA~O0uRUqB&dffiwaDaP{-2zt2Ma*=>yCpUY;bwhl1@e?`MF2t^Y1M+cKkt$Xy@+Kev zY~1vJiT#FpJo?L!sx}Y7wUhZkPXmWO9HzHqr1pUj7`h_MKQjQM2Ee`~Fc+{hp9_KY z6`1lz*}b+)diUB%4)WG{A;{i>>>U(XXayeNz`nXC1O|6!`5zPGEc8r2`Vj}VsvFqz zfcYCPF|1Zcv|0eQG@S0OLe4qgdH`0gOyR3+uiMn4mYsO$H!jU3kV@$lGD4G)Z^Bn$ z4N>O7E^{*SP`6Lp*(d+C_fWI9vRu(&!F3w1qSKF*q;?*&Xwz_KHM%P@oi{h8AwXtX z%|uvlf^%fK;2N-GGK*eX4Oa9uax?`4b4#>g0SOgeNq)TLvs_Nh<&5Fl?15Pvww@Ks z%9=F%SIM#*j$l8by?n!p(Sw&&41SAqhq*KXlhp>ppvKzkRkzJkojb2$NUIcfd1AB9 z;3YaDKV9VZ94JoUB->C1RcnSP*&cKuPZb<^%aTe(qLR&V5=iNzSuA0w3mJ$NW|6&E z1jm4_(Wu;_FR|3`q;xsi`xE{1fqJfzM$yd7(0mcclBDjY^Nh${==+w`ZKv~3RP6Y` zE%USIx3ZtEle^qGG)^(~fwK_DTv<=2L&!HpbisglvY<{lAU}D&?rT(;xWt=XJ7@%2 zjmdt-2XBQ=eZZ=YCuh0Y2WB0R6sc)kup?40dHyP-Ri48_;m$^%Z68Dqs&Uc}F(3n&7T=Du#v@~e3Lo9)?RR|dUo&#dM6M_)vy zWaO~02r;&EeqA*)b{#=?eses5jNfvZ0j_=|B$8&_RRSpdI?nt!XM%zDcqjyl`pfe7 z2|!CSXMP;wKu^9u1d0wN{ttJRN*$g7&2gZ2JRJfxCG%PU%1W@`&v1S3cZR^3-9Z1E zDHU3Bfzjejmit|nmM|R{IkNoA$l^bEp|H6atys@tEPk$DlacJdg-|h~l>zLCw%Gda z0*CWie+dD?o6MgBM6iJZoQoakm0{!ATtRCgy#G^bOzkPdn^llnLiS;IRNrwqdL05J@4WoLlnzqFoU4(1 ziiS^|kRvC*qWaej{Ac}~fXNm@1i#&gEd`;Z z$CUI%kVM%e-Jzt_L6RE@JSFW*S$_6-t8Vf?LL|>qb>q*L*7t`JxM}AU{s{fDx2c~? zj7XZuGEDG7vk6Q1IS**)6}1ORKB4hWakl*MFO&ZMoWlSWSXhGa8Qo=({3%B^c@DfP zS}ID-8)v9L7v2nMl=>3p^nEo9N}(m8!L3SqBS?x_(hMcd50V_EYLxUykmTrju9E&k zlK+;gZsZGHDRm?(DNt&A)M)A>Q?Xt2s~siMZT#v)pQF?CDNfU;D4-7;&l1`{!LK6` z1}2-cx{xTlZCez&d8|=r%7-D8cT?xSggxUg5~pP-G(|~I1WArUW0f>FNOBZ9QAx=l z$x-MiCB03O|CFol&c&hX`l-6z&om1C>kTNR1G&1;=U_Mf#3g?vl0Qfzovz`nf6=W3 zd+R*gzrtl2g(?_DP~;7l^G-oQ6nf@ZoAyNs-3m&}h*OpkXPRZ{)9C@Iu0qYcwkQt{e}yVP>n3l$7sHxXaOYL}t*H7S;=abkK8rl(_ZiP^jx zj-4{kRa@jWsX3XJCQolq%uz}M$Mt8|{vI?HK?DX^WMjh!fh~yNp!}p&Xig3 z|5he6&6JspeD!Iln+Jh{f9UDzX3Uy~IqI|3(fSIF`w4fuL;pK|PpWt5o%)e)3#ZYr zxW`!{tjXfzO8hc6#@U5W0JdD@+Ws)9oy zQI+r1?3HGtG|O=2yJH!&o*-)9@8FUXpZve(5}Ao(AaS@?y`ECP8GiZhiU0f3DFiJ- z6`h#o)wLm}iBY+qby~nQzxqSKG`|Tm&4o7^(_EyVA7z?Dl*`)&)9lIzm}dA0W14f9 zYdrgLd*IIQ{F96fe-aE523 z6Zll9>QN*zdJ|MW2SpGpEJPc=htk~r_H91L@YF`p4^z762lCLgPdIc5Sqg6=z|{6` zk-BMLkg#9Yhl^BIi~z5DNtd4vD}7pvyYE4&5fz=|ue!xahytj0U*8|viTA0+CYCwm z6rUN^`F@`{LN@ZyI)WvdYZ(kF|A+LRZV_%QX2z4ze9?yeH315=pDou0Wz(h!i|GD` z>9EO<2OW0KBi4a$J*Io@vHG|2z(CWgA6tI>GX3Rc`=U8OqPJ#4{hw1pGIBt=sFjay zmA0Ki{)}eSGMMWVk)d>z6Co@e`aE@-@wS7YLj|#CX9%&YQIs-Z3qgGUR;MyvhkN~7 zIJYWQ7VvQw{l~Eln$JPousut!xoEL$|78USLSyD@#Xm=&Ta}QE^s%C#{^O!Gv`L%4=_h~nE5e^{lU>;b|37ud zKN)#OCDQ``&W8-UG3oakII2sH$#IQI=3Z}KXvd*eIW0u~@bAdn#B5SWnxv%NBA0Uh zOCTwouFptD_Sq8BR{MaJf8vRzMRpVR+N0pC;x72>cH(XLEAS8ZwsSsjrzAO1rn(sh z-Y{^ByS`q|91Q|4wX>LM?PCvGYbWw<%zBGHc>T}QkM%`U`pa+ZONd!dRRY(!>qms! zSKUfqIR6A+);%6-o*DhsCpcv+`&;YFRWa6X;G-IeyLlXj;g*0WrNQ7H?RofM0Q65r z^3&C{KVTS7c{srMP9DH`ynYPh>(gH@u`eNv&r(7%@``?haSdH9*?bi9$L(-iFwBYZz1$lGh5f;i&^yGroM_snwe5I) zc60Z0cxWpx_fjiKGrY+8dh{Y^S&HdEQl;1M7I6+pb$L)gHDh3N3vK&mztSGBcL zRlGq1X>wRAk6A7^xBh1d3qj91+0eh8%8O3Fhw3SlmS0R>?0x=;Y&cW)24w+Hpp8o7lZ z{ZZ?+_JOwSU|b?p>N)X(uAab`wt47ls(8H2|lC^Cz&xbV`;jF6zR>RJ-WeP_;IZJ;_zOJJq(``UCtu z>C_*tuSX4y+SKz$YaP+8*7tsCjr|*ovu!tTL!N^3tFaa?#`r^?Dk1%ZktQ=7FA~_8 z6Vwq?@DLAuN3mKfui|vh;&^=vXU{K)XKyG^5D4*E@ABj@MoGe+zS=H6bSq#}nXTsT zO<@>%=Ido4-@>AL+lpKOxq$^P%oe@%i4SEx%Vy7u;?I;PXAXHkdg$5Z2<(Q>SR~Ag zU$|n=7kgxtbBW)Ow**+i4RuP1)_)~M?)BQFu82$chuR1U-ecr`+l9CM^5P{50%0|i z8~hp$u^h&d%24~74#d>#ONUP)FBGRK2--^F_c?wKEG8#1Rz)(db!M-UA#rmoI%Bc8 zn?_F2QMlJXZoKYB=Lv4q3-%i3`OmU-Lgfq(hHj2+;%z*xnHb9FyCdA#XZs3!EwedQ z&-jq3Pdm06y%Fuv}I;N zopLhB75Z=RBtxkP8y$78KC-Scw!l1q!{|+2tH-^CNO|hKV1S6H57F(wz|S}I{68P$ zu?7Q|()NO1wE)!-oL`N=qMZ*Yh$s0U^yy6byK(JuUWo$vXo@Nwue@Dz1Fc3RJ&`uegPsxXyc-(A2SyyfuAU)o-?fU2Cl)IKkq={(>ZaQ z%`LE)}{~Ds-)X<`)w2OU$Oy zYK6jHpp(oUJSTZEqX@jB2Y=VmP9MYsASXb%Vap_B?OZn;GK6kK#k_0TdKFMNrO#v{ zE@UcX0!dpq@e>D9M@&V-FNN8D?_kDOBuOffjPPE0-Vj9xG*5u=O`X zLgd*`0^$w63v|#4aUsAT-}d+`xKpf>;$B0+1S`IwpfY%O)io4U=^cU^oO{-K-}nrEhlk@r6i+BOPq5n}{a=p;~RYv?v!PMS#lh3e>-Iy$BriV!Mo@Mxw9&>}rE zJefBsyqqq#?pO{mRMz2I(#&uLW35PfCHowdnD76YgtmqL=a4E@o0fpi^bkJz!iSlH z{_!Fsg6z2bo3D|(rVu)(+a=w^;J4U)Fh5Sv;0Upop0E--)o*Gi!t$2*hE2kf4D+vk zjawZztm1~)Fa0xq0H0(-0dcbJPF`lK!>4^=e1N=IzauaDr3HbPDA`SL_DThUW3m2; zIUm7r2ma2n-RHO>U4%hJz61r%|XKB`(om>QpHW{fj6ye^d?+}Us*`_TN6&Lt> z722326f;DS{HCekZhefYIcWvp|0AG6p&c;i-}yYObX*`=+Z;b`RQ7K6Jn==%SM?Zb z%!&x*Ub9BD6fZR{xrVjOv}3^k$GeoBL>9FbzC9{kf>xtDdza3ml6%Y_`dta0pb z>nt^Qi?TxQuH$GN%;Hd8$O?!u!9Vg3!!g4F1fc(|ckqS51Y6!ltqR#{DxFux1Dk>& zMm_)DgY$~YttBn>p$0=t?!Tjn{u+ICh?NvAsuR`K?&a?XN_QFEBj%}Ms2{_`nNq(` zGpsr)-4-|v@#|GU|68~^#+`eR<0;E8*Y)q0k>r1X*+vDCKZMY+ZrVi@2NT!!#ki^f zD+pt4-So9S0Oq=BTBU()xi(aqfhoV=lg6bQktM$zN~A8>wm*wp@`leVe%)q40ruLlmQJk37OmzU|bq?(x!-E~PI+_Kh2Xa@_rb)kCnAuR4mUjn}V50S?56oXGnA zirN90p~WsDocNYMDdxsb+^Elq2GAUC&OM6U3Z_ZhNB-3uc#^t2OyLgt%KohFjE~A8 zDprO`^+}ZX^^wA+7uYn{;KnU6oheJKX0VZH&#%>=s#^p*_ePy~l&*VQPyRocjbagh z_9SRcG_;`jxm#fm#-<#L?8sim%=UOCwU*}4Ha^eHy zeg8&NCa%|zZgU_nPEtE&H)TK`RzmAEB?KUUbs)1cAU8P>CFpNxGn1BMt~wkoam!eh zcKdukPxU|9GRN|K8&4kk8|6vtzKB_cr7ENPj+|2$xkH${2s6a9aT&_aPoE+$<&&oa zzReN|WaagvDT-YQ{|pJphT_kz3ZZB%*|k$kMmVr&x0ZZM6a9liE!nF}OI(Az$hE7q6nxET@Y!!x zBm2hPVn^<4EM9z7A8qnpzJ|xC|F+W_)jMntHm=7jypf~WFpL++mv6F{7Jq~yEn7DB zvVP=rQQ)CuR;K@vmIK266+95K+GYVGGn>^Hum34;z{ADMYbKb~)i-an2p~D6yjvaM z<7O5muY|rECLbM7JnNEgY*I1BTdE5Qxdnw@Y(>uolU*q|@|j9aWHXD3b+~5yA@C7G zd87U48)$%Fy>r`y-bArZ`Xh6`-*DLjjF9>V%9OAmZg_aJ=31-f7_#1@hGX%%=!`!o zdB~e?IgJDV+Brm=P4X>Uj*8cR+a4eMHVzqgUnc5O!*KDss|YpZtaco=35-dcrO;7M z_KU0r8FWecb2PO{R?<8}L#uVzewjkJf0Z-4$f3W`PE={DBAU$UlGou?haAT|3gdS_ z-w*!p(%86l4Y7OHJA>+9SI@m&yR$H;G=FEN=;%>Y>P5x~1U4#^)`M2Fn}rPdWB!-K z^C0G9uk6b81%W|BZK&FLZWtc-_YjyZ27Dik>V*b&g9CdYY@nDf6470BSgM|L40d)>+a~RB&Tq|IH z4~KiN+e3xyEZi?VL<|w=zb^d$5dfW8f`P(%mHrL54!0@s_RFHl2L$ZyyoI7fLw)@l z3;NB$|6P-ljDOE63=U|r^SN&UCFJC?@iL2tzW&D-f<>@97Vp1G2M`ug={RL$Z4WBd zb=5dDWyf1wJ9snSdPl6j1r`;Q)zdgpl z=63^oJOFdUQ5j(V2PzWe(R5DL#E48XRYP+`!%pbWEHxrFImPTWAu9d+xMv&S)qR!R zk5F@N;&<1F6BdJul_VnhEG)l^VmRqU+!+dI2AGsmQgDU6#^U8yl~uFPgN=e-KO#G8#G~t~AxK3Z7*v}w;9JKmZw1ci!gNt~cbf_g&Iq4w zwPh9s?qNkW&@kwibj(>A3pbKFp5Z!;sKcSGHx;5G7Wfx-v?1H+ z!klMmEvHXEHv4&gqc<;Tc&B!I{}>;a^!p3`$NUi1?ocGZU0KQv7`pS8Q+OgxjJOND zX__Nb%t6A|0lM~tTh1$+Se2sYPPus8z%e>g~>PJT(4vEmAP%@ z$P_tiA82c^hiIcTid%Kfz6bgHkDMBzKN^pWTnsbPcz6(>3d_#P6AHy|^;;$r30B`S zL9yfoX1HP~Xms2MbZUFi>BmLqz0DNkv4M_{Vj-Z~cSOQM&@omG!dE;ip+{}t?nNY3 zZ@nU0wgJuk()A&1!}e~n;s22KCh$>J=l_2|Mk6v#RH9KqqoM@YXkEZHD6K<9jXNqT zidL#N8L*2Uk5P2A=->m-)D(jxDENfm( z*y24HKlRYH{n8}2aM#OX-tCegq>&MT76!Dp%>~~K*EB0eK{#`uNp+C;esN`)@5qWq zL5%3v+a08EG+aXV8dxlQ3kl6De`we+sstkT%Rl1o*i+~vF1|CSKgC++Pq|n3CUsQe zdMYrDunKG7p3+CGWjwI6fwJ6<3+DbpDizl-%o{b=GCieCpYz#0<0~th5v#01Id|Vt zND zioxhNmrXIS3-eQp8aBwxQ&V%SuQAUCd1~obuTCJUW1Z3Tl=^1=cMCSJE-M@V>wigf zzFW|TzvBmGFS>|2y63M?XGh$)zwTo?wl~K{>43tF4sJo^$l-8x_)TgxweFld2fohy zlwYuWNB&{=?S^U^SL@kQYvvGDxBhjm-~DhKLhx|W2*Lkp@qeB8zpg+WJq+{(3}cZ- z>!QnSsOfT4iU4)5uzupOigw{eC)debi!EFLZ%?l8o0jDv|f$B=l176Y9voQJJZ!LZw4X zDlL&7vquy-27izCrlop@M{SZ-p!|_m{@UC0F?T1Z7ot1n(zLDKgxA=LFxA9q3fr1< z5-t=T2%Vs?Jhcoqum7I_XrH?-RBJEOU(v{y6SF_Dc;ok=md?iFjaA#x;r?{9rcY|B zNk!_b^^4T|-$^J{PD;TQ3uRery&y9b(}FcXX=8aAdE5z5Os;n8vPl z-IlbiTu0J%fQq>2B=+|(4PK2;jL4w1_Fzvuhaj@9sQJTg-M&gM<%pP{_}1`Ax_O>W z&JAjtw45yweddU;$U`kvi60HUrl*AUe2$0tz}?9ZDzyPzD+mF1hH}4xV7Ygtx{LHN z`*l0uu<%HA>2P)F@B-(C5hIjHdZ9Fn9F9nzRk*L$BV#sk%9|Tl66}yzWg8%H9R;RC z6!;+=-&SrI^}y68k-j7pBKR`?Ek>wdGFVSE1@F`dThoHBP4LMkS%GrszlSDLM@F)&G{ zn*f-qDC)~=J?P}$#z1ZCc^IH>D)kAzdF40bw}dn}5tVojEJ%MMzTt=w zRhjFdVouwgKl@Tv{xR2lGhKLKC+pkEo(-kzmlJ#luOe&KBW252{a2xA5_ z`VCjYs3qxapQX~9y_YIb-J@e}{$tW%-fWLHEh_I(n07XOA)0VspX#8MaxGG=Pl}U* z#F)o9b}~qwryrtVQ`_}9mcPth@{09p1--hnj9$4QN<<2QNzYk_I=1D1FbGY6vdUX=1`!ox=#7eDTF{E}TOP_n1dHcrRGO#I`(_3Ecv4fl@un+8zpt zn-uK+S`SkLp#Di7k)063MtxB^dT@K`tqZE9sJkTy8a%s-S+!hCXaYOwlTFl_CH^oD zx%y3Htt03SdK`%(r$=-vG@x)JW5N#rePqJCwT5?mz~bL63f!#B)#5TC#i3)=edQ{wbN_lKiQu zyLx)pNq>j)w?U$Y1|Wk2^aD$uA&L{3cxLi3LJQk70=;acluqYUg?sv0PfxzX9}pHJ zuSA}(?{JBpYK+is{SE!R&_J42$F%s;{GEu!gL6#q|DhiVepbX*VP++HaZOC=Q;Gzi zDny^wMH37;YL$;h!-dPMn))B5E(Nj{z=dL^X@=HqLrvML{W2990BQ4fQOZ(rcjOZwI zC-|2Kl^>`-v%@*>uwif3dchj$dhS!Gw0_Q>Sj%^ggBwirL1i_w)1c5n?p4;c7X!yrgGDXfCT!3wA;Z9o^fKM9)0f!K!MVyRx|(Ly%x91_ z(>P;|_vTF0y*c;{@ESm-pRj}ep)Pu;MW6MNGOL5UfY#A`t)g7|lJ`aMW0F5Q*=4!j z=**ECk;;>7pXYs%Ud+Uq4}!=fFPYHGKu7cZw=mmS!H@OXMkBEX&&4RW2p1M-x8BYJ zMH|bQcbdoE{$5{ ziTCL;S-Va**kqGCoa%ALt|hk!ajqB6FqMAjOX1utKQoPo7(~p$Fa3u=k3sn8zj{?v z3npu!bXrOD?MPv2Sb{EDL`7O9!zhU@qI;mBD`vP0h;qN@te%c%sdrLeR1C^LDvPF@ z$gZjBUoKVCg`~1aO#uIT;ZMu;2V@GIvX+KW+3=9kMbtx*$53ykIzX$j1}sPq(?<${ zaDb9cjEGMquwbFgZMCH|ON5(#OXM##H4vdn)_W8s57o?J`fNGnp=Z#jfEAU;CW$>7 zr1k);oUZ=7iEba%rVEZlI882UW~CS6OQ*P*TX;J}C($irNKC$3e1bH(r_TMU1KWMT z@6i{-*Qzg$0@s*6L#=;upQ-gv^^*w;c3SUD+7h3(R6hkQ3qTKGZmDtcwWyNo3M49_ z&xEe^-Q&x=x1_#1(ALy9)2Gc^bA1Q<`cD48)%VHYef#uNKwUv=wa=$5)lb*N~;LSLV~Yt+~E0EhgeN z_`lWn?B9%@&*`T?&yQ@vDsi7ryI((D>B+(`@yiXIu)kJ*8PJJ8vx!W6|I{9m$tyOq za*k0sZPIsj(ih%2Dhgk0`5q?+w{9#y3T>2@7l-iFXt0i=u`xdphrRCh{*fuLDr~x> z&e`=zfy^EOU-hX=a=C4*5*IAgsqhz*<50JK)w_0kko%R4pvB~>bEM@xzXxXnQhQ_}|OrFq_Zc4te|>LvhF&3*JS+qdPzN(^}K zP1qfENUC`~`?%NNKjP!Vy^ptHVlZjO&aEAn?VUMx#?Ik_EyHN)`9`!f^ESC2;uVkA zF)$j){6ApsV~^7K_(IFxN9xVjeChDQjx8r6 zHKZtVN6irdRgrwuRPPOX6K@|OH*$x+n>_wO+jPZbNaB#hW^wm4o7_VmkZzMDH-aUZ z`L|sHL~JI33dgF#(PHk=1^sok%<9yP=4R;Dl zCIM;*yJYtqs!=Veez(FM-Iy#%I$x& zYUrSqspi8xz^avAfdR^fHQkY@B}H&#Cu(wR4XTOtO2cb{M92O5YTEOp8hn{8 zIXSFGTuvW(XIKI<8UYy_j&C%cS;gk}{Hy8Ao{(I}0%|k7hOE{3dqv-YhFmsz>v;4d z;ugk&O?{#}<%SMS(_e0*z{ZyoEw8`C{7RjFz{s55jC?fT`qB6+ob!y%jnZwl zS9?a|FeaS}+6P8s@K0M`6K}kh9+o}!wSn3hS${Y^-*T>4h#1sF#h{woSBTSBh|^cN zQ7nN~94bg|exHOV)oN#dW!kys0p2eH-p6ut+gwKZ@ap*2>R?#a^s8>L=@jmPn9KsU zNw3ufl`s5V*0IkQSVtY#_eDAgTi^7Qh!PtE|N9zv zf@=5q$r|^I-C)96fl#+an-uY&m+7-(Ibx{tcq*pSYGnK^$&>zs1kZ5P?(^x)s@$=r z&&>-UR!I5f?ntmu(Uck$m~X=`e|TDw9t>56I0AYwE^=30EBL4<=>y9*43z3~Z;CD8 zt&uboBJ8!vIPuna?dY|;K@}9IBwk_dy;<41wu0;+s))b7hQD+?Tmd>~N2*}5i(md3 z=fM*DJ)x_Ab?q%NBZB3?{(C>|D^S9}`fvGPof*r|_yqgIKoIGA(C1&9e`fYy`_~~P zi>6smxr_1Uv2tx*uN}23DQLBfW+fu?Xscggy6tWuw*|yz)9-;Hf=m9IB3NP;UE_J zi!01$gw3d*wOgF8R@6D08i=fYDO~QiFj@2W#om&3z z*Bu>-@&8585M-=AkChLbu3ZU6{4WkSg-PjW9c{lw=6wf zg}CrhCgm@us!KxRkmXpR{Oj@{dCJ{li<2tAk%Kl4uE1x`)l1L~6}9!;tCW=t`TtP% z6VrvJ*uboes^+QIi}#W4F$N{7tFctMYy_~9$W1b(3J6o-T# zAf6;a+p4AWb$*en!cl}atB#9__IgSh$}JxF%aJi)ran2pl63%XV}Lmgi^^PodemL$ zp%)w;gSMjY67>5@6_&YO1iXC<K%2s5%?2ke z5N$0dV=(ItUgd4gXPO|eHB)-qn>S#W2v+Y~;qM2T<${IIvxspPtpjF4I^DjEjUFcY z2k%$eb1=igisGZuXNi8)eD%wF+fm<)~f$qz>xjzEkw zEpsLLIoq)Z7eJ<3v^CZanP=L%$AVvN(=FJm!pgd|n#0{&e^OoThg9=}mi_h))p9A? zH`V%xPcaP~?Dd9Hf=eU)i=mYMW$o-&;oegQ>Oux#8eW1;tM-@phS0-%aW;Uv&q!!= zucJYXqjrVCqq#)aMlvJGcA-R_r9sr9`o4sPj^c!piXlPnEYk~dHGbsUK(+O+RO9zs z8|d3G*@8oQK)$7aF(QHaBtigCioJzp>C9o(g%+F!PY5;i9gc#Y>NVg`wQee>ZyEHd zqF4Jw@Maj)u@!u+a&1l6tAdANEtElpvYHISV$!2Q@-VPak(aA~+Yhc5v4Z4YhTBP1 zN;%Z0_zp~Nsg#1}pK9%;RJ?yq3`Wv58V*hZUt4^`cBVex;7haQr;%cj_=KH+86^IF zyGns0Wmf#KNIl?>YETqqe1DF{+(wJ6GD4{G&z51R0x74)z#3j1e~8LKBTugtCOkvX z={EGwCLUVih2J$yh8CQ1e^yKx5Kk*}BOozrCmJirtbdx573*c>^U0K)oC(<@cZNE- zbx}U6jsOC+Z4iSB5Soc7j$^ioz8lGNuSdF?E-6=4uB;S*(-dGt8HNlBvjFwl^oT#z zbGea%VyjwwVVAnbU5y|sWW(6`KN15uAco&{g#u!dB^hU}Z#s9C!OF8R9iS$U?wTR@ zo&;`dTtDhAtB+C96#wzW+#E3u=pWubFY54o3z&&{%iVug|Hye4_b1g8F%=EEE{nv&)%B9q%<*MAMWZi#c#`aBNVgoFDMkf;w%( zQf$}ncQJifRhYW6igB*^Jcc|tSNutg3vc{$M_=NH7knDVkB7b>Js%Eb&=G?vPD7Q< zVCFLihmPK0ogxCMNX%&d;Udo*zJnqLt9Dr|3G}=zt`aRG{M1GySS8ASJUju|rE%Fa zu$w|KIuEejJlNd_$B2#0v;HjvgMk1m_h6rN0Xq^fcZEl3?(wlgkj*mp1(pWRcyuCy zsDX=-yc4~@_4KA5ZKiDx_yF^q2$&xAZ;pP6@f>7@R}@TpM?*AGR2{!l9YL74-L`0mx_0D?yLAG5@hLnKiQ=00;~Y>z9!H8l z82jrF<&6%e%YQ?<`iTiN#nZfMaO(0+fZlzXwxNZaxzZYHwLA?u+%X>0n}^0Qg>&Iw z^CO1H4J%P>7xLZRt6ZuvrUB|=8h|0->^iD92iSdXW2?lKapeUGxSt}dqfT|WIo@=g z-UY0~Ou0G6fX(t?t#vVst@oFQV6|4-IUekYgJNLT|MvstJ|Ty@<9T?#M?c-O)?@mx ze%on#hIZd`YwrKRPjc{Q0oc!?Qzy zJMj3QI{aGDZ1N$}C6FBpnQ7QTfun61U~CH8T5H!~i=)I~I5IeLzH8aHTbV_4{zEpS z(;mm-S7#G1M(^A5o}VMsXs{wl1jK*eCem!T{xdDh7`kW#x*+k^AF9d-VACP@tqaFW zDAK_pwL#-tnjyMr6p;HA1?RY2Thegw0Wp$@;oT1Okvm{!bKUdr>d-O#w9b~_H<1<<{hid*?Ig=3>sj3vd|z?0PNko7D={?K{+}Zu6LdwWk3r#jPA=fNDm!g{94zp@UD{gVv@o zxHZk%ES7mSH%Xs&e#02$gRwBmT-sJbzX{`hj$NQxxjzY?-9dH}2%GU%P)+uzZqsM# zp+$@9szR7W9;VoF80D?5l`z8uXVv>ba(RBKJ5jhqM_iQRa|HO{`bO?|3Huf*?}#er zM03A_&Aa3X+TX5GeMsv+k3w0z?>_q-Uha(r;oza9zSPtKUHC`bSO+JjT5SGI9jX?1 zZOC8(v!h`6c;vK*p0Stm+-AKnUCs$YAy)>2Q}BLTl{)CPi!Rm{pb`#yIo*xfH66n^ z=*7v$g#!X=_0%z8~Nk!ee@&mkT4p|9F^iS^Q^Xa)q;i4i%OXxXazfyj3S3)JarG1~y z3ifHttTS0F$hjL#>G{7Gi?*kqFW=&c*+f&9^3PKFx2X1F`R|_hU(5e(DgH8A)!4XQ z+|%e-8nS3mtRYxT?q|Z`aQl>2G}{9|vu_L-url|8fO`Ur6dWULnmY62KV&dU^x2oG z3i|3dsa;WKEUGU{T`@|3D;9p48a|iLERNEmp41gX^!J2ie0nA|ttT%^Z0L1KPky;z zSbHI5%{9ko57l}=*KVlU}qHP5TX{nx-1DLDTkF~Q0*(a_ZcgmX`Xa9 zm7nHv_)BD-GHv;<+%L2@Hk;UQ?--LAN6H0vw=1J_H0n1S{=yx7 zc;~~Ue${@J!#gqvD>Rr`;m&7$tY5qk9#!2wca)$R-wokNr}UiX!umA{{oT8^vMjsj z)#;_I&wn93;0rdLoH=eZ%RS(PK7G>79X&5hrL%`XQ+8I(o$|Qudk5sA1NnHPI5V5Z z4_JkL{{s8I7}g95sd|Bv+l zjMb)|{w@7xs+jgRPya=e_Y(b^-+`QchYz26dUCUZ1n_hD)^7y7t6~83fANIPTtN zk162rePU7uPnY|i|KUmR{()CeEJ}+gr$3Gl(A?HNV-LkNII2!zIc;zH%u2aVu~Nn2 zSn`8LZnDrR5JBbhmOi^YOh3-jr|VTc20JpUWIy=F3{V*%*}6Bk>0PST8bKgE~WBt!>4_AsHAIiY`S}xgBRTV+gj-NJNIVj~+aNJW+#kKK6fQwx^XUCKz0=vnIlY&0 z9f9aCY_pZs{AhJc;uYl(SNvw~kGgzoALb{g;59vz7;9)WOyKcs|9CF&pFd#v9X}mQ zg2bOmAr_(#h&8V4Muqp=^<0+!HVW<)uz*}=n7>K$^|4A3VQQ_mH~IUVA54$r|31?l z_nLTHJk_kt`q@N}t70;_y+Aj1HVVil9y>9XWK%HTeH13WepD>UVvlb`Nq77vmSmf2 z+QOvd+*d^w{3-gn+&yzHHz%?3remi2*Q=edN}L)i#3r96`9h+VMs9|3-z=dktoXT@ zPvU{P+}V70TbzNA-HwZG8lhw|gfAufq4WJgA>kp<6ZZ)bp_?BoW+;g8{2UC$0g!!pP0z~ z3ZKRO=}Z1h0wh0=`sN%P>l&L;efNWqE2<-`WNzKZzomz?pu)`@Nl$3nJW|g5qTH|z zV?Z0_runnG|L)6mSD)%fmEMF#Sqg+pn|{1O!d+sYii%4bX_lf>9rKEFo2FkF4bSGg z54gaHZe2z>a7?+vO&c80y#g6+-JYU@#1Ab#-hx*>OHq7v#b?S3I3waFebY0_Z>d1D z*R6!kQjYgo4NZC#Kw4%P=iqW-glrq|^-Fj`#Lp8%9f^9^D6)Qfle}hq#sz4q;JI*+ zlAjsO4i67L(lJVFx>^-lo*mKhSEqPddMjz7;wuzK4;?LeA;y$%Eeg?|(Z}3Dbe(w* z#J33RvlbJT zquJ>ULOBU*rCK~C-4hTte?!zb&(9Oppt0iTvHuHZtcMxzG*+=yUb9@1ZWsT2tp3kd zE`C$$fR#5#AK=v*(d_9f1Vq?3JS--dZn>7O*6qVt+cOg+ueXd^1fn^VG2-URT`w0m zpID*t_m=2n`i=uEsH{{%)+Z?X&%`A{z;7_q>I!DRqbh^@tfK53dm}hG+%E%PGKGV8 zk0**g)2H|TDmY+X6Pl(&Tk(5+l{+M2B2x*koE0`D$AyR;tOB3<+h`RyOJT!R;7E&K z1)gK2usQ_~SKcfo)Jc}`CPon2&s-w}gUVx6-Li)5(wSzD>NOt6<;pcu^B#4&Z|FE7 zLhj+l()2R?Z`fF=6sRb4pO|UiDZrtkWh)Ob6{pEEt=(O(6o#t+fk|#;Fld+I zv7YnYONXpB>Q48#hGaVlK^p;{oUPdWqNR^tx>Dr8^_#SmtsaT<8ts6CRO^*WZXdE# zz6sRv95HCI?njz!bp*ev#<^)YRFtd#nF~tStUEIQ=+|fki<6t5nkW~cBfja0v!gg) z>TMJ9l~0@EFIge|HH&{$HQcHeLH@MS-kt1$v&jpu@{8=<`X?1YLvm;d2JuUJZMNsW zwXofCvE8Y#oo_Nb4}t>@n-Z~I?=Ny3_#Zk3TCO@W!YS9xci1jw}_@Au@Cv;`Hm+*MRQIJMV*PbR=qsdan*+zI&2!mVw z3H&W#wp3F7>^4Mgc(L6gt*gvPutY^EOZ|&q*?X6Nsk4+O|H5=BU?=iYG^4>RGgQ(D z+Z$BpV*+)WpM(xYHOnh1t-cPf_dWA~G25WGQmvEGCz_h&&NbUiqpc6Yqk_`R2Xh`n z2dw0S$TKXsLfM8cU3oa0HLv^-UOJp{y~Mpv`&OEt>(BCpkBi=$5aeM`ZdJW zN>LSC?&?ohA4KG}7FyH5Tzfjw`Dce^Ue33>s`=vYVI^vz_geC*=`cG5&=xDjdf%Nn z&txQf!1pX}(^@`vIlGc2A;Wd3MDi0p2bEV&k{TXv`nkpQbGjl(OysNlj$`zN9I#d5 zaTSwI+-s#_m%bk8OQUB>bV?{e+50?OYW6pK2?w*hJ!J|3*+_JPL~pCP&r(#z5e1rL zdN5P)|DrxHkQ38QPl=QLrk{w)rf`>^hPU|_PG-4kl;lt2Quu1CA4^z94#I^Up%Y^I!HpcSv1X zgopTUofC70SoU7#+M}eBdl@vSbN56^ zH^+~Zs#emhDCx{DNfV-^E8<66?VwyIM@buY$yH}bF=s{o3Z9Mb8RmzPL+orXm=s5= z^nA=U>?itb{7`CZ(Q6FiSQd2Kv3N%ReLqooe0`ra`+A>$)SB|2(8XW;MYD)4PmqC5 zjVM45JUlquJ(iTO)5Evx8{B6{F{&L%o$=!CLxr0EgGt1x>zl*!! z?wQ6);P1u)a5Sr6+?(5bF)c#v#QKbouv(H*H=MQ}I=+hY!~aV5+H=b$t2x-6SX# znuzS(g0DUsXr$)KnfxA51_>r7=IAE_|155RB0%Gh&27*n6=$4F5AeJlk=UboUXM&c z;vb;QM@Eu~L$?tki9G~Y7_ahu8-1Wi9{U*xg}Qr&!-UKE)Rc*Jl^L81Y_f=|`{mAt z$=vQo(r4N|>NSJ^+o}I-$6rZ2s-*v_MTvo;g!_tss@erFPoGN@jMrg4^UN#U`)_KD zlej(}D$B z{=R|D+bjk~H*o$frMY*760p?<`->2NnzSbT`+5AI*(+9*;eT?7m@g&i@t@W=24?v0 zS%UxZ9x=CH49xJi{001X^I+Y(;Qt}*ciR~L(Oj}S<8Zo@kz+}BcGmaTsAo#fBMK6O z(X&DFApW8-dUN|?>7ALhL81E#P0X-PK#T`jfp{`*(#G!FpZzR z-X>M-Xu~V?NDx*75}6G*O-mgg@b4PfT%@Itbml;B*z_b9&vsF9pcpO;1%ReXM;lgD z>y3vhJ-Ag&vE(L08}~LbvE05TEZC_(f2~%R#9wLNonyFDn(<175~&<@PmkQnxV1#t zpmvGSf^Tr0EH}r}+b@gQwD50r5B4VuFM8kXMfy<+kk$opHS%)gP^DWjT;1o#rs!~= zfwoD1*G)&YyB*NrL89&%h0-~jE3vPCvNN1L8a_~5*aQP&;oi+P9w{G-0B%4eB>!-+ znZat4jBZ0>l3_C!^PV?9BBF=TMANGKmUC)v?nM#&e6|ecxO%QA^Ck42FacVlG0iiy zKZ*Spg{<|90pgld##ABur}1~t!pTFLS5;5mZ%#EN3zFLb*wMz<9jKG@q7&VtoR2Vr z30A$#i^d>Tz>!t+Sv2x;W?_B-zjNHnY4ExLaW2(A6E5q5&piu6d~T}|KF^&id|u!$ zH6JE?4mNzKt2{_v1+d4aa=hgu%(+vDO~+gaR6d{$5xZGO^;e7LA!-Zr{{pT1-9bW2 z2Y(kWUJ1QYQ;+rh2?I&5;!@X?uwXS3ySm*=tox!ri;=}&oP>@dl-TK3nCHcDO{=<* zl4|}@FWJ5mmXasfbFmh7Ru2mfMR852IXr08B-^k-3mVp8X^t7pbgV}@m?inRx~lno1dEFPAzH$5KC zg>Ss7&UDiP6E+-4_ox^F{B4Y6rg%6vYDjxx zE6@VLDUZ-5=v=uW@6&p^htaXD59!C!x~)-OPLAV)T*WG><7n-<=2okWNsmX#*OKg} zkT3esZ152axgNs*$P(5u{H@5KQPu*oRg{i@Q&XLYUD6&t!k*SAfY4IQ1#(j7>-1`GJ5~e52ItGEdKNP6;x)x5=(t*{& zqIqSHhE(u~(waNErCMwWKSA!6n}v?DyS7P1|FR0V^RlzOHbNd(_PlH#`CTJ}>s10Z zjUM#Y_+3KB$(=pi>z)ef9#gW?70Nbgkts9abvrScFdU zuC>&#e9WH^aswAM=0O(6L3bh!leQ#=lX_^jzP7xcYW)LTX$`oEg%o5chdoo%-r*~= z_o zQnD(j^OzmFA{X(Biz`D|1v_k#Q#t!)rQI7?;_q>*AFedV{t$?)z;T~Dx#P9 zC+MtRt`C{=%d*pd)R>Fw4ZG)GE|&POPpxee<9jMOA({1eZ4xN=ul>RDq!K5p6TUOL z;+st@Jj35?WRW-kSYO2UF>)4}8@1=&P-h`-zV zoz7^t+p!T80@iIK<5*X+2U!i!zfMS^fy?#T{c8v~zUM~o2acmWj-Bx1j$GkaFO!Rc z=1-Aq^kv9+hnH^-h}ZUY{nU5m!d`n-#Eq^-+)QQhxKV2Z=@el9glTlRbHq9Jn@7 zgKtE3uUcVkyp1GHw8~k~?iIB8sJ=a|s^ymrjhgsZQW*nYIA2ZNbAB+PSMyKnq*^Qv z)ZVtMrB?nh0jAW*garUg(;PxLs&Cr}(Q5gmhow|dU98Fu5;yXZDAv~63u$q>G*+1v znII^Lau+;lwkw-ht?cL}H*|BfQ8w{$^gc-M$jdbPDJy+0$>(ELP+h2MjrGp_q_BL zBId4OPC#6PO$51TXYiIy9;YxE=)gwf`&Cg=L+cfPGE{g=&^-nx`mRHII zyJ=GmBy;PaATAH@g|ge1wW|5s9MXiFLo@T&0Cwq_F-LHFfi*v7 zY>W$|Tq0w+>mVS_C2#w|0PTs-9`YoGh@bOlBL253Z@8;+e}dmKZMm^xyYjtZsu#Vh zhcc}YbCioY%8SgwNidk2U1=^|hAi?ztdz>DMO6tW2>}*n0C(lttzzj6AIf?00b@Kg z&IfnBge*3R5CBE{po_Lyq90yK^DhkY)53pLN0Dg4n* zBYnq9-gp~KY~}&!QA$iPzvtWNkH;VsYpf==KVnp&G%QMcqZ0Hlzqq|gMd_boVv8lz z>7Zwatv0F1U%McY2Cr`JwDKr>w(=0F%biI3;Ews*#kj-fSBnFwyt+`06MO?Z51u4HuQHdfKcM!}msj`pvIO_ZIkxlsx_2xo`U3AB=Y4@u zk)hnt`vOBBr-aZKsEK@m9;5{i2$$xcx}{pbk@k~ouzN?*FG#gE>vPQPPxe(zx(Vu; z-Bv)A^H@Mvg#8Y70-sUI<3m*Tj!=1-6dLoSqySV}x(8RQZmoK|MM+rdQOWAC^k-nP z_wQG;QIoH4q;CC&{(&?juz-JnAo>T;zapRs^u2m?;Mx{iws3&ST9#>}973C)O&n;% z4(+ijarZF&lE0R^b{-Vtd2Pyd7clpY6W;SiQ;gZfU*eOLG>-E-4T8+yhKLsJ{IQ$H z?fmg$Lp%Q*fM)0C@}PgYKO#-c>AZBb=5!kR1qb(G{_J2@Qo!;=A4JvB(gd>eyLb3S z2TB{qaXunRjZyKRtY!o9K!enFG!LG?k4`5SYP!P>Mr9FumbNW$SCIGxh{*5UNlgfd zAMO5n?$_vUcew}0|5plKrBp;pW6ueLe18nj-Gc7`0e%}_=&-G5^NW8P^&aOOk=!fa z7c@pu=50OAp8@S+BEkbDOevTyXzA8TzPwvIlF7m`y4=K?gsgzbjK6ziU2{r&bsWiT z8OxkXL!~ZS0h$Z1UJI!_~Wo?dnNwo((!a zn7?RUGWF5B##3XC(lltQoUC$hl>;4hBHZ7Hm1UFYXd~M@GW593r_Ef3J4Wm_|-%z-pzSy{% zj#lGvEi&a6HZPX&V4;Mblpt{n$teE*Lm}}VBu5D-d35w!CwoMzawkfnw%!G%;Go19 zQ_%T1tWRE^XYRrY_}v=aLs#_JDqaHscg6Br?;vc)OMjO z@{JuJc35cajfPc5o2rnkx_*QMY@T;I43c%mV|N0_bHOn}j^7geQd0>)NPg?og#*=v z+)y2Q#Dyrr`cip9Ocb$OSt}sGs6oCj!oK8QjPY7|HcXt5+~E=#7jY4N!cI^9)O5OD zO*5LhR89_Yx(+w=9s6ys8x8j4R&qVbX(YW-Ujm>q>52Z=_P8u)RQ#Ekp2C3L+8Z0` z8k$QlqrD&Do1K&9Rrqb;I-+V_PcZ?`Wbt9GG)kp-P;yA&wkh>QOT2D2*`+5W*KC>6 zD@T$+FaBex+%G(oLal=Oy@%3kP`R0ztr2e{jN>RxYWFDlXM5G zE@sZPyfFEcmpMR6r^Iom9ymembk+m{3W6bo3dIB1?Mz(MVa;~SVzhQ+u`P2n8If+e zqNrQ$FG=w`R|<;f+S0_0jf!4JKp5$W3riuENg-^AB<1dkD}+w`6~-59#9!6ouWA5d zVL5RW9Xec9RJhbvFxFqM3W;#K$g*}Kgna5QVW!7}(d*8R8zvLX%G=~GRYXDWo<=mO zQ+yHTr+td?fn3GzS{aZ+3w(1J41$X_{sgI~*4scO^$@Y`me)CO4Bs}p*NcK^Z% ze)>p*OFSA5=}YW05%$kk*7DP_L}TJqSnMCeVjJ$Fj*UE2PeCm;sC-lCH{;I; zrDoPm5bf56UDe}KYz{Tgz&g*K5Vo6s?GHN3FEyfwDK6`XMMHUc(t7whz@{G1c-< z;N(8m@M{mX(ZfJ{2$JjHWSV&VIMW^~69JGOX`VY$stDzh`0)%W9TSwqbqbO344?5w z3zYP|%Nq27bkN^!^j?!d;7wWHQAEf^3pA0gQqLy#<{}GgrxfAl;NHir^4f}w^A ze_*mjE#8v&oNo2@FqzJ4Fs<839;SGDR;x?aHa_>8Or=z8OI^52M(-PtJM~aTN)HmY zzRNEinYmq!!D2QhLMH)=+d+&e3qVIG|Tg zgv0-A;^p;XJ;4y6%q_UfdLo<1uOCYy@KfgQj*==jjV0Njex@b46Z_FYXNDbAqK-m) zQV9Nal?P3+ArJ6Oq|YF4`JX*Exeg9xP-`^oO|={@Sa^%JB|p7QATlycs&PHzEc1La zmH*~@Q27df6_tKLP}#~k2F#e}cVUOhu%}v{rFl%;MZJG3ueeZ>HwtaIRKc!+#MSnk zZXhM1hzjt43E$ta!hfvnNHuDN1Q2y@aDi%pGf3`B&2%;sWg&pJ#>1ajOEt@DcVfIl@YoUN zC2&iS{NhjIhmZK%ZK=NA$5-*Kdr)A-ciddqrY z@)FxPKS*rNQ&71%E$nz^&=PJ`2@)^e0*@Oqt2VSAgHgya=5(W*1_fT~H z{gOWI<}}_fqHW!j8zt_Hy51%3^1O*uaZo6cuVR{Ki)%}YaR1yI7VI)#JK^xo?g||K ztXhF#7U27p@jfItL7Ub2j|J7CKOUpnwe<)5ir<(q z`pca*lRBtv{O{61leZFc8^jpWjPBTa@J|^sB1+M3Ln6A^iif!v$n9ZHUd$}#<4eU% zukUtiXbo=LA=Z2gF7~!0_huiOSOWrUX&(dpwY4uu*5eSO6k8q=5dK2J7>@7jEq7U@ z_5X^0SJ3*ubNvsGh;D67o?z}DJaWVj;qg8NJ-LD;(*qyzAU&`(z1iR3>9Dtcgb)M1 zRfoq2F*i!S>Zcz&@-L8K&Q7uR>pVHv`%fWhy7iAGnblc!i&>p{TS6Kg3mlQgemlwI z#s5_v#RRZ_+O&{{s(#w{&q#x~lu>wL*??aQ11aOPOtSX1a?rmpDjOdiRZD=o@8CL| z`0N8VE`B}L`VTAna=iwX+bb>L?y>Ax-BmxC8(+{1LpjCd#T&2znfHMj^i0DEx)XhW zBEO5qZ;tAiC~t^mWYd`>;#A*BS^0EwSs=d?Jd$-BOykw>$=cDV`UG{eqLKv~r-zPS0~& zZ$THGQ_@An{$VH)-Ul^veK1+`J@zHqQ=tqh3a5W&^lO9)LFGBu!{w+__ih+>nV5eC z(>p7gU)Yk;Qx8>MvOnV}jz{KktUab$7nZBHVe322@uaXF3l(x6TXhjYkoe1WGR>*h zByVmo3-H5L&@?%*FKGsP%6bAF#VhxrQ8b6&>9VR(7LRK&EaldY4U)egl^)z!vDN8S zOcB^%dA7n)+2ohAWz@kY$K@PB;+nAPkzufEEOD6W)+Rie!}u5^%LT&Qr-ZoNxS?u; zA7+lVO+1e&@}&Z2pQQ>Cv#bK7GEGQQJ#X|3mw0mWW`D@D%>rAZSjKdo^m1S2K{0I5 zv51Oh96^cx?%-P1Q(UkgJUr;t%l3*U&YJtH#%y2tUbZ@4)8L~Ock!$7m1%#UY0_f$ z0`Vw6-PUu22H5ptqBwM?Q!O*;U=UyaKcTzx!gr{XbJUv9sihwZbZq%dvMxeH%-bys zZP)!QYU^0}z=xQG4EmM#JNx7J?pUCMZ+N$8<@;<3py7BmC1X(_k=7a?TsNON3`%Jp#V^%~P@!9XkLTELK3+qi^5sx~%Q5bOT2J}aYS zwyL^YkCGtMq1ogM+^1uq2W?@cn(q1k;cJ_|s(r79 zr;+IlT(AtbwdlCL_4}o=D~b@P&uHptMdXjz__YTZF zd~>}esU44=VT%y(Gl^sF$@%4@io=R6RUvGSiq^sN93|U#Kit3Ex$2v2V#@DB#+vXA z6x@i6MsO%N8v34YsgR)xwo^f)MZrYwU}aX#D-J0#lC|FisuLp}NhxBa+(Du9GBIbD zt-UxUY}}{um5bY`-BrGE%$mg)jhn~t<8@KH3*qK-M*2=-I66dY(vo*w8}h|S_(FK6 zbz89P&RV-An;37IXw*(&rir;LS;}ecoOn|~CbdRN0x>LX%vj80HHyp(XV7RmExMW* z5_RU8BbI{xLy7hFHlD%AMC$Rs;8%d7$U?)n84KswDo*HLPX|XL)#C5fO!FyPzTR>X zjO$ew@vv1rQrRu|;C|YlW!pXa1xSPhVB-VB(a$2DMOaX3U{e+~?)qc4U)DXp~MpXJSV_aF26*LZuf zoN`F5i>Alhc&F!XmSYt3Ad-){EfR-D6K(+S)!kD!&!5f>L~gI&_)b@(qv1DHGLUUX z{NwcD&B4N*m27n}Y{I+$RA%z_wC zHWzjc6EnipwBv9uiBn08>#Gjg8en|9wUfSDru}~pC4yfR^%ZbG-=tz;1+KgMyii{q zJS$WlgSdz%-dP3EB_m>zSx^6_EDIWC!Ixe#>wP=^q@lupLnTa~KBM0);+9UD)vaTv zs=z8R#Kyi$1Mec`s;u~!=rGK!=;rQcRet{8?uvIjVG*Jb{&^gBH;Scuxg&Tgaj!ea zcPuJhG9?fsE|B!#G-*v!(SK9C(l2REXHYXQu^=xBn;qvqJX?KZ8_X2+c>5|yOFMLz zMKw(wgO91$zA?fTzl|6Hi0--qh~g4Rp@1zs9|HgEEA#)fZ&$pWpKaeCMCy|Em9(fh zqB^eAh-x@ZD2%B3Hn8XQV7|1@y$A&wHOC#vn#TO+7@}PK;NESh)AhdAWGS0CEIu^a zT1l&}QIeatAq`M`xTFD~7r$>K-0wY5@mB^L`h$GbLEKb}7WXi|xTIF&3x7hL%_3?R z0B30z5w@spA3Vp89;)cYcSIGb8YwDML0pfJ*!{{-AZkAI++8PyYau8N5>(}NmT{)# z*ZNzl;<2J%p&`hQi+%rAV_F2Le?){gQR!03_vk%4>m7cGx3g~|W6#8aS7cc{<3Clt z&vQ`uA%8i2vhpo{eaJS{chnq5tQG!~LvX&}#82CQ?wepnRk)AeHAps+ibjPfe#%$T zBJKysd3@Q7v{0oAx`DeyMeAl;beTMoj6`QNMVmZ?XWRJ5Yi@z5x(L#J-it2%+5O(; zVRt_NBkXX~;DyB&@-*KveRy>kZA!KNiT9v#keY$xX@o2e-QsJqIR9K@rqgzXHQ2K? zgjaX)QDOjC!YC&J{~89eZoM~p*f4s~Vi9^@ecq)0Ql9C<`fcqES#T1j`37@tW`#YM-b7PbrLBIovjVMvfH-##@FcKWU=NeE>__ZROwZBI!II%4abt7h) z+{#|tWFp26yz3Cl{ej{ihiE#AeXZ2nI{^3Gi}6vdlm z%R^UEWGj3BPJ2X{(1xqZ-MSOQU}COP;84D^XE(mx7gKGC1rvA~GxI{J+SdERQpuf- zrCRUBiDv2W6a2XH*OV9Ra?|yC*TJzpK4hTiqXA;ASg09z@xMv*20p}K& z&{b&s0_ORtI{B}d@B#_eLQD0Bq(V7{4gT=ojL!Wv37AfKzOOK4?z=N0uHFxEa0Aza z(Y}HkyYhqWDk$+EtUfi=ZNw%nS{()4*`V{jQ7_~{zn@Qn?PYM|r~aQ=BAfXA)KH1c z_|PknPS*9GO2@Y0rLMuUCjUUP3|Jz|Ly)+NzdFTbnsQ|m1NEa8ef|-{=wCBpDEc^f zy+@H8S-)TM%%$=)yV`QR`H;!*;{RwhW9V-5Qa|<%Oorb~K-xPYawK*o@-~6RJaPGj zpYG{z{DhYx&qPQm{wRDxDc)}+4DzmPq2T-jo#b~7<&Ef4-WH|ho$JfnbB*Qg+XcT~ zzC0~69T1-2?P}KXA=?ncL8pP?+wQ#{V0d3ids9rL}izFVXC9UBNx%P03&bTrj+fyxgm-{Mtg8Mki7yM@GvKv#r8!OGDs zegqdJPaPmd;Maw{A!XBES4))${}4-=DZ``?H6uja-+FeO)y^Ww}qOR>~`CTeKU8*hE+g%BLoL3@Yz5cz=Kp zS>y+kUR4Cu@Z1-DnFn3Mn@ZougX&fPg342T`hC18{ab!1O0W7Cu8*LL!rO##eA2-U zUXhQhZCQ8sZ_}A^d^#FMe!V`otfM1b?NQ_ju78}CvRl6Qck^Mpj)pzjFV`3SvvXmi zV7O+XP$ljO44_*W-f~fmvS;<|BeP7#^54c}%=U_}AkG9!^bYrcZ$xYfwtRna3{Et0 z3xRX%X#Hn4acBHs2b+#LXPS9DS{YZ+xDz(;ij}6((YdcBG9>`Vl>(TnQv$GODZtrX zO4y_n08QShiZ6SX;P7vG3&aPDNG>e}xW)kDcH_PXAUCW_+O>tW3Z(^=8*J~Tsi%oc z?pgCfE1xU<`jG$nQ9mzU*S6*U%om^IdY;^;MACBQJjL`~wER!T*;asRG^Hh=?cvhT z_PUYA5YZA)&gf$Z(rv!mjj7iB%BU#&{Tb(^Le6lf6Z^w$-wPT)r3MDqk-LI_TjxEM zlS4aPr$q1?JW&oaR(Vz20LuQ?2`wEl6C{D6g3fuF4yh4C{q^1Aba z{2#v$r6YF7V&r)x|9ZH_3^e6_?qwCW&9q*~YyVZ{Ty-CBSz6|lB+5o6WG?5XCjmtvc;>9;L zE0&$Co^Fu&oEN2B{I*=0$iUl_%x?g*3p&o?L6y6H?=aQ8$Yp6|K8Q&~C;R%GI=Q4t zMf)0$U|GYG2N?=<<=%$e`@C|o*}-$f?-GadN5%E5Ksu^d>e_isul2`6>AAIeDCuCZ zcJd7F6C~~-pUt7)#zVB$=s%M}%&&jTH_uayhBsNQ>R%epS|jmN>&c#%&=4fFW8tm- z{PpgJAJ|~CDV*UOP2)zZzecLRMiv`~lwpuN%YP*I19My-I%Ta7z8^*Mo zusgIe#teMoWN2GH2ix0dXR~lNK^Pzewq`xec&5?lSX2_bNJ#|sXg;KdG;A$W6FsD( zhx+JYxIJY1ZkCra8G)n)jA8UdEyrqJWEcnM(DdQL6*&agEmwO=!qpm#6jhgG?aDb` zG==EINOfhXMTk`U+LG&kqT0muumH7b*i9Xnc#{O`cz6{M*~ER}xeo3Qd)FkTdT;aI zrPLCYRQVU?SX)1>Nx_UnqDC{rW>Pxt7C(0%$?T3WK&}m$E#Y^&{{svqI~xDOon!hK zclL4H?Ic>OZcy4`x!Nr-8wt0c&~5FJ-POYpvAJ$L=*aya@EffkBNfh{5`J5gy@5n1 z?)r(c3DdlnS6F@#Q@$cdmDA>OA2m+ds;G1zqtf2ELLI?B2HQ7nNplDq&f`_xL9lYs zc;@QrYl9Q}1XoM>4|=hoxBK@%PjhhcKn<_EZ8p(2DB!!XNyQ?ywf@Rw)}PK?t}ofd z%0qn=$es3`=N)Sq_D3$KD%=^_?T z?@M`^Dl_)Gnhkp)g^P^|-G%VnM#ABaJhob;#B+!@uVnR1{_P;6PQVn?<1LEI`P&+@ ziT7UYOoVWLDVv<~tI#H%|7}R{+)LP%&>kVjim1YGI&8oPM}x{kCvIBSw3_m#q*~q( zDTe%2!IFu`0pw%I37HejmT_!S>HF&MKB z?(^-8^qps&tk1onytJz26Z0K`KR5kU(t{3eJ%{&O8axdm{MLW znnO>c*{a^yu!|=qf%3}&A^FA{YU~<@bUmX*>!*JBnG+x_&A#sXqe3YX^o+h00zs5hlL^4SJbfK{d0=_2C#kW8reP99mf4ldtxRc%AWCOh`d%r;%g=&BogeIjx=QfFCMB5K^|(Nhgy5c zCKrb&V|2{<74kd{H{|t1`9+U4vOx)JhcIYn_hbye68=a{-8}(anm%cyGGRSYSWhgn zImD??2Q&PdFiqwzXUfC8vFqhav2@gagKPWU$ZK$;ty=2#TJya1n%`TAY23MK^>Wsv zrLwJ-Z!GrsA+yIUxfyAzzh;o^>7u#E4FyJ}bf>?tsYRC_7y+-j%SYciAdYP#e1(`h z>+tpFxz*}TvK&>O9>DanPSEnpL?|*m(`#^@iiK#{4X9i`5OiJLR=!Wb%E%}n+sXyc z4H@V+-i_vYpq=e2cc1QLU8jCV7k2yh=&s$`I=X5wU9pfKNEX!vBGZkw)afd|QCs~| zyRgcpwA5?_MLC%!#)5pQ{Ay#xoR(O$_q>gKwD(z`w1QWX{28CNQ-zh0750FdyX1U} z_I3}N8Ub%!$ug)zcnBAYrZWV1<|xk0H>wj}qwn^f;z(l6_lY5bnRE0*ta$+Y3uV_S z_sjDrmrcEB?xUDmm}!vBZ5uJ}Gw3L1x$ileye}4eE31Uk><34mn;kqSv$#Yny zJJP`wMtHf-nvHVT4Dp%(qR=8cn_skZ=W>F8bzbg%>;@e*uflg!PwRl(1^#P`@1utB z>&gD>A3ZEvX>&vQ;&U9NG_F%uJQWd|X_O)GW;Y91xC!#O?O;~Md$))ckd!|geM4d} zbdf1y>!db{LB-pu^!of5cOQ(aN-vBR8mI5qyx3cL@wbhmGlXpF5hu?Fz$^v6Sh-F=)U_H#s2_y+4MM8mXUR6D5 zvV}ucO)%Y;te8t+^Nm5@O{h}SKQF1E%uEA-yO_P6lrGFk29-No1wK#Z+Z&Q+S;Ijr ztLe@6Ah{`j8A&8J6cp4b)_&RLVE6WKL+pOFSlAT?8`;W#TMEH{>-vYo<$1OFd*XH9 zX+UA!qkP@#Q};~1=PAE(T1hDvM5WkSk_tUlnM_JUxnrY5(SKlWBXNiX))eSImT3J# zrd-y9ow!aw0p@22P^C;>ENY4&+O1#lD@^p{AL>JC-%F4}%w_LGW#M>;K65Ss|hiRZ4O8E5mF@El=^ivVc)CR7D+)D4#nooyU2h|nWE0r}x7bLqIjE~~@ zO~3^n`+G0XV-^a@R4zXoo|$Q^Jda?G7`yT%zG-Xmv;4;T-t%K7?EAARhZ{)5qp%-i z7SGRWNfDnJ$Tm`+JVzx7=cNmO?8qex9W5Pm#0oDZb-CRPxbH6wIO^WrqGT~imA4r| za)81329Ez@Q2FWxU=v*T4jlkCy|`0$Js`p*N|oRLM%9b6HTUvnxULO~tHhtY8F@u8 z42KfA+4?}lYOkR3@?x>+?0sQd$8y)F9z(Jz24(`S-49p^xHINCi*KsI3R)$edJU~F zeJ&UrWP3u1-6MAtTq@E*w{*fE-8UE$FnFLen2!3{GemvcIO-J^2Xjw;0Ha+OhJMT| z?Zj`x#WyAUF~Mc|St1FQPkGvtzsC2P98$@_8uS$Cg?j4Tp6Yu~57gCbYF>%Dni6B1 z%FC>(kZo$oN)H{3$~cSfLGo<=N?n~MD7dGHN9#o6hr}+HA5^bh;5AmX$-igc;%0LR3}1Et2Q#Pi4CYYeOT>*iJ6QuTv?vjOc*delEHK6=Vh!}SLZNz__-n95OyB|7aH*2d-k zV#>GRxjba+lozZ~Z^QU)Tvg z+tP1|48VSaD^gSQ^52_2xsQHGXYT2Dr+%~kH+90?)J84+Ch|$Y)5G7{{07P2t_#m0 zRyUBph`Kg9&UzeT=w^8RYD~C9WeWBT)rINDcb%(mx{die26CF&o78VK^@+kOMBx?g zT9(YFgY)?R+J4Jb$8@fU8l7Hz?7Fpi!d+ z#TpdaL_q@teWF3*R?$+$q7*AyghWw;1aAUdAFf-quC26c)w@U5huJX74(YG~QIrvliQNmOUFuif6IKXy6Jv2=)L$xt(s7 z)bK%k-cI_K*i;!$eXgPqWJ>930yAoIms|fzthAYE_*^9D~nV1p4#Up(w9) zwVglmM=UR;%9e-`CY9&jEr3-1_Xld2yr4wdgG06G5VgD;OBULz`^B)OZgc=`%jhG( z)1Pf^yV%)Kry|@?6WDUMN~t)NO<(E(v{Fu}{Ls)YD7nsF-7lVSDgd^MZ-s}+8 z=rpfQ$_N&UBFUG zF;P(PUDpq(H>4({57Grmwx|+X!EE*r+I;q2WSy7WX&If>1Vmkx6KU8e=RExgY%UAl zua=eZZwLUA_ijBs5}4^EaN!UMc0oyFC;|OC2^hduC6L}E=OC5;hXFg~q_5X=60hcs z;WAPPB|VT&!PlPXa&&h~n$6vSa4~4B3X|@|YcS5(Qo~8Vqj6+%)zD|sdy}Fu=nm2W z|Kc)&I;O%}TY58D5kcE>7=+`dk}2ZYzYL(K45(rgwII9TRN4Qd(wHb^WLOu|5Rh-E{mD{{9AIILH`AXpkB;N*bb+;=q27FDg zqMY^@{n&vb*iuK&y1DpLW)xztpB%Ot+6oOO6EG+STk!BnVT1Ww$L=&3Ydarq(W6Ft zZV68C%rR2Y&}X51p1PAtbtjd6{t`0E%r}7!E}q|A_DCbKRQ}+>YBL(Mrud`QqVHXs z3MwT=Or=Wg!9P_?3^c3fx`t9?Y8+%94+X&SG|QUa;I#Kzw#&D#^JBxrLreY6Lt7l* zl{f$#vBkcqlR6DXu`?JDEII{DExa*Y3?TQ{uOL#dHofa3itd;CNeILAb}ypLQnVRAsNRpmE_8y(gD> zgICyqWYT9|{5QB6eGbz((Uvx7BtJu2pk73q70HTKvueFbYrQ#NxeMy%2vutMUw!~8 zf5h8fYT(;4JyXo(7)jHYnIh_OcByqtf56uvjuOS!@JMnM`qH0XG1WwkdXrwyVo%65 zN)5l%ush6^@kJvSZ{9737F0I~>5bTbqnVc3vXJ+|p;z%$ylHnb`cJg*x5`gEt)Ggv zy82P6nH|X|^a>VC%OAg5!E=ot`}z3YxF>JkIw0^2sH;>p$@zM9?jY7>Q*74dxOCQyV=?Z? zdqlh_tV1)+lTHQ$LwXE>`&N1whf2~`RsyFcywWSy1EC^iAE501@J(NdaKp-S^@k&j z?1YsVA&;o}Dj6iB+%T7+QmJ*x8+UdqUqM}23JO@DdB6LqdJhF#^j0^}HTFtQazPH7 z{pio_;`A~*$E$c^{9ES-oq9Yw(iIQuj5DwfAnTBOxBM(0ZAq-r~c zz5yOitDeBd)R!8L_9lJq&Dj#U%aNWE4f@sDyX92-!#?%sckv!Wz1>oO9HE%b?6X?2 zYfqT@ch?RD*RV(_WSOLO8=a*OL-X_DK*nbp#%JcTwqvxf06sY);Pm~n{bv1n*wxvm z$q=;YptQRI!&DWyc5`u~7vX!ND!%dF3qN zaec@#K3#6@QK5ASey4rK6>*aG=YkiHR!^kv64!flvGFI_wq2!$8+k32H2KGn{tBTE zf!juhWg-MW2@Ti&hxOPxnq@{R#zCDtvwf+U_Q14Xj#2OuYZj#srKW}H2j$vW1X6*i z--n5n=A0>0^%ALx_^82La#Sh27V%sV_AnG~-UJB$Mc!CyalX4YDbZm@y-Y^&8b5!G9SumR!hNNoMl62Xpwaz{zU-4Ss z&0`o=Us&;fiXd)G)TVeW4n%@U#CjnwlP=D!qiijD8Rz{du|yWJ!i9kCeE3 zz=YKamsM{9UV=iHus)7XTEAZ*^Ki{F6&g!#9D%RD33U69V)U z$+T!JXaMaKs)bg-XhiK-W1;6uKWI9+UszMMpjNoB@)|hgh?$R8@pDtp_)>gsgH)@F zOCF)pxjIW7RCpMwQ%2qoP*!RI=i|&`8RTMgw0?v?y>IjS`ooB%$>wMw3^RxJ%-Imd zG$Y2EUUGCXwgv=X$oSFbzpT`!9b7zQ%#=-2-25z=ES3Q+G#~7TRfZ z_prg3VQY&s)|}k=e1weYM8Y6~nitUt?M4Z8qKiJn=kBBKdE57c6)T)6`BV~5mb|h3 z@g@t7__tb3Q7`2t**~hf&~G$nI-;tRDsS*AUaY^+^Di&;D&DC-*T1|kcWc&9U>f}Q zpQ208)Q>Ryo#)3|<#ld->d|l5B_dOa*(dDIE4q;d`#NI?r_gTyjX#?DlvazVf__fSMaRuR9D=&7V2d5tqdmYZKiHfuf8sH$O95dm$EOpe}q^mQtoDp)JchLzJzAH?z=V>-OX)bn0F86~lDeKUh;i7<4L$ zyjF#;-{+ORpS%$hoj2CrPJ=M&G0@K+qbE3H@HFU1J+oo!|e;SVqQ6f6~A)EC4T z4gdMycW3xRi1!$^8Gm@OC{%pGfREx^RE}fFV+15{1n7Z+TbkX(IgA(BO^o=doUL=o zUb?i_&Q2+{=tZlCDipUb*H3A?&gu9Ql#KTn``7gujv8B_qBc?%oOq_G#Cxws>fQFp z&7DL7;7;f7JIBDjzB>YD%6v9pKox`=@){l7DK|#oO#i+ETrk}c`;7aI#gch8rev?3 zX!_?5pDAvU(T*mA^aiXJ(mBFOC-e2M?(3-zmQY0cMZUNke^y#5w&HJLspHg`iow{G zaNT+E61>S7+w^nRtykJ-1{RK?Zs+fu%sxS7W>nI+4w2~}gYYAdqoOqke@^e&xvPkm zm|p~l{JB`12S3)2zuJAg1HZupjI+_leV-1x$Epn-$53X^jQ$0m{KC8VtBKv)Lx6*z zCGSPvygTkQWk+{QmcjZ5Tr&y{V=DHKXn$Zm#*7ofR{pmhN#nz${L`V8aYT>j*=Bho z9d@_%A^ZO`QkDC|Td;G6$a&F|z`m`dFUE;}@aE}OMgCtRSxx13MR|~Rk*)fnNQb+w z@0R-`fHDuk$E=YBFx%1Y7`Uu zOK6TT#$}{J>2BpI_<*^ObS>*^y7jL*_z-(FGa3*27wU;VUQ?{Jw%GE&_s?nk=`B3A znt*v>qQJK121$=F$;u);e<64|EXR~hEy(IRyelR{I zG96Fma9~*MCywH^*8=Ou(pW6DhYOv3J4gmhO0>_tve?gtsfUni(N_j2ZG5xsXd&W zwl6lU+`pB|KcCG8Ua~JZ0nvyi^!8Z#6U+)+D2L%xEv~r9M8P2|L-Moq=nl2P`~xZ- zir}HU|HV~|`|+xOXjFftL=A4Nm%*ZQtF@tr8S0}$9UO|L7>V>Btxqsb7?tZ*Ale-s z$5z>r&EM|Df$DY^*Ooz`pm?xcqZsEi^{f=MdS~RG-Ul?Sw}ZuwpufgiBu(*>kp3>D zNil1&c|GeTxwc(7SmMF3Z)y4f2{cv!IX{2Lk9N<|33^X4xCepLL_1y6kNtg&Ac7Aa z#Oxjrgyas3Uvn7WSHGJ+m>+LR&XRLq)95Vy9@Zt8wG2CR3s0FL-nm}a^Rt{kkA2Wm zCB}GVx|bH+?5`3Rale>o(>A9IaMCJo&Sn?f`kv|gpy%b7`NJ4e)v4FSM;WSwIh!p& zofxE-)^}qzQ1-9vi-TQ|=-?y}ty`(`j~O^N*;>Q8GS(Z7^(X97Fs|aYy4}Vmt9B_c z4X94m?NZdy;*K+7JRDqEAdiiPr0KNY;P7KFj+Ti2%->x3Vsqa#y^zC|%0E==nEa~T zA}{6|roxdGtFA0U&IDBk#l?N{m1QBh*aFucg@7?JXpeURe(#1%w{=dv5qz3)`c!`VlNuh7h`XgE!tfY&i=ECx` zVmCZ-e*8P!MHI5oeuK2DsQqq=HQrV(Q5JW+X)6EN?1v*k#F)w5KjdFoG>VvZD*r&z z$NK&IjjLEyx7(=X2-Y6J1Jdo6H!is{eH(gQ?Vs9@75qz`oEjvj%~x_+-WCB|X6@y> z#fs$Zf(8u>hy9mew?EhAVk^>ns|4BA2z8%m!n)#>y7!mQ4X6-;&d1ozXYHK019Eu! z35$i={~SDcuyf{|Os?c(nu8BIf*b8SI_Rk6HB@KC14JFU~r)n{gw8--_5 z{-c&$!;0=ng%{cLsmwYJnrDxi$(c0#Y__g*y2qZwy=X>Q!&=ImX+N_F6aZV!ahzRg!ME`7}c||E>r!i=K=SvPrRj z{#86?2|!6t(te5p0AGSsxmLO*60-2lmcQ5iqJQC%7~O!;PZ|w*nU2Ew6AUTI_jh$&{K&k7(IP4c*Gbnn_ER*t4|ox#O*B zo|+qxIi4r?XRB(dXr~YRpJHH7&WnIi6vlH@22fci|7#)^RP}*ZM*vN$f2Ya?veN4C zFAnVJXsE>0a6t&>^y^^m=$XffG8ba+NsJ$IjP7kPKLgvcFb1=n`JhCZ* z%(~LO0SnG#QbVgm=EE-0i6ZH9MC+T0yo;4D-U=EJjZq2h+LhO>$yL0>-q<^#tx&szlou*H>+b3J{j-@@I&hg|h%$G{b zf2zgfrFU{_&oPiK_8ql{Z`W>IRR`-mu(=e5UE0w@*b*NAe}8a(t)jxMk&lPeJDzK{e(|Mf3&eQHjigNmgKMEsdM-Z z-n4!Bp@$!w1-14&GQPNeyU>fzWwKoHxH658(Kh}#KTGb_Mrz&9KmJwXDFlGt<1M)~ zxhAm*dO_EW-cBdt<~K4r_2ucZmEb|lv(pS7(3-iEb9U$VQ;f;aY( zp31NA-~^HqjPeBien-_Qw6aZkUNQ?=7D<)`k|jeel_`lSzXw#|z`jm5rvB|PSFxnB zTP78Ii}y^euI4!tX?&h%9YZcQ+^Rc(cY7nEZ2N&Z_|Ja%cwd|2$fJ`gp!4e= z{2;6nA=_T4O52~5nB7>sGQQ{)+^*GHP?tI;citQ)i%fDSpmKV4N<;AJBZyx&n`NaD zZEvZjlJSaQ*?x?5YIk!!Db?^J`Cy5KzEhds2BQ9Lt#jaSXv-Jg1FR#d0uHC9lApm# zSAR?y`p?X4B;t88!OV)kO zEl(9|rvD{1uz=XltrD5LW3egU7~AZiH<3rqRJpNP^>WeBmWov~DjECE+2kP1%kyiV zD{9Kc1TABsqx&wu!At#i9Y0Om5gUAyR&lG|DppNzL52T(s9HP?cGL@l64;7Kfnr@7D1NY{{SK0p)EWP18U5i+S+#|G?jl7R{{wMwwEviTV+d z-LK~~=%x~nV$hO8G0%Bg(&xCQLDPWK!imBk^3eXPVB;Rvnm)6iFdw{h%@@36$&k6W zEz%rqie&d;hG5;p(uXeLobL8_wMx>({>t1l487hp1M|sWsvGU4=C}`i&|*2=*rx*W z<^&h)6KxZ%Qb&vm%?g9a3d5}ViZ+aj*Xs^Votc|l)miz=;)`Bl=Y{Dzi$7W$WS{?spJI znG}`iN5)T%of^3=$j|fv=_z?LL-0>iyT-<3>y2NpJ?(;jjopI*oo4ppw+U9pj6>u%%oW zkqyG2a}7uP^CZi`OSzuLR&UQJoOh=g#;#IT1AjQuD2m`R=rzsaI7=pWq8P2bR+fh}N%EF?gF|E{F~_^v4%*cOn(1=9s!HmjzL? z5AjlGFyA}AfaYG69C&r=l-y2ghW?UYi0koiJ#iV!bPwIMBSX@RNt9M=_&`_FP*NOx zez~JrDsJijX?<#X*j5FBlczBGb2e4Nv?RI4z|kpivo<}`8mw*lkPku$f+>$`9B%o^ z+Wr?SiFi!2goE?7?n7Un4x1=oc~I%gOv28|70ET+-tr56~tf}ud_NK=D$Ce-dF z@sRyNzf*pH_}%t1@+QNEnB2q`QY#BS`@M=OWMG`4Cr?k*Hs(uDgmp5)52|*x)|@JQ zV7*9$qRN^=J*d@_gqaK`UzV*4s{x9UK3cMS@?K=e9BI~N>ZX5NmCyLEL;1v+p%-_O z&jb7Z7xMZ0KeO_gq5S^vbM0s3X@;$YzI>(m$nAIsJ*=TH6?vFELD#aze%2Z z{<8Zuu#ex=+WrPzsez!mSd;vmtWD@rAKlLnL-fVT*rpY-X1hMCaU%Cz(*jEI$(|j^ z8ZtFa8bmO8JN1H7vqPBthe-93eNjw<7ECW@;f2sXwLcyF@*c*nja}%+=W5E4_JTT2 zr6psJ_!BGr(&+>9Di^|wYX*~I=Y-D%!Myscc-3jsKCuz`mlcbL*ya5Au~S#VKJym$ zBN05o)A(rngogR~dw{26#Vpos=C9wAER$BTta>#Lqu+P6$`Aw$Wio15BBXv{q5Uvs zVIq=wk1Z_xoN=7j`cWSY)Dd}p{s+&%XKLUPNNjH}+2;s`7|0)D54MR|!%rkFcUYIT zUsX=9jzw$2*S|MkviMzGy`MvoVN*r^IyzBkKJD0=9(p(05gBk`%@-KO*VQVy?V2%@; z6YTsak%_hKC86i9upfEH80Vf?BnD$|&V-lJycunLs#hlSq}sQZ3~`#vE2j%vH_C%Nyv!tZnn?t8Vq zBY%WT{k^B3HZu#H=Ji`PGqMaI-u#Ia!yojdQgy6PtKQpU_w(*pZP8Dd1J{}zmzE>u zD@S7EL2eBMbgptA@B)r?5Eo}Z?5PhH>d+wFZb*%tqEz!J>|4dsc=Kx#NES?Ij^#!m za#y*_cUZ;5ln3C~3LJk+h$@!WPw|$>iMI=KShU5LBT4<_&!qk#n^4gzhh5d7iFl-3 z7>!?BAbIowVbyPr29GW2z)aFhJ(Bunk{0(!`fUFY;g`{A5er(rl1chJ8iqAmPh^tr zjD{R7IJq#B)YK!XIg@mLkE9=El1}K6bfP5%MGMjC!`(Qxn?66P$UqnWg^qui#LY1e zU&Q-iBkb=GUO(4srTs0Je_%r$eoF=JEgAa4>Bk>IWLK?Hs z^Cyc&R+Q!B5X<7i*~=qC3=0Y0$yz1bHZp9^rlBwANsS;h%*?bQ#%0lUKbeLVvdTj6xM}# z@TYlP8O7HTxhCyrW<;cI^E5;Ele7ghc*JM*Z|dQo5xMni^l&f_D^-9>$>Z~Q0Z)_T z-(sMB0oCA6AXIX>B;}I%TT@aFP;0!YmjS(w5P&HYiZ6ts%rN}IeIBB$?lXUxjUi{< z`GLRLmZs_Sq2TPFx-rN|z11HUT>GR>Vzz54t+l&>1gbRa=1AcbmJUwcH*B1P9*86j zR8oZ{UD2!kC*=Ii%t*2+;Q*H$OOJ;?Aik`RK%m4q!Nz@r`-)h4ZwIlU2aZ=V5Vqz! z6+62J#A6wVMTh|^hxLHCAp>!ZgSeyzAJYti%yZ6I&%0e3hJ!fwM?CkdN29MO2Rd>|)S&J>NqMqc(Of$|~o0B<(X15=d2=Chq* z-d`7~MpN#Q{amq_+F(JUOtsk^)@RewVh6YM&q>BAxWveh?b;&u&SrYPe#(i=k8S3O z8#Xlk^D40V=f|GsqXHv4FOR+SCm@%{mg~p!L($K9S~bCPHEp|MCF#7IDU+?IWsCj1 ztMxJ%M_dDm)EOOK>sLp6i7z_5eO`Bx$+d%TXzCkxjyL@kOpNlryGX~^j67XG1Pf}% z4sFq{SnOt9$;|4Cjq#MWRn+(=6x4usVvWCBjek~Nb;UCFgeI03RpbA@Sc3zqsqZ|+ z912t^MZv?2xMco{8HaI#zhn*9rK+~^jvM^QnTo5`y7j}q70`H-qX9xKFIYj{^O+D` z4U_WE)G<2&6U1BoZ-nXZtL97@OtprWUJ+FWb1rs>FuBLpaHe0E#pq;=PC&)W3pyT? z^g_;x)U!Q~SHKu*{h#{hq}jUE5e(^Vb~CK2OAig}>CyvKM_a3&)UW||3GAoo66OD- zm+}YqP{-+sOqX=?H?+_ke*=A;s_NDs_^G6F`@~ayqzdTVk+#*DU3E2&>u}k+y%H;O z{rq3@vcn2I-sUI!cR5f5z%?{v8+&K2R;4?NFY4F0`5d?0G`{Gh+{VpQ>48xq zUV8CTzrCHE%j#9_Jvzw1FRI_yf&RFD4+nOUwmF^DyK(b*_1m*Y@ds8%8eK@Jzy4iU zq1Fw=Pv^*vom$uRO04LWW-g&aC&uKYSzj4GVZ}JvWn-WA1@?EY{z^&8EqoPk+C!2^ zY>dU5V|r4Gu{NpxTaLBq_4_;4&Z!^hSesG5D-V4dH&5Y=TDA4`6Vd_>C#|oxyffm> zkGg^*h4bUhx+2!$xF~MN_c}a3te@rZOs&6&hZu#X(+^R_oBP0d2Hi%!0s^|r;?3>u z1))OdZTEu2>NtDKy};Ue@n*%@9NG)x&5DaJQJ0#I^CVu|e`bGgw!hcgU*G;VJMj#W z;3N(&8Ok5?d-yp~^K0GJX^UONU*>lJ;}?CQ_f z>6iXYzrob7Nn^#dh}4%<7L+U$2&KTRY1?;d(4S*EM~9srcW}*`NCV$gqG-INIZ-jm zx$D$zGFj;|4`3tx3eq|MVhKi{qc3hzda_98We*yj6XL5ed`)2{M(z?FE6P?G>RW9L z=>K-3y(K@@PjWf{XBPN_ej&UJO$Qm?9hnJ)l__4Lb&IXUO?-w%aF$2z3dbUXrDW<# zsFSwkv%CwEdE_8dQI}&l9}WD+a(QKZB>)HB)7U^OZ?g!NEMT}7*vKy zq9m7)=kq*(KQE~A2VDZKnpDZ>V~Kj~R+H@eIj5vESXfq*Tt6 z)*WY9quGK;XmrTkOXF(Qp`9$Wso^buRhfo?9sQTA@D2zi*3cIf2Zhc7*xD11A4#kd!Bo9)T;XrrV8?9d=V);q2`er5{^vC1@YJSVCvwLfZv#aJW;T#Dl@pSRB;IV6o z_HOk)*MEyIb@(>$o%{b8U;nM)!{$lsU5+3NEbKqzN_iv-C6wt87Sr0nNE zq9oOa3=?KW0n<}C`Ap&}lG9i0%Wc^ci46%Z03F|l@PZ3T8$({+GC%e`knpX{E}lEV zy$r*<`QDF32Q%*HS7zxjo+peVI#c%x>FAKvvww#LeWreF$Om>+J!2}ixGuwMtdHT4 zy-&%Tg=Wa z!S%a2){6c7<&PR;7vWl7u_MAt#Y!?P{Tl?eod}v8g55wc8U$^zQvSkZhuaO8${!-M z5|c4I_otj8`#RFg@ACP_`g~PT#9G*NZ)^ZPz3RvYKU5xVKMa7j&Zp9>2kz1y;&VS% zQM<-_K`r;Ee_GYaY;3+tLF4U}8#x)7qp|(w=YvgAJ6c zwabZ|pUtolMWvU!DO(~NO$Hr1hn4MUz;LBTA;oN;O>D`VHGqC>R^g1p=l2=lbu6bl z@LB_Agtz21e8@~_SLPP5Wu5xWL`Z{|*P9)9-hQ;@?^M!*zxzl^$4q8@qHgl2bnT^7 zHlkQIq8M>hhI0oPjsDear|aXTCLG7hgyXmO67Owv<15Nq?p3^9U#}9BO-}Zn+%|?D zm`RCL)vnCt{^St?x~UljOtqq>V+vUJrZ4^}1;qS02XUw(N5^9wya@n zzLA=y)WbrBsOMcm!-PSt{n2390E(ZAT@_u1Z2QPBAPOd>fG8`CQiM4GyXVZvz}eyf zRUsIL53tD&tm4!N7?Q~e1_2g~ceFmcD3WTMhn})opI|;?-t=9eK6X(q=I+K*<|@>J z(sqex)451Hf-CNF7SoK6eR9fS_6U7Mxx+RbIcbx&KVCt>O3v1kUX%v%lH2c$u5YvR z{z_f_7I*6d;)}gr@x=v`byKXG1UH6EPS)~?iKV_&`Ct2(b@EcD<`v10vxS`#@=BX} zvES`sRqTYkVjYU(t3{y4Whi)Fv7Txt^K{tcwyL}`3MK^X^&$(N&S<4mM7}A3iJyyH z0;|pNSd4s2&@LQJx%_@ro?7C$_jwBvo44)9_kkD zRBV}Xy1YQI^}{~$O3JGJx-y^@6=GpkjJ=EXgfd!t5ixH6J!d_QS4o3!O>yNjKC*Pke8OINwnOC)BFwd~u)4 zt1DXKiMhO;nCeqm-MX&N34YafVCcAVWKHVCj_QhMW}FLP&E;FFD_UoqaU!Z%jVhkt z*X*1(juH6oUdM|W+_Uahft|CW0}c}{3Rt;aueUz`xaxMlhitMQU#tI{l%xX&8+YA) z;T1FTG_NAX<$b}%X84@s>K|shH-5`L3`XONWnNM>eM)sK75>lisy-Yjig76wjC46K z*z-==r;Mm0`jl!au}i{j{p>&Yqug^onMMzwA*~Mg^-|$)TT{tQNtk~g&yA618l3x% z53GZdH5T;{9_K2PA}gh5<;XnS;78*|zR43-nmSjccZX%tkWpSXQN?NZVW}9+&3kuW zWX};5>aySfU)fRR`IgA@!pyTjlcxDcgNrYo2@iiXxXiQQINZ~|Ngo+&IixiV401@U zZqxKEV-wtU6uP$8I1H`16TzD-#q^!uFp=;BYxj?WInS!BE}z8{U+$BWGdVfJo1E-ht3(OV%Z?9CBq}iW!WcBhlAI{(Xk5mKk+GD$++o9` zu|wYn!xV(`Nj&uixvDF^jwg2CCnx9F_~IcGs~N2)cHr&A)YJ=es#`z65KKLo4dfq= zYkvRAx^bLQ%}A_)_;72-(Gu0nn!#JV)mv&RUWq4G7U$%QMN%{P^J2BSxg~swSd^U@ zFs5a34jxzWay;=9QYRmq95E>)z#0VEm;+DAFNM1tnzI*-i7)Ou&EO{peoV6Oq;aXq zw4KbL9KcM*Y|$1lY1=U_bzTQ3;tR$g0K>2=7*x(laQM$^@w}PUswdJ%RMSVC;MX0V zH;x{5?pu5X`*K6`0CXkRi`e^t*Q7ho@#;1aj9bw9E)2DeakO%M6Tf9Rv7^S7z)zneG2GOoFC}YJ#hHvtWaHd4 z4OVxGEJ-nRWi`}P;)~BjHfuQ%i@9X=5t!q(@x%}9?XgT#J4Rh?WlcpJf>26EhEhCL zwM@+kss3?oHlC=u^(R!IT6bWyt=`V9D4IMf@pW#zsV`wMJ@%^GT|d2_V?Q5bZ+h)zfh^RK&1o zt~9ksE)9lmkZ0dyVpg=%RVI`oJ0ZcP@LAynKlL44-1~Ke~<~*&=i7@S{*hI}w z^>s7*e9Q^H%gQXFHqksL+t&g&`sbzoSh9j=-I9@L`&9k6JfdOWP}S2nDV~Xu_DniTT_}r*c@=_W+^rdiB zspW*#?4O#;q{K^gy}41r^ZV%HCa%ZHNd8otqX=utuP$~qMO6e}EWm$zwOcEkup_wM z09S81mGNcq#nXy7GyQFAmbqWZwNZQ*9oSJqX?77{53CZcqJ=*LtB9Ls=xj`DoY-TQ zc(YARjk634prCQ$jsAaYoHu^a**Mc@nZ&2Tmx5|Z4dR)S4T|SRnafxnS0Nm5#DX>nX6_(vStP{HBBXl@2;|MEGe>gt8a{B znAivpYIvn#A{9Q6hDR~vK$&Pn;;Z9LZT zma@S1w5SiLt_%89=R$0Uk(*F@D2&Npt)FK$7LgU>RiE0OlD!r;pvCrQ&9~r%(*y-E5 zWE%D#Wy&&rsg)e7nh9?QU(DWS=_6FL2w3@OU2Z3WN52^YpgYi07C*kklj&*Y?VWnM zYgaw>Oi$^t?yz}E)6>m}7k%8(a)o;O3yI$8>F2izo9Ssi8KtA|@QJFZ4FzADJ{{6> z9Gv!idgXs2g7m(YDWh^v{70Fxa&v-LW~tnj+s+&obgL@27sB@k^|JzcTT!_Uw^})o zlBpc)sy}dFI!pe2y0FfYub=fFmAte|rq=%`Q@4^wRj%=yA?T@cM}IQ}?5By8x!1Nc zcd_9Xj&$ZX{c{$3nxmPu$MOT0aOH(MzOC4)ZDRU%h)MC4yx@}m2t&GU6MdArWix{E z@PZNB%9*~{fHfq^bX*E|_1y}5`d~nV>2ImC_VXXVS$*3hk6253j6J=!gZ+{L}cOoadfy z(Da{W+@RPGe<(M|Ws15%%9tI0RNBiOp~HJeiS=|eALleYR-!?t#^~4roCjW{nT@cZ zsMbWir|@I-OPPYIX`=4j6xs3(?pA!Y|AT*?OGS`LHEk^lxa3I$ViCF+%zFWOLpVcbx&?F`r*7E=@XGjo1ea zcv04I<3+8AC)#(C7v;j*8f44AIg#!BHU6YB#j9c`CeQ6v>Tx_rvpZ<)ju7PxxO~i3 z?%>#*b(3uJq)J`;FxqPyQwbKxv(D$S-JE}Ie5GoclM$obYLE6x=<-V45&_4nMOQSo z>g<4qUZ!Rkj$K@yu$<(za-t0mhpmUK(eejZ61jwuKzbUM^+bO{FAH(V<05=i)k`6c zjr3GA@Ua-y)%atG#<;uODL>(vyKS+`xYPv<_Z}?SNTIlZDBje8HYudjbT61#7IXHE zvddF&o$wMW_%<#%QOjkHweQ5BEkVB4IQiNL>=06FQr{y-OZ^N4Rv>}#z0iFpLkrtU z+s2r$QJwrEoiMKe6OrxM2h98r#FDN48b2bI_J?X@ZL+9dy!5|DmFAcxOy>|cMh}|* z2TTkqLQLmk(2o3um@?HCDW(>`+=5(fuD;6Of5{E1rfCSBSk+%hs16gjCu|Hg=RjT%duEBs+<9 zYq5j)mT3Z#tTlmjf%WB4gmLQ@4>80k_NI9iaLESf#MHEv{$=>$gW0P63VPB}A zHBre*WaIoXUNuqO=3EMZthQV$2~RTl&8Ti0V?71mKXl*GSb{fvua(Tx&oM^tYC``$ z6zB49wA0a<#3R+)u9Ay2*XnzHiOsK2AzT z-=Ze>m+pJF7CztnxTqffdisAa!y|fNoA5ti>uPd$`5!QKHMuJ;{$?d4Zfn&RX(uwd zs=tiM9h>_1CU<{JzW~RZ`d-u){E1=S;3>2 zdK!i~-w@kY#h5V=t_k!oxqtKjFO&PML0nLtF}b>#Ycbz4O`y}{{*3vFu9AJ~$N#-N zPBd&8lUx5kVCpH^1OIz$8N-uNP?_9MrKsx6LX%r=CifbS*F#qR)n;-{eloe`0Lw$0 z;l7)zE0bHP@98th)Yar(anXM-!<~9yJLJE|mMOVADC1mibz#vBSAE6Ox4y?7h{eYc zR@|6d-`Dex=@RbMNWe?}hf`k+4U09bYP3w6^*ZuR=lGlZ9s9t&V*>1 zg6vpe9SG9TkGfDv#p;h?Ego$X+5$%^`B(hTiFK9W~+vd(;%E05hXj0d;LdN zo0RYy)fR&(M$5LoCt79mUss9TY-0Lklq2{yt%C(ehuTkd^3(JK>-bvizV6|Ec5y#D zxt~7n=U>lR#`W&!AMPixA9qIL+P6To*a5d(p)t9OXt?;X8@(y$UO9AqeDP&WcyF1t zFUvL=b*4tJ8jS-m+NzEy#og^-$!Q4Dz=Tt{q9Mtqy>LBEa=FSRyy-{L$>0Z$8UGv> z8-4gjX3-pT7=7IwhSr}Sy0x`X8Oc*E+~2BN_cN=Tf{|cre_~tf?=Cq2dXW0&i2b)e6I6)i&7lms@E@Ohp|%bsK4CG#RCWR&gNXoy zlSZQJCpA#h>gDDG1q$tHCZIlf#E{qtshcdCdyy3EYs|nO3S6mqNC4R)9?lQ8RhEK? z%QQabAU+o6uJZnL?5N5avu5wXAbU4(hj<*V>4B(E}@i`OY)W6w5Pz6rywpSThUGq7i?f{ zX)1QwXstRQR<1Q%Uek6psXn;1EP|~;z(L;8u8Z(kK1Ml!FWleYC+vuJOem=huSRb@ zTq{Z_=CG3BOJZ+Xc_dJ3?t+7rthhA-JCV;SO(pZBe*RK%nyM|foyfdmzwlm5 z8qZqic=M}L=x{u&*c;pox|zFlAiZmWKe7SPnp9TVhG|3dNk`%zQsU?5pc!N2n zKrmmb5|YOh_`^pVk%nCh6zO`*K39>A5{*}h*l0ZeJF;taGy)7;f%f4MTrAo{Z#vL2 zCpfXg-G1X#;xpPzC;~ReredE}ic9GMY?qqR5Oz;tud?(!`gbP`r{A-8HN6_h212Pc zi`kx@Vyi1`C44drds>^?_%lbgvi&*hji|W1;I7H8(kingC8-PHAuV&Higk_V@~r|^ z2@tE@;SV1y3hK7NFlZ$zE!~2js|eNir*#J z^X_@k0;Fv%q`EJs7K$aebcJ}CA$h1yDw`mFo`Fc;LE;iK!{o1ZN6c!GxAZ$0$!Ru? zFc7?5FN={OBD1c_DNnCpcpJ246ZO4qjGfaUf=oqQtqO7ukQ}XhIX{tVOT|vPIMOE$ zlCr$J&bpolzK4Ckgt4nLNZAJB+4}N3)nL1x{{$@$LuNz0VV!(vRP(PlvARFG5 zdKG!>1@C4<*08*oRi2S*stw2}7y60kq}1k~04&nnjcCF-);f0>oGggw*>; zR~==39xb%#eQUc~c9JSA5*mNPj`SB&XOQEdy`l4WuPCNNB>bq>oBcwYtZbA$RDW8ENfA=uQP4=P&K%`DcLX_4+=#Z`wmT~c1{Ah+*mzh|XG1`|JZyMkL38==_Uul2}n})~vBxkZi;~hSGsVj>0 z^{0|a+n8d0u#JCqDFrb2-As(hkNw7d<)q5aAS;qh|H&Fl)bITL4^%`a_>3IqjF23u zk+hwN(Zx?~Hh3rRGYn371>8R08g|x6{9Xj|&@Pbav4~2O6>bjcun6FGT>Jg?4jH!sVY?3kB+FH;;dTpypKqBz$6bfjrk$XZ(G%ybfLjR4-%6>tiGery_K zRC6_{svRX+$TjR(kUrk9$V6!B>xu}L6T4#BSA5aFofa*v5MNX2fK7L@PeJ;0T5uH& zUM*Oh=lT7ZZ`mz%W`~_PyN8{)Q{Pu#>p!N;D9Bl+zq#5#)vdihEUnne`u4=eVyC%o zm3nZ~hnW0S?9=EWOC{tDp8JRE3yQ7L{{3$T_Va@y#>dXGxkq4}j#;ccD;(7A#StiU zIVYG6RPeYXHT9TC>aI%N=S?$UAAgtP52uFBfOVE9RaLUe?Z;k%Z^YvDN64hb>-Xt5 z75?J#F44R1;c}kD1{hqd>kQD{-w`}O?1z#*dtijT?J#=x?<#4NTd^ezb+IeP%X>#4 ztr$yy489Patx;rDE+WTmiwIs7``v@v z9Fa}?cQ46m@lHu#25p$+h%6rz0W)p*HDJL9LbA1zAch*QB^vICOz1&mYDmO+4qHC9 zlAP0n$XF3++y;^4LaSExo(9jqYX}bSL8nhhr`!tjQ%7gh!0v^4i&6$f+n}S%+vy>L zDUQhHC6U}#_jgK0NUYe140S|q>_KFvi2P1SwkEMM5t$bBc0>mDAaX=VgzBSOo@2QZ zb$@6NBD;#n3ELuq7#7$ZS#Uci)qo(eU-!biB=%v@wJ=DX<48TdX9UtT;65OO_k?F_ z<*8J83WCEOoqc=I`H|7Vep`9I)`gcGSk;5b7!kR0TSPn&DGFY|2PF5?`$kx_nu&!( zij2t3j>zT#5il#s+Y~X_V_QUOMWi%1-w~PIgUCV&i0Vg85Z7Uj$W1+nTqYuq3CY&P zMMGdn81!*O@_GxqrP+L=GmdSHwFd zq3$3u#SwXSj|iBF>o*p$#HZh^`LXC=v=ie zI<6mN6cW71xi3hgxCfo>LORqSbZ&7y@K;6M%kvHl1Ov88C%!mo{VL5y)+RXDk;;$u z@y`CM5QxLsB&Z$asHJ*PyI9m76rLW^gPK-dsF51A^{nNgV2?#RN27K~cWQrh9q!&e zsPz`Lqqb7C<2sn{sGZt_+EXe@v}`9hYQNpRyCmgL1*?RIc)KaW zoTpV!%YvOwz`Z$u$pUk4y8CPW&@22k%+pjwBJ{`9FyhW!@AS$Ry=N^yLyMQ{FVwP} zJ=tQokrl>Xa#veLo;tIXJ>JQyB}W!HeVx>Cvl{25@{4{hwrSE{ia+crES2QL|36eyk&I^>hVbMXBu1WJ5BLoc=ktI3$J%}}ez-OI{1Ok1nxgMx)f z2S;=C>&(F*cci)XT~Q3?TkvWPGJ6T{xrcw-qUFb3?!(4m%q+@Qw3l(mM2Z8GnFZyi zx+6K9Q^@H&giad)NNn0O-gE%y5}QWF6McCgx|Z0?^CrbAQ~gh7XFZ$c2W|dcVUFK_ zS0Y|RG{BkYO}d2Audj=5Fu}3jN$?8#9Ls}>yp~PN+1OR7QjrPykgi5X{0L0oT~ON+Wj#j;?mDPpW_S zHgYiu!GmG0DXu9>c_wDr&mQ1kh0aZ?h7eZUn`C$EiF|qR)@x=MMi)kq+lalt`7p`{ zH^Hx5=levI2Lt0*f9QrAcdo!>&@8 zWGdmq#M3jE1wUD9lKd#@NXZZcD-lW%gIwk|j|$?TJXaoHlM_4ylJ@SHp8K^!-% z@@H!_v>S~J!6p-6YGENyJ^-4@OUNmBiwj-2-{Asuksa=DS$bBKE>@lu*lM>IyO#5- z4Ze<33e>Jt;eTe z^7ile2R9~f>{W*~bQRNnZCJaN)NW(8*oUvBEQker#YmW(nTLX&rJT2lNtqJ`7~)Kq z^AZ#|=Eg)%iY*~`aIBcSN~zuSD*b}RC>>*V)=?It76%6xJ!(Vh#jjYY`$juO>puUE zCL{kwh=e!s^>zLFJ1otVAgv^(+sgnAwty%-PQlBjXUUndoTIb{!c5L%rU&Ui5r6E| zEmg>4thdZi(hc%M(#Lm!36}j{> zrv%Cby*oQ{=o?(Bbg-O^?ewvJCp0cK=*N(4zXp>M)IWqek{e{VfvkOx)F3+vtZ00bx) zC^tP&n3FEF)~lF!YIwj0wnlAeYg8e(=lBV=ZLTRg zKG*g+bx{GSWD&eztkBfVLuuxrOb0rASPtB_eO>T0!vQ@JUy)73)pl_xp>eR6kJ zdnYZL83)rWsT>{0zv`$vlFJWu4+QE{>}D3|%}e!KmZd4p>e7aSb*N?g)i#gb-Wn_& zO{?J`n9z|9h0qx<)O_|B)E_KUHLbuOaI@kZd&(k$&>@puS8{^0Ix@++5V`Yfa0Z0h z?+x)2cWhA^i90UQFL6ixTElYtbmRS8ho)Z{2Ta-ueo%bbEG)n2AG*K5E#9VOao+>8 zf8xkaD8CHXq*Jyi>qMIm_&^?mG_~j6g555ZF}RTbayd?_^-`IY@Na7prnJWIrQL*y zYcftpKMt^&&bC*4s)`rlSG}V)%`S$8aHoHI7Vr9}=SSQl&wbP(!G;@{$t>grMU9-1 z;WD@zQJN2t2^sUoq%6it72n8G@+ctgcFYDLnRL& zq^a=0Ob>&09snaom>pn+nluN|(^_C!#fc}|~?^-XNbi#Ii#gh-zaxYPQ?%0*mA}x;kfdyyEU#nmC+kQ?>@HTIu+UAx zT4Tb(lW3+WwZz!Hfn5}ffLXnq3|NqINQUhYNws?Uvc-z= zWQK3*<+qtK?Sjtk!q!K*hCW zt?>=nxG(sZ<`(H=&iOII^f_X@tKM}P~;p&9KF~(SF0M-qUeu`b@-JW zqqbJb!qZt2zFepBBxVq(yx?q@P*HK?xd6HI3C2E~AjazErYBP+_}94BGjLK0-<+g5 z=DsV_1Nk02e7EUw7De!U1r@Xc8=0w~F7msi1lb{g%y@yKVBvCt@0g+0*96xU2J=DE zzT9Exl0QB-p^|j*nS#q9N7?7(MO4tR{&qDA`ryh?0b0}ugXdXh8{EP-a@_T!NR9)= z$864(V~HM?i`NGVo8P*B@Zt(i0KE|IOd)ZAR^{QNw2Z^%J$eUHLmi{B3;3 za=aD2bfQ$m-(ll=aD@0Pbo{+NE5cueKpLJj{>Enb>nbekhWFS>hQqa#;7wS`xSH`` z=eUxlhW=&-NWVD0(wM(7wr*dWsa$@+U#u|Upo{pxjWpP84U=|K(z^NKFPjD(1t$`eZkKpZ|ok;oaNpy7| zA`IO?|1Ii$#LNr909lrux*^Th81+Se%RU^{7akrpi=9Zc;NHP#XahU#=fCbi6_J2D z7}3>tB!31TJL42YIq?Wk#AV%cIu^Rp&*qQ4JfXjtuFjA|FlTER$PcBdGI9C?xgwFH z9A(L+L{QxQAg%3OEp_SuUN#f1-rQ@(2!FzjMI5EPL|xaKbvtnGAvu!+uY&`9GVShU ze!Gx#F$Sr0Sw*{t+? z%n#VQ%Pvg_0-f^%Zd*5KZEzs`_8?=xLuRbQ%&O~D4y8*#62)#g>|v^1bWcOB>ROy; z?0(P?x_5l9EL-0A4-iFE(RCQfXb*aYTCYQt$&l0jeDMC^7{Eg@fRVE4v5S1-bDt2S zU8=0Jd~P6OipRy{3gpik&pbwDIFE7I?KY3GVW}e0br&(wqv|}G6~e09g3h|-Pt&2+VJW=TQm$UN)EeO8=Aq}a9>u@)FE0U&MNAF+nkDrb^XTARM&=}y(Re9VH8vA zM>EBwFlEv|*ZFrT3|DkYobGPuY^R!`lT}qc6a%Nzc#5bE>!q_5O5=}k(Ue0@Q=X)4$WLaUTD!92= zIiJOltf+R{s|}GULnRD3n*;E#TKxe%Th+Q##VQ za%e%XAiV#FHjn?L(Vw+f+!5(_7r`Ae%{gz*qv@%S~%$QwME9(yqEYZO@CAI9xv^)hOX`2?=p)~cUAx9x8qIPzwFms zmB$LxtMZy(t3M$5&JNFxO130daADkD@f*1?u6~~?-oJ`K)xD0r=BQLGtqb+|`93&_ zaqUOTNabJ2OXNa3;W*mQpJE_&Z{bPTA8nQm&{Oz0^rh_OboJX?zV?T4cydURxPryI z{7XGcl%R%nz1lwpYG`ywvL~epN`D{rDA5bAgGXsM>_K^hQ(+i!gsxBS=6NW@w~L}fx$9wI7_Ai`J(Q7lA6^ROX6#si<_5ZOxY z*I?QhmytuW}m6nn<~qjhKe`yyNwfShl^_+TI(8InanF z4%Nrh@Xr(d@jM6a#UZt0;)wz7tZA)GB_NZ?!NaaL-R2FJuN zk1t4?W=V%uI2{^&d#FRwnhW?AUo>j>`x@iTpF-76ouZWUdA1sHYV)mqT>V;~;1SC{ zp*LRYtDyXYC-Sd%QGFV zTALcA_4K#RB5HS#ofx)+Z`t4!N~y3x<^^B%-g=Xo;X)#jmhg&N!us?OHG{EO7<%P7 z%VskGL7TQmn>JCj86TiYc{g-w(u|k+@ak1gi_*W>^keFGImL*$;_diV_vn4jvJMWJ z_2#^n!=}0P4f>SWOps_1_}DEVMRls2)Q34=NtG`>p_>}d_%?J7of9FMF1y|hkZ%T61^$~1#@bgF+&gou;>Y7yH1&#f4M$rxjs2$Gu4qtAiRHJBwXIA4;C)ZXxlf+Rr zpL1{=B^#%2PuC=&_j*n8z4RGWNpSa#+bR|qe|TM##u~m1&(LVUttRyo)lYTB>(j64 zTCnsLI9_&B#TV%tG~Jq9o3T`0@~iZ0n}Kz4eW~(76_sTK!{`NLC#b7)Hwh_C)=lr$ zxM*Z8dhgP%Qn8bVxlUnT(Qdc%_SnrS_kP-q-9@Atq)Y9N~mG!>RPGSm(3^T)nMVv=4>Hiyn5C-_~3+-h^s)X%b9qG>;n zaeDd0$=cWUm5T4zma2zp)@iKqMc5ZOC#Kv;!ydtbrEKV7ofx}EXO?=&qc~@dpJ$V+ zx!o%Vsd3?2WA?r^ZdT(ga+i1d(=uGZW_sD(PjtK#<4^M0#!Fmu{!-l-^Pg)=#Z|{r zuB@0CvQ!rrm?sqpSCe7=$Qn+(1kK}w5kwrhnu={7UC?e(+xDl!>i~3ZaHn_BWBhfDtKVYPZ)V6J zyYFKv%SmXZH<*qo_QFT{GU!G9w5IcQtW?5oTlD*^kkWI#p?7X0;c}}flcF|7%~c&z zA3Euou|iUU^d_cG>X0P;!cROM+f{$^WI3ocTJBO7UxaFI>NA5I+fAv)-37(m)tyx} zq$Z;_ZIz{N#^p`@8FGY84 zURc~}O**OCOpn661nt*`HFdzT5t;9!>L@ekEO^Esg3k#Qq!}D$JTW&SjQV3moUSg8 zyNq{HkMio!@BU4ne|6Y3uM(-#!;v|aDEnzr{_^>(0-B)yO>NkgB-$KvKNXIP29`Rd zf7g`$4UdrrrC?NskHq?iRaQ?Cq|+au(LPBPNNa;HW6o%mHPO&Om#GML#ZnOp=gBrkY}9#i&xcSECE zCy&;MU}ISu^CI)Eh5$nJI8FUj9{uYGd6?b^cRxBN)aGAUjbs8H!7mqBY5gITmPy^P znRJ#H7cgLd6piG2bPx<$T%Y`4=smk%z&oQ~<6Wp>2itzW6PdzJ9s|?7l1oJK%cyi| z_xg*R)u7eLai$ZRDZVw2+^7fs>3P0;M4?<~3~;SqI23WK6S|kuGMT*)pgEh>2gMT) zpw75I>v^ZcxukE$^3@-^=S#n=oL^V6w`2&LCzpBt|Ksglz^f{*KJEmFL?xb}M5AH} z8f))yOWG4aZ`@G-x@jT@0y=TqLnl)>!S+i!%%;Svvl-$hp zljDUssPBfglw^k_SudxG$|r=v__Lgktsh3rrjvaURq z-bA{)v_o*@UuE!NH_cqGURxI2>i7}SbQuNa!r#P>+*1~^qAmzIK&&Wp5uer337z%; zH$GxtiSIo?yfrSlAu;M{ebrkc*^wqf05flFsfe5J?zKR=^ED1b)=ZfqNv$}zJe<>Z z{m31DlbA2bZr`o~QK3pa@BYnsErK?-sDQLz)o_!9w1;>5Q?&_V+ICQ^^(ShhnP&wj z3xq@1$#Xujr>XHgF^GLuI2dbPw@RvYTw6f8sv1#BzcF_vK9RnI@;3p^Y1xRC36sNiKTc|6KkV@L#`^Vv+B~lquALD3x?zm9VPXEX= zE7&QR8vSkBe5klPmG@#*2sU)5z|^kR<+aO#78B8qrbiLa6`EU2`IfObtVrKKInV~H zncZe=9~DnNt#5wxz|x-MAA>m_Oct7dfHP{zNcWRvVrKr6g}{`+)f4SUUU zqniH+;nReMbh|&b`}XJ-6RZT6hiNFu<`uZNA7)AR^auSX#&SOWhsb7k3!mJ#1)9oR z{ZT~H&DvjQt4i+MzUZW;782Jrwy!+XjpV$iU(P!$CrMB39}$85B?8U9(7eMD0n}69 z_35#m|Lev7EVk$m-8Pxs7x`@igMCw14^D3F+&QB2Ux(!G?A$ppJ_#(`Udes8_=#GSL zZ@Zhv1o!(gV8}hIaoG(_aPv@W8}Jiii!aUNl>NWNTVEeMZvCclt^dd!*YZ(r(?#c| zO4B+#vV2_Ipwe@LF}$!ITZ0rGRMWm?YEd;gn}W_wC;I)TlChYqa(e=y+k=~9~ehD z%EU8zDDjNAWszn0&fgfc()gmY@Da^egt=M!*04&B0QKn-)@q;!w@b zOZne0z#B%%_-%+c)KqeT^03l_@~t;6I^m$P=(WoCV{PA5Qssumfp)_P!@gXuizr-o zgHEA|^n4ug(Gbd4>Xb9|zKJLi2->=>yJ>*MinASxd&UG1Or#7>*cipsNfQtZnH$TX zF9{VSlq;ciM`5ge4?eO$^z>r|wm@{Ot#@&R6eN(eX(g!p7|@{hG?_h;lKjA31I{fNEH+fpy_10qni##@yio z`*8@?ATYt#d0D$j-&1+d|0^Oydn?0LVFoX2xA}5sycz*BSvw0b*X~>Ky$>U)=pW8s zU*HE0S&3@JM`!JhDDy+!ypVpkoohO89G93|fJF#`_ic}q%|59dw>BJc`nG6^r_{6$ zA{lJNxi`!ZH&iajCIaT>c;rs+*YNl6G=1?hCK<@z z{FR7yfiH60e#(80a`&hLTAq-xk8OkoW&g9!{OgSo46V!mrp}-XeM1^Nh9^Wh!y>F6 z3c-9s#(A*&UyhV!?VSynTjuLp5T&y9;E~pljKHT4N9d5i>9nEu{1VHDE*@@b$cpW( ziFCCWxcek#`RKcw7wE|gTr&bUU8FXFJGs{9@&d7+5{rEw{=rY4r_Sw;=*=s)lMxP4XpbERCqv@AMXov}e9}V^R zPv6p+vloiUbS$K~bFMuvnysJ84KqGJrAB-E&AC5zAGWLoWA|ZmPj%(CX~PoOIb3`> zWp5q|6S*t#^XwB(olTGTDW&=GctCBf3ZP3&*D#W8e#l?Z_6rd%i-ruRa<3giGrc7C zyQwT4?c`S5X(zCGgZo1(U!8iC^-=3Gx@W^Q5oyXW%*&}U=x*&rkrGtO0{i=2n{bGB zt+h%q_M`FNaYPQ1AZu5^D9oQQB<0`fxlpZbUqEzww_Gf^z7B<5;?x#vf5}MoWq>jK zSgZ;mnuw}`JK;PuBE0Dilmm%UYbjN;CQ50#Y;=dzITTN*wxl*N`ASMu3E`|(NfYJt zsz9ktZzwCGC~R9f89{dQd3Et5j?-5N=v7@-a7kAu%U=kG%nwZ9pb8FNYuNea1vcE^ z2ry^2M5pBx9|KTqk$rCsRrVZIS1vY-$CfV=d^=mdO z!HVBV*5sH{cV604y-dWKEX1vV>7LQC&O59Q3;hk9sHrDQ7t$iX-EE^-VzXFcvwQ6X z5#~z%H)g~ zOQM-qg=_e^t7He+_YAVZY*Ri=O1u)9>nWfspjf}WF{Lu-VCy$}Si^L_X(n1$=$4)2 znU@Y`qoZJxXrlS0Ey6sB63_F|jpNXG;S@}^7IQkAnVCR^m#ii=Yn<<~NY3-fXo{1Z zCngJuUO0xCY-)kflgs?issVV9*gTK5KQ$$s*xI<^zYw^J^z3TKzR4j{RYGxCqBs#U z4?3vxde*MWFOZR@32w+RdZ`j)k_N^Oi@w^$cpELBfDS2q#O0?pN~!q0AHE&2mkQMC3+EUX?0l*ec_boUcz77Q|5w! z^HFx&_!duHMTjl8rW(>&<<>z+dv-7H%5jB2@=k#($CXE(^CQp2damY1Wdbx_rN4-R zoy`td&ONp&Ys-VXUI0SJyFA6jtr|bj%%u{)>SS#pji|D*YUIFhKP%pEcF$&ldxi?% z7P8BY(>9s>HU=`7m*F1TCKj8n9h^7BY+TUJ;@Ax@F&EIjD@HKDGjx|vzK~GASldF< z@k53f?9r% ze@+|PaOD^JaB<&*U4IoWVF_Jf2|onI6)h@{AEzH<+Q(FuuUyy?UchQt>J^$aUuWp+WWUs)*6iB9I$bzcX4U+l1G>uF4oZi#|S*V9d&O z(`Hyf7J@8>5G!-v4{h&-YoJULZ6B4njR{4s^v9I9r!5ae^S5?@J;)3+>_gGwa&D-$ z%zgD%YU;DTG?KF1?U)_Jy<8wPmHScLGyt9%^)w)1IqnJo-Oqe6g-EfrM+(CnD*Md# z8cpJ4=czFQQXJGR+gGg(hbA@69ZE1F8|&sDu8notLhE~aMTLqbRq97lXXqLq5GGf(Ct`<9-9A`=_sNVsxG45T%|U zE>K+qd05m_T%q)wKLj4#A_b^{sWx-Ny^JkZDZb2&bF6(Ng0DAd{ecyZZ*ge6KSRy^ zn@Ax@GAZgqDpGBqHLT4+L(eX`!@!oWkDx3Lcin1Bv~f3k$i1SCGaCQZATwTy%RJcG z{lI?hi8DId>DHA--@t}-5IVx=9}%UtREzsgSWT^wI>&>#Xf+0QW(XEHunqW7pu+R3 zBh53UOFT9YMtw5ox)~hiud@6LeExa;s@bUeLAuPquJ<_5*t?1gkKxvprbOUn1C; zbMRIJ3tc-BxN*LDBl_XpK!UqZ;ZG>+$jHOMlKv&f;?UTC+i9NZZOtA>N|D&_B)X&iq{ zW-#_(TyKm)+h#!<)yb9?psRICUg$%tM)Ske)2joGskYRTIf#Re7rN=XgB)4DclH9` z*93K*?`wj3&-XP!Ll56?#cqNKmq%S$#`njH`1Dx4bwvj;!hrqxnMhX{-wzJKyzDRV zU_~ndXkMDZO^ZG$97Gx@~GU~H7zQ4zc$ngFD`20t#iqvEbJv9XLe4p>Z zHb<*5uyaGOxHa$f+pN;pRzylOyvsZ`k31hqFusq4`90tN$md_suNtTNvsAp+gI&@O ztTP1je1Dz?%a4kO@%>!}7UBD9-@GIG;XRoI_shT&-7}s{@sJ_?%%Cm2;l?~enLz|A z-ks3~qo(p^M-PfEfuG!qEjD=JeaM)k-a>i90_?mgCUq<`B>jaCBsGMV-d(zo_jqs> zUE&Y%ax-r-dhgM%h9zn`^eVS*Im-{;Yog7w-kWD&;f4z-fGSV2k!r%=8ugv?k* zZhsHi7$q*IEaz#5kcO-inHjt%BaHVQ2RGBSs z3m%b!V@_!~AaU-_l%Zas=N{c~z^ESGP^Bcq+k?n65N4HWqL(_$%S24pLa}SVLB-~c ziJsG3ss;|fJ~Ta!+!4XkVxDs?$*o~uM*0ITVKT4I=#CW_Vm%HXW;;=T+I?zHuXx#T zg}6{1$jWR-Va#zjLI#YD*Al2)V4gCDgNN2<%d1D%cPa!9HMCvrR%y{ z+y~eL=_;mkeei!uWZSjB*{%DHx4)8|;URr{#M*5;1}!U7qd*s5_Z8IMN+dI`w+eGn z8g80lU}$jP>PwOUJQ78Kp>^9(PB*h-Wsa#cQ|T zA9EEFB8ip}U;2GZ?{tX(JyiOXPpQ1Q(KSgMlfTv+GH+eF*!;{;rdl)ymn&pS(J?9;DqffBT5BTN1=B&TWHcT#yMgO%+|*sF0)K1AOF6Fo*|5 zd%)i~h*4CH#K!+_I$I-{+rKN?CO2mwa1d*+N2b)~Ur^AvN7ik&AaGcJtqRKL_%8xM{bA~t?_=KJArQ?Zx*%$FW# zqE_a$^*@Gs9UIp-#HVPWFIl;Lc}15>+-sYq>fUh zaA66oUIzBit>8^CPsT*@j{wD%Nik-Xy2Fuk0{rlozeQf2>k&K4w>F?Bd+_~nwxkC&)bCbkP&S%L}Jmr6*@hl7V9aZ{( z!7XJ?g0Sl3*6QRo*05$Am|!n6v9PiB{Z(9RM`65s841mA>nz^34aQhI*-g3BL@GRV zROjzLs1KFT5GQqq^6elX5y>3cP^0_$PSk0m=q0m(xu5n7* zo{Cv2SvBoU#f?p_NsS|lj8)d^)HS*CVlxO3{Jb=gI;)#qsHau8zS~_rvNOTwhO<*+ zSc9`j+ox1aefrDtI9|tLgt5J;lC5ged3`s4g`GKbx%yVUG36NBI}(gP2+|EY-RI4+?^-3 zNxqhTR@)Qt0Yvu-*#!2sX{y;>{2q0jxvO|AolkMWuGXsPcBEguM&D};D1;%wi~iSx z+b+*3v@8=LOC;{}t*wb<7LeRqsHm>_l9?WPQGH+jboFT_Z}r)fKH0B67&@HcBcFcF z%1u#~^ZL|x@u#a#=APAOcHe=0>YL*wnkr4gd#cP)l{aTJga7T_-cMP7UZ#FMxCJr~a1B|E2!etVJrhS3I*yZqT@Ljk>Qco|GXWA@?J8DC8z1Qn@( zPBdr(i>B9Ansp#CGG#CEE_An!^kQ12;-;&bifA|asAJ-YyOxU7(?QI5y+sfFldAPF z?ty>9v&SQ!efcLg>qbHDVttkNG^jn4u)XB^%4v+4+%34QMBr>K0Kr=6ADU~EO=DRt z1oaSe%7r%eLk{-<-JrH2;xhMWNwH^jX}Yf8SUp{Tb-68YQKR=#{8NtY5FYjye!r(59ur zU1p;Dc!cj1=%I#Fw`G7kWV0kj1OQq-X$g>To3 zF7IEoUCS4J+G~qyz4%S`4ht>`kdz{hSFW8=rV{I8i^mMCYT4NmYdu=y7ALW=6*UUi z{DPK5>j-!E$31y6y#gV$qS`Z$Symj*V?@RqZI|}SjuMfLYOKd$MAa`I9=&BW8%UaI zeC6L}9HSuQdZLJjl#grK-ZG_%$JOXoM$;+Bj86`EBHm3Df(LGXR{1BZr0M{P!ZO36>n69^%CH{zM%V-7410jSfPCp= zpm{vWf*RdREhuMq4Yl~5?NxStny|HQchM$#>H@QM#H2m_)nmV`5dC*;zaXh&#d-81 zBlkiPRhz!e$2+IA#oqD%DB{-4n#vbuR0pGVI?mX5a%|6bUx|F7v@5Jx?C$urFmCht zQ}IEY4@L1^cjg^(_{xT+$1@|G3So=gk_Uxg*idxS zD#B@KvPogRXCCx!6-p<*%zb#i>0Q>bZSXzX8fUs!p%j!-9CC#sMXnNAl4;tgRqx*X zZ1G+9`u3sPG{Z;VmWcDJ_=*yxp_zxe%tJi$&_AgnlT>97pn?j46DcQOU;OlQ?^iMr zGH@ppGDV{x9A4wn7Pb0A2Md>0offv*f&chj<6kdP>^;8yuh0g`Dt5fKpd(xV36Ako z{6Q=92y>D+2d$(zzhe7LUSq9u?PF2$R2?e8bt$de&zN#OQ>G=S>3EDGX9;mQ4+Eih zlZ#)DG#O>C)|%v2u4}>-*VAs>`*;OpYt?-#wgC~%HOjV7<-2wJ`>`ofLRY8z-WQA? zQnUR@9%)YU*q%Abqv+IgBB*lyMNvVBYFfvh##6I%N@! z*RjOkrUP)l@4~+LnWsO!mmRNZdzM@3q1bL1$tOYoc>FPNQKewADt04>Rpw|2?A&N` z`m#*-><~cMJ&)-*RZI79{qf8lzI*PmkB7W7R&B=D)VhOnaAy0DMe4KP4LeWzjxLJ$ zYCKmqy%_1Da&-|}M_U2uqC?e1=o#xLxw<>kU}n=fHQG!8)4{1RcgE3gVNh4TD=Eqt z6DqH3iF>Bj_tjkAS6t0Jb4RAH4!JeagSSpyIppi7c%1zNFE#>>_ z4eP5C>(abEqmJ1En(vl;Th+RmZ_|SSfp*QN6 zI@yPywNZ z`+YWnvV9TOss};is0MrJ0lDuVwC-3);MdW4bu3Y#&A@81&YcS7`Egssk>?~A4 zN$xU{uvh?k#ff1jDA8fp3w}`BdTjna5dWK3uDv=;z27@ehFhcdrsn^gFx2aKPKZf& z`TjBK$#;tPG$QLvhGJc^P`S2gU$~}fcA|8A&oD}bRbi{f(+}Cv_43#0tz;Gf6@@3g zqp<=}c$~7kPa_wiFy$Z)HOg;$iCf`e>S)T`>cKdRsy+1P=TTHwEPlq5X@Bx=kFI9PSaQGkhH1ko8)FnjSbceIMJlO;V~z41ArcX{rdgOr)_CLss$ zZ*}CXx$ES3?kbgB5-Ifg*C_N+E0Ca?pmzB>GXc*-KFyWG)Rj&DE*gT^#dc7N&Hg+BkM9(}Al&kA))@rOtuej0jRXU74=A{QL- zs-MMHf#8hKCW3)ALA+kGls$Q9NK~$#dOS;E`Qh|cP|Yt=!yR9YddWu~AW~exbav+Q zmK^yv8P=`}3aSU%#_F0xl8e@S4^=)t<;0+3$LSvLv6b81A4BeNTca5F_unu^4hKIx?FoaYz2zE5x#_LW!%+3JsXx zbY5XlbVn}jU(aG*lFeVN(Yzo~hA<}5>C@#P&SHGeo5DDuL6+QI>)hCv8BBkN$J2{@ zAN_&3(o27E|Ijzo>7h;?VInokh^$XRi)V13-1K@x1w6;@hOQq+$AeT`DduAs|N1h* zj@*`;Ks{JmW+E5<;wY%lyLhoM*b_RAY2E%|to`-DOkx&aIEWDV_P_e)JUy@W&wI3R z4O9D*{$+5>hn(Q|5HGAimdI_tP*|sYw0&=XQq3MxYFCmv5z0Ynt<*qDHfhYbED==U z7>Ji7DxZqA)={1v-uL%Gia-#z)da(fYf_iwCX)A?ySS$E&#~5W;A(Of}65&_PsF#d=A+M2kYRzAB(#znaRWv3603#JU7` z?zNsO(%2bIiM=-`xM8JzsJ;ZVr;Beh4Grc_=2Z>xXqrDk03ejYzM(w!s1xI+yeW3* zLz#R%GxluO*t6Mf$@gTjP&kqV{(_1Cbff(~(l^VpNS1AYpq%n+0_vJyx|vt)^>_MQ zxu)rA?U1((3(^vWa>^9DuQ5kbOjQXt4NO$MOMoWc7mrzZAZbbmrDymf-dzoP&5$m*wccLYtH7^2sKM4ie-+(u zXe%%iuOcoZ!CXZZdBM=g8?M}$nmASU(Aad=eIyk?W!7+0lP`TC) z*Q&k2^!#|`j#w+loaH1^!;VV;vr5mw@crTP8AntH7Z(?^$vxJpscq2wnc*B%!m68& za9sv#z7%WSK!R5G>Vk{+FXopOzG1f1R~S!)9z?!+!_|#5Y0ZSR%rPuDcxSjdo9G)= zZkiQURwvP+kVnGR)r|G)J|d<`B=dtxSjhO?VWz_P?h6rF!r`BHiWeCC#nGkQL3Kh?-Rifc0eD_A>;wGNkwlDl1^DZ17K zuhlKY}T%Q)4QsE1!$a`Hh5c zW77UU8$B}NP;#V^#j|s>blCH;)^jDjn!L~fxF zZQ-jMjiCvjz8}3Tc#IMnI9!kx4* z#|>5Lkgxz@V57|sRP2^-`pP^heD6UUnHMizN&4r=<%WWklqB$ba0^7xE1VBgiPJ z&Hgd6ELUnOZ)Lx1zZ5;+QuVZ_N>2D*1iSeejnSN!5It(dB4UpFvT^xSr`peQ`;oiI zRqmxmnhV#K&oT_^`CUr|LQBi?#7l?rGXg8cwfLg0@jqAFPi*n&dkCZHjP!XD^2xEq zSJOMJM8+0>VX%av-raGDHSUh+rt{BIhkF`gxz(3ioYk1{hR_S8Eg$8Z8r)z!b*4W3 zIQ%r(K8?|*Tf$G%?bAqoY7Rfu+oyf>N#(oyJqpjf6X_P)r@nWc(dW7K*je42$Q0UH znV;VCtKH4locXc97ap^P_w0PFnR0hOUpoo=twduu5jgro31x=(?XtJ5JQx=)wt2Yb zrpyNj$I-!=hpOa79w=4tkBhMT{7zD?=c`;gjk(CgI_BnA@6Xl-8{M#%-^fna@KR84 zzw=~ujz}My5-dOw&Yovuw6`5&ZGOfS$6;k2&S%YSybcHH5ZlF@8g?slvG2!czTO?9 z$j)?ra2yWo!dUC8bUeO;y$0pJi$bK$lS?Y!g=JFbbSIxNDKuhszC9?e_!tglX}0fE z4)TFB`u5t?VePA@7Iv?;6dVF?o~&M^{U`X@VGd{QRlYl=B(%KtLPcztvTr!`EsNN_ z4_Zb9=$35}&NxiW`K~S55W6xixs3r}%0V0nJ?I=lzp5)=n09A!dp3pozhT9=ulk=a z`9hfymr)QMnPrD7*TQDA5!wFymBL)h+S@PYk!|KCuRk9wU8rtJ`Cn9s%q+RM76=M; zWrL)mkiMr6*n3{dXHCNcb_x!Q84F74hn>d^=LWn3@Sy$&u`rrBi^rY$|yVH3}V|bfiAX!lEVh_NwiF!KQKR;7&xTsXYO4lyBsB0 z@RfJ>S4e03y;uaX#a@f6HMht_0Wa$|Nad=mcT7n!DpHt+U6hMf%#mV<$KtGe=VDXV z--^mZDeZM5!$IA0q7c;mXkHEKdnhTDch{W}8KSZr_fOd*zjMZ&1Vu}JoNs%H8T7JWgx>r>ZqkbO6vgke~i4l4?5!U$&JYOm?*+ z-lq*2{hEH7O|qYWv-{>6RE4hj?(NTs&ALe)+}o!EnM>r39n9pMA$&g#;eCb`aj^va z-?s76kI;?(W4tZC)&M=}3k-ovr|cI`4PwJ>ZyV)-G3uLLlL;<#RPSV!p6tnr-H#GOV~ z8d*lhF#=?9c6)czk#OG!^TarkEOJd3U%?J7{OF(T0l(15;dYJdgk2R!>QML9L}P52 z@kcwL?hE--P6>wGtfi0>?Ccym_%mcd_wR}WXIhxHIwd&3>Th_ZEmiKtRc`yj4GTA%^xhI&yT zTrIqaI=dF^n!jSRZt?w34_txLqfQhoYCeb$qdfXnRfn68QR3%oJi;;Sy#haiIRLia z`MK0$)6fWw>ae2g@iAGbA*4MlG-%Lklq)-7QWfrHo1EIRN9fWe5znk!j&VpozY|pu zh1B6b{HpY%xuZQ@pqGZozw0}j=WdB;6!C>y6K063HSS_uK7jqCAJ}~%nAct>c(CjG zfi;I<)-7%y5B8;gU|$3bB*(-jt%@gUeUl&b% zES`cG^0NM(mH)~1Y?PG>h1lg$ZPkZ=W3w>7rB6zFbQVRIgQKa{3Q}{#n|_KVB+G({ zrG!Mj9-qXOYo}4qgz4Gl zgPGvEb(xsAv1wh`)@Kn2q6xz#6kpCyNK{S5!q&bF zxjU0MTS5&My1V4$oJ%>JUM7bGj%1JLmuCAchG3h8*&1UpZ-<3=M!kl1|$>}yN zg;vk^s5qE`{yCcEG5&+FX%P^{%Q<>=@@e+fOeF}Tf~bp~*{F-wjk$?j!eO6^cdsFF z<+#?3*N=O4BjK$R4qQE9Waqd&->urRvZZm~*3QA>t&C|;x-*V3Wek<+SetjCP{yNZ zs^S4vw{lpPlwhy^n|dYa6|3(s9{Hn=Y42#}Y88kY423U82NMUumF2BV2PdEH+%cl_ zokMb8?A$Rh_Rvxjs_{ApJ>)*Wf{b!$d?TWRN}!Y5<4hsvp6P@**Y*;iUiidjohIjK z>!#_#X|iyd9OOOr*8VyK#cvB_7TBI6pk%@JQ(4VKMd~LBD_`}akGfanb@7_x4*y8} z0TY5899{5F1CrJaiZSQH+SbQr9brWt5MN2H zD!k~+9^fqf=mz<2eNLVKjLQ4dn_+o~p2CBk+2%799Bt4~$8Nk|3CR}cE+U|t^&E-F`BiH$ks(NjdUv79#w(ZrYaBB34{L^2auvWNUi zVFS9?LhI`+8???_=(Cll@6}KoUN!1|XcRS)L(_Bv7`cOv@{Ec6qNkaT&^`OF4zo)T zpgnZ;uJaj38lz0LA20LG3~q0&%EDV8W;4y#fD!l5qqfCccXo5F#e(=&ZuqRt<)W+i z(2^&zNJ?17pi-;)L+getihmaRTVEKxzUwa{5;oqJ8K$q+}*Kb$k)rE!Ww~gM+JDUgn zW6k_%tAG)5iYUsCT6_0hQDt4>uDPF6#`jaXD_5wC)93LA(CsIOxXDy;%T@xV>zCcP z{(zK`$BgQ%;Ka?|eM`0Wl6e9$ay+uJHgk-n^6m@^b|ZfHk&YzMJM$%WyXM`aq@du3 z`eCwg7-)Pu1O4#5v_RCbrlAr;g`g|$3hsU#f@l_8**SwF0Q2VXPSL0NqEB3rH-;x5 z@(#1&#Db}Um_0+B3sf}BiHK^pk}Z35N7u9b=VFq6)w)Z54;eo0(Zt>a>_d+O#jt(i zp}DkCgtft?;6ZzqGl;QDj!ztn#zDh5qU>S~yV4ttv=v#ajVGVyii-hg^W17y6F9sO zmr3hS`HO#P9c!P}`H9pQaPTdSrP?h`wtFJDcwJ#lFezV)#VNT+$F&WljDc20mBDeH zu9Z>j%eZh*HK#eHv?dX2&EqfVtt&|c-=>Ve#8QqfXd6&d`DQGI7uS~DN~$YAh@~Fq zO*vbC!NXa>unp&=25r!aD-(m2vDWzlP7T>UJ}5ea4w^tv!9=8RdpzKO@}!{X7{2mx zzq69VH=GrWCF_U;S5azq?gJQD({mMn^1Wq)GlVlTK_c2o*yyT6a)@`Ux!7(1wP3>1 zH(2>BE$$niH6@ZAXKRvg)+C>`(6gH4Uuu%e(%ekm?M^kY@QeE19UXo#a0Lz4B>!AP zyy-nkjD?BzCD50T4>$d@#s7?W0v1|>~0!tN~pdb3dee{D}OO`tfR!Q#zQG43Hi}sttsE}^A7xO5X6%k^x8z=i%b8uaK(VPl_MkgdNnz7j?ju?qgBWb_L|P~IB`n)i48r1F|G z8P71pd&pX_)KYT0*h!xG>b^=~b-Fs*h#vXJTei*b-@Q=w#LP{y@U(xoMZYQk>z*7W zguEe9k6DyYgP4nlGd7N=J!Hp=P?(d+Hf5{{yIcw0=b-nQD~ktde0eS2+C3(g>J&&4 z@AgmgRI2H-P8EioY$4c_-4)2I)z|54-HX9d^G}@`n_Ol$QE_anw%+^LGnrm?x$}Ip zVU;pxhp7XT#k4ySj4Q0}?norZ6;`!$55)aWq7OW45c3#UxeHkwk8TgLDZ9CR=ZAZO)^fce zXLK;iPu2pV^k%+0%+}Q9;Z5ldXXWbd=<1NWP1ZP^A8Y#!57&QHiBNzbK}f;DqpNUa zkGcM6y|IyTb>kjvmfkr#7pO5w#Al6qGYGqJ=5qBadk^wHh@Qo92p`>5W4%rheNz+d zG+%}5(Ld7Vewc3oP=iacJs?FT?j$3x%xvqKEFHc;pZaYGhA*fnqqlcHr?fE|wgsO3 zJR)QRTBmc?2sfI!L)|dtXck%W4=~mXeMW$UU5p#~0bvC><7vV_uzyCH(i&$!*{xW~ zSJSzqu4o&oz8uG~l&rRN#OX{SA!;eORxNdRgf-DUvOK~)EBWqv`)>S)#l@*Zfvk|^ zyXjhfV~g)BhSWsR=A}8BrJF+CIVJ^=S>po46Cy2m3(8aE(y zL{F@WwY{vSqZxGIE%p_6KCIF&ypilslCBc8kF=seTaQj8Qt@}sOWR<8dQmg4olILw zEp`XdNT^XFZk{gPQDt*LcS(t{hnjWb5FUv`%I9FVJ;m!_)72urMEX3%Ae}TFDadky zvZ)GQQWPIgh>KQ>UK^)=vl*HhplX!L{}ScvdwJLW`k8F~q;f;I1m$KOjG5Ak-MlJa zT8ZJ4{-;>s%15B}ojhfzMkKqcP{&NFv-9a} zV!Ts%Fa1?0qd(r6|510>uiarF(>1gAd^t9&&hsl|xkAm?pCE7Za~iGCSLLMk5Im?Z zhbxWZaPIBeRxpAyCGEax>oO@XMmRPqBR1;GqAgYuXKiA;f=$6&dQTR-t)HM^t);GR z{Ic@sF2kZf@TILo3|A6QuF@5dmJeTYm7ImBt}0VNO?F*rl^R?|gUi+61Jon1Fl%9}rn%=L#+r90?EuU3mj zTLpWiPqrQ}So*Bm0#B@-r&$HWNN<5rmq4?e^hPo7qKA2s8J1yQe(7*VzN4f56I3Na zP>il@A?wwn*dS&~^Gwb_ZC%qcdw#wYo?Qa1?J6&ZfK#5&03MJ5QL;*-_*NYz-hHqs z(rxzRk?848n?ITD-*3HuVTj)Mt3;VF;Ea;D8yQe7h3=~3JspcBQx)O>R0YF9Mz)c1 zt@JWFf|8AujkMCnoT(5AW-pV6fdiUh1~dakmiYDBxxQEm^Qx%cx-F}AD9rXP<8jhc zg(@gQ%0_G8(RoDY0o5J>M9q!?SJmZCQbt3@7* zpjIguJIZAVmeFWQVwL=u=ai{Xk`m0EYZYElX5&h)kX#L+co}KLMHhIMGe~5iYy^<=9u?+p=D5*&0sBAc``n4#GoJ!nFpaP-4IphC0YOZ4DA zepgtk8D5BIKET&t<_r7pGe{=Lq6{@<&-6#_mG}?Xg*oUd@q7bKmMBl zKBz8P0kT~nn@w}_t#?0xY%4bV&h^HF8%#xAKiLI;^)G+VPt`5o>|OrPe*US;-|JJA zzen%#&;0b|Ti8N=M(%dURzLlBFZ#R}f4+D5H}0nV*sRdM8<8(@dt4qE zxJ&7Xp7d=2acm#^_=oYaFcPho~Q z#d>g0`Bm`}wW~}O>Y>~oC@G$qrkRx7SBobT`jk#ryKL@`YIY zZAu2IDt_%Do_VOXhhTPx5@=u*#am&tlZM|=q9R(i4V;pIj=xk760^vs6z+UFLTwLc1L(kFxUDJBVvMz@w5+GJThL-*lo~W z*gr{?zp$yhyX%J;rl2g}eLPf9Jy>U3C<10$SV05!>D2%X+}Q>YFm7L!a?*>i??#eLq$G2luZ3;!mnSHmhCz*=tPD%&g*pmZpp#>6zKr|w(=dibr~W3-rq4`g1@nwGCCUCNnCB&AZPPg-WhfytJ5(l|s^O5+yR$x* zPZE(w?KYr{uPC0JX(dx=Us1`Hj;PFxib_%MnszHIXH!$xd^i8ckmuhKK?%v!i#}8P z%ggXj#WZiZUh;ATmF-GiVzbuuqraL_t4Ys3cqn!*L#b7+n!$ytJ%~m8ApN^UH?7(s z=X6qrhQ4EVLCkr+tK@kKlAf3e49?J1E(LUmH8-O{BbIY-4Z6kR+%nzgPW%zX)z$L- z`0f8Yd-XFtn9|bSX_J~TAdd#CrOE%Ry;`%7mhRqO-QD~Id-b-oW@BDTM)u(TNkTIB zEzecqlwjSxaMdTyPhzvsR+4WtPG){U)pOTVweIO1&&$bY6c`>d91iV;M?{1&O1eZ3 zE8xG17ihkbbRC3s;-i1Y2r*~mbyoo$M>;}=8^lAOnRYYH<+DaQp_e)H_f&W-y zl8K}xCfQ8!ROUDD?YH+dH0tGt{HG5yXpk+`Ad^eM87n*UMVVj_Qy@U|u3QS@T$`GZ zxz<*?S&8iKvb=5K?L7WhC4>Ok+~@k-JU>G|=<+A*Hrzd#{d7igC=1As`KVG|pX;=u_5rS3$ zI>@fy)r^nL7jX|-)dTvM5R_GvqTCP^M-pyA4_ep*`nZ9z)!F)>=!p<-+4#a%zaDP` z$RaaE*-}N#Z>rTSC8UZ*+m2r?CQy$;@lt%w!e7+k+sWj$=#L>JGhTwSJVxlfOgra> zptXQL7?K2I70;Rnt?dCl#bdGfAHqUM-KC1I4GW*H9MgS{$vrtvw!+&=ThxcCqOoCf zXWOga<*PjNJwO(xCzUN#^cSlryss@)v`3ixfiSmzeeQ+&lFdCetaOpV<=wJLJRP2- z4>vARHj4L$`1f%25msql-L;;p*ZSN;ZBHGM{r2jAeQpEDa&_(>g>v47fA@U3(dWJ` z%>-)@g5@KA( z3$(6WE1kAkHp^yr@Cs4uO8$p?jdiyudZ>zlG}d;zPz~76%N&AuGq&Df8`)H&mfz@{ z!*{Fyxa$x_KYgPh7)sNx2j&3*R(9%Is9H3~ zt=0>bYh!H#$>H99m(X4Aht`^I1~{0v(5SV*K!b^*v8P$nWZF%lb^En^gsNDVqE0b*-GOow^T1+i*&CB)ht}la&#zc~JkV%{0WsmRu&;%=O8id17BndBE-1+)u&lzxW*pB5r za=_XBT!mp9XAU{(2|AsNDBIQ+=~HHRwC&ZP4~!p%DTzWwB9UqpE$)3-$-+)$zLE$G zP8Vb6;36QkbI{YKXJ5Y#_LwmGC2hD?qZ3H3@f1AMP&K=;^f>LHw9GI7N4ICd*rzCP z&L>D+i)TDR6+%YT*#@D<1=kPL`MeWJQ}uPE*@3-#l;FOrX#o`J7YLMzOzQPm}_#YH6P|Ni1-D1*lrOYitzauROdSHu<_wHTze)*k>FwN*cr0}iBhy%V z`~*(IZ=X^?5_u~G!gl>Ceu+|VJi4a+AF;Oaq;l>BN{-rn@$XYa__Z*TAwy5{G?w*; z|2GFY)NtA?Jn88UT+<7xRXw8Xpl-f@4<3jJ2LpYxLo}*`6CvGROGG*_y#^48+ReJ- zu-f94AMsM4Xyxrc*_Ib-0lr z(i>t1QCw-(cGC2&f9kdA;d4#pyX>i5!EyCE(GF@c5crN8pWKqZMoKcu5!yO+ydtUw zf|eS}@+wHWL6iz-cTlPYKR&|;>jbYP8A(aWI;Z@>{G4V&-@tc^z)6I+E_r|#cgdk% z^Iy?dw=W=ISrsi&GbF)FMj7PP_6Q{Wp5wk7LaK0s-030T`$_~7EOXq15K=W8kC$J+C{nw%Y66h1MYv^9 zFpH?@l8G2%P48JJK8*{-=r}Q5L!V z2!p)j@(3hngygtH2$?13OCIv-I1At!qvQnZ^HL4|#92i;cxEF-V3JE3l2w zT1ZzLY+fogm1#PmP8OcOilRhFz@xw2uVwawZ)6AYsWsL z`t=QwY}Rv63jJu$y+o)lkbjKs<;JGUakm2L{-SaK*GPqGnQL`qyrQ~DSg{eSUjMk; z?dNO!W?iI4>#eg?PKeK*zmKFIu39$j7jk!cjPzjp>U5EQsZs<==krocbn^#X2ZPZ6kZr*n-rOtsVuFl4fXN@xvIA=7ZGD^jqsQVU`3$?Z=NXa9~@Cr`PS4J z)VQ?txCw0x$j1o|Tec#h-7UXfCXB{w2w>hwNt%H`ECuPbZjTXRD!+`qh5+vD;l9TW z8a=7(^`dCLYw@gd`2~?q6n5@165Nl&j16imr4{n)kKdiHN!Db2*743q^NrB*aSCsPWTrwKw=2FGpF`WbX#Yj`F&}M=BPN`rZUXTo{VCHL* zg`-1j7b4?z3MtM^c1~%F+B`{n#Tlziy>2962h7JrD=~T=KqV^Q@>}_BKD%|pcBnzN zf1Mw}&9ZG&0@<` z|3zlrgal^wk7CvxgGWHD!phC={H%ekh&4Ay8hwbBiaTcoD)UUSZY*g>|{E| znn;v49q)d{DCgp8VAx~nuc%baEfO1?J;R$kOl-Q=Fm7U^k zYJMFFNyk7_>{>5Ik&LH5=D6?b?x)i$^t*MrP>Qub#!LDh{z#2T@2C;dD_qg_l8jlY z-a_{@5kab{*x%9(l`Z(zDDrzrA#_#y5Swd2pm~i^J-DWsHWC9}(|sG{htKWg|h)u>UEVo{{-@a%J3WkW3{urIQx; ziUr!t4=2>?n+Et>TrvZNJLE~B&=wLPql_iVAS^ATf^9a_p>F*HMjn#;^#>!W?NB9r zaEMewTj);E2ox@3*a-2wQn_dQ(nvO@~d&52Sm>S3h%d zBvl)k+~@W(_umMgena$(m*Gmk!0J&XKbp!pKbY2jEmDk44*o}#d|QQp{wJE4-*_Gq za}l;8$PVm>?Ax@$9qN&(y(UtN%~F$l3fa-!>6IoXEaYJa*x ztSt?-Yl0JTf}T#H)f|7{{;;vTAA}RZHd2i33*rk+KfX>zAP0k0kzWMLQuKeL{P_%A&mbYFb}QgK!craZ;RQ?|X{J5@}5hceqsErlMs&@|tjKui01g^+PDW=56t z7YUYejsKK(uI4m>5D8U<4lK@ zu*B2)$-RXj|%=2Q9Jv~%N0qWv!TwM5i=_=T)U#Z8*(4a+lXnH?L)sd;fO){Jwp zW_;u-v6R)9+i9apx|&cGcT|_n3LkmLM*C212~M+eIAESp_fFriMby`g;pZZ$#w6jB1`p7{xC_K)3 zkizkN_olapjJ($PAR~O~Lx{N1cq%St1)?f;`^wg>x#_PG?~w>5;>@nDNp2Q&`x+w98W_paY6V`%T^#b>B3tW%o3&uR+skU#9P_u)#} zdh(Mp3qXAGWl_}W#49|1#3)te2Zfz)42(}&({-O#9onO)-o# zeo$S)MuzkRIYU*rF=ndh{i{@DW|Cv0`Wg3R8y#yOEO^6+Qp(bg!*lG`oG#h9sF^Ot z#TIt)rSZ&uz!V`6;!Rth)baAHPnyBbU^ZQ^smyP4X+`fvr=!qBndR$@)WuUq5LuUs zXDXp()h1`xBYroJT=E4SV@+e z62|lb48vz$W}jdBSq;IK(7LT8mO4?zaXBF)ZJD{JK5HMI3@7s+#t0pefxtR5`D?I| zhq8q!^jgu1>g1RgF!lYK=Y+P^O+(_Xoor(2;7*>d)S5*iE5Yg=B3b*MW z(q`QKgbycNj$&eG{4sO6*oCWFdZuo1n5s%RtEzeX33=ZGU7c?IHIz966Ev%9^w7hP z7T@XbzTPxhJ>C#c=?_grhs=(vvrJJW8L)oxGtcmds$3hG0eeZ$G!PLznWKj#miW3% zd^n}0Fvpb+&d$^u{~DI*UB=qwF`&zausXy0numPZrV!#;g;4Lx^Nn`bMjcOP$NT%n zBZuh3y+SzG6Z;FN_a*k{NN`uFI9i8tG9^{UpckH~#SPZh2#LSjuqc8LDk6b-NCNwG z%$dfJ;=VuFFnecQ--`YsGle>8tvDW#52>n0z4`Ksei`l#GgK*q`vYU0Tdl%9o+e@y zLIGqurRqgQCz8AC zo;bIzY*rDsPJ@5`@`?O2wWfD0v#_pEfqI}tQcgTs?-c3@vdGv*VM$HpxSRPSJ_>`k zM^I(gJ-g@E|4V(=`p@*P@1d!mP+yAKuGGBgYe^pZy55B1!O}YYqObMKsUqhs*q;qc zv9=mPArC67Hb4WA?vf1)cW_2rG*U)Q`1kE!Zd_e0~!7Bh@D#*o}Clz z1$9RmW!m^rerfnnk@-?(4{~z2TVD2(q4?t_f(G$nsQ#^;{LN`h5YTaHBdrWERbx`P z^fX5>g3Vkm`Ym&H7;Z4<_im0z&j?Czw-msJYe?;ST&4I1iJRKOMj1olV^Xbf5wn##*44R^>bQISrLa-{{>n^=G|uYRQi7@riJiU`*?3&-y>T9w>iKRC9?s{H9k{7x zv`bIe*>`^|fGb0wq=2$#uEfhnuMdkzDO!w!({+(70CZ7dr42o1vX9v};1NvpTL1{zIfe zdfEQ~gyCtN4&iqKwXeQzv~Xh_Uai={xkey1BE=Yc8*-&ktEf7Txze&w1gY$7eA69= zM8UhB5OnCX3TfRI`5>JIYlERfNj#XK)KVa4hPIVs??^)(UuUfH}^j z(F1Kfu`k}glx1ePBx&AX{7`scRRqjQ8(#~+>>-N^mEerpl-Vd+}f zP>(QN@G8Qze@M-n$x<^y&&<$RkpHIWa9>C;{4)J)fuw?H6nNWyqbJJ@k~nsg1p! zXU-+64jFb&C$y_J@3pu6C3@(Jf~R;^Ftm+XashDLZkdkD!osQ0$r+UNY7<*%G}Xj) z7lCVj0fz0mMP<`<$DO0HGg@9`#EWz$-gDdHil>`d&SUZ9@KRUzSucpK+xBSU_Lfj* zF%GJ1)z~#pU#Wd|tw~SOR5d^fJ+`=L^UWBSDAu!l(iGK?ce4E>2>lq}?52yi_(czv zwr(FVV?fsr+y^_1q2nh+_(ibpXc*32_MsR$wAEea{$=XdE=)y-2N&w#@}^ThVU(0W zyMNh<2>lzB{=K+FRJxc@4Qk3*vjb%CT2rZ}YoV+0c%Jp^2%eu4o^3eH+#i*i#d91> ze_iv`%Jgt)+n{JAq!F3+GCHK+H`XjldJ1K}zT&^$=V7^PBrVst&(X<~TTNUI9XotX z1P7y4j&L|R#G%TXGeb+MpI|zK)1G4YoUN(CywHAlY9g`Kx;)ZIWCk6YF%!DOrI@8CJ=c4-9Jpxy*)%id8<55nf#OJ+>q zo=43^PLY4kbRXosUbbC@jl6CvJ)(X9oSo-$Kv)yX!%_FQhGSd0oCY)Db zM71uTjy1Ad45kYMM6E<-TJ+-EJ9N>wXA?+f!hv zyswPzONJ`JeJ?CT6|)dc5Lim`_1qTA)D)$ijd**DsMLjihs5{zQ97qz+5hOK<`H4p z#TM%#5(E=*^{sFG3|GvDh1iK~Avtb-SF)H~tA^J1jHpJS{bu#0f=Uay0($bqQOa(( z@CLndp{EC9!F+c<_&|i}^1ehkSqZ>-midYwNB8dsHcag~H!Qp^{jwCpq7SUh@17kg z(=55Sp^7^l{&I(q!){n`lfDW2Je?WlvOLsFo~L3BZvv4kuteaU;vny;q%K66dMv1) z^a#}i1qZ*Pu?qXs#0)+_;NXm<-Rnd!EEw(zqtMKp!1m31`@gg4F-Zf(bp6gf_YGVd z{m+B>lO(y1y_mP?3UYTt;eVf95`di`TXBtz#Ak|O|NMxEw$G|AzQCGFr zMdDozv=^#WHH7Iclfpg?32mv5pON9PoAwZ5FFns)UZ9a~G@YNd!rsSGk^T(dvZS_$ zUi6O5Liwq^5tiUbMM`-ElUS9g7WsVo~p7>^oYK-Y~K$rZEFX*I0T`Ce8T?I zD4@tv>$0gKTnno~LtC~V*f^l;UUG+dBIUpZSk*Xkgn2J|PsNWHJui^18?LcRggxU7 zZ!YD-!G+7*m`U*G(*K_S<=4Xe%f|Q0|DQ{Ckv}$TA9NTv)Jw+dBx7~ZbF#+DS8Xf` zr}pJc>~7e!AEW5{Mixl#GBX)AuEOfMnv(*4qlu1OWp;(=4NsZ!zIBm)*i84d+r#ta z*Ur$!N$H`y@rEaTr}{)?clt;njKt`cvXa?}QZDcT8qMmoe548B|LAza3n|r2c-K_T z-qFQx5!p3kezv^Dz&b(C;O1;LEGnZ4 zl_+HPKM2P^5Q8Qxstk)-Vew0SO67gFUxr(iAr)qT7eRZ3GQ7wq_o%9&AdKeho!5q4 z`z5|B+U|*v;aDLs;4P^ZWiok~F4?Pt`RbSHk`%7@s(g1E8>CmMp^-%QIF2_EY>7@x ztt;LYHk+UjMP|FAStIcCo@@oDMQ}im5dWksk13Tro(N|v!%uyN?~jUPfDLk7N*QK{ z89WgVQii|s$u07jO>d3l8mU|dyy=^o_kFvOvv+&ed<{kOSHdv+>&L06w0^o#ln2{# z$dd2wA)jzB6qTattC3Q>e$z*OW3#^Qa})7$uM_blVRO1yAxu z)$QA$k>`URE-uF|Z-`HNF`oMrEamxG#zf^ZF~tjN?qqRHEgVy~%>9IL9hl+=(WPc% zikC3}-1Bsd+L@8h%P<_=Qr}zK#zuO}nBwQka=%hVW|7-{P8sI;3^R|2WH6?ft_)Mc z3}u!fPZ>J+bM+(~yKFFx*FUYF2aI^rAGZ*IW%oz$FJo2*{TT zcY$(&ZH3X(G}djKj3UVik$R0HYlPaL{?(fzU;Gar7x9t0UoMMeF^zSHvfQdv>L{@W zmMX*bKEsfxcf>T-H$^xOG*W8-!E4xLzxg8D8%@Vy3A@U!!Dz-E?y8pz%*7Z`&!Ug zy?ab*dNK?Q2WPo)>qUt44JOjP$KU@d&o#S~=ldyg7xMfiFVD4-=eXoKt~Mdw>Zeq} zsc%Y#S2rTV^K5+Jep+OBp2-u>$Z+072NyZ)$WKgqwx)9F)kA7>Ikl5T+jo??dj){a&ns|cVuNOn_$<~= zvv?sXz}==hb<)nVh`{BR!2zEUbD0Hvw-&e3_ zgct5b1p9GkWLg+qIyN%BD||N*XBH(>GXt}Go{!W$@bE~hO|buYM^Rq=Cm{;~NoNs|s9aWzHh61du_hME0#PQoU_h!7QK{M#TdEW` z0X2}oCV_QWMWwCQOR25aT5qiu(0WM-62M!8DhO2(Z?mRK1S=pye&6qTW@cwL8;tn= z-oIWxWS*U8p36DsIp;j*InOP|3?{ysIO~yR{(EPa1v_2kc+{;wMX(E5==Uus6zyN2 z>I^6-?&^@C2Qy??8I)izXNC(1*eR?A=yWRBKmN6g3?kTb-?9aJ2Blarrdd!1DPC%K z%+@e~CBy#D`l2xd=DA~P>)3;Y<2Yk_2A<8l*8t;!-uOv(JAU@dXxy3A^EGYN2Doj~ zyUD2}>6x_|n5Ib2gsGX{t#L&jo4DQq@kDx%Gh9`Bc_Kn)A zjgWA44TrZVj!(Kt&Fryru!aRdcq+3Y^5`?I{(b`FIX|6Q^X;s8_74@~Fxg7_87%O* zU=`w@lyW9an#fu}0+R%qY*IQ&HYo$o<~54C{Xl-X6ir(>@TkW3vU+aQR^guIP%m7I z?s&e?nyMW0s*BK?KZ11HlvQC8K1ZRsfDd?TCadKGVCIv`s?{?UxP>;jLHU7d0suD; z=ZL4|gK|K0oQoOCp$&8NC@hPI;gQf*VHAS)*H$4_&-G-2nBI+JTQu*c1r?Zf_4`00 zE~Q5|!{K}SdY;)bC3m2>1i>!6drA)i6*0F{ri`tz}a!L9ZCRg=|Jyf3Y8ejP)039K>P0+&+>qW`&0DXFJ#p z!N^?0WH{gB9lT@t*H+-u(Ia|n4HLm5iWD*h6lrc_dst`1G*;W6v!54b3KxbD006N- z#m0D%y!eu1j(bZTnGFpGppnL`gSSFApvnb(P#O-_4O;#20$+|ES>tvg;9%nxy&bp3 zU~*a+y0chNi&Td7Tny3c#a{LiGAJ;$%}qD{*@jP;kK4xpkjyx@U;~%GPv^pT_Qw-& z_jhb2h*fM12pMJKyDZ`Vb!FUW&$*83RCex0?BmuH)I`TjuA43~V51!nNke3bS0n z%dl^`1pGv78khj^!>$N%*f8RaV#9alJnKrf?viRC?(De`%tcbh`kw^Ygf&rVjpW9e z5N7*FsvUAjb`-|*(pex5oj0;~&V^eG?$5hrAcBk2B^x$wVW$9omc(wz456W>Pl%1j z6uL!zWXIT$OKVZl3g+P6G=!Wno6&*ROP7n{xmU&}b=xt!D`;aHX-_;?ePUbTLb$8X zA_618S^&JGIy67u=3=QOQgL>}%jnRJ{(q5R&_fJx-wf}@yQP?df$OhudBJUnH?lvk z#MDS^_%>oJiwdHd+l=hD84HAofgbxE!DNCKgnD$5Ky54{Q(=51fTBHS6l^Du)5($~ z6erqZ90C~maF7JCTZ6HotJa0mo5^>p@m6e%0~Y_v4DhAB}d{I%an zu#xD8GK|&~^P|12%|%5U=TFrQC^D>sL{8G4rOPT$(#`x7Xj>cZw7P?m5kLGeWu@R@BEYU+ zZe*b9(4#NLe=ODXe~-~o%r}8evdjtr1f}s>K!sg{gIyUu#;0)PVhfCUuB4ag6biVl zdO&Yxi@(NYXR(o2Y_w4c6BVisg$j&Oa|~AZu~C2u`!e8DDAO3C&6FyOUx9LXA_}$* z4f=b5QisJX$6S7t#lIoUTmd^#)+i&jw&0p#krGrj10$N;>G7LnNNsgt3)iw|YcfAw zt?d1z=pGY+(@tDY?e@3CYUL7M)jw{9^^E>8AcFjGZVp5Aj}ij9Jidc3^BMA5pJhm| ztt=g|WJ>P$B0Gm5I73_cs{xS@hXf0EYju~fIJATL2)0d-KA>K$Izz> z(w`-b1q(v8#SN9x3>I!tOtn4b{;CAoI=DsDKOOw^3N6DAR&Yj4Z?D1G1ob~d#EAad z;?uGa9<9}9Vu8hozFOT&Xd1hEZIupxvBFwgHTBGL94J+HI}+eSJ|glZVi6-&&gvKZ zVjZ0LGnl`5olXLz<5Zp})tQIgX{>`Cb#3JhNZE{(XG+Rum2wM}X&T5>+e2F=D!350 zSV%Wtf+JtAnP~K0hr2Aa2#>?VeHP6jDk@&~XKsOr*=n)&IeaF|&6p4yEghR;22^Y# zLPc3fU6qBTWL4H`S5);|XEtI6KQ}ij@EU8=wN+(jYO8|z3*T#p&6M5*!;+8!rp2c) zDRwbIc7l2gP1J^4+1}RMUy}%@gY}q~GOFbQ%XRwg~$!!Cx zXxscrx-p^!<; z_wD%IS+)`Vw7Mt62(lFeCK1UtZPsNCUnA^X90Gwg8?EI3Lju3^8YPch9{0R0ZPW+Xe;cD`X$Hlr7$SsdK5NajipMsbnWO=^)Xl z2`7;9j?}vQDQ}0-rgbwM;%c??B(a49_36b_ndUz+GUl)VQTN;u6?KA zuEt61lh{f|C_Pi?jCVGWu;U*-a?!iRqF9ZD7QI8goLnmyPbU6_lM7`@F2pJ$qX9jr zE!X2Hxo9QYW40J1cWP`#7`sa!ObAn#CA%}>>nz^f^SEe&|47hTssyZ@_qRG3zhsvDOFVraUgC0_4MKfp4J=ag#y3D0&Xq=X3=xy$ zcUUTHzJOSBh06Fyhm1WoiaK=~wliWq2JffM5N9P&3qpf9G=ZvFuPyJ4kXW(&!H5Cc z;w7ZdF%@H6g#crx5Ete@wCnu(rs<@F{r|O~?xchfITg0W)q!0{9IMsM_Uiu5^=knV z+Jiq1`XWjC)uhZ(zoxUq*zilK@M;hlGR8omj)y{Bn!AJVyaD-jqtWo8SdhvlY-)F^dE=y{Tdkb=;zP6jtL zrb5Xv*#mBr>LqcaVuezu5rre!_D(+1Ab{20IVo(kv zu0Vp$QjIuHtLuZ|Wc(+vF0Diz#FKMrK8#Kr0S3LjmZZ_s?kCk~2r7Tr4yT`lWS#0B z{cM#+kOq=rvT`~YM{}g$sBd!d2k*Gc_{i!*6OvX62V}(=GQJwg;TVaGs;q)3B-xe=x=ZB`B`Ltb@j2FKRDQqa(N4wI15mD1UFcsEwJRNA;TLRTM$6e{y9HI(HRTY zsG_g0LENahPhv)&_@n>x^k%GR#f+4nmw?$`Zk&8Gr7}?)VyE%kk?pn3Q=SWOd-;Cne zxSG*5`$lPtzbjEw`gT*mXp4_QMC8LBjUOH@0QCkyAB}4KsC&=71Z+#}7Ti=zfZDaR zN?+W>zy#Yq2vDXMeKQXR6XfAm2|A^n^7y;k6U~_y*;hUH6xF768!B;%Fqn4<=D9$1 zv>wF4!rE;5GbmFI(!2ZF%Bm<~KHqI4JOL@_laY;Z=-&U}_;0vDlj4dI>+N#lo<;6u!b4KE4(}Z6% z6i$rw&KO;rex88#jYsZk^oq2YXe7}({e4bl98$XQfi>K2$ zT^gVcDWy~9EPihe22cV%7s}@{xE!&%l%HEcVSLU}pO2N#v&z^V2F0bLK9{M_UtWRZ zmSVx_9M2c>v#vf*=jVbAm?EJWnnO2q9&V`Rc>{AoCF+=$kTFo>1WD~5MOB0}Ob<-Q z)cd<7kpn*MmW3z*zcMRMENNd;62)8#+zLr$&3@9%!|WH%_Cc143B|^sYXH!>a`tmn z4}_u{S}`3!zbE=ubH1#KM2nCQN@@M*G<<^eI>@e^Lb`79I5Cma+QiItD7Sk>Da!3* zmD?Nh8$f46{AUngj?7ijL%&JU4J8W?U}$-r6ukO!1uzRPW5M5%g6T9S%p1li*Jqbt zX2Iz2uG8v9p%6fQsjG0b(T4cnph##Fs={Y}qr%}H2#`Z+IUnJyte=1vIRn2~#ZH$b zkU$)t-gC4uDHCkxk2Gcgn|@Io@s0a=aXemzw&-;vks~P5g4*Kse2L9Dq(^7zU_S1O z8fBby_hmRWD|S5`!ogtO7Zp`{bY3w1wde*|Cv#^AJEaBZUZLY`t0+btF$0A(=zIAF z@A3xObJh4>hC0#b#qqJ;M;ZM~P^2C!%Y)mz57OnWOG6jvtW|W{bMk15?5%H`Klmd# zOi`_h{(t)$n57>TA2}%?tRr`PnLf#2WWO~{CMj?OU{J&*{xQ&^e}cLt3&5tC9|x^^ zRQ3%_;D94lI!T|mlXl9zaYNkp?(%OsT&DO4Ne>=&Dw&!pJ)|SPn@)a8l9Tj%NlBUN z5vFqBA8&*+vL+hE8U7HqLxhH5(h4VV&GN^8gk(@^8CqQtelZ0^U(cG5z8aE8H z_A-72gR3f6m)WzTb>VZc{{ah>Pl#?3|D`)m_$5gx2`b(J0ZJiVf@eMqlR|jbc_Vaf zHv_8}(sz?e=HI6Q#>W!{Blo6haT&Vbxd=xk5 zJXKW1KVVod5eT{eFtRQ{ng;dQIA{VQ72QJk=%43)H5KGX@?PO5dtSF;rMFSv6S}n;j~H+YyU4 zhV$vTs1ay5vjH-@&k#W9DHBEI9TR9%9EQHkRuib115g|lD*477pw-CS7!R56v? z?!ph}CsYxa1Z z3dh4Hv`hmtw)QI{~t*Rf0s`_5FtQJ_pxiYywdlqdFF78>vU);Lo z-rxCWP%@e33MSA4FrlGy%)IBtLE3Go%R!2>p3=-K*24=rwNb4{L}JMFf7T&t9HX#* zGRKv{&kScU!!Rp@aFqE^W~fAzIZ0LXmHU|TT;^J>CaK;%157i5Oym0J!KX5q0v9)F z0ij|ds7SyIqt?9Z2CkuSSf~n>v_6!mz+3(>ln=0HlIi8)o7e%`UJBaHET}PwzdPpt zPKW#(pAaU#JyrfwQ9t0G$tLCl{DZMmq@he`ACRR{jE``O)89@91kWc>kzZbX4qsji z4$mfOtnz-6syv(*k)?KGsfxVipAL8fgjel1B)phr6;2Tqa(TI`0b^clD>U0r1H{jI zAoiAbUW)dmP?A@%O%9>R&JuJ3=6$CsI}(g6`blKeQWU>oMSo&N-tu{Wdp_YkoP3IE zl=%({=TQY;wHrR)WG-w%J@B0!tu#Xv&BKBys8)PAu47yB!_$zaX(&-IwD)i>8?){zh(uRTF80-p95WYy&;3T7G{v=LJ3b3WplT zpnE>SS7YS83>xFvdeQzlKZK@v5fy}cVsH-++1qn^=+Vy#wsW1(oi!+%QJ-ilORlcj zpI-4kzWoyl$~uPbr@s*)`1BM+#N8H}r@gfLhgnWipP}@Z@C0%8n=_skb@a4*gS}k& z@%tvFx|AlG#J89)_}`<@!J(Ci9z1Rb6+vSM19X z(R&^fj0O^;vlB|pgHL5g{V=&hK@X{d=AfWt{i4-xR`x3N!Aw{m&=I9}9}~3oxz3J` zhAAk7-iB5q7j+s%B~iI6DzX@5gp6JjjGiUYZ6(@cZ|doLID=9j1DeL5<1XL`bT)=Q zSb7lB9(yH}{wmjW@4%Ww60IWp7D|Nua0y00sTFrV?q3_*}!<)~A z0A8&}2ir+t#)ga@_!dfULc+_CkV!y*A$oKlm`+?9wDJP+t7%I{M*t8=w|V86HXs6k zs#j`6ne?F$VkRu=Bw>6W%YzOmg{+mqF-7rbhAb-sngn*NU?fn)-=#GfrR7CRybH}j z#ox`6sk#(9k%5RK>HYtB9pmiW62xyEfnt=9dued@{(HJ=l z?`Tq5-oXh*Rw(^Ne9b9|V(ii2CSYFtT9m4s0z~r!3x2Cwhk#O$n}GZB6{5)rTWi38 z@c}5*{NQAWjUTqLS6H>yOF`IBHvolcPSH_)Jf^f1~m^-~%8}lj$1MpFs-XC4#9F^Gp(;#nb*c2O)`mur1Ia zzC4_-Bt$%TyoZRN!ah9=Kc(1@zIKkXiOt)w4~b1`H3zP=-$xZoSoznU zm?FPc|Nde4*~q@-e)3oLgAZ`U_K(KXHK*OO7+EmJ!ZXeM(PCEO+a>A1;0vChv6GLK z*fLiwt!qivpDw3v1~)*(fa2-qAOG?$LVtwI5f^M`L-d9)$(KgZ_DagInYE-y$iam zOUx|bc4)5iLx??73v(>)aU6wY@_Y_F{pQ`j#$nKq7ThR<0}uWIUJine&Tu3~v1tarx7K0-n6HkJekAl=wCOn|AC@N`Z>Rg6k-zQCT1 z&*nMrE5bwOQSNG%$+DHVV33q+gAbYi!o4^~Wd38BGD<4h$C7uvherQX(wFZ1vW{PF zGT#Y+8ee)EnMh>mzV`NRFg#6cod!{DT|kN@wZE(j_2@Vxu+K7)MM7Y)5Iql*fuEd@ zRda`h9gL7ht+o+w1>2WQ%N+o#IjDMTQncH+kwKe2Go_TI$|M6UU>17`=jP{}M#5^~cs$@wE!GqKRX28qi*$2d> zdyn>`zvd1}1)(%=#l_ZAZfgsxHAiogt&})rFGE`{Lljtqb~$nmp?U2P5d0}O!9Da8 zeVN=>vcDi!GTb`1LPRKEG+kt z)Bj)>PDbwq>qwZ9xR%(c)VYE#Rg9nb2j)^rx+2{`V^)i&jA4s8e9J zH1+RLV(V(9O_JoJ@VM8bL&x?84u#ZA$^(^WOs3l{7kQO(){RR6C0hxMW?q9Ey+}>8*%F!m zF#5k;PLmZz3fEm{x5%6N);u~3t&NX%(z{er%sw+|Ox|jw7<)drI5$_$hBthF#?VJ^ zUyr>d_u!Y|>l;Lu*?==f4c|=3m>pZ#7slOseWZy=-}ycC<_7+N@%Id~8vREy8H~TW z4b}K4mJB?xyLIi92JPYv3^!>0mfhOrjk~ozzG{?)-y88e`$m>5Oaz=QoO0+%-=vQY`^N0By1lDesozSM%QE!A;jExGA~)zt)~UeIiSDJB&P6qFQfX z>+)R?4Y47KfwT!F*F64DYS0vbgu$iz9}Ltx_s1PU`TzW*r~IXdD_^U>i@eei2k>W( zewE@*znKLq7F}HrpUd6Z2N}&#aOJVhAfjlC&;BmSX6|-54tg@9oXcQgbsNjK63l}G}U?ONrOK<|V1WqV=vAP)hDBXC}C|;g@|eAKV*fjO`yg=Tb!Mx)u?udXLvhA0vCl&4e6EQbvg8By5>8e3y=( zBJQfE_OgI@YTsB$T=j*G)tudGjQ0Q-ShhE*{X@#_`xV!WZ!T`$ha@0wRhwQ?w14ge z$lDf#b2=QX%`nc|c@794yCDx&Rqs%Aa$YF9DK1L};c;V;S!UZ{C6FRkehL#nL|v`_ z3Pm@!zG^nquobu^Ji+|WB;_I2%t)yUaGp3viinqk&ZZ^>fTvgf+T!Wc|7+O}O5gd> zdcF9~xO=0htk{z(1kK>y9s(4w@FoxbFYs7dp5e|cY(l3w0Nr{YGP4& zQ?HWX9Y zZCWH_;28=OS<^~hNfHs7#@|#cp0j0%!{c~N` zgv=m(CS5;pkQR;nMUq|THWSz%m>aER(gNl*mF)TL$=1Xlk<5Hs)phD=uDYO{a30`q zg$1sK851vp=yXEgj`J0xCb^1|8Kf`OR8A9$>fmoY3A6w@GciU1EwYqt0(R~G8U=wd z5zb_O1pBb{1%biSzFPe|ik{GPuKoq(z%v74Le1ft67XM+b@ZX%oVG&9_PKj%TIPao zC!xS0ifkug?JyeQx7%D~<0##nX(dyQa0qK{k!*rH88kHLXC;F$0-Y@?*+1RMq_n|E zW?rH|>aojJS8o>5@M~#=IL>_S?7oRnsy_%4|3cCbif;_iR?LJSQvs-&>H%U9L@dk# zX=L<_z7gud9RGX4;isp#8cuj%A!z`LC>;7K9HzbLf>KbOY9&*I`wzT3pvYMrl6~Jw zrU>_fN_Mt8nNXy+l?)OB!riNqeX=#V(hmp?U_-+r*<6+E(hj9Phh*k{EVKbgx%*v( zh<;HtbroNDQEdc*+ApAfiOagHdpjEr-x|WAW`evT!nHt%^^Z^7Ok^*u>;XJ?58oK~L`ki23fk2`mlvzlT8lXqVA=4^4#`Nedw1f=b&;r_T zw=BU6YzV9r{yl#Z_d?(vglz+(Tg;fe{xEAkGz$Q&T!`WZ*aL4Ru59YyZ(_4?hFX?F zr5VSgNRbdRCNSvXZHR!1zJl-ZqGbSJIhq$~1t-_vNs&hYDKuhhG5sKAV1nmPVv(KmewcGCJS#~(C< z@-?0P?Q~n;l!?CaG|VVCrVH6VxT~h}GFQ{U*5?QYRt-7XZacaf4tvSdvg@d8=+p*h zmRU~L=@7mdIL~^HK>chFu+(AvL65LT&lmv;@aR*INgI(~Dbsn%hOOvfMk-j~I^XA~ z9E0^kG2atCc$N)xXUwqd<=6Si@_}7M7;k2CiEB_V`e8*k zJ$fPm#4t2@Hu`0^QGrSb{QW!GhY=q%PY(1KBkvOvn|2T)ads?tIo@1R>ByI|DaFzSR6XM#YyF~x3m0T>D1-AbUSr^z!g2JuGC1ULiczcj)Y#0`F6THZVT0?-%Ww)e>bT}g{n--9i>psB&tI^sEP{tpKFhiDS-U+ zZ8wl~mZCk5e$Nf0v`2ZZw8s^I`0(vm)gZ&sL>? zWyu?a1yX^g$+9S0lnUs(UULI2l>J*ofPN?wK>ygLtSm~}1GfII9(lh_@glT1#`7cl zEQUuQc6aU!Y=cDq1DU%5OfW=`{w%AYLAy_nuEVPDG_96AxA4HYpI%#0F<{}B*IfJ4 zk_v6%{%gZOomtUioiFdZl;`FKnt9rN(d_TzJ=(tjPd##|N0qjkSQKo)r$PM?X=ERb zC!AGjX*qJ+bBH=G^5w~oK>36Ea+msY9|PpzmnHmyS(SCy17#kpcoVYV_IO zBwhE-;tWf4H0UuJWXk@yu3y^K=mKRLA5C;l6zQVq3rFXFWuAVOTnFT5lR+(r5TQT5 z3>TGL`7`LCk;+H^=mWjeN`H>^%D5!Atjz53GM6!&^cjHQA5Os>S&UN6_R(pm3SYQl z;6%Uoae-^^F4ABkc@wd!Nxk@3jS_wwR>U}y63JLLntvg zW{(ktF#^|DvD6EAwS=hy`S%p3?pWkEd}ECm*`5^!^B4|A_Y>)@n``5xiz{92kifaxANh}!7 z3LgPInGjd&MGAFv$;*K3%iVNiPN_TgX)9Ljy|M6_Nq0P!M7M|*or6XL!$;492CFP( z3UJeTK}l1jf|JehxWS%0-A&Asw6v)nk``==Ujmvq6h|$Vq#3u;^2OTT z6%2l{9UGc5u}pK?aakoegtDY)NBAg|if{5yk1Sk)AL$mGIOWCJ={j#Oy@XyZ0RMGh zE}NwtQq{f#uR(d8g)t~z7w)e?9*N;48xliBA~989R273y5_1alt%|`9iP`GJKr=~9 zJruM`10qPwaP)sFCSb+vc4C57%;Qj5t#p@J%8eW zuCN_z^u=ofGm&4Q@Mx~olrN}%rlIkWXV7?#5k$*3=EFwuNg6M3Z?UL7wPVZNi_4_9pzq)dN42ionm1@H6zl&j>gC zcqjafcHqa01wW$+en7} zfu9j>`0-Bo8STK27Ylwy6aGXh!Y_$k@atd|;U9hg{0N%N_W;{r;peu{g@?FsRIB|H zg#`>Hrt7daedInUOKh+Z8TwBa^sQjUkXSMFV8sYGR(K~?jCQcXi-i@ViB%#Mv693t ztY*uSR;xB(h3`#fHnA#nNku{)4v)`JH$DNvg_0Q(ABG-$7~#eT@5G1E4nBCX@L@FZ zNu(k^lGugMePAeQC4K-t2%5~1IQQ*{@EPOACrG$}2Seh+(1Q;n-1y*~_%PbR2QL;r zj3z#bRK!OTyYSgW=BL);2jGLC$^0dD=N=J0i`@9s5H6I=koYk4;KK+vK6ocSjCSzB zi-ixPiBBRG@sY$Xd@^i&_yPDJXfp4?*>XpOPe!^+e$br=J`9NuLk~WTaN~n_;=^bM zAG}!jFq-%zQV}0X?84_vu$HtBKL8&DP3Fs=A1OW=ZhSHrIKVp2c-1uZ!_#hN~5PI=Jga@B2 zg%9&N_+&ZwFgx*aQVBjx?80XaSWDr955x!iaLvnb?%9#GkKc`t-@*r>;DgYM4oa8S3DJ55y+`e4fQ2M@NQF(2Y;f!Uv(?gV2i)B0Ts6 z6+X=8;1hK4VRqu}qS;Pc6@BgLo2jZck*4?@8Qp%))Sc<`xF z_%NS?PmO~QvlAaDmEgm~E_@b&wG=-1KzwR|&!8j5CoMf;zoElX{SRkO$kB9Wx&~q} zt#ECIJvw|6kfxN@WBV-gA>us37;Nm`=n*K z@xcj$f(I@svce>MGLrDgQ1~EU0-p>AA58GDebVey3LhkP;jVd0aZ@X2U0=YMj< z_++~A$+YmvwD8GHZlBB~d@>b2$d|w;)4>PX1s^+=!Uu_6_#BB zAEafu@qxoc+6BHyD@X}M)|?Y zv+N_sC*Z~>VBr(6@ChXITObLafWim)68Hohe2`t*$4;g2L1Gs^_sPM)LcM^(CxGz} zj@CWG_6fT230n9BEqsE>_ym*i2`YS$FM&_c!3Ws|A3K%82Z>$yY?9-b1)re8Cy4P+ zJP98IzU@8BB4&EUe(_s-oY(N^(C-KC=6a6URr_>fCY)%I({g<{FF;(;SHo*9Qw<@b zckYC!u7_e+v4J1KlIGxaXmT9OHDlHULodS#f0%Ts!Wuny9csQt%8%}J3M;|HTzJj| zEcGcd@-c)Sp=L9R4uvl-F=oM2cqsg1d@&bbq`RB2CJe5B(>Cj$jUSe+P4d!pbVE&~>d8n_SvUFV&3vZcoguRvfK8YH9_z zrUV<`T3B~hllEv^>wf?*IKuJA175J5tf%LaM}jFccUT{1-a13Aod>^gfdxQU-f|ms z2`zcxdW9HPQpHaLm$(yH-+5CSY(FgOievJ_m12*!0P|Vp+Sv~umb_2t?w z-}|6mxmNh^2FwQewME-9;m@e$W@JtlY4tPIFX*giIXkSTh_w1)8EGuxHT=DazjyH$ z$KPl8+mBMS@0C(_^?yKxgC14kNh?)&`g1BgYn=*5z9M1azc&z+O?+(U<9$9p;o}QF z+V>P|*A-{gFbHKWV=yIa1%qi>k2APBtAWAHtQH30tQ`!hvf9dvwOtK-Y~W)PAKUqO zpN~)Y_=1miIoUJbqx@V{)*#Of^4uiP?ectIo}b9`3wgHh(XLCwpYF$_G=N80K8j-z ze6mg=#piZ>oF2quMkyY%rsFYhmV6;7#FbA118j9)4Vn-zX?0v1BXxZPsQwqy?^=sW zcD>BU8+^RO#~MCf#ha!9TEC~mFM?w!-!J1^{8Dwfo zk`g3s*A6rnWPR6e{2fRoq+O5O^&!gGg})EVwKs->Pj+ShQ~(1YsE;*IgYas*TJQ%w z<5mp`C1L;CwHc)x-Goe8NDk#@p(8p4k2iYpn65Au**5sg|I(&~k3mu$H&@}RUEf=` z_XZzs@4dd21%$G8sOWXe8C{r$_`kBi1{9MaU6SZqTdAHiG%bUleZT3hw5jhN`^TT; z#~ZXE-0E7bN3rtj8VX340)A}gn`ZyGDs=&Xc^F{E2F0O(QSZ4`{|i^NY0KFIp(d`f zMPE>bP8&v%#=ZwV2fD`iY$U^en}BoFi`Bol)8oGHsbWdw#K)@SIo{-n@^PAjRX!|1 ztm}(o28QM5c{AW(<}7UySN-5uaQ3fiMt+=*{!^>{jU9D42;Uul8vZU~+h4&)Ihjy6 zu`(aOs`JaWa3lWE*kQ0ucrRLQ4gSDN+t-$BTUv1HYEX|f&;-zp?z~< zdHew9{qLKbjYT;6u)X@`kEBwg3IJ^01q;Fm1D?&Fw!X;*vf5MDPgl|Qfe}EHIxmi{ z82vn2L96|4I?6BFToP>wX`v=qa3J|Jh{LZ@TK%0!STk}?nvi`WqCrm~ILHWb+0v+= zMRI9%`;ZXd&LjOVfX(3j+Dqj;j}3D{Ao=S~D=!=C0ydVX+gey2I$* z@XKF$3NodDsN(0y1LL#Vk39I>=b!rqo>`SRPp`XfXgJiYLK|-sci%VO2=zeotq%uu zZN08-&b&sfDbA2TvXLw5>0Q?ak6j$PW#@h{k}n4-U!wmt>U$3w&L4O zy$7Gudx-Yi22Y;II;{O}&TriYcmntpzzHB0WUcGK8^_>p2>!~+DAxtRBx}GR4IpcK zd&L{sO2*zR_yWLxgb87;uli z`9oo#)5t)ZKhm{VbnR8WV6Rp?1j&H+tKc3z@*(lAK#brw-lzhFz+W%p2<`5|U$Vsx z%a^BO*X$BYeY}MC@$Pr366h1z`81RK2MtmZ{W288UL9_%a+#V+pA@y={)fnyel4;P z9Euf{8FPn~%dxmq2DFzOXO|a!8twxc!hyGC_O6oVZiKKYG;B*r^oJ1Eeck4sQ*K-_@TD2WC&PHAL+n<-W?!xCDbH~C= z9+0jNTVqV~eTAfws;`wwi_qj^RK+JoxbUl@x3${oh;crjkC#@A^7duT%~hxUP8qOY zH_q0JKGkZu%-TuG<9S;@KuT@y`F531$3Ey9++8g>!u_4pdt@01i>YXZ%ol>2QMD{% zQMA$`ElASJHLCu(XF^~m(B2>L8Ga3bxWUrevK#Z`BFVLnurxd09n7~C`G(B>i46#H z75mzxloSQ<-eYMXEpjO{{~Kwh6}F+8t*B;?Q_XqqY6_V0@2Dm)_iTuP0`Fb?8t}p= z;Wr@wdk7trq|^HEk=MV(P|^-<=#Z({w?hg^k^d+QxH%22EPh(y4hY;1RPeb~!Q*y< z-?ugx*|#0&FY9kHK~wunu3U-i>#aquCg`yWfBD{ZZJJh#GuLR&6X@`O&q|sb;WSPw z8HOI`oS$gDLq!`Z2jZAUy=d=j3`@@W$;5WXX^Tg)yx4+vJ^j@<&JDq+H=(a@f~16` zXUubniRXI`zX#%Ql{sQmu4~uA+L&(rVZ?@R#IG&=8`9{}y?6=C9S5y7xJ@r=o{bZ> zn*lZqAJMn3Y0qq`$SP^Z0%yn+JC}5bRUu6q&7A~X+3at9u4d%rU-rjX_Hn5cB0YG= z+MV;~t+#28mjT-=PDbKDsOX(4GZcNt`{^h&oLw8}zZum_rC*jr{rCjC3rDg460qp8 z^OWs%0zmnW3ly!EONMwbJ5?OAi5WJSti}%Hwdk9hcQ$_PN5NWcu9ZUcjQya2GQ|&EtCP1U4Fg_oX$}ma_og;P={suUcjAfsLtm&Jgn-}ihb@P%Xn!Y(IQQR${ z?6!giul=^n?Dg8g_GNbUXm4mvEyqgD_Lq0(3@z*3u>!4k2OcH|^u4iO9OHC22l{c* z9_k;c>czJ#tQ41zI4Gz|>(fK)GtQ5{0RGr51^+MVFqH7N-b*iO{_gC$K{Lw0|GoVm zCH{{K{x{_zSspF>l1dzwIs1!i#cafNKK1JGr309F9IxUqtSQ1Tt@eBB9aCNd@e9NL z26l{EeK!>kx8-{r5-mJX1O1LuBh(946yfDuJZnZ?y$3y?R=XJA_h{8U@HY;_p6YQJ z-BgdmAf|d;kdIP6rt>iikHsvG;W8^+VTF%dVS^R6Sm6#UY(uCoY$X8t!e$j55O5Y{ zp;wdJ;a)fhEEe*R=Zrb$y>O_y2mZ!kKmkbjn2!84QcSZ71h+YF;9Kz!*h+Xd$a94} zYuNwd7k1hnVh65AKEm9=Asi_E!oiPv;15OP5#*z@qP0i&Nm-qg4nlO1ZpA}tkhplr zGI_3$=i~BhkY|fLcgV917C@?Uf!^1o1sS|06c1^`<`7Vzc*s8fXo~j0&##)wqdm&; z<51I*9!rXcv^TkV(&9(1o)^~%Ir1@*ofk~i?`H$z0x_IKz<8 zN&Nyho~eF;8xQ)B+UCYP)r;cBm*Hst!gtK)N0S@>%;GViuOBOna)8TmE6>{NYi`52 zMqur5pJ-dpeShH&vv7AzU+wu5(0Wsjb&9;#V~>761*nckA~jju26Kx8>xq6mE(+jr zc|IQHK|HQ4#iMdM9t&pCL0V6?;*Xn!yYb^UE3BA%g})K=K!X+YsBk!9R_?H3o+FQ2 zO?LsRtG*c3RbPSXs(*&+s;@(J)pJo@bv3KAWC=fRv8t>7?Fv;?_3y3fs{heo$OUsn|*tJTEj|Iu5pd`~VI7=x2KRn>b8gtACWQvOVFTi)4Ca7o0(# zW`T5HK}zr&4x(Z2=)>L?RkV_s*zk*c;MYyvZwd`=2hW7SGu%u!>@yyJx#(f5v9RDu zi!>3eSnt6YBZIQn)Zp=}W!NrQ!+6RdWD#-KuOOvIKVA|&Fk#qc{w`_Yb5cua*mnN7 zWCx!=X@kLia)^5>Ak5;Bni#;3i-LGuK3z{=_rgIaii6b`K$@#BhBQ}Sf!JmwpZlr~ zZ%6upwT%m^he8>E@V@{w)pM5NaU-j*9{V_-=dDs9q7`^tUZXGkR3TM8ZU-ByfsM6-jfGFU_{qvVx6##Hc|c~CACGwiuR55| zr%t%4OH27IBTUuPXHnQ$2&ftapOUy3iyjt`j|j*|1mq(E@=*ssp0LPku};@v0Xe&> zaf-oRAZlpvG6quyuV653@Z$`w9^AlS=HM0v;lVo?R1IzeIoRoRMZ>Vy0ewQ~b`VS% z!s4r^4Po)sSEDyUFmnituMVTISeQ)Srx3x?O5y-AVWMoxJ;4G zYgz(=kn=snZj263`l;ESh1i`T0zI119kE}bUkjmMW6w0(XLLt=xzYWmi5ckVmRz9b zE$jg+{2TP=;gW`!&kvrlwvpMNUqbX#YtVu0uwv-`Tm2E4%O~BW^p6;1`{5Gow;D2x z5BkV-teva$twz3fj8vV$F3OPn-BKn~`)iedQ5Bf88oD7xfq_I1?MaSp+Z`%*r6mg9 z^%w=4=)Zg_I7Um``8n@XZPR`axIl6O)!3BD zCR1F6stvQ8?IC`u|+!W(LKNrCcAPb3F@IY+9ygxH9{E#boe7z*IEpITLG-<7uyGc}{J?-`%SWKBNhNCQZHMRmL zIH9|~x5d7>MG-^MKV^HfxlzP$7FNi@a3{6zmO`iT_2@tmrCeEPBvkgxvM3u+D@?!# z$hjB0Gsf(Yp7sEq!)$8w8#)5 zt6ZI%x4KXPMD;)wmJeI#bIhovg-`x1yY-zKSXizVS&6{rGQi`+*IQZe}kaZq} z8QO+>R@?ve{B`)UdW00$y4%9VfmaD=b3;T`mr^jTJW1=NXoF+G+T5Ih&I#1Gx3dz+ z<^eQ7o`bn6aCMI4aAIBULE^1`Nj?L2OMg1_;#aDZfvZh-639v7zQ2^`^+$2&SogDV z6bWvj$ih6DOUaqnK94z(&hN{qoRNe+nk!$rB{W$fw{NR6YcP&XGp`(DFBii{IDT=Z zOSHFeqe_HmK=s21b6qBko}&{pZ0+N!CU<#_Sq@aIw)uE{PatRKM!B9 z@PnMX@#DHS^D?J^B>evL9L9WCK;bx$svk-4{z1VDB13ah1w+w`Mi+{JV7$?w;s$jV zRT)6RX@tfNSS)ZTJfdJj?S=|}0STj%{qn$mkf7Lj0Lqq%G~friTAnf_z|MLb#yIaL z!GvLSIM9@(f9xyh<2Qe@`%8R=Y+4}jq~3c9HsHM4Ezbg(RQD5gkze3oNHfn2dT8B& zU-FnJ+ewr}&nWWheas? zsl4?Z*-Ty|fY7S=jqTv=Z)-oSIemW<_6g{fNhzfvJW5h~O7h^!JfT@F(f32a(E* zIf;_s|JTzBesBF3b!?w}7yosY=cMXQ=*cYUG|O4ra<-YbzAm3}?{X4f>*x{_w zvz0s>Is{iP@tcbM7H?JzgfQq32Hg<`mtaFNeTu)2%_4vzN7ElMzt9*qZ#yT69!c_X zc3MH2`Aa8J5ZRK%Y*UD1)<6CTgc*!hgeYYjahgNT$2Nz&} zigkv3fYb8yDELa$7WKV3cc-gsN4Gl(s?6^8FHQc2vg~i8yx(xlzr!--iOx4rMuucL z=#Q~Q=XWd7JU_NA0S~`w_2+~1pb^SR>i@Zb9v!f(f8@=Yg>>!K(#gzjU#oowzrYzl zuMB^)pfYcO%6w6){hgC!sY;TEB>0;ZK#~BGgeS6ua4~WNOdK|9lp(};3!ge#6C|9n z6J+d1J0bdpYKB1TX7JyusZ5D-N#Zpn444v&Qzb6ym{_ibF4z#~5;dJ;P3fl98A4b< zYIaYN8Ad#TtQ zw}bqGJrZQ59BT|GIjUY^3N({#{hNP%5{wzOtM}?}t^RhliRTPhzyOBHlj^6c>Zj12 zo0b6%7>H#b|DV0l{V5zSyxIpSqgT(brPm98Pf4#X_RrF_48<5t@slW~NMk=onMfzfbCJ!1!|g;#`nDJV zbnJhw^YS-~PwJn|Yx0Yg_gTNE|sndTDa8ikISGp%MRNg z|K)Meglmb9xIY$qHN!#GqDNAHEcW(WXLdr5TmV6OkOi_Vb6bW)G_avdF!b>n*p|lf zw%?5%`3YT>>Px{`>`PDG?&?ePy?v?X{T69NU+Olo1cl=|L*XZnfsQj>yw!o8TKx-3 zpLVVP3|}ifA5dh!iJKIRSqSH$-+U!}vV5Y!g?@58`bo>>08MO=<4f$iWVY?I}wi{s5)%F~+sPFSNSYWjBLO(}oq zE0(+@jW-{{8JnGrH?Q>aQ&Rt%G5`Cxm8?efzp;L}^N5BQnd}Sn=NZ4?V|@JY)W7%nGAwdf8(GH`2XIIIzzZm);8un*f8QI8_%5`%-nW zQb5)7=u?Bz#VQvUU!{vxujXwJqk*~j)CNsLue^0pU-oAE?mWY8UrRs06mSbyfQg=U z5+(H?nSjRD51=YE0w-kDc>EG*2cs+t1CaBvEfrrODtI|Z$qnpHn4-%YVMBsMI>cov z#6^wV^N=LZk)4FQ4${y9@oB~1M;`Q(+UE*y`%rl$>zfya70`c?ALw>O0yo-0qP^~P zn>I;kXa5yw8!iw$^vCW}|-HNz9NuTcN>z~MAGVNn8`&bOl;^>FbP6k;wF@i z7Z7SH2&L$lVt5=Iuh5D#AY@m}VRaDon19`9iCybUpz0b>bS=WW5I%#y)#j-Wfz3{K z*vy09*Vw;fVbA@dVV06VxBYu@XW}=uqdoW6zktG>+P@!@RG#sUvVS2X`^IXqNBCJl zkg?A|n7?5Trbcwviww6Dql@efp> zC8l);hgM~PMGsU==PO8Gl>yoxsF;Lfi@Srq5cODbMlzwtY_JFodjR)=QNLUAu7F*7 zA&3ki*G1-Gz{B~ zeZK9_D83W_VHe@YrIzr2b_W0Ttl(SuKc)QJnp4An+_#5c^zH0nozVZO2VC%ry_MwO zOgW2T=^!sZbW#6{8NM^mhR0HbIbKD$9`lsuvreKUMVLvTJNVP*rP6((f20m7S}G!` zf9N_#K2j(!(cJb71YQc&bcC(S1h^e9SS7TsF~j#mQn=5|rJMQFLm#bvI~7EVBMm$@ zX+l{(_gxQ-Vv~Z(rT`e`-(O2IT=m4a-z0x4O?3HkGfm)2ZPjTh4@txEZ5FxtSGhXf}|0Zz_y!FzU>l0w zC;r|xYySvDhqw?;DGy!LFDHR2=BAVEwoanyv8d|X=@%*g%%;@(<>~uS{I}DOoMShS z?hO7*Si!f_k5c|@ETfY7g(Q3Z%Rh7ue;4&pCgGo)YtvtJMThx48NZ+IBuZ+eFri2_ zUd@HI1mg?az%3gSoqeaXLrMCg^6=x0kuu%@r_$foweiNtj^mA|R{(Nnyg~gB2r+2E zwXKmaN6sIC;lyM;`nKNqUN>XJvBtohqIW7zN1dMmtEx7jb)aG}Uy&=^1|w!qg{HT! zVcx2>uqUwLolmYE;=d$)@E1_NYx;0K=x;tc)YC?>TN#^BU%!9Js}gT*aeo%I!WDMr z&%DJfY}_j8EH!7!vD!k1q(;8w_YnGXJVKv@PeV$4Qt3Cr=icXC`mKg}Q7!dbjUZ;J zxF}ylUroDVsxF$)Ips1+I)+_L_=eP`E9{tesCG2**ckq58=l#BYxXWpMKn z^xAs-tu-IK7igZS(DdL}*+qRO{cFYvc3UM;u>{3`JAEMKU-?{Weem%;-&!Aty)-6Z z!*A&We~ON9kdr70$*T!P2m2&Rp4r-|cth%6gcSp#?_j^5EPMgyj)*1(6eSQe%fpk@ zQ<)#%?UrY6`*l$tD*T6Z1%D?|GX8|Z)`v;<4sM55EcjEgEdYp9I>5y8zm^ z>W`HDiWLE=`lFw-_)hxMF8BxTTIbPWk;YVP_rRb|aQozUsJv7EKqdW07$k_JcSyEmPS5>DyFaNSEUuq1@SzqxHOVe(6>44tnSOR^0(&)OGBi zD|w$CCZA~ugI@y5*Fkq-`ut*e7E$%Ps9O0Pd+CnP5qpHh<@kHRKoViDCWXr}z3LfQ z28VMw4gp+;zdx-uWq%76cl-FI;};w6+T%Pt<6bW(iG*iLyon->Iga8taWR)ndO;|? ztCYgO1*lheOoNW})ato{6Ep>@dgk}FRWPPNMs3w`TsAljYX~#2hA@LK^kL$wG9cl@ zbR3#iKM!tWS)8kPmdwS*0A_aagAQ6P(E2)f?KS+pjK2-$3%>!lJcz@~|6SCt!v8~$ zwP~3|ifd5zx6`ju{-Tws^=mH{--&)b{QP)EXY;+^ZKTdkAuAaj{e#A@QGKWW!Nbju zXMBtK-q*1%fRYrjCCM{Cp7FKwy{|7vdwZ|kBna3z6HJR zfAVnj>h`tty8regpjT#R^lE;t6MAKKq}Qpa`N-&%`7P*G@xx1iU#SiaD?Jo>(tUgrYp6!O?b{VVHP@9W!%{*5mKMZT4N zE9GZkMS|EjN&c3bSbQh?w~ONoWj`Nn!*AJdiEdWm*9*WHJdwhw&8-ICI-8 zosF-g{-KXs_(7$fVUMpc^}+>JMhT{0)>rhE{c~RY(S53Ai;Hdn1U26Nvy1r4_-bdL zB>a;MeLr>%na?_jlJRHl$@n|#2VFLsqJd}rui|I+++PJJ_Fy5Z2~wE$-g&we?6X_-W(w_+eu=i{Nd;1?K+T^SFZC<`o(#Sk3sJA3R6irI5z=I?q zCeaY19I-M%BuJ)OaCw3ghsE zs@IYSQr7~4)};w*S?ia?wiJKr3Gu72Han56lD zWd2H$&#~WpzGH01`Hqc?-TdWrEo#1F?6;Wj7~6&Uj@P>EuaNnH=X!eDD0#l)u_wI! zKxgwEbCZiva{%_XfW&-<^b`vl1K70hRTg=asC=iGBxaaf59T~t6t72Kwfg>Qe?SL& z1OsOy19p!UtIe^1s72(*LV}T{acbK z3)D1=okU4(ZPWtpi=0lDhkRgA<`XCLryl^@;Mp^7u`=En;^VLd^(4-lQ=2c~aeJ7DZW+$bIWFJHaiRm3L~-YxPm&_S$%s zc3TB40IuaL zq{mv!cm>{a@REZi0vBSfA{H^KwTf8M=xy)cU=4z$_rt>|eXg~N3Xr99K}N{W;Z`fQ zRfF8ed&r$c?=H&MNT6@X!qp0TF$(NLW-|th)*C{Oih~-N(xY&1#(rx%HK}*#0V z->ax$ZOSuq2}rVk<7@20(Vg0da_}6;AbqoY1KjA2_TfYGQFH3?hgSapI0O0xllI(t zhB>i(B`{K+ip#*+TR@iZ7C&~xZ3Zw? zHfNO-wQ);aKYL4@GsfL{k42G`F8|S0w?i5ZwekFzV^3f-qkT=Er%7Gg| z-cIMEHXeq)-L#l2K&Jr(HDJ@&wQ-X)?m-&M#?9F-8ao>|N8FX5F?v$V@&!556^V^- zH-FLY3LJSfB^_o_aW|MnYbvlFJ&E4kw54-E%desNcYtjCSU1f*{aGc)=jdCUxz(8O z;hTG=>9Cf~tFBk-5K70g@Sw=B4kdfrz5RLWlC|qJnx)6GFMi@^WTK!U4SQ@cs4I}`5(4X{yBTwuwR+yTb1+(;XJJMv=s-gQi@)h)&okppWtg^$|X#FcO1 zb0hEJyw2um8;UwsTi#T=y#kHDuXVM`6Fwe$1TuwQPYgIDbE1U>?NT>xJaBxSdTiuv zw;lx&jgTQy)?gHEUU~2MRSb;jUqv=#0FGX=;i#g&ah#Q;;w{2ru~lr0qIr9N z(mWCE8^4TH2GhYZR#g7#0I7`HfndMZTgDw!J4M^(HQi zBh5VBSe{!$1VDp%dQ`ob-`S{mlLc1vBL35%C}uRVSRH#w^Jw9e>Ct|S=oH67)gXqb4hB2x>I57q<8G$}$G!{|=gJdqqGu zYAsk0O_)&wnr<|jPWCeM&6Ng}K6$}`_SV;NG~B@vJ<~$`%ySwoeFU|^D?9^c5ciL; zxIBUnmXSfSnElg$P4vQm(f^S<0RsFddUPxhxDesic!?ztrNooe%Q9Ear)HG=$lCfk ze*+U}+nFeUtOt#IjE*~46;1Ul+#wX*7{3?tD5W@G$Z<2IG_*?Vn+Xz|8DXHCoh-mf z?SG?c|6sztAc8;!^h$?}@(pwloFNlH8Po+Z|UUQH_ zk!JeWtJcrqQGY)ojsgA>pDu_ILc4$?l(|5Kgr*0@K)#IDe+#=a3mPyp7YAD5Ckzn9 zG5NwV@9tL|gXZ8a#Zqt$PSA?YZrAI+sG0-s!knL}rC(Kj_vyxzzHQhCJa>W~#in3^ zpKVI~P#Um3@qj8#fCZ}p*!V;zdh4rp?I^Qc0#pLB!1fBX z-lOvXE@~yA#JU?*Pbi#&N|7%97MjMqY&IHchO3d1+UHlQeL$_56c|2GIq2pz1|$xx zV}{p})?{4r*KhEq3`GD-vcstq6Wg3ZD^5qikXI}H090ML8-%J&kK&H8{q0(t+qDk7Z0~esH z^ee5V^IKzIQ8}j(ymi3)JUk%sj?tORIR= zqmt(@fO}?w2hbLN^Uzw0>Oy1#?nL8Qy{Ki*DYf17k)+(5WA$qqglg$qi3}KknImg+ zn#=-Kdlbs`WMQp@s5xmy5|U2OU(o6=LFW#bW)Y?tglUG}tdyVd-OYqA=4)OK31vGy z`UTo4=36E2F!P-L%l8!yk5s&K19%zgzwT48o;k=y5U`h$i1YLWmfv@<9O}kW)xXSq z?L*b&VNz=CtR{2JHquJQ|H+0k1<2=6u(N6{XQUc;IHBzSxde$u3+I-JS6Ywtf0Lg;Db?Jk3OLZkts9n^gFo;z+4H{y_uYhUGhqXI z}33qv?{Faf!o5A&iV|s zlt8Op^Mz7dIKUPqoXrw&qv6?E#YX=_x3YK)7YstwTzs~uYaC#DHarkh&d!;@Z)aKG zc+#gN3h)Pu@S})-+C{u=eWe+fRuY>9hHwG7^it>-`}AjBy(4Ne2QNr#4365iqXHqoc;4yR5E-JI)}>kyc} z1dFdjKq<>yRQ3Oud-u4iiZyN=l&xsuLQ_Li+Y}j?8F(ovO)%7jZH>%|%!)c?=CLy6 zVg-tAP) zWqinT7(1uJ*l9m-z}Ru8*n1|Xu}+4QuSLvce{4T|%SRx_KQ0h^M09QlFE#Q|T6Ia& z{K?24OZlTIe{`cT>4w=2-T3V+%FdM=!fuS`JM+O0>VP-VjjIUYUrp*aRIMM|o<%+* z0%Nhna9>e=Q8w#^^GaeY+kqL?J)sT0>Jvug<0$e|h5aVw)BFLNtv~*)g-x@5teux% zkzbTE&{^lpz=?6T_dU|sEE233X}|yNQ?qpOAxk=|5)X=~65;^tybG(+FqFSOV@vfa zV-V`r-28#6ADT~+^#fCk$m0#?i$8q6wWvi=KpvjO^c#y$_?sT)Dj_Di1XucpDvd(o zH5!03IUuBur&!G=y@Rq)hiHjPv`(f9%ua59IX2 z@CGXB3I2gb4G|w9NeRXkC(SX}PYsf#&EBn}c^T7Akp>9NiEk6byYDR^vBSGl=hF@l z!+Y{?nh4+}R4+8Vk3p14kSu9hk)JlNoP3@0WE#~!mFkZ`gDx1!uvo7xZj17?{Ff;a ze#1LV=SzQfbRAFW8m0|{Yp54l{Hq7gn@yS+%60{MrJL*-08Xp`bAF|lcnijlV6g-5a zn;;5KmI@xi3*OWCnN$=EgA|<^V;n0uf2TJX;>V?)d-q%C^ZM#kY>J)Nx8}=0eRW>! zoED0${fYTJPf7@>#Z~Ejh&*BNWazmk?&KD&=sWXzwLO!rp-PB>j0aWp89%@wN`2N( z9)h-bk@he;^#H4IaXo%mB`O9B<6GLhUE2B_*c zTb4KLM>tQWlDsiVLVuvcG^Rt`Oks9IBs5fn7`mH9cNo1x)sPHzXriM1H?eeM=tM@! zAtaXsYUaAXldQWIL@^~{hKIZ-nMMjYOD#2C`Uj+PKbK0N!cFXB2+b*|{>5V}c$CjU zH`We4cK^%=6k{xfo@kwdb$_99_`p1L3EyJfMBA800=fPCvPmn-dcT|%dY(Xw9a?@k zWyLHJV}<6rHj#${=u*a$;0?U8-xwgsJjWfRj%xz-K4$6e*=R6mEYxj-3Bipx#OxDI zBl-3cPb>u!W;7qQpc=81AqBRpEm|SOoj?U8U`Ug3MPuEXRtd8t3Dvn6g@hcW&hq|r zbouk5mQx9+Eh`C{S;a~u=gk}I~GK#kL}5cI)o{F{Na5QN!A z)PllNRrP!9p0!{ST}t&!x_cRyN&G%-KL0#VI;;#*Aht(p}Yye<~0ZgavoL>|$ zDd>>|kY6-=G)?;?(7{pQ8arb!d5x{E8Jz==G=cUrc}aKJ9jxwM$FsWcV-1j=vV*sn zT)r{JZRL*8Hu!VV+R2dx(7)i> zN1C#aXqx?Lmi;!C9Y@u>!lv-7`<|ANdr`&PHqCl`4^=#zXN^GCA3-Ryt;uDVHj+K*Am%b2q$lZkV%QLfya?kyIUsX8#>=_df*+W_ zM}*J{J86XnbkAUCd1vgA?Abf_{3*@p!DH8uEFt+|Q0b;Gs!^x7m+wN8HoDOzXVqZKB$ z_UO5}=Z0rm6z)7Ry!b>1=h3#sM?1IM>pV8R_*k2E=bcA}w=0Ef=AC2O3e#8{U(!RW`*Srl{$ zOQ02&79Y8yxb6zAaI>qVwlcDK?opCxyDAteubCoOr9c1%5GCJ9xBs(!{A1()iG5s{ z%k0Au5ex(A8PT$RBn&ys?8EN2k7$LD#3ASYAJ|6=g>%c`R>Jg5_OZ)vA9mI=RPAH- z24){*S8ceJFuQ7Zn60Id(3{#v3(&?OUeeJk2>xiBc6%F3Q0=1wONWwMDyX`Ys$^*& zoD)T^N`Y4P(WL)645h$i(0ill8^l-iWmu;TeaJTS%%l70WgTY?vpMu_$_)^XJFG^B4sJruc5!!lg24(}d;AzfL44rf4 z@QDJfJ;O5hd8;0x7vpzj?j~c(h@>F-G+Ca3ej6FjE|^Zv<(jhtR0cEaL^g)yDa<(I zblLcl>|dzA4s-TLCav%+_OVPWBDXi_Mx;KCQMj+9x-!vq3USck=`bKUzIZmHeV15d zgdiRkB|Ga7EZ>F7ldF#4jJ3bAI|q%XCJ>CjA;AvM#Ng!k(wRBq_|G$#oSI_uLLS%x^2g(?=6`d^*|kuI1ZSOn&b1!B)_E=@OT$jSSZvqwGmdBJCyB;< zB^So9e3X{HXV`LFGLBVmgK(~XLaO3oxU=Sj6N)N&F&jfJR<&mbiTPaTInOb-qpd-M z$2NiZiX2R{4ocA044pAK{``#Fle9HSGg?hfiZ9LVMl1C371@VH-Gq10);MN_#GIdu zLmIJTD{klH+S8LUq5Dd40nJkTeTdQjzhpK|v%(4{!wj@}*qepHB^wcM!J=OL_M9=g zYX{D`PR49o@wws2F%`*Gbz?jo@Oj|M!7q@kQl!|%a#;>Fw>qCzr|8kNikcnD4O1#>X%qs(@X{LW)(D^`o=FN5*7QW zv`1|oP548EP5Mii3!}H{vB3_D!0zeTx>2JoWaA&tv*=`;z?TB&jaRMncg}9>j!2B(mqTq-XYG-9h4{eOUotP4=Es{Wc*55t z8dme_PC zI%zT_F@E!$_DQhX(4_eNvtb5R*~`axvbA7`s{}aNOZ`1R;fp=U_Jm7m8 z#DI7KSy12Fg)@So2#NyR_a)n6NY6oHPw zslnFS>cuMFovJ!07doJGx_k6@oaee{wRRRAK`E$*zv}*7D^wXH0qzS~!qp^(i-2Ae zO#ZKU>jj=&EsXG}i_P#VIb%)ny0?g@&0~8Plr>va*pBXKc#t-~JvGjMROoZh|#CsP)?_r59zKNz4$m%^^A+(mp;^mh2DdlsZiLyJ-#@-BREA{ zoCb|Lu}KR303%tXP@iBK??n_ul9AFIKYT?t=Rg#3)$jq!W=26z*JFDJ`_{EJSj$oK ztY9gc5KG6P$$koG*;-|L#WJFy-<%k(&C8z(xy?Pv*9unhbrBE0V)ixj2{!v0uDivf zxf>`YEd}jZLzOMFjYpDT)bH?hVkrY{CNzq)ftzq#*-Zr97?gAEGn1M&>DbIcZe5>rE+&z^^<&Ncj@C) z1g-zjmVev53?+}}5-5B$Wjpr(p-@Zpg!N)57>L5(U?fStQi1ZwP`LuCs|t0hGcnXG z)Dj75bw3hT%TQO!P+bMoOH&lC=C=%Wn*=rbB2a67lmz$@lu1+LnhMpsWvIIQ0|NZv zT5GNxGSqMZwcs&@t7kiz1;{PJW@8q?b@lW`pnm#6;%fIa&Q&`VYD_aw!YqzT0&H^; zs7x8^aRD`NvclC*I0m%^vzQ}6z1i1VfS1Tn4gcg^wN{~KwG7o$f{MKe)N*k=5^Gm4 z3#i;j6|S_Fp^7E5*cfBY)nFMaT0mWRM1gu=Yf*p?NKg|m0=4;oWETIO$_4nW3U#id z8A@2-B@)yh(bil&C_{}GP__S1xZ2qal(4|cNr85icM+&R_e)%zc${;Uu0lQDGSm|i zRQHQOxn!tp0d@Leg{z>Jp$14$pI&1vz}_-cCjs@O3NpCrKd zr*HvQKcsNguNf$zt7Q_@zCPAm=`z&K0&0p1RocPKm4LcKf_ma2P(SXKxT<`NbM;G_ z!qvoUR;SWqTw6E)r0aRH!RjhI&WdeP`D~=Zx*27YJdcF_eG$} zzL&WA`cW>xyH%*MEko_NH((akS6Op)pA0olK<&C;;p*phEpnADLFHZq>eOzDt7DIF zu2NK}=URs9E0&0v3uO=}tI4GF5jZq3z`GSou?>J}BMb<0pUN>DFf1gfza0{p*D%8McpoFfHC8+;iVJ*PxWGK6U`YKi7 zYO~GEm4G^acfc&hUj(Y8QZkFL(zpNzs8A2J4CR!dPV~0s>K++tjDY&=o&Z;F+aRK1 zN71v4N+V;JZTf0(|n!>XPZQo2e;=q3<;o}lpX4fDl* z1gz9T$+mYTgmG2~#oHt)eR)5Z(o_}U2<^JO z%?;J|yCWc_7pxF2h!cUBYdSTF^N^_`tY-aNKM(D=lwOe#qOB0#lo1vRgulltJoIRe zhnpmXvK|&vikA`k354fWguTqY`gstVK5|l;N}(#ktBSP>Db14* zT3I1v$Ouye!ooWgDJ@g1RoK!X31NA63n^VHBeW3+T~vf)tz}yhZTi5NfRt{rLil{M zB&B~(Q&TNo)I6i^%kgg(J zp+uneyiL!L5PDl7yeK2&350rG;o*qVriGNEC4}!fTS)188R1HSkgFm*5-IC}HtNH- zZchqGX`&UvHZe|M?V;#SE~Pdq!mEnc5Vn*qA=GuU;NhP#!UFlMq&F7E-!GM(8XMRwXGsyscQPu%$K!h9Lw zS%FY@i^4;1r9B8upB)z9VRd^8DP1iiL)-(jG)lV5o#p5o#f&n`MOl0->jh@Z)J&4ly*VJI z$yNya#R*HSC$Ke{OX*#FRzTVwb)iN^5VlkxA%s{VWXT9q1wyonkgjN2c#ZxN!nMd}^bjo}WLqKpu|{eSM@MrW=rbP@!kd3I!^58VfRuVzA$Vkj zT!BzFL_rv;_$ATevL%GIHVY|TDHr4qt4 zD}=*eN<8dL;!>KfB2+0-5;5);38B3eLXM0uT_Bttr0`Is^eRPs`1yu_lvcE|kkaKc zLPvp+ts-=3j)xZ{gi%%qUyDAafIW815$e43gNHSlBSIjoQIAo!tcuJfan=7kPz%v2rtVB^8~^x0~8)Y z*k(w7-&@Sh43H4k1zAWbPDY3l2t8DUG(&E2!Y}O`6p+#+D})`NOHwLHHS15|_$t7Qb?HD*Z&yBjQ|G+IWuNg%AfUg2R}a|pd9gc(){ zzkDX~ux~h*(k&`N8>KfR^sse6KuY0O2u>LxQy^^Uuki4f5~t~VEbto7N(i4`u#i%u zjL=0Oj8PF%f06Yd+Jjv}a9AO%|5TFF>RY&!Dz8&`XgDS#2wN(P3rOkLzb$yUUq(m~ z2zRRpy%cK|y~;cZp}-2^{3j9*zYpU){LoL~VW(nCB2M>}5c*glye=aw5C{*e2+_(Y zOL*_f*npHaoVSqDjWR-CfneYpHd2r5RmECG6wQN98sxTHHhlp_>(gOGd~R2roq|JlxqFLXd>;Wu1kTu8|RX2!sd~ zVW{HyLm7 zSq~xt-6SC_v_c4$5&j&)dHAT0!h=h(CD9&E^$SR;pB2J8;#1trmR=GFu`0qm#d{0i zS|}lGK5HSRVKPFjKq$Og;bEKNy+wPNBq2<(LOA$=r0MN9aw!c}5x!C8`84kNu9Ohk zSRp(kBTN$rB~c0w#YbdKi_z}BYXf@t_g@xLx=coBFA#JU;rJmLLA2@F62b^8gsEuYP4Da*kkV``gwy|#c=&lR z=i$JW3J+a=lBFcPMuCLT(+XjcjPSfbNK+BMRx~XT`b!AkoUxG7buxloARLcWczB>W zgxxU#DWzH=Z27k&rFDb2l%_R7_*IsY@EXrb2xn_7cz9e!m?RKt>_TNhZQ{)9vYPRAP~Aq z2v=GmyecCU2!#GB!jt=CDTxU5-PHjp75#1@rGYX+AA#`Yrp|cf2zKk$SAUvQV98vTjc=+?m01vCG zEu?gnjL=OW{Ct_h!-(d1ctb)MXN6F_Op?-<{kW8-stCPz%9<9lKe~i)@>dHU9+VNr z3xreHZ6M8SgeoIN(bqT|8IaNoRtOi~lz2FGE$1OqMOacP^U#X-?*A|P*{N1H2R;u*wQW}4E>5n%gX&mj#rO{ogD{2%fdM&(g(WiKy z70%yX>cI-<^V|6DlX!PYAb4biT!HWoX8Qfo0KzgMZ;l|m!=DnuS|eaHCWLEcgx&(- zY87Fu=u>b6F-~|xLb%%sVbkl9l)j7MQu-LX^d%l%7ygGMh`wElgz)DH3mzVm5he-* zOgG91WqY_)as=UjdP@i|Ss~bDgt}!9&lWt~BO{Cv2oI?U z&o+mUDe2*PD}=vZm3T0&<~*F}sPNDr<}Wx8kRb7pEg{&g5MGuM<_Ux+RD{c~=KJhnijxtd1i~4tB}jVk&s1>)cy{8ULej$|D})`dNKz_^;!=7>MJN^P zpBzEVZ$Bv^)E~9r;RzWbO(6JSkrEHpV!Xx?AVK1xi-fS$3gHqNq2VgdL%xczRrD!1 zf|$?y=CVMGyTJ5AG+IWuNg%uk&mc+ZvgUYb zBO%PNLipt+iHChxaw%P=B0Q~l4WWk(-2zeyw?c5r2$=%mEl5J*;VLl)!}TD%_f!et z(<2sAij)z$2!yLtgn{C%O^$%^DA`h~gy673SpT9VrPYyKN*^NHOFY~w#?6Ygc9al) zJ#4|l{W3y|K)7B-cxJ0?OJbbxW!Hcn3ak*$FP3=t-OhQyiB>WX1I1bi=RvgT7bJu} zRtT@l2nz(l%__nZ6*3QE>>n*5Y&c{gr5k00z5;;`E0gr_{r570h@u@OgomvVzF#Cs zsp1MQrO_(FN59Dkq9@Q(LI|=#m?*MhFoI zcd7_`6iuVI26)?Y31O%e!e?S6!q$7aNGJ46{D%Xj7lRSmu>cR$jD=x!-^K8Db^`Be+lB_xm?q1G=)$6haD*+wbD27 zkvNriQp2`gNjr3xws6wZuc-dRaTq}e#FGxHb@4+udQ&tn7^5C?E#~l-X)7W9J;H-(N-3evpc%t$3I?2{j@c z>V4HXlf#z4$bjRupl3EbW5*M)YJiUV68*OepeNC1%&B?-`u9ZNjIYNwq5qfYDQ5bA zh`tBkl5UdTL-a{zdIr&Pm}JxR_Y-}JnLd)}ztbUKYCW$bI!?!>lbP=QCrN{|0jEjq zb)?65U9@Sovwwq*u1Qn+A);Sqrk4@@Ejo-{h5wZ3SDEQci2flRDzB!WP4w%{^vOj3 zs@9Z#9MNw!({CVpF&&1kmfxG`qs{a-MBnz8DgE!~LBG>X-$V5Mf11*-Bl?48`ujxx z<%}u)LZbiEOwT0x=^9h|2Z)|!rjH`}h0~_={fX{0)4LJ9otfTH5BefHa#oewaiVuM z)3+1-O`N>jBz+;#BhB=;iT=Uwru6fOew~^AB+1)(Id=sUmfUgA2+2xLG&myeFxD$qBHzde%BB^ z)=Yng=!JB6otl0=(TAGpPZ7Q3m?`}|MAyyq;Y8nl)Rg`jqE9f>HKHH*$&|jf7W6bT z{V>swA2FpbC;Buq{WGH195$tYjp(z?^f^RtIAluy7}4|0^xKKv-b}xd=!<_em2(Br zyP4^2iN5RyQ~E#7f_|l$zL)4L4w}-hCwhM~{R5(ZdBBu@5z%il)3bpoNZ>xn+zOuvli`}UgB`~Cv`0WL_hVtDg8S{&otBL z6aDYqru0t{{dqI}9-@bu>BEV>aF?l^Ylz;(OxKA1#!gfE+CM?Jo9Ty%{(hAyeL2zl zndzSqeRZWN{cA)YVy4d_`nnya^p6oe$xOeU=$p5j(%(q*6f^w_qVL&eO5c{~lg#u# z&VYV&t110nqE9i?*AxBsEvEDz5Ix;YUqtl!&8GBOM9($TA0&DkGkrAC7i=<>b3M^J zo9UMkeQAX$y{`uJ-e&pQx}-(aTCC;E3AP3fN^`Uo@q z9->!lFr^<(^l@hTHALTCYD%vWeWICOdm8j3C8qR;i9Xp(FDLrRVpIChh(5zie~svM zMW*y~h(6m)e~joMX8P?!e__3;oEwQAZl+&B^d;*|>Dv;$rxus9cc%0o5PguDzKH1Gd}~UdMf3zS{XwFaePc>Ln&=KQ{d%JB{MwZMGNPxN>ApWe zKeX1A{shqE{zY+f09o=&j83dx&1}m8qQJMDJ*( zUqkd)zBHxRh~C3Yul*hL2D|c7&HAwqE~)qN`D2>?>5uh68(oyP3iym4fKc2^u0tkJ~5?VPxL3v^bd&s z=SoxhMMQtrOwS^EkeU7<(dT_^DrYp&JDBO$6aA%+OzAHpdW4zoI|=&RADYsiAbJ$h zJ+|``1H&GCgqMar74&%K3RAXKL{Bu+mlA#52d4D7M8DZgpF;Gt@0-%65Ph(jK7{D2 z|6@vTC;IhfdMMFX{@axPR5j=^X8Jy&zyF>oeG$>GGSgQOefhhl^oxn!%S@j|^f&%x zN}opb%gl70=&vj{rH>_gCo?^Q=nLO5r4J(dC1$$uE9eDpo6=Vj-Dak*CHnJknbI#O zx^J0@UO@D0GkrSI&%J3%pGx#hGd+RmXWlTSk0$zbGd-N>zrAisU*`pVs+oR-=qHw% z(pM1u5i@-i(SLf)lzu7EA28E%iGFa2Dg6|pr-E*DJksFv-utR_Xq9sQm^SaWRZ=Xqh9F<!D52w|T2&2~@7jU8@ zJ6;Rtc@d5IfD}5>OPs^@(HJ`P3Z5c-C7-Y62MP1FkH%CiwF>pGs zVoU|YE)AT~)r8+wE$~~OkcKC0_FTt7!`UNn{2z);1v@w=cmJFLAmRY#@&q=y%pL|; z;S#RLS7mk7T{`N}Sl4~Yf}@UNHQ7${)6rKGfXCMNIx%^T1H&K@a)@gR#auhh-a~T! z8R+XLQbC4(2)qyEyes@zlp?kA=s9g*7|!DV{<4sGFkNaJvUOIJE{51R@%Hg+U7Sxr$D zs0G!*+1R_XX6mj(x(j-ArG&e?_HKpsgq;~lSX>C`k{vx6f%Aqr55WiY_{~{8kO3v( z{Kw!^q@*+wVgk;f(@TxI(M-Rr1`epN?ia2;h$%hFUi}|quSjstdl$53RIr~ow)9R? zt?{8)h=k%q!(fdimd;2+JtttlCu)zvW`d39A{_2pLmlo*9P#B@cP7Ww=`jtuZ+qaV z@7gh*L7D>xFURRFT62U*9Mt}d)nSbyL9M7rh7e6QHpFYdE^w-9^=6|ludMTYg0?7? zti_|-^VnH^<)sOvjq(z@cnj&7YmaveyUI4U^zTL_*oODF3*h+`oa5(x2X~UK(XC>? z+Pt*{;5->k_GTx0Lq%zc*54jU#;9)sX*txm9p%w;$i+e2+<_Y$37!n!RFU<#9#gEx z;PmRvbR?nftichWm2?Cs#F~I+I{Q|VErd=*vQ4$*IY0_G=6B%bGL7)1SJaCwCZ(|( z=-v+9N0;iZ&DCp-+L5eXt~vl7uT_20{}q2v2|@n9=I?_`B>uR2_4Ak79DkQ_{wnuh zl)s(aUrZtWrIG&7PT2Q4{QgwM?utxeY;hta&~` zeH>_Z)Yb)Uft^5H*|ZOO65@w@I@&}6+Jp{A6YhvF)8^O0za+<;O2$dSzDwimI=l*6;4Cz1JJ}oxW}co7V0JHv$_3ZDt3#A;4~Y+Lz(LEMw8sE7 zilq#xlpS@Q8LC4v?&lDA8npQvSw7IgXQ)2^HiX_9yKv<@o(m}@e zwZa;_6Ulq+*#pb(MBb}Odw!S7Rr^aQL#HyRuoV9dYgRa`mHqbECX3G_h8q2n{`O%- zdn`Hv|LP+;0!)C^5n!Dc!}UJzGokL(XF}a!3jpB;LAJ2i$RGPR3+ucOwb;l|ejDAW z{)yz7n$-V2vQFp8G-|I1*YpSIQyTp(i}Mf_0;YR9Y;1qF?r*Y+y#8~R%PXPj35;9- zlDc75sW7WFnAKrDW(zf8G_iBq{7$T)Y}Y-r`LWIH%;s}Cb*mHp`-YuPMQS2Dh@s>j+bvfG z`g+hG_4T%_Y`(8|YYJ-s%Z9VdUAv*c1emv?zsx70JBWo&ABOHA5$Zt5v62iLat$(~ zgo2<;@+Iy&pwM=DeC5n2tq?Aypi3~-a|n_$!%bi};D;aeZ2adIR*mhuP>pBg2&dFX zn>T>l6AZNZ_|5x`s08Xd9bx*k=6M-V+WdJ09J8G|lybnX(u4Pt{-Lv)*=a)U-&6gj5yN;@ z{lUgFe)~pay_%_%Wwk2IZJTo&SyfmrU67J{186;!s-8yPj^i4cJ0aK4q28wLGmjjY z>R+Ja6jCBu>I5oe5_wx@<=NyD=qXAE1U*G#NgxqTAxDjoj8Dt!MMdJw_Pj2*Nzw{i zC+61W;*e%&&f(D;{LwPm`BShXc#H1aq5CREYK29jEI$YxZyt^8?Gkg(A^RT?hr@F> zvf~7D^tF{&_1Rn%Ns7NvI;^w9)rq^lx{+K<=4%*h`YDH0m1XR;bFw`AwK!C3GX zvS_BBnC*}chA&(`j>swp>XAw^;wpq-={Wf4L^vj@7~39XEW4Q+p6==ibIdr6k8}8tb{EDOAE3PtQ)maF{CgCc27PJsqwJZ*K~n*K@G=z1k~91=MY8 zl(DgU2Q2hKih$}rrTu3PgRR0jPeVoFk3x-G{%kQ58^wfuXU_&W@l;cB4bu6I)WqmYUA*`Dex&Zu|WCele0 z?y&plf@zEpHg|zM%zYR?u-OLVukAp7**qTk57kx~kKn}a*H3o|8XBC*V0Z(@S>0C+ zB}J9lp2NdnBmYT=^OO@#!(*Go_Fn@KE+CX%Z87Fg;NB#h)Dc1Z*l^B++qU=&x|Ky4 zy>wUDCm+tPL!1Hpm!7MP_XzNY@w7tP{cYTvp zicR#u{Tk`516{(ltnlhjNdO6`0CR@CkJMPAF>@R0PY$7_`g`)CW>KqSN2)(SuNurf zNwH0Lt&E}r&2^8sy7QvK@mnj@pUK0F#N|j@mM|+Ap#d&4H3gj*ZP9UZg6`>Qdj450 ze?R-7;|G!lvF)*X3VzJa!8jlRc_5hS;C@!B9$&BJe@L$gP>Ax5Kk4OI9fgqcw`a7~%Zr1;K}C**_;Nc06n0Bb>VGu4EgI`y zyUgFa^moo-33d^nSXXlb^`Mq9nPR*FhxuG8<{*YR+_%B)V9@bVC|p10Vdnn}H+oEM zGovod)11>5K10u$-C|OL+*!EM>jH^^O{Xm22(CmhOMz4j$`HusdiH0l^b9Tzgm-gAH^X5M83LlImwCn~tVI6AfO- zjiODx5@oO-jlxQ$!I^7jDzmKRw3Qx=EP8=%P{u6XSEM`Z9+?BE{oYZeH@EGd>;Q_q zsO7Arut(U>1yL33=gc%ne+n6G-ccJ3jBP#foQAx4@8LHa*afV7VGkPDaMMM1c#Aea zixQ#JHUCMv!Mqp-&S{vDOVnO1N`lA7p!bl&GfI-lJ_mK2heqi!`ve4Qc?p~d6D1{>)zlY#=+|E37ak}A7 zcRd3=Jss=r8v8pL)4g_de)4xyS*}Don9o2BE6@g6`_BuaITwEmEKguv#j?Dp2$Teg z2^TYW19_fO*cdYHOt+!-v+Xdz=|~hLQp4diO`SNMH15KMwBD-vdpPsn;<(aNR6fSS zb-2dTy~h>~i`QN7^PapY_84{@YP{k9kOf&_IB(5F?~IWo?o*Ql8JAEQ{#x+1 z56^(P+e&RA$k)cC2HeVjb*V90P|#$WXTWOQR$Kfe(cHp#|diLvmX9N+FY z)m)BmFH3wTxW$GnOqHjlnzcdA{KiM7>UV|Q3wmFNZ5lhT=k1e(Mm>3V*ECl3!4J_T zAhesLs^3i_Sx!~*TQ)PK$GpsuQTysbDOhlz_T}2*tve^=(@3WZKDte+;68si_imxY z<+n};LXdYI{czu!h9Hj+Q@!L(1|e-YZI(|MZE1e4-eAV( zUhm?+z~{r)kz_C}O3NQ(UB$^UmC03gSQ*k5zKiD$*JkexxVF@~jibfrkmvl_q(lCQ z?(T4P9ks!m9}3szdC74&PsRqu6U19e9@h9aFrPw``{-8Z&1AonnH%>c>NUWDVvrrt z-Wc!YT|ql+FB?5?>Qi7D=U)7r{h01a@nOMv<~=%c4bckITl*4n8^SV1(AwM$EUL05 zJ&EQ#sKW{!OsDb2ENG9#)m*y4zrY~INa)9Hr=)tFvEf>FPo-D?CU{7nO^yQfFPi-X zR>4q#;+gkTR}U4K)XJB8J`5{|jEngFSp%up>7R9RPz`8){vtJ4*N6&96jy&|3=;%k zR2!5#mDL$HY5toj{+sFk8w(!)UlajNB(S+hW5;@!M7=Tz(8M0Tp{`uh@$!_T&5W1N zFyWWk#^52w%co$mDG$P|Jhrdc_bkMC*$yU+dq$FHqV6g0@`QE6`2p^*w4eDh%(VpS zvb6&d*_W8IM~Li=!|f9{&~Q7FvSVDq)~sA%2S7yjh>vO4fk3AhT#fxn9KA97ESCM~ zF`oSy>a@DT{>ig%`%21A-%l{!Xqw%{vcD&?^Tn*NY@Yp&zoqQgQ}+9sW}nKkKO(Z1 zQ@e77-OsZJUy!oLQudxrv)|0JUoEmf$+P$8*^jX=>j>WQ0l6UK$6K55{=;Ar-Ek<5 zMAwyP-vJ^-w~`&sD6-#3+23xOJ%?rgKxF?8X;As;Jo_?set^i1!)=0$2b*U99bd6` z+sK{}`lcf5FCYN<&{BzSdS}>(YMONy%X%HpiaD3C%^;N7wj6FcyRw>!Bm*EfZuG<9 zpw;^T@ti{LO5}MUf2oigHo_ank$1!bfb!&Lda{rDs2*F9@?kmH#sWF5 z!&jZto##f)9E$qB!E=UG=&oHfIqIw*HIs_&P+6nhTa2aPbOBDo?g-QQq>@TIL=^|&Hmk@l`$?7dXS40!=;MA}`{WIsdZ1FA2?)C3$D zhMVNdNJ`gJG{GmidX_X!4;ej9oP)EY{sQxOG+-3TvoSry7Rwvg4Q`=YEs!Nbnb18$ z_PCuS+MLTF+7O5~yhGJwt$%Swr)M?YS3-}nf1$t|TuOg~{7lID<`qC$(Fnw7Zm6rB z;$3*$Sv|fi=LW5C=)fe;==F)Yb=|XCJIn3Zu`_ch)&xQZjP&RrpX;6#lISe5Cl0B@ zy08zkKxNsR0T+w0u}~`gLQM9ncvuwEj6#&zYdW9#B{^T`$rS2;=ro_HQ>D`ovbDTi zdWPDkYK5J0>yx$l=i#k#>#x=F(%8*)THZ#eo*w11eQ&M~yg}%mu5UWYq0n#wp*I5Y zCCE66hUo9O_0`vcgny^zkanUWUiP;WCa%EIbnr)2ac)S#90BVVpnbB6QG-Jxh*&`7 z(`+e~ABvKU=L6+uEZ6QSLQ4>(feU|WEzxzU?vs?dV>&a)ASYt3JNm@v-mtpkuOIEA zb$?ZA5WMswxlm358J1_*CVlF-S97xza@(aFUyUknw90o(S__89pp{g!hB}k zn2^y5d*q(KR?EMO2<4?z+qkoF=&WwZiPxM%K&2Mh1C6x5mj3}BC*=9G{KdG@-D~YA zRCle7#$`R_)P1GMm|dQbhbhJfMB=>Rlo<1eY&VYPjKNQ>a8M8Qz#rA}+1!C=W-x8n z^ZbP}G$#$+w8HEj!3nuO)a*+t*jd^NlhX`?N^-M=Z0)yjC`$6h&Ug-gaTX}j3`t-KC8Dr*B5>bmIlLg&(QU>B$@2Vo>eKTyhC>{CN^~Kvs&7_=is94U!W$cU)Vbs6EJ<}hl$g+h0o5sY{TfM&eVOaYM0$PB0V z7ubL?l|9$ptGKLJu}a2o@sd%RYZj;{Txca+Xgh8GQ%DI3#AaOMFD3tM#^nxoE)|vR zt8lp3-8vGk_a-FvC!5iYMczla0a^3Bgd5HI3jHk{)QOuc8;p8pz+}rbPa;b&h$YDGButhqC^<_4CX14a zn8_ZdzlB3lk}pMkdiQ9O~$dFq~ZT9 z?HZQWZ~jaQ%>4f%+j7)u_H*MMd>98vXGbz3P*xngg2cMz~md6&9BPF=N zC#w+@*jy^QEwu;eKGax^elmfh5bB%;7xS7h3l;GBJLh~z)+*uT5Y8fwlS>yA7k@xo zFh+&KfQ&{kgfoWWutLx^qQL{>SS>dD!;JP?VMOlv!82P`zl9Y-*d_I((K}7S{AD5u`&LemOMg@uxDLqD?Dyh>>kK$LwJvcMb?3*>%Q&g;B<5(OA?7K?r?&?1+GI zdNFb6)2j?#I&n;;L%jLr8J9Bgxr#A@U`f}p7Js1nqyw6>S8vtH3}O(y$r2I}>?v6^ zSzN3hQ^9*bo(aKhHVCZ%+V)N^_NkL#P40+8>#JalejZHZd2S@ z=3#iYo>WQY*#JUB}{jh=(`M|Ks~=y%TFgOLxWr}7B|%I z)3v@O{!VuX^c%y1QZ5Oato^|Zn#IMuj+BRH7MsDW@?{Z zr_;rg`YYaFnE4zET2Pz<*NM?`1xDQX7Bw4)KX*G7-oGNV3p%F=7|g>oc6yM@_99PF zoOK9Aci}~Mr3-ce_CkUX48HHJ2;>e#8RPwKBva!ZcG1Essy(Q6H`Kb@%$rcyj!mqd zMRcj%hruE%uR}?V_5cm&p+TyRRNmdJpui(=DSBrCS|GWOIc#hvBa>=Z;+JfVmRjU} z3o7$>v72x#`qfSJ_r%^7_4kxte>&IS8AX3*pug|NHq~Fdfd0a@`R{T4wbvHD!u7YP zg2`nuT|B86H1C?3iGmz+_nqO&!={cP5Ns1sGSl4|zwY`4L_!HhvINChhav5FUg}MB zA=Tk|$XqHgkU1bbqq+-I-Oubos#^rrwTJ53Gu8cB&Z_teU4-gTUWez;Ky@gOtFE6^ z-kYqTz$3Yy=HyLP$Ao%@RQE1dU2_G=L!!X^jt2{-XqSBd&vqLc$lQ}f6z8!2XDwYl z;z|o&j1E_Vb(KnXPjh)ie^9HzNFCi!gcdAPMm{cHGelCapULm-pK_S0_I zBK&x$(H09T<0sB5Ol!)LZUJRy|K&K(xH4b!OD@$^39HSD`w8V!R1zsU3m zci4rkv=o&Rj@JerrYD?FdP6GgSNg)eyX!%^xKixyu2n2;YBaW3kO3_d!*O^%Bl{@tkH@Zxvu2-<$JSim~pqGuBVhg|WV83yF!bej~9C zs|je!6E^xNX&Q^dR0-&zS*10~OP)IcnCMMYvzF#wBhQCG4-)&VrbJnXaikh~vy zv?-7xyJ3q}aP?^rMmp_7rnPRG@Ir~(;l+1876p+?uMfFQS!AqF z&6vqSq!BG-ViPl|=*`UJYq~Hq`HZDyX3|Y=Az^)vbP8gdHv=u>i%+-}P>rgw2aOiE z{YFSSep!D0l4u!q*?tp9mmYh^ur>#gl6622;l?lUI81_=K1zz}3F+g#Ia=$40WjS& zy$|sAf|m|hGPWm?3DZB?szheY?wk0Z8f~Iv{{LepW5#>vd4<(CnGsX`|Efm+zk~aK z?%P*#w*>!RLF$98b1%tVGjDVxvLdg^|KBbA|0eGL_X+>cS5!UUMdgA&a|pNoWw^GNr7TnL>KtiDy@bo}o;VZ-eQOv?wplFN%y~>psu=d$T3+EhA3^-TT zXyGgda7LLUJbpQ|@V#_l7QT(84a5M(LnIz0-+0FFXx`%r%F zj{zN7P3iFq(qn%N$Q&S8|3qw-W2_gEoEllb5>=IAz<-}k5itNcSra+9#ot6au_Mj=y(Fq@3NtVKZJ~)Q z5KW{7X?twrVuhXLi!-B`ovc#qq`p)M0NPf3rP2?F-h!XL6AfDK7J2rvs^ z%4dqd!AnEsfGNYDlMQoybIG#%Cbs;4oWXb+qd9MfCIKMe|Ji<{e*p?Zx>)Lu``=%H ztHh|;o-vAScnC8a+$6A`hw+_wam&uknuWaZGl);jX3)=IZ%WaMA*NBH`MV9xl#+?9 zW=v1$_|l{lnuy(B0$bh_uXFJdj1QK96Y7r2>%r*P?Bj!%o)iV>Pcr^zlXSGJ3Nsn#xUqNor$&pne1T->`wb``0%fmXvJLJND02DV6Xx&j zHhuvF{BfC6moOY#+?hLwpc`YJc!d=;#?%CLfoc7eiYlTjOlLV==WZaGlp2q{3Hg=4 z>SXyb{io5}8P1ca#Wd`$^3WetekoYu(A8NVtSx9w5AYJhVxo9v zHt5cVEAavc!aZh2o#)$Y`8tLEb#J`R{&lBMPSB)R5mbc!ROz& zjJ)xCb8gd|A;^rm;|@bcdhWoSb3Nvq3z0K%$N|l{6gRZz-kCu++GkskaC36-rsVid zGj2+bFU}gQ`^p_IDk>Yj{RL6Wsg7u6Bn$dS_oN>BM`nuM;~QpSw$C=D3%QoCd+AbM z3UkB2ie9^hXG|sik;CXnr>hdf+bJb@b7sHB+l4) zl&%4eSRa>VrMSLY9L+hUdab|r%W>)9tNw>x_D+zCLPglBC;g5uv+?mjl8W0lj6P`Z z4(m@BE-G&&>6TF>}j20FM2ElF3`bDDB3r|M7qM2Q;0s#?k{U zYIN0C(t8egOW(Idve7h3GX!Q7>JH2Nj*K*;50P{>Nx>Vpzac{T$0|FK7V4?{K<22vh%utB)^b0b?R%U0C&(?M4=uMdq{gkSP6+aD&+1RNy@QRJEZqXVMTmH`_1hzDiY(Rh> z+g(?Sj_-n(l_rOYGik(h)fKDgrjFN?_aZX6yhS;lLfR=vg_8#p+%_h2xlCua%`5W0N(7Isf0Pi@qc2HfqBk^!n0{QN zh^gw)X2kS0(ul!9Q!%~Wfr;rIy0|EedRSVBX%oGbmLkOD!`t&hzn-xAZU2*)XaVi1 zH+ij7n-kM`|3g_!;fw(i)4;~ZTuf@i$an$`<1k!gz&UwrM;7`UMxQCXsqOMEMjF~c z64`=}W4k!KU06w&|J@bm^R}fQ9^2|Gh3vhHCE2G0WdBehm;Kk=MDKc}8QBj*8X^0P zCMJ5*B~13$(uJ95Czh6(=pbgIvP1HOJs`$YJdcN=cXf?`=OeBO=pBO$mya7R%6b?S{5(1~>{8|EgH6=;qTR))C>qis z`qB)R*!?j!az8ytVILRCj+)|d&nHfj=ho3hn?Dzs@tvsIS+vZapt}$$$glJ7s7)=R zQImhJRQDtW1D2$NmsN&0_J&ZA6cSY^i#;U12*dt1m#bZflwO9!1N0xJp}*|JH*t(l z&Yee$!b>~VdB(rkz3~RWT*WUv*+q}9)jaJXsJzzL6vr$5Cvi+~n;)Ya)E6Bk3P_Wv z4hTWU=XiUADlWPS@fDhrMQ*BUSxBq?Sir!JD7+=iRxk0sFLnSxcK96EA?3C9Gt@o7 zGl*>-snOwHNHrJ>{_jtodyek2CX9_K9_v|r1l_9S+5^eH&HnFRjHS1%%N+5WX7{5_ zJPiX1eGQQ2YcU!FHUxCs@`ENsw3$b5$vM7_IkTg6M2UHBuTLC zZrc2Jm?Ubng|rQe3YR58hVuco9grko!UfC_Ap)I!X(*R!PkT=AT9Jd2K&{1DBj^=# z&vfPUmUy2T_5({CgbfR9V>VZ{F_A!#GlH`aT;ctZI`zA1sqXZ_ys1>_4g9Ca_RC$= z^2ro1Y@P*`BD3Edu!F*T2SjMxy#QVy7f3v*YHQ@6Gec>N`*d|0g&m4kDzEHU8*o+wLon&GVP9%TRoIUtnQaRgXi29*| z{rFZ&Y(%a8#c-V^&YJg6XDGSyJ`k}Xyi-Sr=`c7#;83)b1tBQJWt1BD@;%H_HM;cstWnDibzDUdih*pgq7{9 zK=(WwW2L%?nd33D84{|yUuSI2Jz<6A)3 zqv_y#&m8f)a>j{jXwEfAglcq&z|J64-4R)q9C=KK2;U)e z?k5xQbQrI@dsa|TK*h;1y4UeGAcDwBq{0UpD$qERD#9t?MKGtr+#JO~)@mt>Q3Gj+ zrCTj;DwPf)z!kBWi-LLQz%vvter%_2KBQ2~KAVkE2zS#?8e&2?9R?;liz^+NZIgG- zC1ZbKWBX5b?M&wF-{I-`QgYR?u`&A{o(Fx&ycK93`bwD0~Q`2Bl?eEZb~0DN(r~ANxsxZ@czqhw?Zl2fW87)pL^q|sUFM_> z{=wC+8u5&XEx_2@iBKUPun&tGy?6$awD%P<%xp$5Z2Z!H9?WzXsX%4~@FK{@56m4?ZIy zoTl?LY%E~nFPeNfdcwpmRfSlz`+YsW684ME^f&XLT4B#%>?zH_*dOok#P7*?L@Rue z^pdwT9WtYSAWaqQB`F3m*&A8yi3uJFLqM6@6p?!+k7`CEw7AQ1l3cd+P54sD%-2vAhoLe71 z1MQy$%oAn7aU%Mnl|xuOZqmza{Lb&~d?obhK}P4T#_t6O;xt0^m;CAcRcz{iQ7hhs zbDry>Ejj=!+I0<&mvgiKeTVoOyl2N%BYM2p`VY?>j#mFBTD`Np5_2rRWKT~7pBiM% z-bne`YjQly5bZR&6*(Q*JWgY!bg>OPzAEQ9-Yy8mBuJrkmQ zj`*F~Q<6OsdivtdCbFIPY$vvVpY_Mo!XfS+ z4n&#errp|Mtu>uqxS-KvprNB@#rOELUD})V{5=_$>8=BaU3hCH+4TeZsSejs_JK@B zK3M%TdKzAQZP{nMjP(Jw{n&5G{7T*qHp~W!7)LUN45W`Gp(llJd)Ml&XG3Y#-JVb| z1L?+u!icm*yQxhcPrg<4@OWWdesry zBhFvp(RUr=`aPH&d2lRVlZt`!#dOXta~%ho!OB05v?T7az03rjO89Ws9q0 z_54HlJb&>C`1_Jmy6e1N{KpVIzkz7S;3rG!c)FqfbRnSq&C}iDPlt(#5^zT44X1Q4 zPIQ?!>n^wn`t&^;^x+eR_yo9%*kFShb@T;)%IhDB*Px5NXnAbr{t$|^yZ%4c&Ii8A zs{Z2}Y&wv6r-Dub8+z4|mQ%5qf^ItXPVaP@e^AMmnc}~ivH|Ik;oV@j%Y$ZAR#d3{ zu`;z^L{yd=5Fn=UrxdjkHTAj9KdAi_Fxl_@`JU&wf3|^Uzr9}YJokCdbI$jC|DW&q zo^#%on;*IV4Q6DxJQa`JPxAg7v7Xl|7$NH+g<^$o#ggU8hwGR(Dtv=tPgutbH~bbf zv}?$!S_$MRaZ^Yl$u8!_hlAXhElkd{AMCF#9gycQ%7y!!qRZdVt2N!s2Y_GMc65HD zDundILt-iuq^av-IMKHE|K(Kao1UG_QM?1-lVje}W9`x0cYlC)GCSfDL6D$ei9*lL zp^~f$=3g(I&8mu*_KbOpPq0rC&+i!<|E_aQ6YuU9@ob5rchjq}cb*|cG%}KSmB!*; z@pf{!>r<1qX-~PtH3A?-KJ&X2xR4+9sWC$5BLX_foYL5SpVVJxE?XZG;O~Ihw)>o{BSnyu6{gn>s+BfMF`@}SfU#(yO|hB z8N(gC3pX^(49FzCHcPNWPHpya>LbBqb!^-=S>thV=z7&x{nTtW3*XAdPi;mQMi(Jn z`jZJ+^G;Uly`BC~Uz9!a@3xDf)Xop43sp2!GX2vIiLCY)5=Y(i^gcr35V6QQkT?Q? zQU6gN{gC*q=G+X4UJNA34TVJM&&aJk&Ncc8yByt}z8Zx3jW?k}kKisxh4$m`*Mz=) z`5^=q*!&BNckw3_^}OckF|p-C_d4={?jd^}X+wZscE~BR*dX@B`?lk0X5)H#VdzDp z-R~VkiD6zi{U~~SF1*rmsm54sD@)>D-HA2Q!gL?SxN7!DP)8VIg^J&>!N2AOp^rCP zZr+18eZBt_Q&kwBosk*?pN0WCV=-~hS_QxjAFkS1v4lyyfLy|_aq-KwFkgbLIQ`>q z1S?vZXISZnkBtr=d?Zri?}G}<4uFYmnGV08jc5s%!jIc8j3jLG&KtoN4w4pcRM%(J z*D(;1b0(fefbpJL-aDM#1MA*2%DT{~W-D<$#m-5_I)y*DwrJ3ACmxpZa6}Y0P-qm+A99DE}P)->ZvmbNMwVXijtP zD{e;U-e|jU;00GE+-}qFlo`^FC-LnyFR(<K0UMH4FYa6&8_ik-+v-V!vw55LBw)ptfEOV`QE(9Dga`vbO;*9&T z)bMO?Bm>ar^sud$Lh%45f~t{)T9wd{T+uLot=>lxzvp+{8~et_eG1M_6|Fo~n;qQ6 zvw9Z8GP}RA_MNTqbW&Y%D^crs@?}@a z%-;!jcTj0VaurZl%&u-o{;^^FmiokdeEK4~_cYv^BWvO*IC54=ef73TVm(h!@0ze@ zgLf*r3H<59wlxh zT~mwQGPa%d=8wCGa;)9*>sCCG`G% zKqrGsx_iq-A%-yA0jG&?vJHVh8O9zmES*qwDvt&1HI^eNpOl?}9hYpLjX+V5 z!krsu9BSk6nsQ*E#u%(5R;j?=YeQs#pU??LtN$UgxE7d1+Aw`DS}4)jyo9Z#?{RMl z_TTL~sXgM~BlVb7I zPm(h*moa8FW$u3`I7oxe+Z=F^_5y7*X~YKmi=ypxCzcwm3FqW! zb3FquVZhuDa~!qFH?+^dre_<*_0%WdW$LAY<=*3;mXp*RPaV=Q{#i|pPGnPz`Za%) z9M>oQJ#zN`4b^|0IkLWQ)!E*)KQE}?@PeMUy-X<`D=_QSqhD>Peqr{F4apZ9#=p`) z{x2IHXbkl|YKVK2f3;4&!{sk+JGJwlk&atiWoHvgLU}8#D?U*Xt`}(L-Mlnc;S}% z5P++@<)qmG!CP8&a3i>ec0Z8A&9lHST>Lzan~6ed z9{Q9g6{-mORr(|7qbzb&SLhf@2Z#&(Upy%Wtj8Il6L1inj2GhNWIN=VlMBnsiK@`G z#|r<3ajW9V%V|jZ4@arMzl;BN(bDPGl3($ZaeTG?3e`rs1e2Kg@h)Sg%#YV>0Ob@? z=HZjUsA?98GJ(~rsi0}vt}p9~4I*y-w(C%i&*O4q?@)$tJmE!;f38>T-nKcZFo8E742VNxR&g}=|{^fxih&KAD!FRz|NifllEMTZ_qs(cGy@H3{WYJ{GNndB2!oyKz%E%)!aDW_E$To7$Hh=SZp z%y=U>Ci=FfM;w!$q^&>tO(k>trB`)=zB&sS0xYNp|QRdQ4B2*ws14a!6cH{6hu3c1g&>>#;15?zkah zA4Jg-45VM{$Cv2p1y}6#7X4=M5$T*lL7-j`UCSdDHfj}iJlY08Z47G<`lidpYgBnm zKigl3t=*CzWb>Ii(^#8|N*`AGeywCs%qv!9J=cMzxDH@)D@5Zi+E zVnP~{kJgi}l-yA7;_CIAUThfmFGAkYzJ}yK>c?%W=RAu}?O71-e3L_c1c_Jt!wI-e zYkC;W(!Y+VUT5fzg<5W4HXANT~_H??0K_R$Q0{Ema$46$lJGHhL?yF8Cf>! z`GqVZ#c3SN&zSchy8!a|!tQ?C2lReT=(^6J+$>b!XD(jJM8l1d1uYng_U%_hIxe@H z(Dy4n|<#9QfaHF_)Fe&E6592xPF^Wp7!-*>iuyHclm8Rxo%qRL+3ZsY|$~G=VV3P+N zwqf04k)K@$=PYHFZ-Zd^(|rMD!~2r(9%89XEa`}*au4ml0=iG16$NcHJ?{0PA zgW?FBDX=)Yg=;LusZZO)Dk@RewaA^`fC93&A`bV>)N1O{r4=6gs?sSefR@ih1VntnK-2yXc67;Xq^)<-f)LYb`WpFVRc!r6MFNYq6W z8cwmb*2i{3Dw0SL%sZ$i&7rDn5!Sm=gd;h@RlzKAK=0n)K(Lk{pbuI(iz#RTg5Rcw z2voD#);Ib5Ywg>wY<;BnAyxZ;UWvVSDf@aOW)cB$Fgi?$$pWi~H*qsgCB#!IVX9TI z>IY=)Fy7OTiT)AxjYu`@9zPG#u9ek*01m+@R!`;^?Th0 zCiqLf9s^1{VCYYZLd-MJ?3Izh>b6X9r5&3th*n^UC3GeJioenrELNo_a_bjGD|L&{ zZ~iPo*{&v%Bba}CS{QlIcD)(cR#(^-wUwy~0_2N(ur6~V3!VaLk!6db5%1z>O@_Ac8m3EP)a3oz8p)e>C5*4pr1L4Lib z+#&vL#z}YJD-;`6)b?G zDgX_TpNmps%lfCX=uF?sXYD&MOmpq#ik7|GcU&3iwDmWHfgX^TU^pqXfji-)EQS2O zCv$3oo8gHd`jT{-rNW>NG>dT)tW+k}GA@(T;lHdhFuRzm!#G$t8^~41kkaeCA{;AG z1xgN1RaX8P)zGfG!a0trs9x0!nT-3kpFVSf%m?rUCHvN zIkte3Nyx|uN=-sUzR7R#p0f{*DR0xWkSU$5Kx?X#ck)JjDG&1=E0tlxsiA~W+2){v zMq|UNd#VYW^s~6Sd793V5<70S!g!jxGTh6oX#>noZR}{e+g@TlbS3w7;a&D(v9s_D zmlk|g50a1IMY&a)r!pU-^YU=|End5pYXj*p^@;8Ob_bMd)5?WzRpb9h|5KqhJd>Hi zc(gImz0t<2YS4xiI3j@qMhoq=r)ob-rb67CC)VObT(cXu4)$NUfUh2-=!`pPo zSv;^E7IL2YGa1MU*m?K81qp?DMji?fq6sSe_9NY}vQiYNQhbXk^G33l0>?c7s`r*j z=&OGrQj@M|DV>D2Y5@B5ErFam;rK6*dr~rB4usxV7_HgpAF|hnL$W{mViZ7er~tC^ zkILI3C&cXg<4zCQ5rxTnqj!i6vF~;Tj0f~v)66NA0}tKCr{|Pe(A!ihBRf4~9%SJK zRtTZzLBBOZUaMs7Xt7s=d}jJ^w+QuIsZ1Ir=b|REc#UNtGC)2-@L8|e(!slt)ZS+zi&my} zOb7~WsD0${Qv16qdTn7Pzoo}~?Cb1eNPfs(nqvcEjbqR-WjejJW2xy5M$%ffz@EY6 z0jBS@XZ`ww`Vy6qp!9k~T7H3k=Ph2z|HL1C!Qk?5_J5^5?r;BPyhT4w&+X_`fk5$* zUr8K2qm3iCjur?Tw3YTFf?M z|3~E3W)()KtCp@2ct(MLpk$A@-gy^5fTtq2zGa@BYi@N>6-!EqV5(+IzTO$})>(lT zhG>bMg^^oVNCJY)WQK4I5(7}HADctwt0U{JXHsf)QJGD0CJA)r7rgn2%vWp>ZpZFE zAtiuq6TFdSOQT!3)^trU7gJ7zO|S-#v1$Jh#FKcRXStT|JoSfv*g6L93P8NLbx5eD)mjtB26&oT}AD6RQ#{s=Cf&fe=oCuXZxN(Jt)Y4+8sVdW6)J z(C!g(^SchsnI8!3UZMxXE0~DGs&lMJ z&C`OVdiCQ;Mv_10%>?>?%sEhykF2g`VzKMIYC5o1%sxRv<`sYMZh?vIH0_)Nrh-h* zMg^u)(sImmvw?}z;lR{Fqo&@)%82X-p+F0v9RFtA8*zJV`Cd=l-8^~t6L;JCB0pY8 zBIu4iLipp!^?$&G5I);f^Y)8f&vm~%lr*T?@f#HpIK6(uv*cq1J-cuyJUQpkT5mej z>=WqQ4VrGRF0A#M?PiGea)aA_+ACgu*DiV~C*<8j2I*zv(7X;>^zU?SnLVxdD`do8 zNrjpkcUB_DtHF==e`*z4FvntZ=GA-|K@NirP+1w~r=^oCQaRvQ-GQ$RJfnenY7b>WZb1!}R5*?;bS$ zq1n#mw4#%b=ikCjJq~o{Am_xELOZpX?R(>1-7##;QO9Cs?<{T@+Tv_*s34(Q=j=M| zrH7MaFn|V*@Er+__=f(?x5(27bP!O)Boi=O@G($ysjojJSIB?!chdNAZ`6}Z)MeEp zn{5M5xdwuw!XI;RM%F}#Ox=Mta%~837?}muz-!Z3T8Q`wT8Vj+Z>0KIk{J?LeM?4^ z#XY|tm#IEWY-#PV4@(_&dX!+9d^3H7tMjn@I!O)jc^{w_a&4r$%S3E*gqu3+I*` za?F>6&yb`RVK}CCukG*7h|C!FoOu1e@*3#-+M4u%5<@aP!KzSGw2t#Lc*4@G#tL z>_*tcar0T6ZlQ5fsFIn4w*9PN-bV49AppzVPOX~UI6ZwW8r8pWx%k96L>fD}J5KBq ze}DVCA%BMx4U(Z?qT%lc4QSAo>V-rM+Dx+nAN;*KeW2BO+-X*)6q(g&!#=B1BAFbd zP8Ot5mB3CPZsXCVZbm={#+)W%f(Vp>i{uNlO`_aAl(*yME$!Ny#B#AVWdS}BnJ>Dj z^;vQu9FOtzr+TW@8^W(?3-Ifg+$^nA=c3D4;NS!B%-4FHVaBD7S*o|rz9gnq(bbR7 zVM73zPz&nb=-mK1&s>~`&TQ8u+6%|-0-e^lLqP9+Sg$lLLZ2V`wNr7$Z+|D$>izI3 ztzMn2R7nYR1muL`V`u{@>DL1a{g1BR*dI`%jpJM|`;lJu=D9J0z$%$_@|Hf|>_ga2 z4$jgi@y6fpOf&?^i+R!R+<3R?i;u|j%G*yx`l1~&NnfNzdHSP#4;t2Ph|&}b>@mjJ zX$s~!o%c3X5x+ z@veEbz}YMk&XFl;#@KjL%7RJ4+gz^dofMde4tl5z|bHFl<`B?pkm zVy!*b$qC~N{WnbEWuP%YP-aUEhG6?4m{+Pu8p7>Z0*9r)6>^wya5$T*HY@xiIdM{5 zL_-8KgA+C04dL(P91yyf{00<){jI)5n_3>r+)~lujSQGyl;TT(lNh2XLw23Vp4|S5N;lIQI~opA(!}_`JGkw+jY#NiEHNrCU`K3^ad)V4z(wM!ueV7c0M* zJyeIOFy#C!PkG!HZBo<=k_R(R+nQalF0yQ~MQC+!z*^HZZnPX@6DWqak_ziW4BRU~(8<;0z@4Toa=XkhZ!)k(awUNZJe2dG&g5A1Fmuf`HsFFISKWKGW zkzuOdyMRGw(WQdn4RN<3Yl&@C@Hc*~t{ZXb#})gK)>Z7|Xcf`x`HxxOVh@qzYJ1j6 zE)}N9>?dWDQwRzZIVy^`#g0KR8GIbhL$DOU_9MbiSZie-j4rY3c~n-te&%)IZbIJF zF`vykD*ldEAu!a#E}KOZuaT!&AQ1V1n&^m@=m!zhGOqg5y_`+EC&Fd~mh0%L7Zv^&MoH(IIk$`}>zS~Cex=(>t=s8J39})rlQuHikF#Kf zH7$JSDEe69O%B^y5%cOs(#@=XNBsSr=Q`D1A*mx@_ygqb&~Nou8d7~#Br&g_m)xg* z`v3g7br(-&wDkC2?Wg~kdz#pBXe4o@zV;^Hw2YL#)QBe(yP9X+V9_4SD{IxG>c?+5 zu|C-y8@H8iMyFpE_s(XJJ8Hu*=ft+!>vI zNX$DOGgta8zGDNFqlL5Sdw0br!I^|E(wEBFI>v!`gaa`U3;?Jng499|VNZ;hOVT!x zC0%_7YhGC|j!;tn1w@iG_^x(vO{gNLzjk^JF^LgK2P1)Pg5}pCEQpyms?=Z^d5i=K zSWHR~Bj>RH=w3tO_uXZdgY2vJOT^y-ZqlEW|K$}=wH@e#^gjqFcR@Q|@T%rEaT=Q0 z3$p{EzQ683m!*I{Haj1w>B@SMO9sp@!PWc%KWvzspkCif4$-23K|}JLlNuVh@OL#T!e*V zsf!5Ip0#tgss4!fM^tNYKAgfPjYvUZr1MOkQslipigcdHkGNMmM8n1@3``^QH=58| z#jX{5`YWEsy^)+#IWmf1oj+_igHKUHjuUkh_`PONoF$AbE9p)bMV7IJ_x7?#!i};= zy&W~F8ctyOZ0RSkG2P;4f>y(`ThrVqz(S{5qO)qd;^j>8l_Z{xxO!HqoHzD9SI=Im zhv*UG>FsmQuI(COghlfOes}d7GmpU!k9!yNg`3>P$8De!#5NI7wsl^~?%pBZL(R`TpiUn~i5tq-MB8IZ;e8n6nYyp@0g+ z|2~8ZA*5O9^WhkO>piZC;?u2(qNw%R+R@z<-IZyGir=NtVEe$v!ohWJW8bh=z-#*V zQl($9R{Xbu#zsBmh2gKfv7s8P@W;|bU`NdL4jB-p4>6>Hw3>4uq7xd^e^EFxnLDnk zqc(>kZApO`E{N*PJV=EkE{c9z_vayupMh6Z5j0~9d|RLr;tsU^>0m?KAGx?;ei&Bs zi^&bH<2#l(%Pq|aiV0^R6|h!DoI;?}TA&fcgytNEknN=)%M!qmfxgGC*&$RDGR|@* zZ}N{8NMlVx>*V3g+1_-iaF#z(QG6l?XT4vC`k%8(+?WT>9%Kmp{XuFnZbD_GpF_v` zubzOqxg(=(2l%i5lGNtwTd;&~b>rb_rfiZb1i%(nZjq*;O!MS|%`j}DftNPlW?9R} z@e7^e**3##*1)y>2rW8`McMzv=v)_V4b|-oQ@1x+W5M#9CSe6y+ZdYkt?Es4;Ek53 zfIu8YJ;>1>kU?CgafVa13_CxX5*ak?wBfQzhlPnW?7VD*$dH|WkTawdG4;Rq+lg&+ z=8On-VMtfgjmdpvve+Z3t+Y;H@s=0hAEoEF5x*-m*3Jy-q_ez)GfytSh7JFW8Pi^ zSu9|Trt~MN#s5n+jPZKTz<2QRSk2zXAFy8-Z$)v}(E(JIb748Qn{n4|JgM#>SH85M zAhCTa>lV0Ckvn;zP|MFrcbL1qT^}xZi;-f2gRpOX7Q`jC@5z3Kc2g4RP`->_b$q8- zHx-cuKL>+z2?UoFL>B%P-Y`TVdulNghEiGyW(9Ux>?|Ksit}yHT4_(S3Styv5WT7v zld=Cw634(R{oN2HVv0pFR_Xk!anjdxlL$j21nma|?HV&fc(%>D0*9|6cHrBwcOH)o z!yVIpOLc*cIW^f+yJ=f(VoRhxu??g4YgOqTH}0U}S}|X=2Sc3bDRJ*Y%+batMV<%Idnq(B&iVSJa)9ML7_ki%nqVKam9yj!pS#bE>Z zBJMRB&oclzZoydDn+K!qREkFcV08g))1QZ{{V&~RF5G6jQ2wF$Y76-av5dVlpU)H2Y_ z>(*FOPHFL93q)60;S618PcypO0%qtsOR6QyHI$7ho@;GGSHeFZn65uFc#o?elTX)k zq3cs~j)krVh_38rrTq*0H8lI1Y%isBDX^`!)BBpBmwt9$NXs_45{f@U)qs|Fu`8ym zAgDEa2!2CaGJ*>_;T^a9Bg6aC@=K!S-Ajy?Bkt4%TE5jekd~$}GqgO~8VqR}(kNgM zLu4AMc^~4<%n~nZ#)y>OFMD&c1+$l0Dr%o?S4Arh%93NFT3TpGy!TajBm5emFzOh;GU0Yd^`ar(8e%{*62iPhpM z`1;12y}OD&s_mqhVw+(e!KjrT!q-UT%xGg#QiWm>fC_()J@RSOBHI#Uip>CX7OVGO z|D)e`$e%pJD#KrJaH&S_np8I=w`ygw?k^ss+9|Hu3>_Th(+7#jfB2pe`S75f08w?sZUkH~D&O_#F@l0ytGkg$W^AZ8ECDy}|rVytj;AepDXC)(yo=JS^; zETW>h`Zir6FXl??2A1!vgplqm9}P^ERAjBXFu$NkC^F~Dq8ouCQJuC?bI7)kJ{FY1Wi#j9M%KMCZa zK_-p0@4#&NA-(Lq##q5LJ{G)0!yYr`x(T|Dle--)_HA9y(3%RW*GQUHGDb%j3 zH`1IRY)r<5C%PW`oY;Zvz$I2g9`1N-XYnPMp$8}K{dq4r<- zrlbFHo7zPGeAAil>+ZADp>$&4@TxOm7vyH9&%z{UxmRv?2JpzO^Q_0_)jA8lx@eE7 zmNQ$udCs9-Blg$Cu=D-{py_r#umm1HZcyS#;56iTjKXY%-~65cG}|6}j3gEWqzL_` z-bFZrFWxk;v-y5Pbdb7iB;gc#P-*%oc_Gt|V61sJ%P#xRpUq%(fB&-|CmO>*of-jM zqDj=UgPF^T?pxshnFD_vr(n;^Mc$YS5xct6Ex3a&*UFvMe;@@4FxcXzF@rnM3GR5* zB+Ln4V-6Pu4=V6yznViqMlRZgghF83X06YY`=^Q%+D*MmVB7=;WyzT{zp4504-b#< z13a$=N99(Ce(wj*lFIjiCo<1>{8ib1j@-C|j?!E42|L++&hRD;XL+z7tZ7}by zpXk)^=VS$(S`KA^JG(fsZCLAw#I~lEJqdfUx%mVA%J%!|KXJR1qJJByROxpa4eW|O zk$GQNM)`o80T9p~nRkQU(dDYhvVF9|x@O|0)_vRGJv`EJ0B_ovjPBT5H#^!RiABY_ znHuRlg&RynVPxSp>_}u8S%qFRXA6<5oOqkb$`?6Xh@GpOced}iEHeKz%CztJ6tmg{ z?b>%x<9#@y?K^1WhunAM@4&>G^@%<{&>}3h0PlHj=&&6s*2Zk;6gDM(7bxt=KcIM0QgN=%V`2vys~Xgta@wU&Wv9j^DfO1<<0Cr(!OIB zt59t2H@SoUJx)ZHfU-ixoZG7@;p7fmkduB;b0(?c^S)=qIF-wXAcjBo)_|x*uAbr# zQjd8`aV1ZM%7gxYpZ*umjBxi8*MHLl{Cp_$;^E*0b1!`yG{ZKi=_k1LD;EYp%>S-+ zW)_zZ(V6xgt*u1eyX8-&&!A!|ReL6=}w2^6y?f zh!LAv&pT_S&@3657d_k1kz2_a>5ecCY(c;^=X}R{elnN$ z?fF2(=>IgOdi+fl7_YO4b>tYYJb#hFOK`sTkKhCHr|uD8$$O(qboGKOBL{QB6Wg#J zpHe|wU*$+()R?hkCDartkVs-A@0hwO?5mmhW~8$lmcwuqMsB%ZcixouGNYKR5rGn< z5(lw)!4Kh@s|AR3yge8+jrx`fCjB>MQ5G#fivd{}KYU$7 z4fC6c%E`~exnkoW`*dlvT~`KMci2^`1@g}#!8Nk54e7NIpGGip3r@pomia#*ilF-7 zr?_Ux*+RuKJ3`-D!*1e%jm|wHc#4nlcBJ!dH1lM&7V(}}Teur68z8gV0}?p5 zPj|^8%uYUgjP*3NI5q7zd|czh_Vc&lI^obzx|YHso$AXzT-rd_lm!I^#COr zhMgoYH@xgrCZZmw%yOL{I90B_C9MZ)lktcbCZ0;4$|3!zW|2>?ZQoYfa(&#ZXU?%_ z&IsllhvSQqtkk=lyrg|;KD)uGV{G(*%S$@HSB;yNHa){2)#W9rc_iP+$;@!jAdSUH z$pz5n-aB-b=Qp!rqwKCs?f$x_l-J?%ih`B;zcByA8wT%?^GK%C`KP)>^zz8B#VW~1w9oWovp=Pb zhw+?yvsTHN^&D%kVcQwrh&@=`JpJgp$gfAluBc@X@`KLs;%rBqWQogmK5OF;Y=tsX zRGiR`u$DH#ruV~c5q5(P4BozRYS{d7yJ`NYy3~lS!5U{P=Rq4^FgK_1Jb%#gQ%mrR z2CT0~-O21swxRw-UTjNZ`=v7`d0n5y3~@Vi%;cZ*niIjg!nBoZadzgeYUk<7V7qJ- z%D{&fy~&iEtQ?7m9kWPW;F<~W9CC*J8+D=G+e+54m)QMO;&Q3u=G(pXlfx@jo|Rhh zRPju^52D1DHF$-&1QBeph+H8evpw+Iwo!wEr!4-&mYo!cB)&x_WZtJleqD4*FwcHP z_39hQTGr z4Th^o;!fVDioRC8^@gQ$iR=w2m_1v_Xby2!lfjvdn94l1FzV|IoV6=3|K ztoa}aY|caA28Y1J%|c*6{(MICue5jmZTq2Yo~F4_*$k8y+hHj$#!qi1PVPfg=6n&d zct;EUqh{D;>`YyfBc0(jBjWgSra2kbrP5EkFY0t*h3%o!$G~4Fi=D0@0d0}izd_^7 ze87XV)s3UOdtXAi)zDVv%|?=J(ps&W1O0$_{Hvl@Ui>n$toYXBMixveoM8u0R-n5o zSGMlyzh#`Zy7+ot7W&6s2p4`EWL~eeEOSzX`V9plq|dge_a1hYwXjHxlb7|lzxf_tBYTsFtUJM6v9{yb$wJ- z8UribJpLm)`g%9>cv~v>@xFRI&;Q*%pyh28fkVsXv2g!D#oKQH7Zr+amn;5{^vSTR zV$&BAXTNvSc9UQ0U?q!07|w{Ic+>u$^WP68agWZwTe`cw%f8q_6y(Q^$bbEyNwBt!K(R}-R=kgBLyPlc-#L8W?}I4dNWSWmkoz|tCj{Jieuk0 ztAE8&>IoiaD4{|1XQ=vn{ww(Rk$Bwo)m^}!-uu6W-|8Q-3;4gH>URPEX9wcPVMY4N zky>N&62br6Z6W+7ObO1_$_U3ds&jgRmI5wyawx<9uRj%*7BHGnA}p3Cy_!Hx+I5pV^QIwiA@ zWv(B(E!e8mA0-QrREr0r3a$VJJH5ul_iM2SA&D=J~Dp2Uul z*(b%kG3Ulo6P}EvCT+G;8J}mjmz}L2KO@!BQ*uVCts4yNY(0or-GMmHQ_IV0CjNuK zESp^Md0P)=q`Xj`a(RI~<^QCA7w)ouqzj@n2kGC11N%36cm2EYzw6(H@6*3acT2wm zIF}dBf_7t8xDcLbH+rIYcaXjv&}MPwT-u$u7qnXt(oR>=54PlUqu&9uKf?aHMeF%* z#D*&(pXh1b=f;3G2eiG=k2d-~pFX>Xf3Gb3w`AeJ@sqoNf3Jb?-#q+%;NNTZ=(m9X zHvSv&)jaU`YI|`I@cY5Pd-<8XOa8jT9H>EPFnJ(<{dQQc{N&*;GVd;DZ_!=Xiq8D! zc0D2cV%y}|SH-j@&nXv<7bIqiwVd==toq&7&mh&0LCChpbjsj5iR3z+5{Ldtj$jjV zQCXg~eC%@nZD#&uE7+sEZauQd5eNr8a!Yf9WoMj!)}HSIOTaTtVYS6Nv$z=~yc zcnvT7gN_eksz*N@Bd4A6v-eqDS5m|2^*zCZw%7Gxqp%dyX#A1cXqgG4yQWsv*kJsT zwykPzihASnAn?>~{glgOuavp2I!vALihC{y;z^!)VRE9*Vh6~K#>0>UrRmSr7Gv7O_lnzkg$#1Lj@>gv2H;o3IG@(z%qvgXMBs9(cwwu5#c}HY zbxQBjZq~^zp-jP^W?kt~8RRNo>0baKy&WdsdGQ5VMb_zdTut~aw)}$g-CyjTw36eA zE!ZT|2-G(N9kEx1V#;DD@gY-;j0hs$2BAlX{f(s-_BI^J3dAXd#GZ~M_Hs|A78KTV zZZIbvmo*IAMArNelJwnqv>ki$#d!roc;1kFs=lXp-}=P!C$Umv%t!01--sku(2>)+ z#td&rZmREjc|?8UIlUZtK!f)=n)p{F@og(`-ta>A`5u|iDM2%o(6UA*HHNdgIP>vE zL+h1iprs8&froQ8X*Z{j_7tf@3zS5~W*RZK>ubk23h8-bA8xFF>WI=1T1UH{J`zd1 z1`=4pT*o^APvpqP zTDr3}l2FM1uh&D|3!Y(2-&vVf69HO=Q+PFOXS9>TTHI-}sj>?u*#hNI4+5QY}=9oCO)- zO&Nm}3^wHd;3!R#)-818EpjA&;CZ{**s(- ze|@tBx9zMQ?WNc`#ilCH;mGfek%dRvj{qDHGRuX;YZS#~^Wf{NNZT12@!n$qLw?Ta zNa7Xl*fHzqN_)xKc1g+*t>?Tj4QLf7l4D;W@VP11jf`A{ zepT|dJ+9J?zg;`4L7!$kaR|W4j~Z}-=_!KRRmA7niej|Uw^5%|IeIzv8=fjX=!5;ERFo<_p(j8~|ANPa=HP&B zbp4OgK9dW8JmM*bD#i&I8BNX6B(Zm1uP44M?2X@n7k@50CDiL|^&K3AC(Oj^y&5XU z#9>F-d)2b98W@B))QLq0piU4~=wo811Z@3`3 z#Cmis^D+r7HU?xNv&27lm<%+E$gR~o)@t#Obd@Dn$VfJ`;#8DNb08|4-AafKP+A)r zdFXVumTMbb8B7RZa8D*T1GoYJnB9;m(4S^Hme?Kls0Ig!f9};G*f7us2m3qbWC`p~ zYY+s(S%*Jpd;Zf`S+mtE(+5l6k%}-FUmyK;`Y=^bwW?l!n&MWM)Z`Lfvt9Z1&iDG# zC*v~@&|mH1_{1xy(rb|ue4ZLdCp&(+2CpyeiBj??PK5UT-5`Y zqI&K=IFt}hEs}JEYKAimUVz=QjQW#39HTb&KJ9zcjC$S~EXHDIpp3_t%mq+(`}O%`?SBy%AHH~DWQn!6>Yr;Fs92`7#*{OuasPI4_8aJ z+lY%QgXVZVD1cz9fF^yX==ewPAH|GkundoLg{h*v(tjj8nAT5e`1|~avbR0|( zeUsRi8)lu4v?EdhZ)}9*5qmUYpW61FfcX?Z12CVD1Egf`)YKounK-PEo?5*<((x1L zi$8ig;my5kPV0(CqqXg@ZO12g!9l1}k5jU6ESLpu!@BC%tfB>NQX&i5H8pw&@LU@` zjQ`uBhbvxssD_VGj<+9y|GRH&SWkV=3wy+erR#_Nxvr}%dRRQUt-j~=65St)<6A~h zGD?4kkPk|Y?qfFWocFNm-vdv2ULC+Q9Nky%4rLJxX-IX^!?-zxjYMXCN(a4;U)$hK zL&d*$Qhnlo`x?eQ8ZUe;4vS1V+lwCw+vU^NRzCZwFE|M}ne;B@>3PLheUcrE#I$fs zlhf^oZOR+hq2*C8E@?xFBZqV?3ihcAPZ(Gb-2&jTRKQhpSBZ)%{rfIgWAt-qq*FP} z))!ow!pJ-o=sK-1r>Dch4i0B{eP}`YB}uV1PXf+q8h;*_g>#yN^X85JKXC35!dV2I zG;5Fm=a3ntU8fBJoWlyzHPQ%w|9pTwgQ^**j>v(k*+J!R*d^`};CuI&17+ao zPFO%p(t48Qpko3*BZZZTnbq zZ@|atW6c7})AYuEeuA(&hFx>;5+tuBeg*x|CeaLdZTy?hPO|-Yy@P9ncnWzArKk5R z?eCUGI%k4FTUzRW^RiqlqC1OUI5taL?121>yVn2LSoA;P8lpaoXK{N@BQ>s($w4C+ zA&XY!FnX3$LEaA}+al8SWAcziW3+HkP74?Ub>rzj|JU6>$AP{m{z3Wx{`04NPU!Q` zv5V3irS9rdKa;wvO}y9F`Vlcr+o%To1-2jmhta$tnNFX=*YWYsi5nV$w)vPW(y=ds z_T&FOwDBNCt;=l=tV0bq1795dF&O%cHSWZ}PA}3z;CufUv-YWMnrzmdSw6(qMSu^z zUt>1?35O$e85PXphcjFF8UAm!Ig>pxaI%FgXum{F)32Y0k~G& zWo@zUvhbr_eYZcN?Qb*p71!du&i}+7i;99o4W%rSm5^5@sSnLFU^=^qbZex5<~ zIo4qD{#V%?{nGdKIxstC#mAU*#)nfFoCBq0cohV{K#wOJ`+eCOLn>f zsf<@*d{4jo{BvxrVTYaBm?}Lss6J&BC~k4pcji`4jW~u@d$#74A01fpI|g-F^OO6l zudN4>oNyS`tuDTCq$L#O+O; zZB9k$AM@VK*Bfp5?SK3Yn1Ma#GE$tCU(-L|Rqqq8V4}kL2+nL~=i8@SN`+oRJ}0ye zjU|~wkjdf9;E&nxjCl6Sw;aoZBUu`{fPt{Ud^o89Pjo$$lZ1im4U-iwe9|o-cVPof z4fAm7@7==+jm#?Xj|==8zJ#{e%fDtTJvc3+hw|Y6p!4&m!UFz^8=T=ncr8wNEn~ri z_R}3k3;*5xyw!g&2?g@A`p?h*lwG2BF~1#|_eY2SO5wjkZ9eD7QrTdhYtLe|)GybX4=dGJ`+rUjYpU@2rBMs^HH23KBhl5iqA~g&~9A zmMPQ^iz{D)P6uV^6k3fudPU})DPbNkr;du$xF3CE`RK>SQa3S){CK2eD{#4dlV^me z)R`1%B+q0+q;rjXfTQziaMsLqRs}JmNXIR~H!bX-cP6`?HC9gC&^nEKcEW2M&pq3) zoyn23jUSu1A+o54Y?V`}xJqMxDjsC&-a8XAfQUplSFmZwP;|^citGU+dGDV{R#{69 z$}jl$bM7B>sIwro<)Ua-uK5r+I!s)l&vZ6@9vD0NVauc9B0hHk3{!22t-%20{wD|d z@eGOyr%b&Zzy>!ZUOvNDgH9kiO0m2i~xa)el{_>m}XOp!HV*iFEs0gTsKipYcQul zNkNj(g7efXyO!_BJhK=5^poJ%a-sRZP`in3g{{`980u-p0j8)T%h0PD{Lu^%XC^rP zf3amMK|#K2ouD!?eK_Obpg1d6SnA6}4+C9cJon4rx-Y%r^Vph7)jAy&Od_@&zb6l| zdbmT@{}O-LsvK!W2zhBzJom}~gre3nLJ)?|z)?UQMV7_baSA7J@)p?kBIEFA)3#dcirS8?MR9Cmjgl zD?d{7Vb}4MdxUnJ5%c%R8(m_*o!3r6GbXc}CyJ#!VAo)!6E3HHY3QXZHDaS_a;K)q zh}$<{m$6##0c)H)_7f;L4hx6qCaG903ekAa-{&~NVKF8=FB2?frrnG(lTE_;S{s?) zY`@f+Hd(#Ieue%atp!z`Ho;W|u4KZ-uMOD8pxh*Zz-L=RZ#bB%zhF!=!EiAe1&PZE zqTp1XDp(c{;oMB}645Y$qm8^FeeO^bm1aRtn9{%2K}{q(7y{L6v(!H~BsZiVf>yC? zcAH$-uLU5(FSMq{#?TnsGVLcJZnPEf!}TPweZR;p+ogAT4jNb)->YBV8LwEtKk-H% z^N4&Uw0IK;X0LcPmVAfRruEg`vq#dKz3Gcm-B;K5=~>$=Z24R-x#L~YUXwo2I!R;z zcOfr0WW0Z$Z6jZ58q&I7P}5$h)4d9*a!BvbGQmYn2U(W2=+1s8@8nGQ#e_5j&t@os z?fkrp(LccH3c^E&_-r2E*Az~=@UJ}AG>-#25Zv)7 zy6`|6i?#R5@U58LfFoTJ zOC2o*7tUq3UWt`u_-rt)sw7zmf4#vtU{{U2eNk>BxA`yT{oW;P59Jl}o1TO6WH@G=-Tv{Yz<)VJ zW^Wh%OYQ{buI5O+;@9@baKtIchV*>nYNPqb_H^(3U(B@MqwRMd54?0t_|0dK4DrB? z;(=80GU*Pl^zw>W{tA^v!WM>4JPWp-WH!NRK6| z#NnFicOqUdj1W%^m6_z2yff{*zM2N*f@uaOj%LyRxL1gd&DzTrUXz#5^K22Z@sbkG ze=Mm>jXj8dpNj00OHfo|DyeS`Tj}XO`3QVMfD{Lg| zr$5b)x9f&K-QVGE?S4t-z9@RQy$^{G7xc3}``7b5x}ieoYmy^nQK-~8()+f+s6V+2vrK3LEYDpf6L;b>iP##G zbZ*c&?~?BO*qS7#T@b_DMeIXDTw|L3n9mQ!c;)!%ork;o19iVWA(=^S^Cyn7JuM<+Elx2r@KBlo0q`=)r z=os1DrXJyunuo(VYYPss(UyBaRw#VbEFqsofMxcPa&zzDi+HN&&kSzbhSe*{@^lTY z$kNR%+xD06V*)c?r?ukT=~!ygI_4vpt$tC;n)&P?-%8Fd#EPk`h!t{DIS&f_ou>*= zb1s6p5262DRe=&|W=w+;3F#m7$KW=o0Aj&SraW3GOXAz?nA!qx*r-Jf4-iBzXppKo zt+IdBd}Q^sEr+&aM7L`|IQJjX{a!*opSa_A!h?!BSR%}G;GXxq8m2(G9>DKggWnUw z0>29$R0Rcm{RZL_g6G?GH3ds8_O+xzRa!}Yl>3j=sgYci@!AOOh5PFTligHIJJ|}i z1V3D$wuE2)&8m!Ylk^H~mAn_+lyS8uj!qX)uJ>_&&Z+VW{8@If>uLjn!ZzRVop^8(A9ZxUY+Ys;c*@U^6LCwRYL<#sReaw^P^0w zoAg6tP_;HrjlfMo(i^}0s|IO+Jw&e7WONAmtpTu(*W>{YRAK6ikI#$3L_Kv+wHs?b;LXP-l>+vrL9 zJVt*3MT(*}pFs^J#>pX~RA&WcjXf&En=0M-dj*xF+A}I82hPWXB;YRwUuU^2tj3Yz z@>+-R3Mtm6SalEMrvTFQZAwrDRqto@E3$Pg2>9_FY>%O}D0-qGaPpI(e~oLD#JFxE zCJQsfsjyVOAdW`MjrtaQu-xhxoc->~R2Cuv_`CE0m1jG%OsS(G6L4-VKh9y~aZ#BP zWasS--igLz^xke^UB(0Ld|%UnoA8n<0+JS8@h1ASOSDEG=BlYYDaDPpRv+N=RE%Ja z^`R(wwN(pub2aKZYCL|@Zfh&dtt~`qQS_?8D@zViSq?%L+4Op#p?)kQseZXmyyO#$^%d`Dd3^6ilWyAz-L6;@zCu-YEb7F-lxu&F~<3n&6C&LbL-S@=pxS&)fp1c zY|=oEynT>*bMX3m5zOm|wp&$UY%dJ_nIbQW@($R7mr%jk2O-)&HmJTI?Euc{oQGS_ zVv44ul_iluBYEArpPjQagb7hLUN8m2F}B{erp<9E%jK@2{O~7i$r~z|%if{QD21Lo zbWIZGxfGQx+%nq6rt-$T1R>5(&UOxnYxft|62DGy*Q*p2)0BA;Tu% z4~9+kkA=ggTZuF&Q{DzCE&r2No`gS|%@oy;k>P`k$Wk{*-A6iRzlq9wgKet)`6tNl z(?M?_Xj=NmdUp4E2HW4;nissu8*f{@_ENz-V7{-$q2I<|Qll1m$ZIDRS4rmc7k9J=U9!!DJvUw9D|= z$ZZpP6dILV$izJ?G{wSEqM^T)mpvCfVo;QrDGiq`o+a!)!W5 z$mq^;b%U2ntUE#W7fjrwmurKU1_i&j*l%W<^wPI4I-D$H@+HhNG(0Bi5^m}hBA-xz zbAoi^kK3%EkgaahDpN>hX!W!}3bACW5I-Nf7&Ewl5`$p>sQ@*BVgt+y)l%sKjtm4a zh{1+ta&(?lo4k*?8Vv7Yw9mgZkV-x#?&ugG6G7>2{erb0OQOyGHBQy&Yr{423)8@n z>Mvio(OJNNb61HkS4!XMz5aBsGIo#dtI&60Il2IJ5cJk@u94e78%$s?_T$B2)$b zK2N%!;zW_8Mp#hcLBxD{z%dmWF^AiCh%v_$%&qJQT0U(VA zDY}QZ`qTXb?v?_<*K=2?(v^{AUF}@E%ogXkODAbi55BTK(FrZwn;HJ)dNadLtksBm zss{R3?#%R%)+Yq3Q;P8R<%+dZb)X--fTS>X%{O+-*kAm1E@PL_pg)m8z3K`WJ5Jj>H=w1?MaW69P)rc{uuR{8_x(rBfhJNcnSjB&3G^uIR@}GyPUWEK4ht9O_GOyX z6MbnhM%ks1{?uextxHI)FW3Hc7kz1@FH_i+sVTQFZ8F7SUkV5G#YXu{Kv6m^O1@8@ z{PnA0#hWs$XbhR9({tJ6ReZYVQEY-janf&u#nSbv$Lbo zFCdk)0K}+qE10W-cr=@N+O`ut&lkzrY;H)6D6daVEypK7y(rM&U!@re-oc6T)Tu3| z+Nd{}z_PlS5oZGdb8KuT%PV@OE>&9EyB`x`sIgvgYO?4V(`iDHEsEZz-HoZMMlEGQ zT5z2tx%#o`(^F#~d3itd-K4F|s-2AG-pZ#`6u8%jfCNgG-Z&kZTcQH|<;fy$Y7?{n zTCO@NJ8S5F|1mcgXLvFc)%4!&536!>v967V#5qH&Kx_B7H}pJq%XR1T_PN4Len{-J?;Q=ZsKu@4RKC+W!ZJ)v+S=7FfMva5#u* zF?`~g*kuhfC+d|LnEM*L4^(X|_(A@c1!JWPsA`G9Zn6^S8LJYqZnHO*Rx8g(}%$vTe)bTDzK@fW#2zmS0`w9}_gd^MG3sA6g4oHf&(azy>Y~8rW>F7}}7{ z%UZzBN3eV(2;x0%wKoqM2=UbECGk{*nWRXk=AB49i_@Y{k+@g7_@(`rmt-h@%0-%O zccerR`;C#Xcm@6gj5CE@5Nbnm$YtwmsIAQKw!rz%kVFgt#%IS-y45rhOX40jsR?MB zaVp^kbGWI%xp-kkE<_{CWgIqll^74>{zp-gNfW)PhI=-`2Y06kS>Z&$X6skzX@ zmr@L7iXcLXewbnqMf78d)oQL$=zds#Lw#bFDH}~kRI?L9CM7nf#XXgD}q)W%N|9*EpW- zUA7e|4>EKEAS4bTl}d2c-TX>_Rno80R?;2wInR2R!+9YmPP5+i<2=57fEFqQxmWz- zf0xl;fe`w-(&XdraMl7wLOfhl8hG3F4ecy<-(HjXHfOrPf8m>X-~LE0k0G46aB;fb zeuiCl-B5QVH2TxMz_$AVLK6h8z2dF!X2I^JtazftzuKDCkP;%4r$2#O%4VZ@rfPzr z0wrYDamtLS~x7u%~e6;5>GI<-1((^PckV}LR`KZxBksj(x-%gJJ zx(dUrpeRF1l$IW9&QNIvP$bzT!vU6l)h35>NDup)vZ3`sTg`)TX;3zt>mJA!8D)mr zb@hIbvO$suunY==SK4vHz6I&GauI7zkN9O`%>=l?2Vf81a;uL9^qkJt|FR`j|r9WISpO4)h%zyp9 zz8z#w1dbDLioLU0Lgpt`2I`jx1e;N?7QImibmops#Q%cXJkSdNl!u+8Yk*@`ZM0~% z;9B~T;QThL{K)*u`JO?gk|%N1Trt0%6sB}t(1ARED>CnGeV)kMe+gw&WdL$BF}$e> zZ(?>sN18YYhygEOZy$a`t?e%HXh2mh*L>&MSkKEW)0}X7Y{QFeUd|RM6_G@{KJc!u zs_AMOL#om#j3G9tg6R*TA1kJRCYI=_>WUXtWkXo8EwOhv{OcUD>UXeT(3|WRv?Au! zjbsQfjM7!cVW=zrtpHypW8kY!kwTllz7~`u*j&jkJJkHpVeWFwZ$XRv(+n@_rXPOn zXn}nEK*=Uia+*t}9H~@Fc6jKxPkqz+^L1^n;57^#j`BC#p&S|w+4!%_egG#CU=3rMT=t2^ocS43)3=^0}jaShLhGIBd+D(7b zSQ##dDI6{!QSTDjof?}5@roC{9qLxue&N>NC$nL#<6GKu6=I3Qn%i~5pXA5%DG;bN zv0s4ob<4r?4?{fn!>`H4Ao629H(nMbSDO7W7Y9;Hf1)}y(CFOQ`f)VrjB$c^7snd~ zQn244Zq!3L2k?2qt5BVll#dG3i$hU2zQ}{u&O-$A*McHX{}E|jOmQI}u`>}D9Nd-Z z84V!M+)U$I;cwO0fM2K~c?#AIDBdgvn3bU&;MBmcv6cR9zXqI}^1#XG&lxxO)0H{! z7!;_S01AU=n!%%Iv}xu@P8D~ReqG?j09LM^Y|o=@mLC`qMoSj7iC3^>K*6MbUPvJcGcq1>V)U z;Pu0w_WOj}r7EE(bTPpKE^YvD7Xgict&&2u;M?ayhy|jqiH@;{Uk)vao#{P~E@g{n~$Y z>2BNqBK-&MYmsO0Un#UtG``>lx&-)#gAgcR`;DqZxT2}0oF$hmkbqPqoljx1LRBPK zG$;%;3RQY;y2w5EPXwIwmvb2+j~WH>9Oj)m8@j^71#b`m)j>^`Bjk z>jUcR9}M+y9wZlCfxYu%#C| zC*L0%F*nyA%bx=AfBDe+`(s+CV`R^m6oBddiofO;^hoQG{`9B((_aSo8^3q-g8cb9 ziBal;#rAGnMa0YR=0*Dq+RbwPv4T;O>7b<%eb9?`oo9rruy3HKm7oG zJuJhQdGwp{A@%K*xpn{(U;}^Cw;Ai1!MJ}h0PITNe#rLs3=B7$Feii0N0*;E7c|>~9%r@50(Ktzh zTMGl3$3hcU`L4c3bIzRBdIF1Eu6l&+cT%Mn+a;L!?p6_e$F+71;zL9L%$E#ilhj%h z!^k&!vnr}d4@>+n&UY%;si@w2Xl<`ndR6@Qb=KBnTzYTk>He+1;pr3Z=~^yk1=NLR z^=OuP338PMkp40=?*O-6zxx5@zx8wY{GiaSHQlTKvizQ<_g_8?y*DX=3DDk$-tmCG zqMQ;77anB~mIh?aGJ?xC&pq{zl!Y_8~Jb zYpp^MpIjqcjasJ*!?q=Q8&34l;|B~BL7Z4Mi(rEU-7CG;7crQ5AbN?RCwl3p*|teK z8DiMz4BgOsAMKbVjyls?DUEaKy@RLww=Sja2G{n9dU}hN#%@T@!e;p2{V5n-o`cbT z_Ic+sI4AV1)2gNtMlx0KHfF=Ixx8!8=xX!!6x0Av>7v&`%8n|rwWH2C=YJoF&Dst$ELQj6;NsGAC1SZ(1jYB zWvFIJ;kR28YA->MO^n2lx^(Xsv)onVxGOccKX*;+U7F#pS63PBUgOgHy$pA~Zcj&T z(bF#DuHL!+$@hTh_i|XvaMF*z%v=tLKTZ?dEOePn7WpcQx*wK>Ww9OekP%G(JFuSU z(;qQkRfi>fpCx3$d1(&B23RH(z2u&wR<7*!znRH>FRm zG~BP_())kZy$g60)%ic3O|p<+)`>ziB52U4iS-f`G(pe+0cUZeL8u0_ilP-NwJ9Vd z+5mw~fORv17OS;NBC2 z_0o%u{3lxv&}WPPa3_?bqIvN}oO!c_m6!~u3rHR>FTlkF4m?C-M+W?6XD0@{Z59z= zNu5*&1HQLH=;D1`91Qrjdb)v6!wh)l-_Y4Kn*k4(9@t9`1v(y055c1kiXMCdTG|j^ z4vrpn?C3-f*Uvl42hA_ggR${*tLLEb zbCv?LFE0m&pB39X;pdVW2g1)2^@5)VaB<-05%qKtpGMP-TOvcdmL~(P8Cgtu()@3M zvxOJnY(f|EO~(vCS7HuBS4=SjVxT3>rS|XSV=*S}fM{lxgc=tQhO8!FdI#c?qmCK42BSgQ zMPG%zzBX-v{NN&4Z9UHwdubk9puO}qSvDWNVnqX;9n{_ zvtY#D`SDf3{eD~=_D;JzP20n#VSDGw2Z4j1vUd)J9*2JMGwG3mt!j0vD|)=nS|Q0H z@I7rr9Mz8e<@J>IFF2Kn@0 z>2dY{bwQ6OD0u*dFoix2{sYDZ_epm}0|-6BJ`?~WGsAS}L^6Xv778O`_U@cj=9qUt z46u8-tfGj#ql=~9VK(^2%j|60a$XKF8=L?Y!Z1TM8@%p=2>rtH;cW23vX1oYoDB|< zRy-Hu;+PFyqT0^kQ|D}O!D66oU6je*fuA?C&za8yD-zo>S2M%ntr40MEGL=ol}6E2WM(*6RXGF~ha$N^J-v`m!;0kY zzo7Riwqa_`;5zhQ+!6=q|7oPJNdIw%PLPtqDu6+EED;j{&%7iEc$OD@1~T4boHrx5`$Ec1(0m4k6{AYh<+dI6t?5wP$9AmFHI1a#>C*J}JBFYGlWq$j@e zUp>R;2WNp^bC{U;h3;JcUF{x#moD>O9HeG$yZgs>^O|qColTf4C6lT(Ne`r*a~zZD zxX;BU=+1tvC(jNBGkT8ZbHhFFj_!C3eGM#9cZjE&TCEX!zthp>iFZ8Tq^~!KR^BXQ5SRIEm9OJ~X!$`p?3i$v$#YspLc;0+(aT^c)qOyS@ zig+D7WC3$IUs$q=7c%g@6>9(-Ky?rwaC2QZZ)5+Vgdz)CasPP zw|a10JF)Ao#p;!#LmlcrU{|D-*jG}bqZ@WmLjWaK#C?v=8KGM|i-0m+E$*1xzH{=qlEcpC$E)T!6v1nmUv2=_T9FkTW7{3S61#izw(tPbMEd~JQji^&n#?l9B{2P9 z>;p)fa30BPAGPOF@`Zy7&>-rR_mu(5|^^-5G#iPfk)#+<0B-<5{fp+=52yJ)p(o8TdjH)0X2%dvC^xh(qHolEB%$T z(u*RMO8u%*sh^b&QuRxvWm3Oe)&CxO!zji9rdun|llqtQ3G06WH({WUi`0*FzZTG? zMV1)L;^+xxYgLrF<({>@qd}yBK z02vt_qClpFlOI}P?Nf>gH@266BuG$)1NXTKZhzZ3mK%;amVs}h2)NSxAENRwEo(LZ zVq1YvQD8>8=4VHl@3(hB?&>n6QABFRH!4l=#>~E~!av)7Kh$5pVQ5uza=AOyg06s< z^2)B$8&~&30dHW7p53N5>_i&)y-2fHezAiVAwMd7NaO6FXkWj2N!HrsNc^fjM!lt#FQUD?0S!TUFh1ANy!Fj~8QH&Fdw`#Sco#owvR?o5Ele_l z1NJ$4$drRf15pKFV{m7N0zRNF$J)@Ir!Dvk1)IOEzg8n6NWoosizM+Q%p^V==7D8b z5Xj+=2Cr9eHe zte@SLoHCKE6xcasB3mi2FDM<+p>N#}3!)B{9K%Wu6+s_=CkXPlosV5p(PEWniyu0g zI#l90yh{9Sh1!B=shIt31GVZ2>TZ-)Q_W6Nr`gK7RyNF2l8I}T!k4+BaSAN3-i|MZ z%dbjm<@OuYX;(N@k(#;vHmyedHAV%LeZEao*p*!%raZWuULiZ)a6xe#Av(V+S zC7j?>8pjm6DkjYmx;clcEMD2Gcxb)2hRmnbPmWN{R&MrD7KT>)0{bmmP;RIN1@&SY zq3}%kr3T`6*jkI9kjDk_@esBciEHrNXXxF0d21`ZJ{}b@3{SjyYqfcKxB=f3mi5P= z{jTg6{DAgVC5@`~n`r-3(x_^`f%Z>jJnWzL+qLS~L`uDl(ZqSyj)RJ~6dEb19L-Xk zbe|XxdH*14JfZw%X#+#-i+5GEj4A8EyZEY>v85R5me6hn1V#@vqOibnpXxXVxl0>n zd8hD#DC4CYyKTp3bTW84wC85w?6pn}5Is7n>o`VGgAebWPPhx&j}c;ED` zxm{lHVP8^Dbl0@QW!&-Ff^QYO7L`?oHPo{Vj%CVLY{I|Z7LSG4s`w|qh#~HKvi(Dq zW}5WKynl}+)W&Ny7f8cS>wYn7Hk{V|W}p>M9M=86`Gm6MMci11^7uou?jnSODxTZehS891{gfF5kbeR{iyrrMA?ZUj z%kTSIiHIo5Mk1I)AHl*{HOZpFq0&Nvs_7@qay?4iidn8d8WFdh%<^{*WR~}4pAXx- zE&58(_>*S&y<<9=<@X{YqH7I7vpo4ga3hTPXTW_w_RL~B;cvTMtC4V6+b(^X2>=w= zYksC8rF5nuJ`cpVSYB3u>sl(W)${gi^FAjONO(T)Biwic&3g7epK%2wcMHxR{-)jA z54#%M6U)vW2JPO1wUlMzwz3Cn%qdHkd+PO^vJ|24uR+oFK;Bqm(igs7M31fE-j}be?;Eu8Rug}&Zlf2 z$tl)(1-Xr->HfDfhWgiJ;J)k>48#pn`{3U@%8$djMfjxhEqKpz;BiE?{#8jU`3ody z{W9O%Ma*>cmuYj)=eR}faZ^6pB2JQX=#qeYn^9pnUCMY>s2Zofz*q#x{pl+$;lVG- z*!P+W+qP*fz2Zpej1?A?LBX)YG!ZJ%W~k%XaV(C6D`!1ex0a`9w}N*i3NbjU$|!<0 zU~itqX)=_Gu8rX!Oi%@#BT@TA;XJt?&-h1&Nj^}bBh!`px)xavyq*^l8-RkDCt}tL zU&N0R#xhEks9G&b+et_4s>~OW-#PRg*03V}N5sop=X1PI;_2di4s6C37Xcz)jJsJ5 z`{W6#ZXN2hg!equDMMZ=09Gfap3QB<0Qn}o7uYA+Hzn$3MK8YKX68$E;|?4nT(2*) zH#B>(OL?DcX!aSsu$`bG$GdTd59grx+k0vLXF&tQ=KE46`tS`(23lFow3k^8?RdDG zSZubC3imhnnutX7O(YJO$Lk0f{mV=>fGa3R?bhJIU(W$17@#wz`iwC+pyS(FDXSCH zbC5bJ4fi5kR|D&&Hwm+~<_Hw|o+b924+T()Zr-D|J_c9!Ozm z_~4t^6)RE9f~(KTvVC+5!@MI_Lu)|VoYjI^b1cEc>D zm)%iWqO`XxnEMLD9Yr6Rut7)y@&NsmV@J?6Ijq=BkqS+>Rj>P6sTcg_2%rGpjkOTT zzGj&BMe1kt9TADCI)sINXq%$J5EdoC4%TKHWRh6Iu2>a^n938)d6b}sf??2jev4cusY2~K-UuvP*m z@RJU#6c!j&t-sK!uY-u_|6xcnUJ-cQ-+)Kv3wHn$`=eqzh?5TZ7)LISKA#H>UM(=< zrdVz;3?gP4>&3NMQ$KUK2tAxj5@ul?DK!)eBiR;m5`3v=x4^ZOtogqtUmCX~CqZSO ztMtGgvT#lPtbc{0X#CB|GrJ?(0V`*w!X>x@1?QsFOb|QR#NUE?mY^Q3ZfxRJRjn{> z?_{muXw>wPRy{&~S+Q~ew+dAtsR1Zxv67T|A7~5S=0ngH_(TcQ)rm)+gLSs#^2xf9 zf@K3AL8LpICOj1YLJtKq=$W^E_ zbQN`jF|ch7>wzCv^-L-g?v=`*w#~dqWun$tBXYQg@o(WP^f`!yV2d0PB>>i9Q;|N| zTWdOY3&Rkaj?YccPIk}irY`4JfCle$aAODhll3rQiJK{~{tC$=7);E>wTOJh2M}K5 zE5p6yahkz2NkEwyX8=Q zX-nN%SD;`GpBs7)kYT=Ns9z9z+ST=hd=DYtV?KmvT**P(*pQF%2>ds=ksd-yFo^-e zEeS)08}~vN_yL7tj}$>iPpo`A_>sfz=9+3ONKasJox-Jvu~(=}@B!+P0UwKX-@>^{ zQfIJe76)#Fl!|Py63IP#)e=0$>Py=4)g&Ltec&_+&+r44nU9TRJp>G`S(RC+2%SOk zGIlzK_SsJ2#UWpeYDYff3r<1JKb_AQO>iEKUMCR``NGzOr)Cnqmw`r?<`Ycx59qOW zHVTm7Y7tWcHk7>B{J``C)`HD=%%tOOtOxY%g@FbM%J{G_@KIslb013ScSdXL$pgg6aoVTI<1*Uczan1@~@KIqFZ{R)ezR!@KCRLxjsR~C37Y4rYX1}X1b64*D&5m&!b?-hL zecIZiFz}_f;fG6n**m;}cTqI;XjGWJSzi{Iul~IIzV^9r25YmID;Eu|ZeMn*H?Ud1 zb<Gv&%Awjz@948zIrgwoxh-vWD?PLj|BUnZx1Ovm@I%w!E={Yx z&&|6PyYMSnn|C{Z0Tn`D-0a&2AA0?5$7wYo4!Cg*Y{a%%zg(So(s(_9_K|zira47! zg@NtFCDB(H_`wG$RN@VM?+qYhR%Gz@5N4Q76MVod(XN*MjI^AU7B4E5AjW1TjZNA} z(+a{WL8N#kjZG$Hu%;pt!jM~ZBEwF5QwGx>VGNNFH4H(*LCRkvSA|R2pM)--pjCUo zC%8Lat4>gN=~{IQ7#`1hBkSr{)E429()aE11@^EuBG2dg){E1t$sF78lOsn$-@;ef zP^M!c#eiQ!vYf;6*7I7m1*<_+z$`XzsU%(AY&nQm24mlcKHx-WC5qG+XV$agaQohU zUs;VRGC?C&;xRM^r8)rmajEsKs7Py(le3sOb2BpMlQE%y7;I&?0zm?CTuRlw{{*e3 z9n^q12cUf$XWHV&>cpOd@TzYqRKxyst>#h|08t8v{{6?7-h$_SN)hz2|K!qZ@NaLX zu9NXnM0Qw1yK&z=EMvSWg-?~|oS0`RHD1x5walBxjeP6+# z@xl(n2+7D`M8Hs9G8C0-fU_M4E~QndY6V9xNODKP5tmMgo6xx+3@GM`deSXyd=M%= zBWj^UP!p|>SBEN10!)S{)na`pJcY)v4xmP>W+WFTccBryLKAFbe{QWuQa{p5wj9UQ zC3w9AJQ=VEj2ODmt)x@K{qAc~Fv|QxV5|g;$H#)P0=#9B8)+bfv*rotNm}(jg>rz5 z)87^Ht9SA)usMX&)Y;t4;pT+eY*tn%c|5-pE87Mcc~QpImiAqc2=XdX+ID1RqKryx z39ccWN!ac)ra@-ypLGH_>lePjx2#q;6kXCof9C?R;a>J{8#htFlI1eYwo5tz>$A>c za{$W`IqH?G;J}P}Bt$X=2#TLD;v^S!#BH=guf*r)?BdfNx`Cwko#lh|niE^v3-C z7TUr-V_@;W=tLM`oBB2}D7pTZi^KSZNRI|=q13H3M;8Dp0AkUC6VTAR6x`I+wrUM) zi$fIL*b@c8{UA|l3vRAvcM#kpouaTD4L7Q!G=+|+2daWYkkbACL#hZ%X(gR44Rh=F z5EGSXGaK;>(3wh#jqN1G{TF0%;4}~ z+e-Yo0L;P|4@L?sPZzY-Hj#qr6VfsD!VML)^$F(9=# z{uXe&&zQQ+>)-Fv<~{-q13QiD)>`#1Nn6TjEA`m+N$6uF2bDa;*Ni8>S)LYXn_86u z*x#I>&8ZiDsa6WuC_>bLMPA@jF_qy4P-4SkRNBtUhPK2=-UsC~b=MwUw3(ecHUZU| z3D_+X&7De)(qcYDBdbfX@pmj@&_rA0|?d3%=M*pfS}dFW(yorL<%%Z3l(Cz1qCL z$`>{~)(gm9fe${)J9Jm8OebLgpjP@x)?quvkw)BYSlBdO?^v!C^Cco~Fpg%gwkBts zPr@1j;=(@7Q}Yz!fU`=Pc{VmWAi|RHA&n|ZWVmhP;7u-3HW7*jwR#)cQbnR;F40e0 zv|>J7faYD6xXGuuK})5SIUNo5E+qSbRZr*-djZhwR)z>@3sx!yVx*H+JxKjXlpoLI zU$5~e&cetI8!&#N2gap+GWqnc@3>Ikw*wQkV>nS8lne>7R29j7Ute~0_UQFX){IDp z)TX$G*!IwR_qTS}{9{n999?g?$7AEDFE{|5UutDLADb%JuF$RE&TS+b#=-oFHyt!K zUXW@;TT}k1fif3io5lYKRb8@MF3f)OjSY%wJpX)=R0H?A0>akPB;pM7y9-Dy&>I{> zp%&>BEpVEr6^A1V6}rMgdnZJ*`PSP4O%$Q=bS35U!obFvXUawwfbzdrVQ0{Y?xJlp z9cMoC`4Ll}PjRJlb}Qp!5H)yYs8&ulYuJ$poA*&{FNI13r3QOJEG&|I_s~YrB9w~I zo;b^085gjh?Fe7nIwT{qP8Q8&PG?H$El-r@STb%xvV-H^FyDsR|>Vb0S-x(gUqr4f^&Y*5eUS$N)2RbtiSMoF9ZCk;J!Z+Yy7Ip$Sz- zbv;7(BH{HT*Y*guJ-d~`)mrsDHLeW&)v8yiaV0HaTyLW^4y@3ZJ@usgo#_p{1Fx+w zu#FyDePb(}wz|>lO4tDL-oPr3D7Nr&6%SrksL`l_m9Y+w?r%OlVwk;U*O7o49m09t zpByo$pAQjgC&qk%o17Xy7i~M0y_g{pDfDwDtpnNi>{dp9YIpUa|9f^TPb$}{{|Gj~ z55{F`)uZq)elY3?#4#Gu)9e2sMXQx{S7Qw33f4pmj@)_A2n8q=Y5Qg9;hiTTjF!4I z`kr_?m-EQ|APqSk-F(oX)~r_34NPHVR$)zH4$Ddg)#`yphIn_fx6N2HPsbV z!P2J=pbGY#6{S9->e|NMVlKdG(_z6F+CU8ujl^=SFLXj6HlKu%w+T5cIw0>xY#{0i zd7*!!4RhP;R%aWZJV0lA9MR5ZLh$~4+WGUTow`3UsJgFc#yZ3gw8N?EVU3G7@CF>Z zdSG=7+Sv~~*t~m{h0cm64uH;Au?xpJb8zzQ5u=@GI~C05q@BU1bVAsZp}*3sgIF&i^}xASAy;f1;uY($8A4Uo*}9liiAFIJPxir6 zw+&cjg_LH6*oQco%gk(&Q3@jBpn>_DFGu)XkXwTto(yxuTrzkp_*ru&_#cOjW-f4eX6 zeOQ+U+C%H9wRVj`q{(9+TOoas_%#FHQFF?9*^_1RvU>?D4j^=gSHrr}wI>bgl9;LH zb{aE5JrxI|rt5~af)nV2P_w@K`Zz@+K0~#Hb*|P}wMWutKh$vuat!D;Qg-arP<_CxX27bPyim*(6(_P~Gg_ zovDs401y$W?nZeXMRng}JFucUL0M!(@-ZSh5uQbw&586O?d1M!#CB34DJXu)9Gvln ze~YdUm^e@$%&W2gIy4oF$8Ww#D6qM%eiowbJ%5+{?`ik*Vygm13c#l;5YdkU5Wp)K zXrKaX1cx4nq2-GLNQ&lu$c+eQvG4+SxA<4wba*FkE##fqH|K!wXA9^s?zE< z@dnuH9I7kj+t;X1097u!F5uyL0> zTq4I~`FF%ibU&f+*YEGDT08z&;fFm1l4hPNp~V?xC&mI4FanPsTM`E{l?iJi@=oHH zZzf4a<*Z=?7fD-5B{ z@a_A*M;yZ!2yNb@w`0HIv<^?d)!ShVOKgm)bkD>%M83fQPGCaX5Eye>A!vLizOqMBT|112tcUq` zqbpN@2tQl=Sc-)kbJRtlfsFsWZT~tL(;W40dKXU`&z)<7<0qZ`?EJg`@l1uP0 zpdfJe2K~hfE?4U2<2_hZq5~k=7~e&EVu@U>fKy<#7$Y!YrTL@}9brt3bRYu1QJuMj zND=+{bPnp6y?YzU3;J^luh5@z1qB(H}0ir$s8$u`z+6dJ+nTYZZ#{_cB~5fRzHTwPH5Z?2Ua} zBkz|gD+}w5R7nN%3o@^x{X_ZcjM9AEs&tQBpO#grg88MH*E3=;9ff6hgtm;A6>Vj3 z6e@`DRARV@g@AYvntfiO2(ZP=n{4r+lx@F1mdDSEP?v1qm3k(qJXlMAc6#m zsT={llrnOu6%WgJEr3?RH#`S;8xA#OS1Tk>Wp-a~%zmlCJG)sHUlyE&1ovKlb3ZIA zG9c66jF8D4$OnwOG_9r=(_M0%r1nR6h_t$+s#<=j)qErOmti0ESgqzW^#fa}hif&P z=|>8BR$Yhn7GvZObOn2n`^D?umf&-()cvb}3>)8;eTyw+V==JkBL@<{ZoY;T`_04-iJqN8Px+FTi7*3WH_xY)SJPfLjyTQWr-5}oM8G&qb$&Afahyap3s|2= zh!t%W27VlY=v4&V0bvqzMXCxh0SQ#|#b+gmUO;K-Kq}aSZh9g=i&w*wTg~*8wV65c7$MxeV!*Z#s@bcy;evc@kkil)Nvz)d z^=P6?VG8Gn@Ld=-iu{p|_o2}cD0UImQ5HGXS%kay>>>(fEE4A|@(N{LfMU5;i8JB< zkBcIJgnr8+hG+7b)}Y2+dcZ;b{S-B*o7l~8tsMr{heGzC&b1207}V2LF&WgsRFczAnL3dPoaAtHZcAW&LYQ2ErbzM9dm9rNdSoE{;l+CoYUbaa)D$~(wLL~PSVdr9kWWg zlY>r;GWsCXrV``a78zK7@DdP`u)-pjbh$!Vgs{b^-Q4>uXYYD&NDs*$FK$QGMn`!| zZ9+IG8VT+pv|cOfG&Btjdj0jgpdk=OU*bkxIEY58DU`eYuF9KHXTs2`=J93M=*HzR zE?Z!7V&9{GJ50_u^mh2?Jr5UiMZVe!N3RvH#zBJ;+JlHoG>S0ovq@w~YBZw|o%bMh z{9#wh@gr74e?;Y4-DL??ErUu~>q`>ya+sioYaK$6jmujc*yyIakc#0CE}t%4g=k95)X+wh)el33?1 zK{3doMKI_XXYJacE?Y>AqzJ9rG^VmH{5isw4q8BUdb^f zp$m{w2iq;n+}QHibT0^D9Fn^?)v}Q4TZ*G^XRij%U<`{wgcP$os5%rHNIifL6|$Tk z{`Ymhk%3lK{YK=bqIVi17v z8CSJ>;a%|J@NKVuhudqU^tNO`0w8DuRm?$7!O$mRVt9h#@gnPbASyQW0Dk^_P@Y8y zr5C9>wVDD-l!g{0Ou%+?Ycpcrdg=AQkwE?DH&q~MXe`|+Ga&Qz)6gcw0XUNe2^ckt zY>wIQ(#(4DBNUxdrHI8^%m>UBa%nirlds=u!bPFwbII)*6tX?$2hXtRudnF!!5j{g~mjO8S-5xO4Xl7Q(cn3)*ir^VWI z|AW7}f~iEDLn4Ka5KMyzQi|#jYT;8 zkT}5wEuaLD3pF{&C0?7`t|&y_*7(F+-=8R2Wzs+Y7h2^j1T#WR`WrS>wa}OUH$g02 z4)8$5nR~&m;&Q+b?B+*O*Op7HIY^>y@9IXMW01cJ8+S`-VOCNdIRyWqiE_(FW#jG& ziM4E@C@ss>Yrda(vQ~EyG9+b`9j6;JF(qmTILOWF{}NN8Hcp8gbRlt=7G2zF9dyu% zE^6v$kR)z#2}xiq4vHkAJZoMCOC1tPRLBko>l3JmFiA)pX$|E8h&5iux$3$9#W;6k zi^L6wRwg{@B0DUHxS?aMCOovrm#?NWT(jYFjhX^bi2GYdRNkP^UNNP6XG9_DC$^+k z0>&G7KjMP~r#NWD$u8GQu;q#kXrSr;EG~g?ERw{MmL5j5L28^?$LNw+=8wNQU7IsU zNOoX-oD3|f`OqlQsa`N8qyzI1NBJHGRysVV9OY0sEMxSFQ83y9I{U%y-(eP|w8Ksm z@y@Q_D-W7oNJm^ui`zle@}Wi4FG{R;4ExXDJlH}&BQjNxb%%uFxl!eCrzb$b7D2#r z%hFq_9APquT}r;Y87Bz@u;a8vX(S2)oE?%lYO6z^Nz``C4y9;wtr7idKRk_%jsIVa zXuW8cXug#WVGzFw4 zhaA9jU`*T)!NhO>mzb!7J^?05Y)t&NGbS3J?0^X;)l0arMfG2ON;VRR(aWe0~TR?%*Od2EIbJv(;Q!(h=`Jr|cN5?)NVL>J9jjtj(jkZF^r>^xX_F#e%Y;2D$B0ehLm1C zHC#Uv)uC$$5LOaPagLvzw#Ooc#ueZs>W)@j!_X9+PnpP*uDbKk*gn+vW>sR zK8LdBihZj2KpGy!(v=X;QXE4k1cu#NNE6dBr6^bV*t;7O6duz`ChBJ2kRqr^j}9u{~z#!2C`^Xe@lvHT*fEq@n_B;0}OO>#-c6~nJbM;4dPVgVFvmV#I@ zY|PI><5=KZt4hh*(wBs%F+YQESXz84vRL?tDkbYmYL~BCoxq}_EEZx>7|Inq$?tfeYPmXmXwV3ZqYw*S|BNFncAFDAn}j;kuDsQh^QL zeIcJ~9XBh;CaF!_BvlxA)0@4qkS_X$9&vHY&`4Z$Jr%-U8a_dh>W5%)_yUCykW-W+}+*lO!F+zp0D&UuTKntP2hM0l)+Q2ISpsKKuS}gB? zRI-UcM((EU;m7*Ft!QB;4DHVg>kY29hJ^j3{QL& zV9Z-n7S9ud6bvXYAfZJm3`nC^w5!z$C9<<}DVu-H+REi@x$n57&FWaj-;$u+m5&J* zyTX2Hb-kpuS^Tv#8C(dDi!NxeWX#FM;2q z!06QZL(_xqCkjzH2xk{d2XNkiMJa)yNkMn5_3}xn%G#O}Kx!PT4}qZ=vuYL7+?bz^ zQX*e?4W?azkCEdzm7rfPwL>l$p7{bZq9z_ZLty^r`edNY^Q2tT9>xVCOi<+Cerc21>H@mr;a&RU)O}&yl}b_yuCM zLVy9?Ty9MYradTC6c^QODw~8NMO+x4aipn8W<(S&qjQvq;_x?Bn=9^C+6Pih)|k(8 zybhg8&Io^byz|vxL~_AtiD6Mp##QwHp3BM=NrW!8i@=+iWNvl7+D~yJa?cLF8jB)z zQp6f&o9rz*3?UOBOxK}U+_H{!g2{`AM z2dru|v=u*M3MhN>CLwc{i3z_f1e9fR;RhBCs>L(FmUGQrr?Rz<66$C0eN4a(R&p-S zvnA)1He6)ad`M26Ec-YHA7be_Tqw1c@rv&7F;Vt7=v0Ej>_<+aYQ<&08WEimznWxT zdM3XXoWZk5DGle53a{b`9yNE1>{P%RIGJgl@{J|%V790oU&rEmko zL>>yr9p$0t5_~N35F$!8RR#+*3a3DPs^Un~Ls+ck|3V2w zb`Jva`C26q={cjk?B{sx5Qvml-JGu;5NQW7iZO}^#GPldazzZGA$AcFh-;j$evBy) zACn^0)-Hk$qO43l;j$444&0(zCF?;VrJGxZh7WH5?}^;ANX%l&&^L~Uq0hP!h6g8e zLtA&?zYB4QznX+rK`PrhfQ>2o`So6J06S zS8pm!g`JgB)`QkuLud&-Fo88qdx>67z2rFOXXCBO)yR__;)Cr;FQ}pRF?<59}E34SDZQd9UK}h<2G`S|zMBO3sPd zHICw;)ixi7aZN_gbrzW|MLJH*(ws#Gu!!M)D9)mW+`b2-h9`z8YT$uY1UM!&RHKkh z4d+<}!_d`gjw%@ypR1_C8K2ujmEx2;9G?q~ zHt}`Nw||L$IljEuZ|@wo~%j>z8}@1x>#i-;PL&VFZ+ z*zvg&oJC%WIj%#TMSg=K=85wtP0V*s#IA;O-|o0QqvL*=+8qSe-<+t`u9p$TL|69b3@^jl+&IkKCUFWk4l}ngWggrl$P|v5=c`%^S!T4W zs`X};8698MDrH6|RJCH7_iL1qs$>$#s^DK%RpD(vyhX^JzpdMhetO=@8GSUrWXq`= zaDspJYw#Al3y!Z6%SI6u(}!qvLlXv%EmL)HJ%TMb%2u^rUG|{ru(u2%*~@d%%8bE7%K}Yr zn8(+MX7;za%g!T0r{l1;p^1aXVzEoYrw9Oi5FINuKdrXD>!#IQj2TVnMEql}RZn3C zs;R?de92K0?U~yFFiOhY7y#3L$_iDGs8|A3bVQnY_X!}OH=(PYJA7`^gDIyWA`$yy zZb;SUrjsyYoEIVK2LDUI4E+ZlG7?#GOwfbZVxNvN-~^$vYMx4?)ukMTMg2>vTFx#_ zu4?%Oe2DUGF_xj*E|KFX{X4Pl8%ZT)juF$Ay=G5nvu7ZLvuu={5P^Ei7eV>;(Mb_tV%dAkKy!>~pk zo?rr3YxDpon8RQPaDv-&F~$saXRu0Zjze`@&5vid#I1YaqG^cTy_U7F{9fPpAx|>; zWQNA$iHwwhzHvK#R(?a_RYZ&y<2z_`pjK|6hbOV265n~_f>bp*baIw2`Dk@;6A!&;7tE)8Kb9lKZ1nj{K2MG{ zuDuRve?F`%5|915$`$38(0a+};>1asEu5xNy|iKx4Rn{a*d4{`LLWGHx6b9%-8h2aW6Gr(!Vy4eo}cpGv{RQUVli%;Jd- zpo$bwaCMZh5ab$!!=lUz{=oLvn@N-y&BdxE1mftWJc_mKXqf#v5?BYesD&6I?VSdNYc9)&ekj4dk;{raBOvYJOgz@+%af4>a;r->hz-N2uG;qfj>W+~}F) zP@mz>oyhzO+!@+zOjcmgNpce|U_N*Z03IL3;8FT&`stl*#Vo>V zzV~YaWLr+=Rj8163KSH1R6CZ&3_!BDbu4bu`Mh7WV)yTCJlu9>0ygsU0;Wz9=zldx&0qY~> zXL4r}_+XNrjRRq(VV|kBAH3fl(o(UcLtclY$(sD;U;iMA3G7&c30B5w-N9$T&Sot< z!J<5F%um816=t7T4CKtJ42s`V7vf|r33uzfoQ-hzDVVEDKo46as0=0Ul(L*>TzrD6 zIJarF^$8p{(Vt+LEARy4t!k5djFe^L02^qiHnWOF!jJo}4c!i%Xx^oPAo3#GvD0{- z$Pw`G2C}CBTcBSsGK~OrD%DZi+_zaTVDRB8H%0c1qEo|{>C*!+Wl<(cj=;lBs@wpy zbh8gN2&&A0vDT}6hGPd`-|fU0B>}%kV)cf;o2S_s&TV8HbfX{4%)`5gA#PUxQi?K^3u`P%I=ybaqEQOm=(Py>%mO45UgNvsZdj9}mT zqVQ-SaE$|j9r)ozg6-c8%A5kO2mYWkz?a~M(iDvJb+u?CuYtlHWb_=?nE4tl(wcfD z;>X5PJynj8cJ@vDU;|Fm2o^!sZYmw92aEG@Lgp;wizw#tT{BMAgYdz+)?n>t?bhA^ zZI;-ImgxrTZ&eXQI0%inHP7M^F=#V`ZRVq76CxnjG_5eFdC;?SqGUx3e*gTy{hJwd z_HP4h!=LD1;Y8KHnRfq1+x-LLRR1nP|9~O*rLROcfthO=vg;h4Wl6HYZ`nSks@)i7CLxe#b~Fp&vEg(=WwX>l|y075@QZ zG4yhtS1~{Y*i?nMOT{!UJ>?VpxaV0d#z%=e{Z-q0+^N$y2L zP}EVroT$vvgJ{f8TXg7j;Rb*Q&jC)M%WIgXNyDoP;@fi&i`2B<>?>syD&*g2e3S!x zaN87A3w)q%+BN~f2eBad0D@>itb`urd-NzVlR;?3NN*9myGDQI!UunU+=RU++`_h9>-3FS zv|`OksJRDgb`h4}5*B>$%Fw&N`WB(whzt0@N)@A3U&)seJ%I_x`?`Nef^H1%iBReU z9mh#A<-zGJ5e~V~_ccjwm(7f~U=xV9;BKDmcQBpNsy74Y%kY83Tdd#!_**X0?h;#u zvUgc>zv|RsN&Tv&Tf3yHPh=wB(3+@ce;{Y2`rACy#z2hz#Rva*<-$aLA}DBoWtL>i z(v9IR4ttiKyz4IwX$F)^)%d=zuVkq z@i6!+OED{~G$e)@kNsJ1XbTvAg~M`B;VU4eS0)fqg=Z)fjT90GBmpPWKo|@t_XXz= z9QrQNZtki0$XvKki44eDAA~y!7PI0aIXgA)omm&JPE0z5{Ub`~9ws`d#Fy|2^sxW@ z<2`Y}KL;L+fq%VrVN1Dqu_{YBk(~KxmLt3J1F0W_xVQ zY>({}`ef;`onoaww$mpFjZ!Mp2VO;_a5&68y_6A^!Ai6EER{%yc5r{Dada%AI1yi% z@4Tc2Cr8SnOZZAsGhIs?sFZqu>3md(=JA0ml7gO$Gr7iabt-83Bt38`Dz{EA#oShg z5F}a*5}g1NwWbbcpQA~eR-HvnZ*nNfTKwZZzvCZ=)%ung38jM7%>{`-?~_qFy#sz9 zQ23oh9X7#X|Dvm?ra};9(J<#Dspf9(bOy_JWaj^-Tg?1af`gecU9*|_)a)=b-#RSJ z%rU!yZiN}!@Z2#(G4m4k62wlTW^a{+DuZHp(xplod`&5;{bFI}e~pR7%)(s{zvEzL z44${N zwlmOx$iNfOhWXi2)vpYj+#wLUB=_zlcX$6YNbXmp!iNoVzxsgWo&piX#l^FaiY9mS zO&2iG9mH(eV3GbC1(~KwZZ)DCkT83v~V(X8W}Jl=(^w7YAbw1f-YfA*`Ml6jBbqm(^1gjDO&A~tikaujHg{Z zzR&S_pF#2slBw(2*nB5$96Lt?j@#YQW5#NA~j*YAzw z`aWZri%z69fTIwz`pKK<_STI>$IEqgD=%8@%UCao)FKt{Vg@U9$YyUnyLFT?xQF$% zbuM5r%_!q{{1WG{@B5VN{gKne5IBt(R`mIJ?8t6mu74cWxsHb=5}bN~MKeBV+eqO5uFZRtpff4TzjhxJdwbhtuVl03bbmmjEn_0-&b_Kqc!6 zpG~IFAOK)drd|3F1psVAVBo?q0DAk|kx`Ws?7v38CM8FX^#iEG>!~yHZRW9%H*KRw;Q-HpVG7?WE!%pxnPkZLl z?RWHg=2Gj-Rj}&>-L-;7G%RTBQ^P2V8Ly69&Nh(Cn;POZ~!g>B475FdCX?dFq(I zNi=k;Sm)XA7b5h&x&r0Hrujtt@cMtmN-md@yhcF|3~5LTqae2(VTN+@?BunKHY~jL z!@=m#2|m{*Mkc-zcj4)uCH10buv0m>=OAgMp0lMI$ztvELF z-ho$-FSA!u5?0_A!y32m?sBvlCyp~3zo@bpGQNt>oa!0Ig~%SmbJZA5`@^xy)CS-i z`2ZRM!ddNvfPyet2`byeYtRy6vsc}ZpU7=yhetv(i@3a;bf$U)VkGV%koVAIocLnb1v*SV4P9@)+7wETysGD`m6$2W zR~tf;cx#Ee&?%fj@L1IML&#Z-+YcC*zl5K_qs3T|i_cP;coN5{l!R7*mv~x62rpVsg!iACx#EnpUO5=jzdLP_d$1PpOZ9vdQ>rwWN^Iv>vby7>%!^ zKQuSA0-8TWbRU6=h6j?aGd$>&$$XH64i*gl%THpHV$p)^ZNSVD)Zg?>xT|s#RX^5n zNjP1!v7IC#Z2;~JXSj9sW-uT8S@7Utx~<~&OY&(8XJL*!3#b0&>&%^4`#V(**ebyS z0QmnMjGQl+ATJv^ih(^yKm+j5o>)qIP85eo-R%`w{ z@s+&!B2fnJ?+~~w;5%XhXP8P=KR})D_g@G-Ffp>g?^-Xil zkK_pn&16`JH72wngQL^+;J8#aeUsHR00|C2d_iRbn@-?+pvDW-terVP4;~c@4DuBJ zsz^PMU{L_+VZ=49G)F5?g2U0uQF?F;+PDV9%()#tMbE(S^EuPt#D!i5N6%#JLZdn2 zhWq^$%KxmUst~FWd)7)X+J{sMP#=9|#;r6GYf8n!dHUOy$uP z{ZVYwk(R`5Gp`d05F_x4;HqE|{fIMtiYSY*1?@_V@duh;To2Hi4LjV3J3J;GaffF> z_ret1RCy9gOq)vE&+!&69(g-shpHM=&j34`$pG8pC&FH1o6(=F1^0C+ekEA}> zT(_=rHwGd#ZYBS9G0kxJuLFO-LjIn;yNcjKtW{8~RZxXcMG4imQNSuLx1KV?HK=A1 z7mPW*0SL$$SPW_{NoChc1k)lp=(F2_v%$HN6|6ii$rnsKj#8cK%!gyPtB>RO5_48f zm38Qwv-)CIKeBW6?+bhfuDlx1#hwFq}jf0$jJG4-Di1Jkr_n zLazuOuyX07e{@N&Duh zKPXEjtI2?SI&tba-M<2nXhm3J9nC9XZir5D;@TQa``7URc2n80I((&pt$O1MOu~@O z7Q$C*2L&gYYul`vWk{Pgn~(oWka@$mK<09hGGTGiQ6B#T)j=LZS#T)=_=Ftdz=6#3 zm0*Nc>2nOE(WTZl-#y_aPc}}%0u5RwdAd2nrF;+=5%H@~d!Yzuj8$`~qr>NPGDbeX z*!nz!pJyrcf@U0_n?c0dhb{mDRG%XBVZg{HZAyM@EXz?2is2i0T5YT|tSd}<#)tEd z5~Rd&&*_Rhhs3;}qy_?3vE*>=Sif1GJo>oxo8N$_xk*Ky^S4BL$aRtW9wV+9vp|7e zw&;M$s?EhH9_1N53SWZ$1|wN>oZJp|4IZ!6{8!`Sq49$!Yc;02PZ<1bt>z=#6GR&n z)rCcB*Pp*NRWoj5iLN@|H7KcCO)I8K0HqoW!h_E%O&WZ@R`Vqu>Be%I4ro``>;A?) zq^CWkr##^2(_(qA+h9d?luD}fVB!Y0qmqn!_0wFA_e0v`hOhjgl|X62WsD? z34-83D3)sV40Tj4XD2rZ-fOMSTAgI{4)NcxEuJBX#xf6n9AbY#|M)`ZxUvb{7dh^W z?Rx;kGMw}AJ-vc_he4dcB0mWt!Fwx3H4u{)yBZEOyoU{dL5hf~Ez;Uz3lY}2HBfkh z2)ej7?$Gnz*NkHhwJ{`+NAM-U$YO`s3hr|p_qp~xaKJKjg!4Uvy!Z~d$Y&8kxlOK% z6)hqKfItT*D_EWr^i1xyMgs?p3k9CNOoFCUt)?HBrk0C)jS*sOg1VG7Gp&F$-SB0C zH?KuAZb1mlp)^ZVq8<&fVpX9cXI9LHyf{GFSjWBHhtijJ%#LWORQNEuNfx{cZUrxM zr;ryoGiS4fc^_#84jeh8W=8a1JEH$4+CL@C!ykuwke>staomik#*X&|&{=GWB*jCr zQ{gJwF}pkNGc)-+$sDlU_O=616U8iv&4n$P7a24U@_F!pwTi`&mH2&QsYN0KGR>0_ zxGh|-Pqf(nqwcIptrze-OHSd?z;n{TV#}N2OMuR(RTKsa5{koU-vye zCd~hZpRQBOkKv(Kx0acVmH=Ko?;Fjy8_!65LfzSK%SJBvaJ|US?CrOfGg z$Lrb1OU5Wq&{V3~ZY}m?aInx5Wwp|Tlo1RR^n^8%*fThAqz1DCnKOE@tw2i8a4IDP zUt`@JU&|=xOFqrW2-k{ni0VWpiy>wV{LMeQqYkb~l5T#$>M<2Q2t?+NgaZ<@nY{zu zK<8s_q3CA5^mwIae8n5kjZQS9Ci6>dIE$v6Gw7TK-N-jWH;L?)R2#s29}sh5qxtuV z&v2WJ!1 zL$!NX6wDu+kjxXbN_=^6{9i1E`%B@)!dEDq*>gnoXDGa?VE#=BJ$%NEuo2mJ*mL-B zf-kT$yl|MeQmZ|d#vOgFJ2;m!im?*?j<#SCerRk1(3Thz||M@oPi5i zB@rX;!YLcBB=o_RoIk(R)q_|^Q?*u-8BW{`_kCM9ByeG@|5BNbppR;mk%Fk;emXVA z*a8*wDbY zjNzXI^9GPrad`1LCUqM%<6-_n4nqdDf$ZhO;NYWmxR(~3gj$el+l4ubROftUw;jV3Z7qvEB|<3Z{G(kqjUDE zg?MDmL}|76+@nxGNp&5>TE%beF2BZ};BS`Q#nA8Y%ly@7G3~FC3;HI z?boz^U*kvki+pz>ewnAq2QqI9j|SK0jIRkrWbBLW!3tf;+5%X%4v#jW{*|MAsGUw? zV_@J3o54|nL%{fIfO$H+3fT_^C zun5iDtY?bxLVu)xIq2SUJ$$P{&sJW5>*s7-gN8W<95Lcw?|^$VLux|>52^|lcB%j_ zZK*&FV8;r`GPJgm%&Wd4+LYJ~eJUOm_b65AMTc0aR(JHj*@4hetOn|9>cw2CLNY1Q zD#q;?1xvRXw|7W8xsR_z{WUg79nWLJZ$5Da5s7Xt!x=8X(-XWz;pxEL)asHIMD0+| z*f;E&I?QJbg(F`XeN5xb`&?qm-`FKcfp7FiZcc~`J%oD9o;FmcD5!cKB2?&)`71T< zyc|M*3iIA5A5xgNvplyj`y(D+R0609v$ygnq6*#`H((X?2WZg$wiovMsL=H;3r*si zz}C?F$o^T13@}cK9R}B2 z`4I8_D2rMSHo{?&mOTwZvh$So+pN2UUf40{ZC_w@s1b?1%{#2xJ}4iq=Y5NVXSt$n z%^tXZ2EWo`WjY(f!}+_t{Wf@A0!Q9wFhfyT=9CB<`=4v$Fe+!n| zfk0tI@LLFJtWPBu&DaC@-@44=?T;kSwC62e4h4P$T1_2>urIirtT~ubEcXhEs11&Z z4CO>I8REuzx}Fen8k&qG$Yy~6V*dCkyfGC>Gi-a9BK{cJPtwf3b%-yl&a7fh4Eeh2 z4e2|!Wac$!^IqZ)3>FU2GKw*t2-ooMZP)uDza+!M?&53cjS6_AlB(LyDLVxLrAgSU zdq)`-1g=fOzTe4ZM?=Xc;oy%Ft=i45g68%vC0 zPF~;}g~H+*5l-Jbod~`k-|~<6SR&V@;m9RN7$UU;wO^_^k@n@EF5dZSETaei7|Lw9n_;BKXGbJ=))s28-q z9-!WWx{p}M(%r~s>E=yRtEgyE)-r{&lj_^xDsL`*c~+OvL`CR+SPJF^koW=ob!*sZLWq$Fn^w4YK3`^+!ARead+9ZdmnCvft)2RY zJ<^cfYgio&6O51a)v_7DbgWe3i+b}WI5dN1Q2PdUOzd4mt=h*nrOkhmLqpVJXi_m- z!Uw>bG$~GY1aDeDGO!)uw|`T`vshemmeHQbB_ZaULz~ppsE9u+2pdSDR-KJvq)q&W zi{EhS_x?y3j-WGel7Q$#aY>YMmrH!x1vJ_wNV@>cVVN49AJSCxUA??j7+h%19iuj$ z&F53gRJHM^>LLCne6EZ|Hrn)evGjn6BzD^HOg!6O2>&xkf%BLBbm5`(Q&60Lyw7sn z=h*icFd2;i$keEn@?vHQPLGo>!AJH@267vN-qxwH#JV6>3%`^?_NcgXUsnvHMg^{5 zVHhK0XfIJ{KRzykcBw%{His$F z@YM8*g?8=AuF?5$~<2lsMMO`Wf~w47RwYIex+U6+)bI83CPhA#8mA> z2e#@BUjT6EZV{+H2-Fo%sBuasd}2;uoWPs4mIqh_Y{UzyD2nS;5b~@hm3#_rU#h$U z4PQVUE*CKMWaJrNuAHe2U!ryS$sXwqUjhmo8e0lNX=o(LDcoSTjnCEOQ%@GN<~boV z%3~6LZ+J1`%7ZZ2AkURAjjapl=t4c8)9J8|4atJl%NUpb?fUHYqRU)JPx-uh(L-q3Ioh0Byzu6Itj+Vw z_qT5JHv9;PzQeblpW}6XcZD&w$2oz0rDv`cMB>+Uts2{z7+QR zz~>5^!}P5^hcPLH>!6w(p|{tQ80+yBN3!+;;jXY4`evz948iLzV(4*x2%-cjs<|tF zKsmVAzo?2U<$wi?D5;gp;!CV=^UYqLD{g>_s8)_Ka04`lW!)HQ=Qmk`Yu9_71ea|B zAvK%lnzm!PDMM6-F4cEb8EdszvTF?N{FoDDaD}Revg_a>~su8F;S?7g6oz>+EXEG9BzEK(>Sn%=tTg=H3+I64#MLfI|l)}x;&FG!O8?dKTcd2;}Ow~^uIFxjFYGD)+~C|p&3oV znI&u0MDkR7s*Bn8<)YA$1jVZB^KYCQx$XE3c`M(fzO<8I%nm|T^ zJQ2eW!%++$=f)!*5;hZDvZ&e}ZDh$ZH26?7zQq2!uWE69qD8*`BjX zFhs3dUpCT;Keq^5+Yp1W7fKf>+N-{c5O$FaLPyd5RdOuCuDG;o!dCT=u&>-2B~>tp zfL)a4EBK zO=u5&$j=PoEY$qFT*w%z=zyLG4(y4dJ78gc8^R{FcGKUXOlePq_VnrryHm>ijqc~` ztul6#qY(KsJ|0KjYjt;^wl7g~pR!jGxw9RX;?~f){O$||MuuEQYIRdikH^0QPRBo$ zr@Qd)O{XV#@p)nLK5xV4sfEcudK*4VFHGJYIvp!?rkTfHpjaP%antE8yhYiap^xc9 zTxY-SbrRlQdlKI6#M=)-i}?0w`>pRdHq`4lFU;z~e0!Juw%}+&H1_BO{M+Yf z{NpJGYIQT?Vc(BT zz(1F}@Q>9ra&3K?>Py~?deiwyUwq<_`L!<{0&86Sp@W-qNi-lM@QDu&2_r3khs78B z-t5E|EFseV)^8(BAvJW8_FKEfVv30cF^Ex!-C7T(U1JV;-^mmU&9h^CWv+P>ev!S( zX?BwymA~vHO26p*D~5a8pNJyx6@$r8AkMtN+^=LP`wyoC*oZ;1al{CcESv%Poq!`! zMH0}N1P6t=Nzf$QeqanKZTLHCv405SDQDQCD}mj>M>ct>YXE&{jm z5%=!Co)2V}?tWN`03LG`?8~Mt)vlmBRn>5w9>g5deI5%N$Xjj*^E7HGsgj^P46)L2?y76s{=xwBorz`-Nz3eu2uKPy~hy4*b zj}aL7*Nx!tyuD?8nNNc@(4v(HP3$g}H9gPl1c8lBPxSw=DTMz&rx`)O6ys0*N`@7Q zbnI=Lz$>OyECA0G)jI!p&nXB0Xj)hCiZoQXsEE$+=j8W7%d{+NdO?mF;d-+}xV=^9 z6mCf0fhrwdSN>1{0$=70?}zn1!}oXJWrBV515XJDqu4Cf{yQcRbm*|i+MJvm?n>`0o39feEivN=(i8If)J{K1+j1u=8e(oO3&*9G*FQ0qL)aS#Wbx7n?e*RydYCZh<82S9iCiS^W z<>ncwK0p2`4yV<65|N5tuo}5Z=Z)#VLZLr{e3Z{f368bDC27VO*cypAN@8OLJgzu= z3olYJ#4Da;rIhxRC)L-e&jlN~AR+%$ln(a6vQjz^3MRvatE~J7&VwPOz|#<_iGaIy zh~R1dpB)_~q~@#GCd9Apj(X&p%@)0`8mf5NN(?yW{hd`T3idb->e6{M`K> zMww_1%IBW_mmCvkHeAXs081E8(6i-MVehOiyU%(}v6osHp@Z1$W9KS}3=G`%XMq?Y`JNHV#?fZGr>-rs8=7f2He{Ja$h5C^A++GvXicICLX)4L+DH zZ)}7Q=bL2p=8D12s7MSquzY?7T)|(-gvfO?5yoWz8Qo! z=Im8qw8gMD?X@>vBl4ZiCZ>kqj@K3)UuxBxrI73G)aR#Bpm@1Nh;NyrieT73fZF&S?4XNQl6t03} zG0yycgv||PCJuWBx{!tZm1w;w=s;jp``X+)75>oZ6j%v>0dyrb04>}-#%TCnlMqza_KRver+b(6J8CuUm>p3g?*EfBI|97bg zXQfTo(7afW+sRonr>d$wG}iQpdDjXcYg`yv9mjk6@GkL1jUuc=Ndw<>oVlZ*3!G%5 zk*2>}IEli?^kJRrx2gq{YGlIo58I*U`RVAi6Xoj~Q2paJ%A@PYvf@vSw~Q%WspctR z_=VFu4ZKLJABT6*$pS(#C%pekh7*I;bQ91bU zG5EZNAO0U}X9J&AS^xhHxn(Hxo(eh@bmr9ILk-0O!yGpCUJjiP*)+{rT2xdhn@k1S z+y>m;95A&ar6ThIlT4EY%W?w(e8@meNmEHv&)w)3W8T-fY0L&ADY(o zVBiBMbMRqKW!8Q)$bK{qiqFbCe9)dM4YNa^W{IYS9SRPiz*I$`(-ncXN>yu67Pd$Z zVk-?Zv_A*iJqN;e*e$u(nzWzy3Bz^@(L=gCgKa;1`G1G+7k>F)vp-vf1%YjbozdpzjwxrmjKhACGr#gF>#z%c524 zQ;2ON|4*;L>Q`8iTQWr!xFWRI$p5T?PF+(?k>)eaG1T&Pf^7hSf~^5lHF)30o6E)( zcm<<93Q!_dfY9}LgY%h5VL8*@r!hUu4jk{(tD4sBiX3l6yu+YzdUL(0agX-S8>sN^ z{R^ijL00zJJb}wVpFI7i9EarUPrpu3!zV8*wnY^bfiPU&PNTMjZufzB?bXeWQ z&5Wca*&0~7kwc1av+b@=dN&hn)uUp;WO}>OHEN!9Cu;}k{Q{MmQC;YMHa7Rk|GwS*~ zViwQhFz{UxGw~3_JlVAv@0OzJUtat1xx3P@5&wmLov=A8H~sZ%#QW;k2|)cH>sRSu^!m&zgV3wA zKfQkS;QueZO8*Ob#h%+0y-MGgUNNBVPp|mg+nxQymn&^dJb|Z>5)&DoCA+9!4bs$- z@bl(z70Dp|h*SE zHd|#--N#|=FF@dAX9F_MfSUq&{ZH^A7!!K`1wJ1WBB|1<{||hcSG*rS7V!3d5eeTUzvPo0VT8TH)yGP2b-yF8{(ENM!L za8HNt2B|NIvm~OV4EP=YK#s%hj703)R1WA zDA3IpN+#_P?*{u}b5GBcXllwaq-fJ)i;}fm?rXNH8=+#oHM3%*6nx*L>do~s^1ezR z1Tzu4S@fKOONc7i5__X26GBcaK)-}3l zXN8|H%|Q(#2)b@FG!2Jn zU7>X@-IPQnzinn80Jfrw+|xf@YHpC!#2VOVBY>2kSrx$_q3vhv~f^I0oWK$^6ue4KVeKU_-w2O?tg)y&vO2 z@fTPp-xMD=%$Z8j_?O$jO&ZY6cdllBn8Y*Uvyq4T)98Qc?6SmL1V1Hdz^aisRV`6awf(Djm(@O02mN%B+u8bKI!of3SbATj^rcu2}&mzY~az=sBfYj~zy9 z?27S`<*p8|!8$ya{9tO#U7Li^73Ezov|P=x;3RHJZ~vF{lEDabon_)0HnfPFFgZ)Q znQsTEr$Q2smNrW%aP`S6%2K1IP&2Dv`E@{gv+dGHl}bj0U-(59mh`Xf6;=S5EeR93 zuck{qUcU#cbvA`^;wkLa24}CnEd$fOb(IL6T<)9?_Ub69gczCX*cb zB~=PnUF(bu82HFh@qmV~FG7#WKQu_o(QUW&g9QLr5&*a@)I= zEqgIZnz3yJ1G_RS#!-H~D>z&%K2NKY>e!rctj+P7o;x$R?$Ec`qK=`H6=q-SgVDQ5 z*{9Yqm2RHx!i*>_6-JP#$)3)Zr7PZGxB(oUPJJLsLfXQ!2}Hx!{7F zbx@mS76f`;XZ|s8QU$OQ;z&X&)MkxI19U(WqD@k0a&;g3b*nIMXi{GQs1q<{UW3s* z(2{ZFqKQuE%qv7jhe&kwZyMNqH6fvga@35tg$qe@sQMb!oS?E|Vg^jYH;LbW6k~t{m76FjA&r4`gmQ8fVWaH> zTD1p2qMjC~riTcX75f@06W@!^Ge;Ig2AxnRztOO6RgO4UiI7lJjEROkA%Y18?KIfp zxCVq`2aDraD|qN*!r2K0QG@h>3M#NKu2SG9OqJ0zn+3186iHsZy0x#B7On|f4BYU; z%h21pY_w6(AG)expxkQGb?Xo~K_0{&{in;mv)_cw1oW#A5CA5bpb!ps8idslSorW= zbboKj_P}TW?2o}%@;{&A{y2JYq{%omv7O(we6hEh@E!XTRrRV7U5IKtY=kp zQ>}^;DFEu=oDrp3t~@>w3~;`oF!cuavr=_P0Z)7V1=yC-eFX+ci|a`voiZ-40F?nM4>}N zRj=L#d+&cjpOnakb#@7LjVzyC*1lu&Pm(L+UGM6V-o0kTq(6MZzh)BfPJEJc9j&-b zUZMZK(#>gi>dwNGLQ&Y0jnl!2hY z8Y}Rv1iRQI*Q8q@AGf_7REEoell>~QjJx%2d(!(_@yAVvy`T&%FLr+E0ONU{2gcBn z@Vh?G0UA;WCJZtMgOD~D^R>H$`}5k_vkb#Mq-Eb#GC%qAFzCJf_CPu@6E`&vWq9qC zL=xo{b4f8S*Nar?Pj%suBU1S6v+wxvxL<@jmLfiiG7N)!`MC!9sg`}f9oRpyCFc#J zB04nZF3ogk6(hUe2E(s#&;NDxR0zC8 zj%WS6;QCqwS43q)U#*qQn_R{qfypP64-l#EY9Lb2a{u!1iO;(Egyud;K02yT}Ow>l>wgzII*TD?jL8pZpO3O@j)^1EerG zkOt0!xBATFK`iqe3PFJsg48?CR$y9~v@~Be59p81ERZ+qrwV7UsK)R&n+~JHcBat? z0>CiEm(!z2V~z|Rtd^DxDi2rH4}ec60@7XL8Vh1ieAUbQVOKdh1v!bZ5#Nx5s~)fW zzE5jE$Zajx9tX9ROI`ml>GEA$Og5Igz&7w#gv*j|*uGM%ZH;BTw1=0n7?LLaC4z@7 zJEqMlVa7HwV_UdzgE}u?gC{bFFG%fcw@`{H-+5V`i*Fa;4(8tb+{>taXc(T9 z^WKcFX(zk04s>=eW zzph!QJJ~ZRk&^8A*bHcWryHd(C7|l1R+ZDm^lqxdD;3G5SbDnhTuFI0>|8kUaAD-_ zP?f}IDxpgY>g&IsO!4NSXboO*)C*t73r<{3w6lJ4NsMMvvBkeZWV%~UqVM_e7e(jd zd`8EHJtIatS_;~M84Wx^>{_b;Lm6Iqn^+AnT37(Sf|UXv{|@aV?AXt5*c7WBi}6LD zR<28b`TppfLG5wulPj2!pDL}@h3eoLW-&b0@6K*kvO+Iv^dgaClfOxOy^A9&nQbq~ ztpE6$%-vw?Km76og^&kQ4x-XX6aQa^MjZS_6m%lveXnAIl06+;=J4X8cY5YP=XmEe zJnYy$C*JuLZv4YfLt-`dMbeXv;oH6{ zzKOzgKHTBCppBhHEW*ScE`~>PiR)A6RbJGwV@~rm+%&zj+CclZmVsRU&gwS7DUe#A zT{J!!Nn^okhp2Jdf%t+ch#k`^Fchw+V`K}39`}o&UE{sWI9zq9T4sSsD)|_JGAi7c zKA3;#weG7ZovubbYrh8`OPZT1ip*B$e!D*3@`zdeS8{-xz<8AlgPU zM^}bB{xS%S&YYP`qf*tGrBP)DOu(ORgwk6~va)&|J7V#!HAKnr&L8PJKdd8X^Hasn zyl=ja%m^TvJqj=PI$6LdD#MV9P26E=(pIPvqxF?EffxaXVu^^8 z!KjyKES;j2|@$0BENWUVGZY9wAG z*{EFC8xRs9odg)jR;+fbkF$2(lyR*-A*!fHbFdsGa1p_Im6Ni{rV7GOGgPeBjA_P| z3elxTe6Cj6M)gy>%)AQju@=F3>Bb!5 zOx0nAgpxpaKF|><%%tq+Oj=E{8U!QzpE}Srd}N_SBaabvCl&@~Q2N^MTqvfFzEgY#`L}P#;WJ@h zO^MF7$~>u~=T4K0dy-LCp2=ZVyCLEsv>Fzr;?Gl^u##mxu!bjarxtD@&y zhP!mgZp{bgBHlJE5Ajs&_ropuu~8QgFu`rQA#BVq*N;Irgdfc>5ybAeorcAkixv&c znP*mHIP>DI5ogYNG@mms@16%B^})V-t++VTy*SI6_1zGs$nAHPitX+Y8CHPEqP+TU z2xB{b=5x@(P`6~g@Mu2S)^TI09#uaj4 z(-mR0$~K!njH1I#>|mJ~;R=DuEQS%?bQ6{=c7X%X5`U_SRYHj>x^*QOSgLFLT4B5< zOfP_k1abZI$?>^bYYz{bgjZuC&_57Z{hfH{CRs9dlZLxc;MroWJYdX5dszOMA5tKJ z04m6h?!ZUvpnu*b2tczu+`|t4P%WGTG=FWbiHuhaO)f1VwNL#Z14Y(=W{m-ecmidTmS8+;Kxd8o!5u+n4Kp=!h^4QZB3S?KDE zNU`p_*#XwjyHS8z$P?b0d3dYQGbpV$!1TeK=$)H>l8U{zn;F19UGR3IiT?UY5h~>A zl2{9NiWp`OX`HXzbio*MIA%Cbj6 z8S_ETchnp8gh4*$*SaJdD^g=-xH46gDW?o#yg{UDAbthZo0~lmhZ%e#;)zj#w1)D?tzY1Xcp;Z`HLZjjk|@Zl&d6o$hxz}#oqizU z(~uJM15r^JEB&zj@N@J-5pYI7R%G8(F?a*}d#GAb)4t^Ks@8b!?x!WT`rxqWUAl?d#=Sl6g)}3t1<`4g zRgGqGi2oW^1dvyE_k=ib-oS*oae1D?jIfqVgbRcyP?#@Lwm@NSEfP=1EYQUi<`h?E zAca}k15vv26sFckoTf0Xxe9Ys{+mc)rkxj2W_VPXTpF?6mX5Q=e);;(kqrER*OT8au-Ol(gheQKTUoN zE$?c5wC&c_u@$+WhFb!L>7+Z_%tR`@4N6Bm8-t!vOhOZ7;kzWu902@GWT3z**=(Sk zi84&Mac-y?cPE7spp;WmXtyV$9xG@}a2PmTG#}khqm<|D5HysjVGZxBJrkNlwjq77 znI<`ti5q5KoXH?ifsugLln_#D;ZJUkz%_c|^_>;TPYcjULDyBZ=vdpjCOlvp9ebq{ zDuzmg34%YUb|Sn+l?A0|ut}xQeLFJ9Q{F=vpZlJp+;^MGsxJ+6 z4bEfEcSYnePtoH>^O$%h0j|Hio?B2F{zma?Vb3svKT>>Zksg0GaIjD9{i%BsfuNV4 zh+gLAzB@Di^^nZ#D(D|}cOcgHAmBL>XP$h==W4Img8m?)D{~rO5YxM$^eeyG9q8%Y z7kA`PwSqU>jNZI?j6hx#d5F%xk=2z>t1S*K#{(JG1$TB?VIR{jQe&P|b z9Zs(;;Wi7bXhoYXyUYhIi_XvbkgF`~xZZs4!m4ugF4{fy@U=D3{n@8WPJ_~J; z^<(Hq@jsL;hqBEaO{-LUY4taOn^Ugs4VD5a0;jL}V3{3H*Bw}sSL7M1&D3TT0)SI6~ zZ!EJaw5U5_5bJd+^ZF!-l3v3CzO{az`X=0!g_q%d^rBp`Z<_$jjdXKuO9sMl%N%5I z&wLrom%q!9zY6i*&7V>ORgyrasuT&7aEe;usnM=P2;r=(Tcd9}m}tWsjqTfQDCJ#U zcu5I)1mJKb!bafeo$CZKul@Mk-y&wfkRyL;tw}J@L$MT7%Vg}^91dcEve9T?v z$$}dxwO42(*-5Co%c`?o4#@b!#T9ObyD4pDhm4OiA8-H5w~czp&~V^)L!ZArxwCUo6JF1gZVvt2DM{}ivi*#==6Zp4Z=%lHmQM*P3GP!-0n74+GiD=fI)5zR;N)5tQJJr5G`cudX$cW?ac(wEy-X>_e}is z;w+$Q1@8!|Jb2=B_i*ypB$ygy|8N90e&f9=jkIcRy8&iq!bp9Q;-+S?`V)!N$*$8O zuro1II5HR5Dgj%8g#%dji`Cbh?18~s=z^nW=rQphvp=TuUyj!KFJ_U(Zc6C%q0F%= zJJiF$NDnR)CY_)e+`TKqd#{CDf6QfKe+LyLFhq(4IS_mdSU}b- ze_a@de|XI_P zl)k>o+oV&k&ap{Yz8W{QU;67G$R@SS76hkf>`_AAG*!BkmwsJOCeF2inKo-l1se&HEz)CMs;8`WWncWxGWf>D3`zAD2|Z?Vc^bt^?ADz9iQBod(z-G;?{;EB{~ zY$|aIY(%o8N1I zKq8Gu;+GVI$Hx6baY5;ETvD-VG(;|j(a=$Q>pATAaYPU+vV!m$Gs^rAV!z&(!-Hsk zu>CKt`WWq(seQs_{X^3hLGNq0)%;GF>Uqc7vNd53t52*%@1MipUPY}B^tTsdq`Cd( z2pXyMX^rV?_(tw55p%!j^eH8&*uqorBpXW1x{ zR;S;>)tSS3H@(tsIcs8bdb!<7cBNx~wQ!9rP5M}#hpA@NVO^%voTm@*xxW@m^XJzG zv8jn+@B;(#@{Ak`RKr`| zde6(PmuVi+uzKHO872-gfeskZw@%Jja9U9}=_LyIZW7z=8WgUZgqu@0={N3u71qsW z4It*~CgGc?(Y)hyy9r7w@0HoI5fR@%f$<3#-;n7k@v-Q6%PdEP3CtSEH~DSRoAlMj zFSGieFrf9}rJ2_!>a|lx$~d?wp*s+RqT%7{E(NgPac=CA)_{yxs+ z$HDn)YXt}Bqma*RO1!h#v^XizNBX>z%Zy--dTydn(L^BybXWqDJ=0tArPsMMrs*>3 zRqwhwgpyHb#VS80zj7qDL1lA_g~Nq`%-aC*uFbv9w?C#HvKoI-)j&3$tKCe9Zfe|3 zw>IKs>~oJRnVz&dvFdkD1)fMGpH95P;S+yl2a54Gvc+e0V$Uc5Xh>x}K!vzjE&anEUHoqs1mThiBE1UAI2q})g*Sg4f<5h2xI9?#YL4*C^WLuITJ5^Di2junpbb6mPP1&$?ajXVzueTaUS?2#i#> z9V(VrP<7aAtKXHZam@7If!>OBN#T+kVhXR^Y%JaRoG#Y*uywUV6UX+pg>SfL@)p!< z6V**z!uO8-m*y%GWi+b+?%A!e%W#RpWl}!-H z)l~Kuk{;=gsghtCqO>aG{hxS3cHnOCY>R(;pyfM${h3BhN$EnKGLgs6-H>{jAxYJg z4_1daG@AGUS=VIByI-08Qxnx%nV71nuwvLCXLWpemV^YQx6O~CB7&f!8#(e&Wc7hw zQ=6MVa)6YgeQS|~F}d7rvJynsSxlGxOtIJqkL8WauLdxUYzE)&l0CdzT zTFQn9h6j8lJJ8` zhuuMjPRqqyP!zpW;4{_2JJ(k4GY-+xORavruFHMBD1#Aw@61{Y?uC{95(Sv~^7&Kt zcTqn4=9f`{0nR_rdfW?$eUU8_7Re?8>^>GF}#k zca*S|eGNmH;a8jf)fetJl%JcHT1@fWS#l*F;xZ@}F8&`$I0_?(fwOejD|BT`e-yar z>l?~3C1X4OOs|Xe3Fqc~t|PR<3;gGF15E^DAtgD-SfA4=+s{5PeZhTxtc^MP)@@__ z0}DUD+CD$bfBtJJYqE5j`@Fc{=P&%t0iS98Li_wL3ta1$xzDG#&zIOxVQ%Y73P11N zBH-`vpYQ2De~E|Ser#(F?wX(%UR?P3zwGlb`p?x(ji6LPzklM(PpK1 z&AuZW6=3Qn7nsy3?CjpT(O9qa?CS zJJ^IJULxrb{f>gFx`*fR^t2c4^S=j?eTn_G#swPgbKC0o(N~;6^Z7#iyyY8wy080m zdG^!W`+vGH`{}vv(=mLy;ZKm`CeEi>7uzx4Z*b`ta>0fq%8?!dZQ4DZ@z4Aq856;E^Fr*QIWpM%EV5} zd@T#Ko-*l=yEjk26xFLYKh>L8#920`&wF!|-Xz_dpXI%|T5mK_iEnfU!pEh$8vioUkWT?3+RRod3-|EmLOaOxE zeYm$$#4izRVlzLSBmO9cR3iQ{Coe7{Dsc~AJI+0uj62T%`iHvX~sZ=SvYI1ST-55xZ0Xd#T(Xqwxgo{y9!(G)=K`OwPY1AlC0 z<|c;^u+Y5*=-J3R+OghfUWF5L2M*-SP-}KhuRMH*$pV?f1}0cby$`T=^v}XE0((&U zUUfdStq`m(|0-CkBHDt3H1Lcdhirh6b3Q|O@(s~Ds71S~r$d`3+<7U^_GXc&fIhc5 ze)gx2=3^Lva`yMmZo5r{V;lKvg77))BD`_1ZMP*2gaBo-O6B3-zY{I<_uFnyaydC$ zU+IcG%p`|G(xt-Jaq8*G;&vYVS6%u3^g3ukL=)r_5y;(Zy)TvbuA>LqM;7RkxzdCQl>VJx<23kf`c;3o|s{a4ryp^B76v2;S zlK;aci9-0L1*8iJMwlQfHK>8p^r*62SpfIJZKN z&rh9EMP`P(1f|i<2J~`M{N|p{M_c-zJP~M*AMo-C8W$KDZY|e%;p%+?wOh^qzhS4G zZvKCm|5qiFGSjy6fQ6@;VSk%_VqI*LcTh>60ujPTFMu5X^g5NL2e}i!pY5;IsT+Jh z+YLhf?jj1sJ3pbKBr;aNQ@_xoRsCS1xl08~-_&fOC=o9wxju!N%UHSKK+`kR{co$AaV{bH=Dag>csi4 zu9(()e@;cJtZfZff5g41;ElNop6U0m9J0;a0+T4j$}t@pyY zIW$s&78hT^-TPp)5no8`|16%C4M1KFWivwm>-xFK}uQ(zaSU zkF2Yv{CY(X#{BbY5AV^r@Rm7vPv;6x1#cpPx52@?pfw-f?hgpBD<^obxyZ3VZ2_;2 zo1fRNc1<^WR3Fbc=zf|~L|Jr<{EeRc8&%Af%X;$|jJfS9kI@C^r>PDPw?T#E|Ehe_TfH9u30KbK-y@;6 z`jh?!gHyYW+2SX_@GdeK^JcRreN`^V+Z@Q3WkGI=NN;tSz|3vQhkA=X`T$V7a)P?~ z0!Ml^2h{QcK#2X0{c>L9K--S+4)jRd9AOZH5X6dh`MUJ(MZy#FU2|3rYeIp{z?N2E zr%Hd(th{&&!_1{4E99+F{%C(6v?VCL>_}IM_+1j7_P7n=3Tjpk9-o1(9HPt6&LPB?#Y5?p74O!wrDXWV_{wepn6t^^Wr@7=-|wJe`tRlH z&w!TxA&{&V47#a`Zrl@Ktq^NMou6uuJ1PNI4Tcy;3gu(8tf(~OFSUmzX(JJ<`Dmj$R;#{5|aq`;w$L|L+|)XN)6v2q6Y~g zbjhzKy)UJWL{M86gH9SH!cuE$LGcESQ=eBk+J#Aqbtq8A2wze73vvn~aE%(_I@-kS ztY5nsoyMdJt0_ZzFdSpe0%}G4!33gEQ_P7fC5hq8rVv4?ra~!I_VzPFT{4-IN7LpNUj9gX0%Z(S@*lFKc8O$7cL`KOb#8C87I>pA_UgxjGi zzUb3>7&PoA4Tm+4#upxMPcABn#UET@n;CXIIV9S|ohhKryLCJ{v}S&D<;l$WKWd3~ zo|ApBu9gDJ{YSgGMzF*NQ4L2!&w5vK_V8iuI)o$s;6;@u&nNA>gH53Cm9)@vTV|NN zq#dBNq#40Ka`-f%r)(rZeaE{XO}wp6w;`hwkOTmusq>U%MA};*$qvTe57?tfQ0k zGKd}cy%-N=`Sil%^sWy%!%A3TeFia0_VAE(GLvKv2+<@RH9I&QT+* zF#jE^U7W?r9+rfg4jmY)y5E}d&$L~7uWc>|!luuMTHDcTSEC1t7`}Rbe%n#}<@ zZ1r~|2%;XZJWag^qOdEtcC8Wd#RS^R{}~rkU?1s0%Rbh~-V>(lANDi6oFPokHL;5c z=VP;vnsI2N=ar#})CibZTUO%C1;ioZj3)4fCqH1AliLbc6uJ4G79?Yz{ORezs1rwu z5z!<;88?yGGvKAn(rg5!S}z*ZP;MK03Zsu^?0z0TSADp^cOkzOlEv`1t9JD9ql6kU zd>JS5o72e(KAdqLdHrS0=a@i!R4}b@e2J>6sj4KLy)v@E{DgKY*`X1n%T)8vbM57S zSKrA0t(v%R-hR%$zMLzUA>hKDV3K@C*p2!D!^!+}wmzqDltGMBzZJhp=`d(v-KzrowJ= zohGNI_j8&R`mo%^FqrKL@dwWt`S$7|&B)2S#aFVe*V*r7PR8hXrC7@mK)!~_iR6H4 z)yEV>9XfcT<36V==F`=W%)Y8R6%p4V3*cw`v976z*bm=*vLmRB*fD0JRmw*58<|$OMi3KYT^TjIu;BN`XD` zh}pf@J_!k#V(y|+LZ4A;Kbk+t@BIpX?{5h!M`OuV^yldBzSXm=yy4z9y7=d3STW)s z=S`Qp=pl%%vA;gzCWM6J{zwQw|K&rwLqA+#s`L$eCBdXKVUYn+%6Wq^MDtTfMa5-!Iaf0rj%(@&5=UJZi4)4)}l8~OBGbbKp%{CEqO$6U|Ue;7% zyE#)7R$8+hAPo`fljC>e(!kM$`gxv?Fyu;-c()Ovss&p9P{rwqK6juZJKgL|AB9~Y zpK$a4iXuu|M{8T7fd)BOubba6(hPEL;gzZ=`WlUIQXo2&SyOpbBEJ5$m)|Rxc|>$@ zoPJAw9y3fM@$%_f&d)j|lJD3s`&9B4MA=+%Z0a9!M!H~#GAATHM>SkdC;O=udLa>u z=z_+6@^D`JQ6Ai9>WtFlEG$Oky3v60%GbVDI%(ETdJwU_B;2n~8fG}Vrh30aOBE61 z87YfAj*L+`RTYKPHaOTTnE!a0gI?TzC2ag4FQppP20<@!zc`_|qVO5YnISg_Qmjf-loGLJXwZ^gGI1LXAfKFlt1k z8Hgm|+D~90Ka!ay7MZ&o`=)qh8os4UzO+KVv_f*tfk&D6pm`!c6gg;@VQf600HX?a zu;49`#N<2?Sp+HTgq)W;em?(ESS^^Y&4hLaQ;xmutSpnr+W5siC8EOC>2iN`Ij8E1 z$#vIYzzHzGhU_r@vP#K+EgrT+NbDLELhhy`W9;|VPN>U z7)ChwYl#p>PJX)^7xpR2)UEFp26e^VlRJxQg+smfm~{~@qbYXkxTkcg?+p~K2jI{k zicFbz+I+W#=Tjy=77so`vr|%>`sPk~tq;CXTsQHV_#)eK&!beIyuGrG4>E46=T#i^ z_yg*LX$OGI38M{{w_8SXcH99absgO$b$zSrldq;_-s_Xc;A!Ng4zHELi`FJY8%KKB zf)kGTDHD7>A#}WhK(F@+&U$3cP{Q>IlHOZ5llX)yhk@fUt{?BmWpO(?vbZALzNgrx zqze*WEp|<)51Md>QTv`2!3p&TO4U)jDK#{7WTqL48)#~F7fw{Pj213!v4 zoJvNN|GRZg#k|Y;f};wqzCy6)$lH{$8(ae9<>5J@gvnWjJfxH886#`nUWY*JtC(i} zIw#UEb?zQtd97OgWOe%+YP7a^y&8WkN%I<8w{<07IJUVJRfiIz~X!G|ghN)ep;)Ls(8rEsJ^ zI0wO59baUV;&`}B4+#UNyHE}rQXh;t<(@bXNAF#mI{b}`_u->ydzYNr^%qG_{oW;s zj&(>506dkRnUNe>mfp!O7$sVB6-N|Nh$T5u3^i3kBfxbGA?H+%`NL1*oGQ%Ci0LA> zhQDR!fQeWgUn=M-!rvRc3k0PBL2)!6q=hJTvQd&XJ-w%#0xg7>mdNlZ+5plmf-H#_ z=DyAD&CdFv~bEUOvvoUI2>Ih^oV5J}nHbljb8G-cOLhxzE0ZCT2WH zrs*1tI>?q8kpcO~M;+n7Itoh`cuO-vrn5;D36Ej(#7KXtF36HF7qyeL+|=IBn2yOaOL8! z%N8q0JFL_OS2A$m9Sz_YPIi`LBdyw2is3^)a`DT$33{Z>gTp)R5!z{wn8Vf=-jw&~ zeuV|eN#=2#^_9n+V|5o;CxoGmim~HuTIS@fMfz-80eiyouL^0wW_g2>` zokE7Su%KU3VTgJIU+Yizi`^}3W~2n|(!2Z+WrO&kVv>2iRuI&rs+j2c)q2pHUZ;-kAyQd{`HGhkkor&$fz?^f@l9gdnDbtr4wbQ;<{2_qz!M&Pl z)C(z$iCuW?d9MFm(P;`(UzLQT6*@&h=2Eqm1>|{Vp+`Zc*sdV6 zpvX#J#KQ{qUU(u{J&n?T!g+>2{Jsfe$q!88vjjNuKEKid2!M3w;BH})al$Oe z)fgS2R4x*4%SUOLuUd9`YL*2n3d_Ch<$1p2K_OaU>^Ss^qv><>$<{AuSY&|wpNmHs zz1M7FQ-z_uktz@vf0acp(hAsuX-84sPJ5Bfbo_Kv!N=^a)gMe63$e^KbG0o z_zuq!+3cPws=C!r*?%bK=* zw2OER?>&M2$Yl`w+&PkGae>yW4ppN;?E32>yR8?z+OomzY#y0%N-Db5kfFMBGFw+70m0dU7 z@$P>4fSx#5`3Ny4E82$BImFm~m*0dlSvjA+9t)eRk3ntae3z`K78BaHZWqcpcQc8B zzxvpMSIDSKGdSl^!_li$mTk; zPUcHYjE^D*^P7}cv=c!ir&I9B_{=9BiT1U^O(Vib*y3SzT0pFghllb%&tunS`HVM~ z^4&OeU_S4$%#`o2W1#81M$=q_mzD2;L9`V(HluRr~}KAojRKl#0gV=Yj$`adNo48jLIbs*~(H8&Mh<*Q&5PL~3 zvHQnYKE510CfT>;YcAL-ZvJe3;uF_;lJcH2ImGKc+$z!5(TUX1O_3kF?R(CFHi*ED zxek}rBE7GLuYAj(JmW@PsCojZ_Wl@TkDQR}ST&)Hhc~xG6v#w7hxX;HLPAflXV#~tTRccq&}~S`GWiAKE>`oErU*&%X-@YyT66;p?r{A)gTnRnI z(eEEu_JeQEzXqn?J3llDEqg!s;&a{X>|OL3_H8*Q($AWF{Y)Gu;M@PKByMq!rEnkB z=?wcM#@cX1j!1;-7UnA9ZxG{}yy&*Vp&0Lv;*y;Mqd3x`chi+zmsyelrs%VC5Lu9zpH}BeTjSY-@H`>J;uJkt)x-qlEZ@1ti*LMmwPwyug zm+u&uY%jWu#@mNNwoNkK1@wAD=oidylXiD#ozXq^lJymxt{b;~H%@p8V$=WTa-a?B zJvQ15HF`fx@mX8r2Jbfi(H*o$2&g=Ac5d4xZ|civZX3gQ{IZaQymB~%(N=lPDt%>2 zf~C)!+eX`^+j84xd<@5zX*-CO{eAG);hPl@;a|J z*;|s?^|x(~vJQ|{&I`GWQX#oH6(&__WRhWko>!QxY&nJ+HN`)SB&n^bBHVPBPHbk4 zlxR$Wid1d!PcH*K5pHBPYy`xg zgG0q`^=G3=SBouk*q^!BZrgmPKSbYrej6DqFgPS`*_D@xb<%Nj1W% z>1^r#e7wUp1n7BXx75h}C80q8}FCWSuHq^Odg(hc7_Q zN>K2slrF;W+U#AFX$XwO1O!OE+69_oMJQ~O2HLEqOenlZy(gt7wxZsGB5!zg^MG1D zHy6v=5sLHFMqDDY@tU0n~+rm5m#(vFYK>W$BPMZa_w0DJ4_CLcH2_kEDqeP7|fziR)sohLT$)3)ID#R(q06GCiBG1BWzhDvpWzZYWL$SCr4|^JGSrFY;9Dj4Lo*Rw-qT|ZSLa1A5Z!VZHcxt>&$h&1&>0wRbl zyWDXrfy-}lN_xWI2acD2YT1Ku-F|4-{kW?9c)_2aYnvJla(*sc-bkzZQ_LVK=&x0) zCTF!ubVXtmHQX%$4oV-I??N!qMnbTiD?17!V5|I-HoN+~93Hn@zb9^t2cJ<5sRN{X ztyDQ@s@SOSHRx>hrREU$*;Lr^m3_~Nv^jF^$0P-Gjt#iHHVf@yy$YC+8p&f{x2;Xe zw1eK=klP;mDCrtZXgKmBiZLVoS>OQmh-Vs#(vT6lh(~LBjD>)a04Ew0epvI#oFj|d zmKs137%w|A@g3W>kfKfXJMou%`GNC{h=C^rN`J|kS?<)*A0upgJg3i-EnYklX?fb& z;;j7*(0xg-&By%Hp3sdgQ^cR-^2)`=X?Hb)-07x3B0Z~kr9VkeH~0Oe=bDo}KPcTA zmFB)J=YD?9y>hWuBd9LpUNWWc(2RTE@|uCRlvo*V%A%Wc-GsL+ajH_G?@Tn-_ozl@ zy(fYtz9#lE8P~@Ity8tfbi~Ps7fWouMm?WfepCw>SFo{WUGn);$GvdsxWAk_?r)mo zx6vwHVgnGh^Xn_;Xl~zjd-$-k#|T$7P1i%gZl2dEMyaEw`qc6DyxYRFdbZ-JN9aO# zU#9yu-3KT2{6h;NnNuS-U5{NW3-5i};l?;M)9IUMDUO{ZF|cMcqPD~hI-pA%tlAX@ zV_nC(ihA@)a8C&?Db^e>A*cy~HC!hrd+L&Gj*hc>sV?~kNt%(5>YcCaOPs%Q(D0ZPFXu( zBm|glifR(0a8jpg8Q1wL3n?SAJ92kAys1*(SV!iO5`Ek-p`Ol6y*e^?=|M31oU>Au zICCe@6gD3?9dz_JrRy)vRa1y^cM}Vz^7PdBgVQR9@b6`n#dSS@DVZ{StGKQYw3NVI zT~R)ccV0@;z)vHsQkkSCa9##GnFVzp52mCJt4}^Zx$hZqvP>%^eoKPF*b0BoH{}|L zzeWRSRBa7AS};)*=G7%P*CjVG?=Ok7eo{=_0w$3)POmY}`JoZIvbV(_ykP&1S6Lpm zQ}*R1CZpZGODPE%uD<_|DsU9E^_5fxHYw@;0 z*I?9?sBX!$)X|=sWPIq3sP6Se6qdRlVx<+WE^w+yG>VD4*`b7Rm4!<-MqdGuvOtSm zwCBSQK$wXto&!dOf#VN+#{DZc0i zRR)nGRM)(yjDoT#0FYD|=J$v9wkh^(5g>5w#JGmZ)Br9C2b@ z@}d)24VYsj>XVPvC)d;`pS3NoZ6;@iOAt4FVt)mQZjdRF6zMxXUN9`Y*S~EOK#1Qm zt}-JAsK-c%2!Y;t%+0;{ERJtOma^Dc(qL94hOS=IM(Koxi(lT+r-`Oj@?O>I+AzPE z#qCt=8p=ivOKDIfFQI`5fQYPV>pTTx#(qZf%M{fNYfOI8FG~QZr&|$L(xyT-*QU!v z8Gl`y>0{(5f7WUpoS^jC^Hn8=ZE(LMD_s%(?j=>Lv=&%Ux38^T(H=jXHgvi@n1a%i z|K_WOWKPp;*5(qwN0aR3h}$ChUauX>iqeO=z;UR33V#NND7=BaFGbRd^jDO{$Z5Y( zq8U?)pjCXA|K1YtmK`NoMn!-ok6k5huKd&tCAz`<*mdVtdb7D3GF*2$OjJ}1xz)}H zs`Y{_9qR$X{5XJp_EIO)g+FNV3h~=>KcGT9{K9|=VMkJ>VlO@9hJ1xm6hH#>@9lAh zdpA#T+@t?hAstY*Z?V2;U%QmcnzK^pJzs)PzHtA^c(S^Vo%=Oku7w-hC@bR=-bL29 zK6M#JhmLHCc(TQ+@jVoHAleQZcu2G(do4qzdedXKYdr>)U--NeLh5aEW+@Z7%c%W# z&85eS>?>!8?8(iEyw@Qn@i{e^u3i$EcVOC1oZzi{eeokb+!Z%)d_{n^9Ane`vd0mP$`p6 zAc)x6zd!Jm&X^MR@}BNvn2DFD?=?|_RhBoxHd|1s? z%aw;`NEWQop!5*m9w}c&=9Ia0Q+id0NdZm6HX%#*YnzA_DIzPdvKRhAI$bu`$fIwN@j(6eEy`#}zXor&75O6)| z-H5c|&$ZkXMvzh$$5C^E$C8VQkIz0dk%C*z8uPl2(SjZE&V;O2M>m5TYbY@5Ww30o z6qbGzGuMCs{(T0G4^)EE@6_#1Q3yO`hzsA_cu$tjP(tx#L{g)=kJNhXc-Jqa9NN}# zZ#H%X<*Nw{GOBVm)6!iAU3du_Z~!fdald4Xo>Wjb2F{O@u0sxs!aINAh>GCB)v8~z zCQ9GKB0-XzT(y3(_LxS`V=v!cQpCzEwnXrf(@=(26(3G7AU;i$iwj{0t*EaeTVGi! z_UaMZqV8-v7u2oU_u22{WJv9-Jw#o;B@&(31=mR`1y|r-n;P80CjG*>Tw8nw)Jmu7 z<55%EC@zQ%voFEy-o+wTWTc~fiC2a8wbBqgg)>{i+?org?ja^QTJ+v$(w31(zzGxf z-h=PUr6-_~xQ^wgi_;LuLTLjyxo5Vz^r>9ULsO#WW>t@W=+-q4Q7a%Ut{*P2sHgWKOu#dov)#8P5iX0q?bvT62BC`MljyfHGBksf z42$}9GCy}m#&^g7nBzS&@Ca@df}Oxztk=oWk<~VHVFV_pGUS_s#_J!xSvC`(i``~ z6hRxQaK@s+QTrcgsT_V8+C4QpYM4k;%7{Y$^8~&(DeQViz6XJQuqJnE*$ILrh<&%- zOK~8r7stZNXERLl;kJ9e^u2mFH z`!_t%S-PI21@wGf_4b>;l`wj?^DaZGf3iqfq&iomfF3ojhoUEk#ySlh@{7nD>jnem^YvFSVxK4Gy0Kq6Fd-f_^LdT z)>#%L{QSS5gc845;o`1<9^I;aKzcM^lA%S&8e-9c{bn+>$l!I*4(Tg>@dBM75_%>tnj=MrO^v8y=10@Cv4pbruq9daRv@@AGfe8 zf~$-GuJ@fhYUI*`=I(Rx(n1$6$^EPIw87wVSKoP(0g1CHbg{oK^H=K#V4P%b877VP z@rrjHrYe;-*PM&@6h+}DwpgjN_jkKokBoO&=JP47@;pz`q0XaAUBUlX=QbTl zFs1J{KP&&C08t5SsbzWiuLH8(oFTm{RT1**l0Mn#Y}tfXc+dTgmW<{x8%jmIP~thI z=n5|!74RX~`NC$brlUjguCo;vL}erq_=y@fMP@dDZA_m)0Xi`uP+KQvgOG1uyOGP9 z@Zv8>;{9uA;-%BSP9$OWPkftHCPOYy(V_s%?=;0clW8|KWl=r+->?jab3J)n@Qg5$O=0u*>dFP?8&P`Yf~2;zy?ki zRUX5_WDU4%(KqbfBzXzT?#mI&RlL!kWTe~fxX+al7092Ewn34N%8G07!*gw9vGEu= zaeN@>bLY=;T3Q^{PD@Lp``ngPV1SlXR-DsoHRgUtTdgl~kW75M`EY@gNHA}N9UU)$ zhmc%cZcHTC>D5%*eaHoc*-STmj_@1%=L+L0HMT{KC2g;lW6bv)?NQ0%yK52Ld2fU| za5xdXXaEu9kX_Bvaw1r>D-nFY$&BvPb{R|(!^%r{C8&eR_n_5%`+qU<4TM?+{_7r* zr~e*FqB&Wn4b2QTqK2PY8_|HU@Eq}=TGm-iVYcgqGSeDT;}Eqt{h=DTJB_%d!|$PF zCWGf?#o@tdi5!2y89S;GrJ<$2t;x33{GHzWRUHx#RTuv5pWvacLF9%C@UbZxdFN-V zxmMzgGt>yCNz*DpY~OL+q(*LyWqZ#jKHmov!4xi!!O)`td4*5#9&pwNYU%Kzv$bLp#puT9_iM zJC_*^1`ElhAz65q+ShsTm=&vXXs5pA3fM+?qbvKK5_T9|joeJ^A*XeX3AT|bliGzC z*;ztZ#0kExq|5!XgNZaTikqnmM*41scwQ791yGLXh4c>l{sA{n%nPxy{0wRx`iGCA9HWdySGl|2PigF=UBK$t=D zt_OI`>`FEr-WiY24fM;7&**S>2gWq+`e4@yxl<>;7d5of{pdl z(aL4MoohG2$WB`@G~tRw4|d2`{PR&)d%4($V_ILh9dZ$wSA-l9 zZSq!yA|32%4bDX`^C_GDh_ib|UKavdg zTnZFE@JK|Pj_td}JFPzG?O2Pr+?085VG6=+Lat9+Gp_&}YuD3!fLS{MSICxJT8DGG zU7HxLtYl$9`b$=LUZyB*AhQ3NJe`IoGUBE+t33~fogVlP0K>*yJa;A2>Rq8a%p%H> z>D3GvdIpo~Sc(-IjDHE_Fr2X=;s^9@$`}*TyD{?$S~UF!^p0l`$e}l&4nXg}{3dFi zHVjwOd{gp>_NKoB;`%IucRBR#*fA2b?uyvG^Bl?4A)RErURj zK=O~zMWUz{Gw~la^SihbvzB&%) zb$x2+I|@@5qwD(9{ZhNr6r}Fv!>6#Bz6LZ^fN{5AO#O|njmDahkHsH6@a;9l&9!=+ zaQ(V`do9?SUrzldu#T02ngxzyZSU=7)DbOgn8o@M;Pd3D~?7|x%JpDQa7(z;phq%Ibc7+ zhkR+|$j74%#G@@A)ijSAL<6c6etZ=L2VrbLBrnBu4Cd7S)92yO&$WKiJ$4!FYctIo z9*S(^`3~^6=_}$#Rm=)j?NTy z(iJ(Y4;FZiiD0upVK93Ar}PcyzD~#ETbd1$*Wd8@%Pq3x?OWv*3iFrYpV+rgR=z@g zMANTwb%ViOX{eMm#c9pBx5xF>CAUpMvGIgWa_Zey;ltKDkpoG{Euw4d;=!r%FsZ%e z^knwxQx`DD@gfCp&&E3rwU?F5ckw2P@_2)S32M@m2^n6k2}@`WB&)+B z8a5_pYnwl zrWC&_{N-jeA2huB2YJW>#TH&^y+)T-_az3#9)6dH?=g2ks>39Yc&Dvx7dB*NQE3gV zb1KfFpQ|!37qa5PQoGhuj4B!kmDZ$A+HW|+d3`MqWrcHp%$}{sWKW+G%%CbCRCMdh zeuNy5Y@)6j%2L;@8cL3*zZVUsYh3Axtr`RoGzKtm>a*VK*`j@1<1her^GY4?*=!rg z%NtaLPpptW3^1=0I@oR;0w-^}YkpW$od)w9N_jF-C=ThhbUMT3Q{)9Q{R`0~ z5!CN%HMFMhz~O{RD-vGsN)n68Ybr|IX4h!3Kz^z>?05we@E)DKD3j!_IrgBlvJug8 zDTvR;A$|K+HwEDoD4lb#hGx9lP*i~G zFRMz~tmp()4Lcfi4aV=A=y-2vd|{C)>UggtzHn2i-Ic``-sbKq;tOZEyPEjITHUq3 z*GA>>MXxD;5}a`9VY}1%_{#ss+qb|+QJw84kcEJRU6epX&_yE#6dNo`u%JOBPH>|^ zQ6t3~{Vb)5Z3+oQ1r1Grtjh>mTdmbf`&n=GS~aK@C4k&iM6e1f7q!J1;{~yD74mnh=A8HbzUMtREAJyU@r97oz_!n&ti=(ZV)8tl_T@HpEe;JG zacp!fP}NDFJ6(weBQb>NXm%=EsfGD-7gS_~XbEoM$`43$A;700+{iGgmT?EoDq`Rg zTEI$DW21DB?zrZVXh*njlKOp1eQ=~YZ3W}Fv0H#Dl* z%ER4L`Q!AD5Pw{%e`NE=W&FV}mosiRXXKA#D6bZYU{C|zV@SX+R?$aT|1kqDLXR!5 z>IBx3%S-h6o+LCivoaoD0!(`o0zI{3g6WIXY;s9+#SKG+D>9@|lte!zF5ReJveSa? znzrZtrg=06UyJW-n_3HkN+19wR_7RZ#&NbZ0tJM!kd^=o(s_=t(|byXfIZ%; zwx#BYt(Ty~8G;3tz(=nIbrrxTaqbYh(OTm&@AAcM1OSkJr=vb8BVpF6cV(p^I0q7TRxy2feL zS9IiQ)TivmVbr*PS4w;C2FT_3nlUOiCDi<79q51dHh6#Q6k5EJ3Ng)0HO#DAvc@cXL$|hJ!LD(DYGn zX{;O?p$6Eiy|LM^;9{`#WRas2`{Fx?!b$#fUVV~sggvNQj*xwfz!&=T z3Vyj9iFfqsSafucK+T=rbT?+;ww{jsls_x;-t`Ah3(haV5(1KesBV>#=k z2wDOva0)nN)&AaHD3C2P;t;4>l?=hybe@{v9=>$uRkF3yiE*6$x$wBeL`{J7!@;Z! z81m>9a9sy*P^ZHi<^^b5yc-j%G!{`A`nt`}_!HplC%_>cm8Ia$aem*Wejm78EqV&! zP?v0xkihy=)C!YqtGIM;D+ld&F!K`&*sROx&Hj=J3XE!YX|PtB@zS9B9+w8Z?nFdL zCxk$Q22F!Cq(Pn&Y100aKXf`C8XRqTXi&v;kxPSfy)+Ot780lh7Is1`x%xd-dw+in77O4uZhT7p>9pUwd`|3|Ua1TJx9EbZ5cn7%Yca)G3T0nCc zD-26ag+&n?uvXj=UtvfJ$5$9aa!Sy$0U7_*tK?@-$aKGhmr^Vsg(wPHk2ov-u%g1@ zCA0^ZUCVBaWx@Gb;zw0RjPKPFS_EE0*ThC%cd!RyRej1toKo0qn$!9Udj#QQIrF4P z<`YZ?m!e07zi?$pc*||d92>~3;YYFA)iuRb>QzE0Du3Ap%$TVFE6#cqWG%3Q<$Gao zbQm^kIioYIte_Tai6Mk*jzmD8t&1J{O*tHK}$FS(#1~y@Vg$UG-4g&n!jqIdQ28qb!HOi3kZk{`gaju(0_ci+IX~s zl`-Vg9rt6&vTI;vIAc>$(#uJe!mRXws#MoYSGqf?5@pD~Nmcs5>269=B}$xqsj4*1>8>oP62~8Q zAuEB(GK7Q%UktjOo~HyLM9U7k6 z;w_7QkmEdr;YaL&yd1H^h(#B&ao9~~WkCHNoJ&0wHq{vy+by^{#Cl^So3p-MkI{G? z9$afU`$5c-e0@Ib!x$xC@U3{Jk5R?on=)*eFRKkSxGXC^1kJ*@Ue@%3(@L``-hpo( zP?4l^y9jzRtbRz~P@X6zSkj_y5j~mxC7wB0$N@ziJLG*5y!@#Z{J;>`d`|VSawXft zjUmOX1X+cH*Xs>1O2phYws7s2JYE;B{aVFZvp)#lzKPGw%R6u&hD6>{eajD60H^t! zD2hBaP|wK3Q3V`(j=bUz#AJpJAP|aVSeJApCVUMF3)kVS-jar7<*j}KW)WK>iqzMa ze^Mb$HuF~-B&5-_;5}EZ7-ezU6;7C%{jTs=X2Gw(B#t=BYIHXIo8a6@Qs#`l_!Pq= zQE`@@i_(ah6^ul)uoW#(3eY+JR7?O?8P+`=6cdCfJU|CEtxs;F5bM~kibxg1ab==! zJp_j7zfaA1#{`g_xR8rfb%%jofQIj!UWrH~h}RhxA`+re30eK5>kqw{dy~p{qPU{RmC=JsO4ozxUu~m^# zm`cxTUkI?{0T-sSZ-{!R4k;3<_XO^Y!|_TA(WhS+CwKzqcTOK{WMZ9u0=b{eP(mt5 zy5zR!k$R_{si}8#I{ZkuaSM|Pr=bOMXk8O-5@R^6-XhC(can1DaCU`}{*y?^soR~Z zi5g~R$snB-`T7BF)0Y)bJpJ5lMys_GxqvDas zYz)pliB$(Kqa2qT<_qe`)2(ufL+e{cbL-hgJ&bq%J#v4qUIWQl{@J}~Ma;1P1GjB4 z@4q6eJCi8@rjlM$!UOOc_G(km{8scDBMxUVa@wm5a%)<-N4G=xGlyDC_4&YywRS~bTN z(gpz{K~5nDescP=Hsy45s+@Kb$TU5;OAU&E(-|enBB$6vcEMzh6$qXEcM9;YhG_w= zz-4+V>hD!h3h;04PZVG;CaP^M!x2hsuC$EU~el9j4z?VT6h@7)b9yKUjlJ555fJpkY8lSq4!%2MMx0Y~6I9A`CPR$w-As z>k`tt*q%mx#v1P_{4_^?)khIp69X1d0HT8CQ2ji z2F`DcI9&_P3GLxB@ei6NE@M3?czUoYEW*pLgBr0YCfCvZE`v>1Yzp zl_JOP5u32J_uf%$z>`C&NE_g5Bjb= z*+crW+Rq)2IeYKcF(<%(gzYoab~X;bLf|=9T1QZGAptW3)1BX2k^n6h{56{B&rpCq z{Fn>qI4_`5T>yRl(nLV(7B>z( zDi&&88Vw;tM_Uk!yR^KF?}_zJ!3L-$9O*KHWtkfqItCX_K}f03o1Aq}h3`K@r6I5- zFY6^P_vvFx7&{N&9W-NjI}$sBZjQza>&M383iho0(&+2P?oFdw*Wk(eNdLDZnVYCJ zNRYu0Fbf{C9wjXy1!3UMS|%85x(PRX^8C!X%qOp0sStm!p))Rw8^fzTFD@LVj)gxj z^KIPixt^Db@&ebnIIJk6Y#k&ep>syLC+h@EeL;q}PLu_+h=%Tx!9JZLv{Egq6c35&Ii?EA3h2TL(F3}Wtr!yb z2bRubF=H_lms1C=3G0=wuOxsN<1)N=26HHf{2_jJzJ#4G1^j{;5Nwsd89tntBCLd+ zIdD@vk-ZIdkjTcpc=HRjAjj7Xb-pVe!#^pm9?vm`;rO16w%iy=Mo8In&k=Np?g z6GNIo-gm@-nK_*rP&bN`U}HId_>`PN#uZ}*Y0;btx<4lwA|C1RrZB@<>SAO!bd2Tx z4DXP$x3esIE|{-e7L8@0)K~Jy-$n8}P%>HNU)J#_jPgeLJpFWe?9QF9-=S?Y7%w$J zD3}(EBBd2)?G#q1;5Vh5A{jxs#d0X;4n8+?raj0g5p!s7oKIKT2%d~zgR|`4Ytq}N;aSrh6 zKprO*(~w^vh1%+oWcqhVkO0Z#w~hu7HR30u##wh$3LJqmv2IuDmjIh-uOo{(nfe_a zssz&dW;I1c^G);CzJvh?HN`0)VXReB6)a?XPKhH9u*Mm9ZfEgTGtl>cDOOqS=76(H znFBuOU-2ApPvn5_9RXVD*6ow9a0RW+;WM@-a1;ZMmJcb2O4%{g*?c4FfsPPQ+5;&2 zLh?u{`^w)c?NtFNybcPWeGfN5doC7M6WRiDnFOTWvffy!#Dt#4X|v_!T}$hN4JY9Rgdg@@ z>T}3y`wli?23|N*OZ@|K=@;T!Hi`ZkG7NQUs*@_}SYefNI zbNmHAU^x8+$EmpX5#8U@y1y56e@k?KtN01U5-mL3{-9yj#OX@xVA*7Rla&whz;5Lp z-0c;)Q-lFBKR|YETcg-j$hQi}u1XEaB!1%jgCn%^KzUUWSx~AczoaurucHplMQUgi zIO9`xswQWcyRJoR1PCqO;Ayc+I%A8w!7^$M{GE7FZ8NN2N{d$G%NV2l4_AMB_pi%& z5#1O<)qg&T@p7eM@(0fgfrU*fzRy^PDf`P|mqu5f(sD z#qd^U>$VupEgg9f>ozo|qh;I!DbX@ywl*(f7R$n%3Zz#MD(}7Zbi=#}nYUVm$w#?i za&1V0Hm=7;d@4nl(VtD`%q+g-A;xWE=yD8O|DwW6VUI;tJH5D3ojq zq&78f6Ky(1Y17S0n-EsXy7c{e%Z}{Fb+l-Xgi_KJT4`D1!4J4qfCg20YBVqdn?lTU zf!~f>$71mq@T&rTeKIh<;)g>roVOi~zQkbXnHe z_e?zih><__%O@?fW}m2W|FEla`zqDMv5_Q2l|4CbURvDeZ57;)Qn+6txJO^N$I`ce zOcim)oU}rbEFjP@rap|HzeSLT4$_P&zCKtS zg|_V%?Xo9bJ4^d1?K1=+?U-)jy`7fXlju6_LT~myG zYrP+-t0^Mt<;J7zsv0p9hg8S_AOfl2_Vf6uH%9U^Gtj4n-VgqjL#u*;?9dFSn1cSH#-!qz&$ zKI94wLBgzvh@@Wa6>j00xZ2wkfv}Vr@+D!g85q|wPM{)1ppWMH6X=RU#d8l1N3#D) zBi2Qrw?~S4@(Gc#PsLB`+~+{gSD-WP((`0RPhgC_42&lxk@>(K%X~01k8}kWL1hp? zSY2da-5k3a=#(&B-Gg*C1KaOX$f}?otHCp@P0h;eK*%_3N1#;4x(L6R_8^%j!AVwO zx(Jco%hxGAM6V2uKv)3N$G}QhF=Q$+5Wf-b*MDSpPCh}wkbBWB>Y;)GagV?cDyyu) zCv^%$gZwB*K$T$)SgJs*P;_k*MC*&cfvQ|J|DNcDS~D zO3pagu)cUDQPyP(0TtH_T!X_m9g|q8H2y1nU|zCG{MjjD5*Kn19#eD|$rQT7FXUdP zkL|a_1K~vV1i`(SK`U5HaxC&!%+P`FeyeA0) z3mZoiKR{Ejm>kBWaT0K|j)pAnBD<&g1v?(S#XM4ru9Z86Y{3?l}nEYT-Tue4R0WsMEiS=q{ z%J}uqWOIuBLF6HlfLjK|@WBuCeAI&!grArJJ@`BZD)rkcjrvu+_yi8iF;q~p>`xS} z6M_+If1J}{Mbett3i3Sm2vg-4p)U$V^EwfkQ8YDid8d8<5n#`wZGrjX9{^J*G=V|R zhAd}T7{LiMa1$kuCMhCxA-K1^W!5u~?{95+Dv>;i?FZ*DUF=7nD3pPH^kyFgx{qRZ zZCy80^(aCMw;5f?Hc%2@*_K^1kf1^~P|gtsmQss|z;lWznv_7qV>Wq-cp{rK1OK}( zg@}a>{&M-qNkYWtzk-N;+qc(;gfFrpLQ{qBO*7Ks8#p|C%QyPq`|REne2cki1$0a{ z4=+e!!+QI%cJYP1)cbekWFG(hyYyBT2p*qY#+dyU$v5*Tx$+_gJK)xRYK17Kwd%XG zwD}XP9K%|H*w8*|@dE_oj%zfbAc~J*`i%?S*!~VORK;|aVwY7Irk2`6)zoz%SV*{V zPG-hbtV@wa8P)ldViS(dl9Ua)Cy*SwST{>A&VF;opk_&PSg94FH#ihbf3j!9dm;Hm z-cKNTT&*&6j=sC5r#K=vwhOGhRj~!87Bm;{3+OjW$C5j9()o-y%)n39sOrl4_eVAB zszr%r*4g5qcQKlQwYwcAJ4Lj&6|?;LyiVmY;t-yAco2Rj!74`@K&UX65H4;~5Q4W{ zn-3a2BKYYoux8*C4}_|S5H{8MLwKsrv;;E$Nn+^jaY#unL92t=vKe@PR~+XTq%*d7 zZ5u6qs4@#QG()ad@+2o~G&}$v1{WDw!9`fP?ug@tVEtS?r;W*6*MM@|@C^~2Onx_i zk`;^OWy9`Z0a{)bXC9WIesZ5zP(=)yWS6qI3my5_QWokI#|pl6I3}}gWY_bz_zS>b zNy1pYdWbHWfxRCoIcQ`{kORhIS`OC#+iBIA`C`Kpbi-f_3F11&cO>y(eeoCAxB>(m zjvI^nN7y$@#e+Fq#fQr&*eBvaiT_Of8M`8kb;XGJFvqx%6^8$)2Bzx-8YcN2GYUv+ z1I8|_jU94lFgul8gTZ8J0oJpJcziEshUgU42+zqg@$InHpnYVaQY^?uv9oY0j#TRh zjw^xaL6&4_!q5rTrSozcKX`b_ki*y=EL7`50f#0U-pNL!HJdErI%Ksb5oQp#Q1_0$ zt`-QvhDV?R4KTYL3t$&#tlzTLh`g}HlsDSwaZ!~(W+I#FSXrg<#0+?1g*>VvSA<)J zSL`7r!q#9%AmQ49HwXn$g^bs+Dn(YNee@5=H+J+xMfzH^A5;s$fHbObpFeH@CgGe0 zq-QhI1O0egG5dBUaKIlKJ?kkw`amn_4V)ksMbv07#x7H~tybDJ16PZ{CDh{F=wpLP zQ!O62+5*5L72s&x8?yaDw`%70LmT!w8Lm-AbV?_%YgxFam@~yUtde*(M-e)jZ9mAm zLKIS-xL7wPHo4{-G&vL1T=sN{^*fR6d{6^UWZPFeO~~6nN_=}B-#%MvFot9%!VK)b zj-fM=8+jwQgj!8l*Ji(s;X`t~mrw5d#KSn1Ll4Qrn6SYaew)a{`aL+qPt*y!6>6ZO z64No5OH9<6Ij75w42YxO_>;$6!toSmGf5K5DOo9m8ieuSK3PQp-U<6H>5V{I7IKjC}>$uNQxDi36h8cs1>qq&^LmJU|Ov?9$=tlZs6{`Zas0c z<6{z0va0_C3cd#cx=92TfduW=3oM4QQ z^Wj=AIir0&5=Sf6jiir3?M9{wqcd5fdod1I9p9U>UO`S*V!c7@l z-n)MesWjvco&g7(*8LX)y+Wj>Hh z`y+++H!gQ+|3qAr9onBf-AntNV?4CK)fMH5k0j7uMA;gPFoO6q-l@4+Qv!U&O)rq` zFmW$XN`nQTxVUI+@8||hywVnRHfF66df-F|92d+0y8e?&qss=qsi_7t>ZML}L(9k5 z1vz0fNfaoPkDRmc(ehG4*XXN`9>m5Jc&l~gAHn==hxyQnB>vx}_>V3p0|w{={oFiz;Q1!4skYHI^FU;PKzG$jtgNo-76WLzf1dZth+G>2b!aj~24|E^h^! zy6*Ht=e8KGDp$MTA05(cAjL?+Ne`C?v(U?9TddoRRs z8HdeO)b>ERlL~_EBgxmUGlnSIWLIT@8m6h=#vb?Uk~JRjW}k zn6F7~YIueYU12b-2k!&pF7hzW-=4igj8e`&E_R#)l{Y8YaEH{|)4k?svXJ&HLm7+& zBi8>zjp7S`NLD0;Vqvq3;t6pS9Yy+hsu#uOy*-Nbt*c1=oJ&I!jF@A;;^0^h{sH(0 zlad3e^1G0O+j_tC4m^=A!9~uNxh|1z&i`RtA(6=N4VZl6rmYxOBvip{>4aqPsrN}N z%)4#mGlm`Y+bPrAM5ZBfSQkUOLR?|uFo_RwTeVn;TRA1RLW^6}j*DA4r6$|zHC5Xa ziW>;nO>*bi*6qE7YO>exacNv8TbPoGgIh*BTZJhPzjAS+f%)RE{J|Wez%+A;HfceBOCJi6tjp)W z;tG11OwNJ+V$nsH_f~lY{R5SjP`Z4a)TS;E{j&msy1elo$nv==^_gUUe@M2pufH9G zbDtru^?N$F!Cglc+!YzYSH!#-am|58tk|gW`|555gy1L9hzjn0w%En*)Oy!eIf{IA z0)G3C@+fkK)Fyu8blm7fBRazO0#d&x3o$|co|17It9;Vu!^d1R@ zA;~NHWC{Y#@l+ccCI!e7?l~g;yS4Khi_5uVf08^vc(PVW{Ob zYt`>456ZSBz(4Jh)L6fmfDs8pq?_Nwh=i~lIWN=VbOE0gXbE-02jEu-{EC)YSD?F= zyZ!w~K-teq(hD;J{Da17CGE#$YQZKoR%}>Z-A&VPc5lk;qny;i?bp&hR;kk_O`^}N zGH~1-4KJ@Cnqow`#0mtEQK9uD_miLlxt)dK0AGZ1A!OqDMT}eAd0)p60}%{pmsiRm zdTwL#jB+d|+?P51d@iYgywv=_88{qA-isZ;#NTh1 z)bGfIQhJRCi(5X1j2jRbccev`O8csrbNL2^y!GXs$p%nGG812L4dAT}DF!g_dN1wv zb@wRrSgB2gzC_1?G=OF~76I+UDbzh_;lz7mmq4q1G5%QZ-wDD#??iG+`klaJS#mti z>}aYDfWjvPGe-vJ>hV5C{%Xp8&yh7}v+ZPa0htY1oj-Jx01{x`cyO1PVUZ{3yJILI zHOH>kgnJ%Kh1s0c@uUR?FLDVNkgO(@H|`m?{@hEr<{S^<-kU)(lW=`>bm^uAIGBKB zdm*XclUrR(LRKG-zX&TZ)Dn0gA{<^N)&`tyJ@+NYp7*`vIP*desvaP${&#?J6CB3* z+s|U!&sm?>QQBcbYiUAjndMT+P3RkqiR5ta+`?Y9{fXgt0#KuX>9?o(GBV4L$fr8M z(!kV-$`+A<;LP5bq943C3{Wpt#g{^SW>~dw0%R75!0a%rQ4vF|g{%ZaC+)(TN{z`U*#lSVEl_=u#A-7ID1-eRLA}HfuSb!O;laUeM)BP^2MOhtOxt!%w;I|S{2ljB3PB!8pIm;aB-mn&X9 zuJ~%|Pw-In;uW=%MBg>XwWtYM8^`4jGoq-9;e?nv{;sYUZa_zhqjrYm$D3X^lC{MDqcWA!#Gu@9^hAI)b-%EuE^XzJ$XG5-t zJTp|X)Dm!LEk!fHN}a=kM8eikNi1;Q-+EvlQn#%UbKF)rW0CrB9wd4895x*7wiPIC z1?h+v2x>iuJv01;)^UE8tL7r*OrJZD&l{~RSutsVvq@G>NBj`q7_~~8*LR6RgfslAYOEXlh49#BV`rF;V^%*=UT&@u@+6LU80c%8I_utWx$2$TO5Aa_cE%AB8XJr5Zg@>4<%x&S|GN6*U^%I z29zg|xeBV5g@S6SK~{-r)ABsY{t>j#DvUu7xh7cKdVXAMIOq9D{#dU^2q%s&3LtV! ze^RJbq*Hwq&2usE%J7UdC@9BZi#r8HWEDVqh9L{r(0!uLu-iOVPKF^|*AdHk>M1wk z8>Gjj@rdu5YrM|4q?5<_9*~_>q}~0$Q7v;AGU_&<+ZO`hK{pZKX(JJfKqn{D1@RBy zhTqbr=4ilVy$o}~$6+|;Vu}jP0BhEBMa$MGMjlUin@?;%IOiJ@sQvM8PR$tHl7yU9 zB;S}AJhgdRH+&EL8>d1}41TqW-#5zlQ&&yv$6q`zlJ$bW;XtpP;DiBA0dIfg?w0N~ zyyUA~_@WA6m`+@+h-ba5m)r?^WXODskbdZsZs2pfEVG2}!*c2L-u6l_?N?=aXkRI{ zN&Egf7)8Wrz19fY?|^J4$=5&A(Zei1h)^?YdPMO8o~n6UN32O-!ri{$1C(*8v0)ol zZxce8MHbrzWj< z0s;PYm6rf3J9-H4qSPhA1CkvYD118;uPX zsp3zCV{rd8h1U73O)B(Rpj41lcx4W# z(8a5QN%FukIP?RWH5r-(9fW!@_)Q!S;5IMuZkYd5m$X6(proh?$0Mc&qH1NXQ>qGu zmVl3q)h{oGgzP!0W}-7h8_w5!-*0})c^}rUqt4+}QonRN*iXBGSRxzI0QCwi)V~ty z63eN_2u1}QFB>wDC@(G3{&7Z)EfBg=db`lPFP_;qz zRpsPIg0m&FhwdlQn$%MC7<1LJRSJt6GUEqF0S{IxDN>^VwLMmQmFac=@a&#->+whBHW<-n*>K-9kEH}&u(e@gZr z|0bpU=Ep(qU+F%e1KMNB>d3C>Ls1Bit;jg_3#6`F$i~nyta|*)!1_JeH3sWLib>Jv zC{!iGaAI>T(C-nDb4d;MTZmQ)z=hDNA}moLFXbr-%lNA0Bcy_+>qW?61_%WO?9vQO zd^?^W3M)>0GhUks7b5li`h$%9tcG8M_FpB^o~ATOKHHH@&)x6koAB_Rff^Rb+_|Ki%c{*o<$pv6Os`Upr7 zd&BJl(@7YIU=X-wdUtFm1-kKET;SFhy^0`telsxg%@jpgqff#>TaurKNJyM<&OT9u zAKwDdIp|b@RucR_#_%2Xa}wphlJXBLr^kPkEtn{ky!yxM1Ug<~Jt$Z>!%P^8-)OX| z3~z4h9?FW7PIBfjlXF{7>sck`)fjHZb6fY}CmA9hp_t?{+#G?E#7C}6`q{m-4)5ZQ zQyJ+y14J1E=;=gcEE>8>sZP7WNL!l(H<^mSxwxQR0p0FGf&s`m;*MuF=qEXH#BiSe zc-ODVBa$7I3MWGTah@;a(yp78(+MyIdG#ccSUQ9=t{^|F3_wV%5gX`aTpa zB}sYlnsnkM7i>B*ar{=nZ+X`8VbnSDw_c{IRX;7ii@(}NC$GPjrW4CfX`0Cr``1tx zYxB*JzDAYW5&=w-zhUjzpJy~*66{Zx;M^BTfcib1+p|B}DfXv+PnVitT(w~hTHXW) zPx-qxO3Q9aHcD#c){hptMrra?avSuGTjeh<_8O(Pc6p4_SyG!usX*_8P)4b1lJO}~ z#^(sHt)k&MMLqB4XOu!TO0#YPZ68kx0TSptZAx45*QNRn-a^Asb4Y83_2o*%Y$%#U zl%uj^fioY7yKu+OtC-9X*`#h#?5t7P{?PJ~^%?dX*)@*AiNj--;BpRNM96CMTNb&ufeR!WN6nHy|)NOaiA-*GiZF${#0I+ui@+#D=JLVYC_PMDu3 z+k=sC5)r~NY4durq2ccZ=O2MDINkTk=d*Cy5X{+gwH|T6Tpp-{ni!+#&yak=PDoQu zBAbh3)vW+wSuhI&KYR5px00HLIAN$X8_YK_H&tY0zK>-~=Ni#a1NQkR zr;N2V;C3dJuC8AtD^%7In3yKntmUMnUK0x=VZEUDCm7Oi%R{l8Y3LQZEFu5mt3`wh zTTEfTdPF&`bKYaT5-56((oO>c+g5ohdo%-!SH%5~Se9&SOu3?zSfP-}gowk^Z$uf) zz*~z{L$zFBUWayusJ4FPX{%O=(7}uR+nT1@!r-l@FSB_I*+T4CBX${VoDu_dz>!QA z9j&F~Y1Tr{cHXN}UFYR-bnLt*<$;zLp0|Tj`{w_i56#ohlrRNZGd@~5&6dpTUr~gM0;d)+ix?~En5F22plCVV56Q(Sr*V6C zATRj|9RUL5a*!KKG|fQMQ;HIh9|Zh^*|Hh0N0=yX6yltE&g{wf|}pa_h(~+CF{zq(T5G zDEKmsz&p)x1mGmu@YNUiBe3a9-B6|UCgMmTbth6h#9I6}>JI$NIK7rmR1ZQ_oUIls zzj3#y9#LUJ7@BMs-Pd*8#^4I_T7=Dv$$;>&&yutHJzZse z+7Yro4RO{OMqF)FZs)N|9C|RfKCJ@T?-V_b>u)^%xs^np^*OyZ_dhj?$|S`NE0}3&MJ9mmvfV++AuGzI-!9RRmJMW>Y;JfmP&IuQ{=i3 zLPSZb;;;k$oRjKqSAFwa*O5e;PmZ|+aQ6r(dW^DA|A6(#y>U1tlZSUgy~40xuy}IJ z4i-)E+awkiqGIEjs$vl<7OPELlqkSbZasL5GOiU`*=62UXG+b$fLG$$szZrq&sS=Y z>;+G5p%_^uzXXe}N-(ua;}h^}n~GN(RlKT@dR$>@>Q7KsBEWb;9*33e=~3Mse{o^R zKg3>hgU-|Z2Hmx;TTCf)W_aB&w^Cl~s$M(7sXS6wR)a#=jr-14G71(swpd0Z^OP8Y z5le*jJ(2&^RfPiFgw~~u1jbw{=$qY57;#sAom3~M!DJB{jBT}>gF+WrXTp4t<$@PZ z6{PS2d=VheesKh|Kw*CmDj(dF%z49Q1REZfj-2HaxOW@}vc-N3!Q#v;PBbd!;(eTQ ztI#Qn)p0j44|gXpoZ}wlh@7Z_FkS>Ob(Bjm;d901NfraQjlAVG6_+yK!IS$kzojht>vw*l$F5%H`-63YM&_Pyb8ZAy=stdI}^Sb!R|rer4e z&D`Ny(_`h1DRd;BQI;*AQ{uIz`Ig6;?ifSCp!1k15ur+*v^0yn4tm+)zlPdAof2W@ zeEnAqQseb)f^=Yk3sOuv5s)V7Nb;$3y&&E3sRyJhU64MjX6p_}R_uBx?q%*IecZlE zJbAC^+vgC1$q-oNvnG*8U{B*hk_zfk$4@AM6ZVOk_Tg*jL*$<$h9x59dXXryM)M}} z!SGeV`7&ZObMN|!phL@I*SW~+Pz$|{EvNXXu3$3P69}z_?mAa9cfr<9XcL=49~79B zkO)gDB-Y!Sta#DUZW-B*5&2Q|#)M)yzn?EOE;FJXG_s;Xd`m$PpUi;Vi=75IVJg8w zc8pQkBlx_V-{HNX=W^H*?1X@Eo$OUW&p50~Vh`GQ1hRhu@Td^7ZY-8-EzLj&$wO1; zU|sS9L4!%5 zw?_FlbiUKj0^N|ohRStAdl$ta63dWn&Cv}Bk6`@33Q>oH|I`qzxI;ly!Gs_THsctaLG{aVGFiuIs zUmkFz;rg>g8luhiO*DZxLqW2;j#OwK)ZmN@A+yN>AzcTE5&KJ)ikm(m53Jw(45Z_1 ztxLKje=YjoN(fWp*+QYr^C$~8<(&C(Frxu^VAy@36CL^~DFxxmIT23@ z7Nk=~i~NQ$$*DX=HFXysDi*UMq=^iQhrqF%{GjaD%axDZWAV|l4z}~PkJvs0U-d`R z+o4L~UntL7X32-_;=@$>Yu#m?;gj-_`xHOWA3BwMI6a};srB=TpwvG#rIO_91e&q> z&jILUybb$UOp=!ieO?jnHafxpiB1p(oLFP@j;`U3b#xuZ-3eIUFG9m>t>pwZv)|(P zJHe!Fs2RZ$X~A0aQ%B^0D|js)iQ$CEmR^NPzYPqEVS5Z@vS@qgcFjQKel$o%SVxXf zg5?M!pcNu`Uo-=mmncP5gE@|=&`9U!;?h>Ar0uSe{?gX%BayZfe+n8d0S%Mr*HO_A zgr^pOenmt>Y2F{vncktpQ}N8)r#F!pYiiJjqkoI9b%+6+!hGJg{vp~s)!kx>>dD$D zi-3K#vG;ur(KesyXyat1jg=QE`Y0RSL(%8czs2dJwXqu1_S44Cw+ej%*MdIV66ga> z*75S4hY&C8{UdUrlMZ#<*%mk^6;nIIl=v*nI$^qA8*P1cgIX>S;%&q?Yagzvz=ES$ z`ZY>iw$&5ozw+W@R&5wVF2dbQ49L{Uv3%eLh0c3aPX`1Jitt0h1+T^3H#m>{4HX*+ z(Q3)gFuQ|DI@fn2LKv8@Dlw~3gGwUn&b9HGvB0LeNC}%`vr#&drL}5}fipsIPO+J% zjvj%x-T|!cB4)?{i#vD1SL%&wfWGJ%i62x)El&~OIB6ttCOAo2hi(|y2|WORp7q+< zWWRc1bD@m)b!+$4T8izJ5CIk`LPKIdKSm)7!znt>K9JU~6L395S?<;Y(U9ZNc{g|b zq6dm(PtkP-k|Euqw2Y?(v^bMk&aveA*Q>fJg5VN9^2H!f{E8F=q0M<1Lb((~%!3Tu!mA+NgWLkSWzeQ6~rO4|fJC+Kg`=f-HsK9QS9X-T=L z+BtD4iJ74O5`mjy=v-wiWVuh1n{$u|GoO}PGH8QMu^#KBH~`D!?oE0W@iO+SLuVsy zF&Wz^06C$ilVyKaIhL0-@FVhD-=(lZ zJgBQ)La&nc$#i%Y95LXOsd@{fb-suK5q~fhgwW9}e&q3ol1MSK9n=645+VeVnIVTU zj!Nr+AIzy|d4IfPtLM=kxvpSK0GzH2tXW8iVt1<4io+Zy><5_CE=R!4+>>N8G#QDI zDs-Z}D{G-;1SnpUVZNFBX_b;;WvcsWv=N=a@moD_P%><=dBk>9HWXCB+a3LcBfavF zqWjPp{-S&A`y#rS20fL1LDB$IHnZ7Oe#J*^8x+|^@F`^_S)_-koe&kly1fU1t<`cR zr0gL##7&Yf+$_iV15S7{G#367OhNDzKhCT>ZU?0MFvrR|*WlcKV%8CraUnkw*yebY z?C%V;E( zMGSS;Alv#UHmhoX!Ij+tV{vb1Ut=$j`MSqQGCF?)6PS;0Be6>+KEQ}QqqC!0m;ysrw07V|ZV(_k%dkdL|@x-MM1BOfv- zl2sMO0)X5JNRfba;q9*mDPiQ>3sc|DMy@MReKP)LV@A_=JU2Df)&-jM)X*LZ+A6jWa1ivS7+7pUZW-aZUeFri2KPxM8lBK4{Dcm>So z%6;xIH_3i-3=8`Sm7EMW2m1+MM-Wxklspiq5re8qW zsX3i?ys#0+UyMcM;zUU_wP?CPFFfdiT{-kkFkyMHbz!U;-`An$4S989G}N*bzq4vE zHIAn6^I81Nu6aU!Vr@gq|5_U^2Vy*VyxsA;%)$R3@cZfIsrY5pjF5Ghg0QAu zzi@hs{3_0J&=K!n;mfbe1b&6Q=s1n_D9&zq-a7pedpne>=*So{00Bh}2orEbAZN{fUe(Cs3lLX5Py%5XLP*e_@B-JyR5Awu z`Q|xD_!hRpAGjK+CJP7x*)z_Or=<@`!5E>T(#_2%_M#u zF1!b}9v-|i_0h_Q3hx(V+lTj#!=!Hx?1oq>*Z~rqE8(J9`8$o^DN9^lq)>S!u4p?P zDi0&nJggx_AJpLrsrh)ozz$O6;YujIAH2a(&hh{5%zcTgrd^l@`YwkD{m$ToX4T@0 zATIyaA+3PBV6H9)R#*(<$_`~HNq!`al(N69ZFwKL$WMN_Khp>fQl}7#dZe(V=iwn` zJ$Mm-zbFa#RQR6*x`>C04^>|eeCP*15_2;yJ_IDNI`MGiimTY(ws5pnCKwWLzG6ws zAFSmU0>2-m#m_uU{5C(+hWz2kN`J=OjJvK6M^}y@;JoiiS)?R+QYUAo&M##s?ybR9=FLuHxq0qtH38R330229fnk=y5JopDsiShbutPDwOFPW ztVkKaKi>sESs&!u37`3qw%{M^I(a9-LkD5axkhDYfDglM6$fc7T=a+tA{)t9xhTyz ze3WjC0HvWCr6hhFEk*>8YEwDCf{D2yU*TfI@)(M84G@(8+CLU~lTnZHX#Wl^>UK}nz zH{b6eb^H80QlBYu`25_n)6>bJ@$*~bKf}+>dQYYR?Z?k~T1v&T{2%$5{eR-;kwh^a zKc80eTS)nh=Xc9J<6p>f!uVGZ;YMYq&v6e_bPeSb0w&S3Nb1Kpd}a*?iB(A%)L-f~ zeo$i_Qs=RCCDTewIr!XoF_QxkhVg4~fTtQEirK}evgNl{5pD*yf2briNgw~rTye_! zbimdc`VcTaRy1%mTC$u1KoG8*<9-mi;vXVc|BJ)ptRg+5n@43$_s)~<%6niuWqww5~tS@-X9F;kA9WL(#?8D!h`g0@JZBN9^ z+QSP?ah6oh-kZB_OdnjOz)D0~Wyn8F9w`2imZ6q`TJ0#4u_ z5>7ZLDg?x`Qw8AredIv=|~xoK%fBiDcBN$|1qGdu?zvrsV4wCFp4-0UpqAyjM_n-fD=26 z80yzA&t7Kj`zu>j(aIZdwAZe#b}OG4?OPRZb9_RZ?Y7q+w*!aV_KpfRbt`P_7HaHU7;mjxLTgF(AUH># z4*)AT8Do@>8ZOD7S=JBSj-!9rwW!zB}G_!F`m zdC~9DBsvxr3P7K+RwRm8)T;x#i>^@yrJUx?Ik0=988>g`%Dnxwx4(JY{E~>^WoJPI zQ_lyOHV*6o@bOqEE|9PlYpO#-ct({GHv^P(fbY_s`7}MV= z2~DtHsrS!O*AbJ9#-dEx5IEzUeYX=k2{OcKOhy;=Jgw^vHk;=Dxt+?McyJ0f1>Udh zkuf538s>tDC?~>eI$M{BV66zejKWN7_UZdutFf7gl?R437yeCDAx zE<2^u*q!T7?W>AB4ia;ZtM!q=X6|`^Ls)>NcEe*iw_PJvCeMflj(aYcu_ACLAi&CK z2R4wPGoC~7A%N^Hih!+UqxwyO#QL9Vv?c;`|4|GwtX?3E{k2bg;dlOny1^(1N8iyQ zIM){`&sIH1HX?x~8~P|*pe>RjpcsHFP=7k!dY&L-27=uwo=^gJS%w+7shbj6tSN!J zm9-j}6+J>dRBpNxxMW@PckBo{!us(DfZpc$5C3=gfB4NoEmG~ke^E{<{DV7t;g@Yb zX5f;pDe(XKC4v7BKWYR1q?749R1dpUk0L}hMbu$Gtg7FVdFW~ zEop>6^pMc^&x_SDx)Sk#W6e-CEmBg6m{~L3N)V@Fb{+xnk;+1-U;CgSsZ%>`u_G(NA30y21n+!pXqb8E~ZVa>Tk|G)A1Q``8Q z3=WugH|k$?RibyNAUS}BuQhE;J;dp&(Ur?Mv^25h%V72 zu6AcYc@vIkI2df`gz7_9bN9x#=o;At7~cwDH3k1~LQua~?NC-#9*`jO{knz{HFJ9u;ujn}T;Wqb|;zC^qmELnUpA z@ym%Pc&zA<)h!$G{~dh)*oboc!rcq-7a%l78`eYDfs;*?5)cX<0X4f8lo_(x{uMq{ zz(?=G_?Md^^Q`~DLWSg42B=q#lUK-yYQ7@Z?eUdDpI3Mno^|<9aDwOYB>9VJ=eFtZ zBy|M&5LY&oeEu8s%$Lu5e+XChu=Yp^{GE1AYWq+B@qIr2QkYI6+b`h=@Uc z*Hhlh<{#0`D}UJlQ}C#lI`FiZijU*R_PkC8#27$*`a?U zq(l91YW?ec>LY-!%CP_Xozsg+-m;i1F*9U=_o`I;tE?{K02pEpivD^H*@F>1pB1k(q46(<<*8 zca=zqT18lrkmM>`p0%z4X!Z?ol^*EY(0_Xx77wdxUj9&wLlk3IY3!U&or=0u-}?3n zx0-)>Q=0M>meWle@24q$==+t&@$I+I0i->A7t_c7ee88VpZ8sReO$7)OOMZ+ zi20K7L3?$O+6?=m1lK1VOr~d&Ju_4MUy^-K(uXVKo=yo!a{E%>-sM*FFQ4W*Jpb}t zY09U$jxPEAB>V;^doXW(Wsh$f+#rf<6rK| zx4r!%N1(jzyXCHs+cQ6QD(WVE>)U7G>~mGYzkEQN@-wiVyxsTHl=u3c<=f--%s-x8 zgLSgWYG4=JZN{_r`qT&e5YK*qG;f?e3H;8XuiT*REdzCCT1Q_agS zWgqvsWo*b>?$h55yPbw~ugUe3^uvr>GW9}o{bc<=qV=qXWz8`W0b9ll|)}v{@6+Fm)~2^PC4~|ptt;R<2B*2#AL@m?8Ib})bZw@ zt#>bSg1V%fOj&-r@!Ivi@tPB^^e^yYnu1dly~}`|r6SuqP~9=NZP{=2KtU!`I!^icr*- zUUB+=;U+%Xqkp{qV%&kFYpM_5_U(zTQTCQAd-$1K#umKgqALu9;{9E@Gr2!UbUcLd zj?Ztv;@T8K-tDGW(#DH}{oY>`_ZkE(EHL`Vi(g@VVc=y*h$m zAD8ScQt6pwPp{mQOixcd|)y~3^L%TIf>JIwGeUy-JKwD0&MPCJJw_5rt| zmQrtj${&mgd+m8@`Az-XFTd{icFN%|2A$w7KU{xd9r2l(rGUL=?!Uen<9_e>J`BcN z?=EzFNs_)XF-IS($#YU%_Hr`KD{?PXoki*>Rg|z{pY$eJVYZ{L6s^=boPaZ>IQnKYwITbRD=aKke;l$|t%Gyp8wUEKkDk z{$vmCZBO}^&v5b#B~SfJE$?$o`{iBxwo?xOvL>PYu>H$lKWX2;6oc{Bw0qm|FN=Hs zNBzrMECTp1_!q%piqp2ozZ~p!X#S-areRb0=lToRNZ3!f6@B>a*0(3V-EMpKWogPM zV)1u7@Yt87DIfhk%X`KBpTB?Ehc&$^W~~Zuwc%gZ_|#YaIFMw(KyFZ~a@k!%fo;cfwknhEPF5ho2-+hDM`@7xg zi?se_u+RIhfB8YOH&2hxW<-$5g5l=7uS)jzsr*j1zbXFO&tJGiwr@xr4X3uR@(Z0@ z2ky&Hdrq42bn6f1xDGzK{UrQGCVOyiedS+nJE|T3fceXpdbVHwSZ+Jz@GsZ(@|GXA zf4N|D`~Ibl{-xJlZTOcfd;CZJ%P)rfSNx0MaHP|=$G`kBbZGviX|-cRy!@ruiaf^U zw``45u|4}{cY58a=G&gV%WcNLywe+L-cQs1_U~EVo>94f@!AJ1A4*d`AU@xg1aA_4o85|zym;y>|1v1Y zYyZ9QsPggM+bHu)XzZ)QSe%10XiVxHnd$VG9V z%lF&!FJ*r3zxR$KK554^Z{w0{~&C}zv7!hQ$V7U3Qvt2i?xtGenWc!=qul@Xm zOJut&aWtITzRHhncdPm9=S0`R`N;J@Kt zh{I0Ik-fF|YjPa?j{7YP1I zv^%*D+P{2Gn(|Kna0r+DeiD9*-HJZ)sr*M*cdc5o{HgLY6PBQP`%~qEzH?ylc_04e zvo^~qd&(bAd&X(Q+rC@w3b~#0H>aWxK5l(`gWgoj{-&E4Ymff%`d7M%uJ-ENom?aB z?H>R_er|Ki*o3#-<#)Wl0|}K`KaG9N>F-0xVXIu4@cs7eqN?juUS0}FR9kPUrh-Kj|E`ix|%*@jaoCL@- z%L&iPX3BX-8Gtj?vwH)6vI;Noe8&gmN5ixN0e z4JN`3OR8}yU<3`CqcYu=XFLSiE6?O96zVu6{={Jk&QB`43|ML-F2czuyIWq1gKL>zf$oiRl8F+TB>F$dyW{-s zFKh%pxbH0+r@7?FxiPrZd-iV9H3sx}wFHl3)673u@LrBBc!B@!@P0Io{ z54^lMfx3o0400O>nc!=Tg}t~@a-raYb7icYd+1)Nyv}`qv9Wo^K)DPGxAu+d%Ij25 z62TVj0XtC@C-w-5VlN9NBWBhxDxeX;*0C~d?4Qf4atU!2j|(lAM-6>Rs6ix$b4V)6HHVx zC_0LBgsco?V~D>Htul#d|ItJOv<)oNXOxfZ_>BOLKd z@Fs)~_c1J{_z69PGGZPC6^#cp+^|Q04%YG(C^9d4b1lEGKHvQx)#t7x9jF0Gsl^Es z`>D^>)W8|k=l#^@uiMb)=lXhR2}78m&%Hy3uFuE(Tl6{WGELByGaZ78u!}xp%LO3~ zTc^HEg3h3nRVyj0I9z?UZu_l*JQSDDbSlhf!qwrTh`whP$NP4o1{kF{7fY+KSi=cC z8W@k13Li{SVL2+;nsSVXg2^iUkM4)0!neyUGHt8yD?3GnA0DSw`1awB3X8FXQjo4t zVI0L}z5S9RF0@xpuq~l8N>*V9dFpzy3TFs3?W*v7T7QT3p`=0d;6~O`g@tgm%=ifv z-shvjw7(J6*Al`L`XB3?G_kOcri2ZuV*`n^;1WUA=8^- z?H1d}x9WM*pr`Wo=e(5zth@%5Ti&*&eu_A9R&x9(@j(6OQ1Qv&F5)q;n5VUyMnOYn zu&KOD!}?&u&uL_0(+umh5> z_=-1i^Js0i;)d2>!%K2y?aTRftUn9ZE|d|R(+5tnG`hp6Zw*Z;ikKI+mPYp(^`8bK zX1~kd>Xb1m*fiotWy70;^`GIb;>H<6T8-8MFh$F>?p#7tWLy z{^ofBHzwb5Y^nLH*2wS`!Ft}dbCF0F-ZEBZA`Z~eH`9E;MWQ>&!pWc)nHpX2%S z;HAN)s_w;&)%n9#6n6((z@dQ~4D;qzqq!BaCXVIp|DFUrIDw~h;5yN4Q7LOGF0LVe zhf#WJ8%K4gtHpV$%d3`I50_K)tcB|1_v+(L^%0Yg=!kqP^R4fsh3tkUH3Jlz(3FUu zcv*NvQ6WWG`ziV>Fw+1tTMbg~M-qqNEdLcH9a>M~)!20)!0Zo#=9BmY=fH|qV<1dC zhah-k?tDHMPd#vL#2npP+PvrN()t~(rTtfxW&%5+ze=J9vN=TCVLfIll`NKi8L1k> z-<~>(XrtpybZk}}G=^`OdJ=ve3~NLb(52CJMsy1mN?~Mwfy4W)#*2hJv((3D@=?G4 z)?2#)WT2E`8-RP({#KmzE6*Ta8FC<``D_Lb8<=&FCDU1(2--MUn6+DVZAfy4jWrVT zETmeXmf1T=K>f~kI{6IgnL$e(%P-``0%p#bp&S4pN(ALb+BQIJc;B_Dy`p}9i0CpxPxyUg0uVb zTND?g?(Hz;l!#f;S~h$`u)bC70M3E`C^KUIys)Hka;MhPw?B_WKZ-;*vhLJ(B3g1I zaH{pZ3_W62BG`o6gO!NnWRwkmCs_Y9o;OB1wU*8P=PiRG(RF15KQ0@-?v~?A%}Bmd zhq4I(~*p-BYFwf57x8ci!_5TL0=ir$50d;!|gAE_z zSG>8EER*Iy)@mFgie8pZy>>-O_twE^vU_7B|BMyq!e|U%I{kbj+83(xUc@}#qf_f5 znJcJA*~UPq0rDnvgL&3)T(?8ZA-986Xv<;1a^Sko%@I+JiSiL_y5tD--P`HAGy6Wd z<=58vPH_&3`#8m2Ssa$jv#k@Q2JU~c$3hdVUh=bHJ*Y0Xo>~EU0BVG4U;y@qrky5; zpBHR84}oIy)DuQGf{=U$)oz}eLqZ%ZY*;T!WUahFpj;v!s#Q!-x2kW*aJ5>0Q8oUk zKJJze(!OT6l924+uREchmXfJ`!7fNh=eUG4f8J4v2wYu-ybjmdx=(q-B4(kAj{}47 zu+I;uuXL@>8J^a|`iNG9br`@%AygvUI&K2t1{_^$E>>`K4gUHTs6F8*jV?D{cvFYx zqoV&Xc7J3vf7UT#4!sk*$O}u~-X0nFHAH%9=$yvL01O@8h5(mDKWllxS~Nzt8w$?8 z6!eb3;MF=(&2~ZODW{f3-vo|9Ncq%35wofl!riTF+3@XC`%uM%fYu`Lq9xk*>c{HCH7JH#?K@030j}(&>Dga z+sKjXF;CGpVu;AN9RUYJmn60emwQJXljCoDlkh9dx?Up73Lm3M9nyzh({RAYZEx0JPlh z?LCFw6$m*2LzOq4)E6Tm#n*5Oi!p|{N9Ycr4>pbO((pmB;Rq=hA2x=+9yAZqzksZu z#wO$KPn^JH_Lku7i%}G8nvzr8uq)W`JM{xWC4S71myq-OsDoifj)uMgQB;K|+g05Q z=Nso?C~-?pu<53*;@gg6eV(p(3+_u9jU1pv@@GJ($8-~+-Y$M?UjEa7m4+`k=S_KX zSNh=&v<6pC{>$ zZp=S*bYu0YnWe2u%A(&T;yVxf4j?@pBGF1HKy4`2FO-4t*atPkjc8%8=^TWy)yVUn z1HP=fB^z|<+VFw8&PYYY@yN1gzV*Bf3-gJx%y5v_x1XpCx6yr@K*uOQ6KZ8uc#qak<#I_v8=XWkwYUpRj)fS*j-dAZ~ZFt@u;;(Vz6&-br}? zJ`x)W;S=EDL>l0+&9ibJ%>w+`1n{lxTB>&iKe$Q*@4rpAdWdumo~ewz@2?cAcI@QA zgyR?s$5jCw%(k@uF$)~k$j<%{Btjbe1L!%k-+%ZQB`!y45VjYmfMDGq%27xS%LYPC z0u`d&Qt(idPDh{sQtO`&3#E=5L87Iqz})X^^0+ zsL1^(_yN5`t%T!OqKkS2Pkt^>$oMIIP7%;L7u~%6PcS<6NMGS^m!q(CzQun7Kh%@& zzyQR>%mqp~RsS=e0PW7>)L`qv#-vdHGt(`d;0gwYScOlNI@`!Q#b8wE#c~)RyaY)x ziS|;}PvBvzQJmDK4g)ah`2?Ad%i2F$&X<;PQDD0eh+usTM4_Ntky6+Y13&|>O4aRh z)^-5E18)O>)cH85Xeg_6`y;2%5eN3rTQP(7Tu$1#rRLmX(4nQM3E)wlLT)UP?4qIS z1GU}y5}$gP7Ps^SjrSytFB3DLGQe`a1ennt6KRh;`X4d07?!d5@IuD$pg#lwcnu5& zC}{NyRRr`;WCnKG^y7c*e$!w41FZF+8v`on38>YN>3l)~_z}kl*pVj<+V4jd?v>MH zz*k=0qrcrv2BvdSz%?*szLVkN2h|=26~gO{=JjH7RtaBMeLkiRkx5=A(Fh3NhUaa_ zr1poZPhdd3@FtjkAe5zM`4oQ7Hvh?nTz43gN)z**{|-?;u^w*8Mc7kJ92d7hBH`wc zV(C=ZJOJvb0LJHO0N-jjKtKhDT}aQGS$tux3j^lj z;69hVNUWE-lSc3QLlRq|Jsw7xXf&XiaO^#3wBrwIpS2hTq~4 zj|1(PgrsqGV~>e(bv^SJ9P~WyTL-nR2VH5WH~_BW&oLXw$_##YU)`(_-8N}b+As+B^b^37!4f3=s)3vyr@-AF6LLXzeO*v zCgPQ!(nZI#*6n(OK28*ujbsSuU_G6SyEk8NrwX;vXSDi$u2u)N#PDqSNY8BH zLr$#@`>KF5)dvvldGZ*Lq!K`D5BnHON0qL}EX+D}$f@FdczyFj^mw3S;P*ot+6f0j z9a5w2r@~Ck8Csl(ubLPr+*ORxN4gWqiNoh3x{1V!P}U&|03$I|vvlLO&C@E_m?Oag zs z!^?>8B{?C#k-pyv^0VpNqn(z$@q0KA>Y+ZGv3rAS42NRUke2 zlZZD0f#9mCdmxSj2^V#|9r5~pGRQKBc%u>>z**1?a@2h!r70=? zh!pO4G*Y(IX}c4^p$n%?&YK*(Jp!~P68oJMxmzT$AJ|7SB+y%^R@GbED7rIu8QVv8 zf7#8avs*Z9JWg>W#NvoAMJ)Q!l46wb&xxKW&yF22t{{>_DQ2ZjHzfCL+X_qO^z9p1)1!b|Ayd zF92e)dczmO>idG#-S|F&I6CtzP>8MVhy@(0roN@w87-hTqhpOa=ymXg5B|*Vk2}+z z0|JX?li#T40e} z_%ZRm%eEBYx+;uQau0K3;jp_j?D7r#t&qQH4UE9fqBu)WP>x&q>XkPMKe|HhDn@-n z?cn82|0N@52#{KNznrLb&I$|*$7*0$Y5vw{>?TW&X=ym$Kv2lP@xDbG#t_She#4KJ zhC_Vf#{1qfes}yCa4r7;f{+^@bdg-UrSZO-Kj+wLi(RjwL_%N;5;_PcRK==F5al<1 zLfip%ukY<4I-}MZQ4ipJBo4Y5gD%0KhiZOMudOwMcF7_beTZYtS5KS!r5%q5hRE-P zQ2p9I@J9m$>Xg@j42JkZV>WUVTb(vBAhsfmYEcsp>P6Kf+GWdVf|*oPKH_R4yY642O^_Xy z3@I$E#0thDE!7s0q;qjiE5rZD3Ye^3Tmx1ByXa3z_rI=&%6U;ec%rtxdA}&M+Cy^G zVw9MahB67Mzx`S(*HS9bVzz>@Q|ZaLp#{SJzGRXC%fKY*-A*Fo0IUT-h~-) zS zWeJq4yrsa$mP~vsC)g?TlM3RMi4TaD;Dg?VMuxD3V8U>YjI}}IU}C+-K{z;#5G6X& z0tSOC%uBmVdljMc9JT!|Z4lB14~5AC^9T(#$m`Z`*!dWjBk_Q;~)u;AK+Nh9a~k8rjagG5{%QdpiR;!&)b1_T2* zjGw&$*S$;S4X6)&RqMHYz5@bEc3{ zy$T}{g(|jEH|%!2s*ZgXBQ8uDaoTv->+#kk^o9CVs(>(FfCc<=;JfB`wYW{AeJrPE zG~}!b{@>#2!zGtwxLW*rV7`hZ7Qw;~;p%xpe5***@ryBf9F3JQ_v!XA+xR89^n=F_ z(I+?jUyWag@`J~}XjkKBan65>-&M3ovv??AaWK2lv|x6boLcKfKROr%Nd4;$C8?U& zS-{0}b$kZ3pTxyl2SEL)3y#yVa-p7fFs24_g4(u@r-*99oI-jdm8ArxKz)KO%J~M= zu&7@|WB#pF`v)xqLa-Nmf*~+?2;edBPw;}^OE%#-53TUPAuQatKEKCxR!)_eiM;GTWlFS=k%7GJ63T%maFwfNS$Iu4u?3Hx> zj!E`nhx2>WBppEUP7+q{R=DrqIJ12E65a&3@Hgcz>9zkEEURt;WYk`~*2Yfk6_I`@ zjz$eI2+YU0OOqSxRn)bbx6wsVkS-W4pqj_PB}8Iyg&Nj~*K0pUNhrzeblMJ-22lSb zeu>=b!CSej-B=&!C;5`R@(ETiun*CqFfl2`tRw$HZ^UW+BSFVYXbm38aKLb0z8l}q z^~PhkOQsG)G>V}P$58jdP{%=%qp0!j*j_Tcf2hl)X?(rpUvY2 ze>nO0uA{Uw)OWIDBTb=$I76sG(UE5RY{Dkhwn(EIBA6}&@sfma{ktI$2+M{@TU30~ zR^Wq3SXL)(?R1c98D*4tmD1Sq~Rb%flEoYwoivu&Ay+xR`<aRH2nHa03Q~`S?uO>8ZLgfnCK$~cj6huByByOcMs|%!Zy^;9NrPP5#kvNW5 z6{4)uX?dNh3Gjk=#>o~+vO?`)KJo@EI1Zs@{0^;V`V@7oN$pFRn93tS3hU$>DZPzM z;Pg6`Qi4ivq!)LS&ZKl6Xp&o-Mbm865-M%sQ#JWtJ4eg=n>1Qx@@tEh3}xfY`WKZ^ zLg5U9LW0UXFC@xUnia?D*L<>3U?4#J+jxag(up}%FHt7d9ZaAlTF&T-9tZGlo zzA1T2t;l{kBVCa}Ba0$S&N6=Yfyg+jXpnkAoWBkwXl`t)Sl5Iy+kLSXZnU63?pTBF zSNG2BKG386yVd;^-TlB6RSJ$=q^oBGZ8~jHIsmJPPeTzZ)T`tT&D#E@P=M;p!;MZI z3^;Xqw+<2ku>dU)$Y`B9F0Q4#)THn%O@z@XdEhXt3j$;Lk3!+GQ0X;2Y0eY5nO*su zq!)SBnhu{(Bt+3^dDVs$87nQcsHh)rGu_^R-Xg0h%1(W{bEb4RioQ!MjnS$&1s@kK zB*qLrZU^M*gd(H$_S++qZVc?S{rd&+k(}<<($1PJX5@UF=86}P3*xEeLLd<)SSqz; zMBt`1i4;S^ApsEORT<0!qAW`i zNJLFj^|Zfpto3_ei}J@pFQefyM0x7jX<}RoF~(po!C(_oCTuS99HKl^%@*Ttj(WTV zDQl*&As_m%H<8i4>*moOC5Tsk&it9 zru{z z|Ie`geQ=eq{>k?L)c-1&cnQK02-Y~L9ONDffTm-joptr7{YPZdf=I1B?8bT(aUQ1_ znZSH?`QI=?IIBoeE-qXY?VMQO1G?7Akyzn-5YKjOP=}%Sj@wh?gNYN-A6gv8%mn{I zH>kmLBhw>AKVpGr_4KL;x<&3DCTsUwtphk& zK;cdw9wD5j-tw+zfr^{JRjKee)4rr3PFWufkS>gNUg^y02PuwrRy(siv>xsJaot$_ zs>1=x43VHTWU!B8)du@10X|A41shJFO@^l}Ed3n9PfS)Zr;4=tyty0$LqLkBjNx2t zcG&R*zsuT;`pN5fJ}cV!)4F2;Bj&zt5N)@k*FWEg72AYX!4tB^{+ii;+A zak`ZdK6MkMCY0c5QhCKa8ABbr5)Chr@C4CM@FjS=AXlw`a`yj#htfyKZ=;wO{m zS@pw-(NfgQL>Gu0pu7V7C$$xbrig4HRVD;Udd$HOjbr z)ABR?^4xn-g>my;KDOV+qidX&(Q+{nlO@gF?&=!b6~66K4!gp399=5!Nf4k3S84cX zc`xukmO8SAI( z7?Z^7oLM)LoT#sGW0xS}IlY(|6TCE7dg(e;E~?^Y2!l7et5F}pKo0-tS>1OH>(wp^ zk3vJe*nrNh*)|yBljdd)0+)sAA^TNo8iq0UO%f_%%4egQVus^_257MnXHT^07O(Gz z4HO-QzEqzWZ;rZtlXjvc&W695l6hIRR{T!Xs>!S})+d%1oily-C~{s66f|d-wG#># zp4RM*=d^{c?RZl?v!AiN_k7ocNK|A#KN({0U7$M;TY5MGI8<+Yo8lttLsNv%Luwd-0uG z#bOQz3P%iS-dp(Gi*`pj_*VBK&T>0YXfPj1Mp&g!cS$o#dS%d;e$|r(>_Y_q2SYp&8Px z74aIK2Kv_<6mh5Z@60m;vgc(?$VaslZQ&&sk*pHUXew%;5GB9-jx*~7-uEtm4m%IZ z@St0Vz#YGk{AOn-=N5Icjk0$guNs3wg^^Z;NDs}N&L{D*2m-Q5yaMqbMqlZjht&(v zTa{%Cowg+c%8Pm}0JynE?*0LHD{{9{9Y8bOKVdg$h7^rR#kdNZ(BjWf44M(@*&vfKc?7_q%pQpHv9ByX z%}9nHm=x4bW+q8^w0ZF+fW=JGZU9H?cZr?f#p19OG_I@TglJ-w62fU5>32H#68hVm-nCZtx}k{&T;>-{9%yUtak zI?1rBUK3E`|BSjih?Yw;pjZK%p=VAe$ixY(Xssl0XfmC)+hvq(yM}#wtebV6nWl3uwX)HR_gdLQI9`aO&#OxSzU zl$j(Xn4V8`$auiQB*90M+U9t!=tK@t0zmANu<$D_(xQJT&A^UK-B6_SZte~j-}suy z(6Mk#B5^EVTt_t%CK^QTq{=*))yKSO5?|N+DP6k$5+o*rH2u`QlakAq`=65<-mp9X zpRNFcq>VeVJHS7^T!7y@EtT9cJ0WfmfPbc9sWIO}%suft{k*ULw3h`Gp})JCAZ)rH-s6g|lDx;X z{Gc;!1gG1gn;RI9)-oQgWqWrEYzy4zrh}2I`wSHqxlY@9&aUC11{`(=YGJm#XgNn+ zfm$fddtjU}1~w1RquZ{UIy$25UtE0$iOQ_19UM_LkVGJpvq zh+C1|g_2067e|&TP{*v+b|3BNQCbJPT07V?7SrxKt$Gh0wv|-9Ab>~-gPrYN;L+%+*XY9s&#T8alr|21}FlFBQg%Bv3i*Cuu*Nr9~k#eCsI%!KNy4tOga zwSg_ z&kg6$qt}yev#A!XDbWE*PenF2ePKIrp5=tj0|)z?i9h4!HYmb4*jX{ zL=h@nF3mytp%L4hB##&>%#-Gl1C?xq?!7<=4YyUMywPdc)bLdM*g7f6pDK`H3A-4A zuY`PH_Qo5IPXL6M7ZKUx&?tLQZaM1RC!qh4enf&fi!S8)QvVJ-jc#i|Wj-$apWz>< z`3|Ugi2HXo%gLOse`OXd0p&9#)dI>9{ zUO1=|4GD21{1K;xP6bAa8Rl^)*l1qdgl;kWVhxVgzgFeut9>yk%r?X}7HZ!nwn)rZ zv~!@-GMw7em@a4jbgrtv?jNlMa+{_6RTUJ=i^(6*#9U>Ov8Ezvh8-Wkxfm}xGAuK~ z&7vbCOg3=iLL zz?rcF3tVjs!a%q?*;GR~K{RFxgxm-sp)tQp(c(x9<)}?4&E6S=VFRJ~tr$ryY{`;l zVmC-()M!Tq566mq0+;Fvl*K0X#DSZ2E|N)>q9Z1ep=>v@5aklIRSo;wTk4mw+KeQM zfoQR+3jaN=ewQk%+^j1?IzYmxetTb=u6}_XlRnUBXHK^6C6P)5J&;Ny5!Q9IBs6au zmc`I*#)mqe-myWuZZc+SyPwG$nvQ-awcUuGM)MvO0GH6bL1=UR&j}pnTa4zlCFVjx z(9U<0G%N7SzP8QN+K#~cpHkbs)5G-j@+TG%S^CP|RbQtNn;;d42IXRDmahu;k>+C% zJNjT^-&D_@K|QV0av!wgPWVt#8JZ7U0W@0y{j{Xqd}D$Kr=&=UXtOa`Sg|u6eDMWJ zN%yu2Zod!di;e0JxdvOavCMaeLFd|QNEtDQLY@rDoJ{*V=q~6zt{1Qg+N)eU-{zGU zb?W@=a;*e4vprVSL=+%D%fHx4e;)pbcA_&4?Zm}i)J~JdEp?&Ju=Aof=t^0n#f+Vh zfSzX4c)de;F*zv22V=?E;CoaLVKcVY=|=DAmN~WQwB7>c1BFB78Qq4ga0PzDJ9kJ6B`Yr^Ny%N!E&cPE{FM=xM!6Ihfkwpv2+;LiR&(uo;^~ z%vN{x&W3}gEO*I6tyIH)JN}7o!-ULpaxu|q`IB70&EPzgKM(&v#e=@6$n*y7b30jv z{A_i$dh*63eg+T7yc@DtVwSNzaZ6xqz*R52e&Ds>6Az`!d%%F`Mi7)V|>W|H7 zfv*clF2qWjXR3FIujsS1#GhV z~jfrjeza-tys^+JSOd;BXT%VM#ga;-Iydz*Q(j-1$g1<5#ri7$C9UNiA6e^bt6%7w6I4~`7c%(pzJAGb%^%P zWP`@1$<;|->X0=<+B=?$eqZafd`=$+t>1u^2+dtj5!90~Ma$4zM;WP`UWi>AJ2iUO18&tK{ zyzmt6W7fWh(=tsEk6BqVOD+6y&XHq-7jEjG1Y|&w7*&@|_|Um{{YdQth|UBFXikjN z6Zk`-lgV*R6V5}AKxk5$a4_)AtSd_qP+P7;lQ3UH;H9p6AG+X1*iMw5`=jueFHVO@ z;%Of>Y(1Wyhr2J}{Tv@h%XaAj%d)HHt`DXhSL(EW1Oy=%D_GtW3)w+(E|`tP&&15# zNMzpo=}pfJmRtWt56T<%aRj1|xIWA4&%?5N2vPr(Qu%rm=^4^v zjrdMM@cWYpsocR7IYv)O!TP_uXvTEU9d}hMT|m-cOGf^wSlZ4%{(K@?@C9w2m`@aZ zd3mo~Mzzbp82*0=QjR%l=!YQmSg7-gr3=}DY1Xz^hW0c8{Zr&}Mvud9aoV26o6TKU zoO$}yW>vX2XvKR*2%>lfDXF`nxl3Md{WqObZ_u@G$P4vnY;_9G?1g`Nquy#Ap8?*j z&ZW!2r9e8a+J#^B##mvrM(EY4?*Y(P@VayHayW@~c?YlE zjn_2eP87x^9R38kJkA?3tsaYm25s12;C&H2xN%7JuW-@a)phR~cR8&b1YY|3Ee$ia zpxnQ%(&&!X!w9rDXg@Qc5{#t>#?ptk^;q->w8Vwb6h=^}wo#_OgTf~G*aL-hg}g}` z2QTzj%TSBqzsJ-r1#f5vI`a1F@s!w!njX!W;1S)G}We|p!QV_t7Pn@xIyUVKx(QjCG; z$(9=e!<7kq=L#782}Uu#5qx*72mapi&d8U9 zFbm%`grNg2gqewp=B^{#cYD2l3P8KxfOZ|Z?Cj<)8FK4PCP}@VLk;U_!FNAs1bF=x{L-sX)BoHr(oF1);hVToTTf8q=Q~I$f zhLnmP%uzr^UkJSzs>OKK7_dDzUKB>~?M^gM$_;<_wG@s2nW(bLE{D;2gP~p7WyE5dO zU4Azh-zk3@9LU9HS}Nf`dgzc=M3$^Qcr2K;dGi+N6P7e7{`JgXU?hZ~mA>7~8~7f~ z8>En;Kk^+0Z!W+ z2gubvPTN6!Mu{}sTqvU4~merMf-JGesd-Ha>kU%_!Bb+G<*Z_7X^U@GKr z;u7W0C<@7sDv(XDQUlH0c+)(N2d@;!?N#Kxd?a$Qeffig869gtJNI>3&Np`iZGYf> zr}bfJ6~mDcf=7TwJzB7{aH_fyTjFb;_WE8x6D6#~e#pow{9~JG1H{UJ6C#Q>$q(>3 zt0-#F(GVoi=IV)T?)b~vLSk3JTx9 z>_^vH_9&h+2x54UVBwmBrliXQK?i=|)j1jp>Hu7mHE@Z+a99{fiQ01=2Vz*ic`+pd zned&GX&E-&2*#cu=L~~V@i2|Zpr53TK+$1HT??n1UzZZMKrriIQ*k@}ZQVW)PmaVJ zg+9(z#8==k;T|1TXbK8aPt6vBeKnWK4up@<5JSAj@a z1&g(ww$5-Kdy+}OD%KeS0dvf-ch;-KOX_kQB*CtM*MM;WsC1Q*3?Zr*UI|Bt{|~vB zfurUREK;nn^?+bp24L!e*pB}haEa*X>D9JcN>oZ>PLfkqU!8A7Rfr7ybqfAWUR=Y& zy!e>kOJ4k-L{$xVPvctGLHS>hbOJjlt;YONGn2RY`Qtr0rDH2?hmN zmuGOjH*6zAVyT`YQAL6nmN7*TQipVROw)fSW7<10CRudaaa&>-cgC^|gNshb>?x6B%JvDCxw(Uar4`i? zwDaA<-7NQ=s|%9!o=yx|5!kg96;nD`e=s2r7uaf17zb9f);_p^4|D}^V%Amt5>t|7 z112+sLHK%%GhP6O_hi!RUk@^!@3d}~W zGDLCbU&ZNm|4Vx5DEfxLk~GdrWiS}V>(`2&pkHAjrM@_3nh`XaD)vp4?vE z7q43dmJs$j3Og0p&~qtjn7Vi4GDl-MTJM9(VQb20a`?Kg%Rr)wlos8{fv32X! z{~(XT98|uRNtD1K%^pRzNS@pkyJ`^*0i-hY4-juNy{CP+v8~11e_-p?7k}4+(RUs4 zoDnFE}?QN=mR6Qnp`WMG_Zs@6LXN8ad~?8>s&oVNRrN~BF9`67lrz{HD1)x73fm7BojBpkU3J3+Zsa$d05LIBMcO@3FJS5cS!B}mWG!SHIq-o)o2hZR^W$p?t3qd*g+hHzc zA;|)(wCa)WAnmBR8fnADN?ToTDneTHh~V79@Xygh5;qR~D8puW2f+}x7fu}mLAt$M z@kmN@M06^O)goDPX1SZHL_6wIriaa7!bGUY6^+~sW`FE9y`z{Z-6{&sMW6tPAf4_d z?WKmW4!sZfhqjktBj2(?dUySJu}t8{V)gxJS|17>sE!=c`t4Ng7IgKVV)PlXYiz)0~}g zj~J6QNBWD7By$#-lEsK%YK>qf5iF>yWJtB&<$jI^^RvY%U?yT1`ujt=3+COwP6Cs) zJvd$i$8jZt`Mb$k!SsfW3m~9_M$cLTIgO|%&PqoVbt(g5xFwbw7)1@t0)hXN6lec1 z1A%VA1Wsl{2`fZ&n7(aHvI`Hxo~rd5wOu&2eG%=#F_^RhQ7OBav_hDzPfqCxSUKfX z%!OJ2&*&a7oG=-Lahbqw)sNLZTJKnO!{cj22IE?z_)o(<(pm?ar@Elh`zbbie{br5 zN-$j|m=23x_6|j23;h4!#fW$8fvGTp@d&7a@rv?ve2S=K;&aKbgrcM1#c-j@e|s=m z`^i4P3BTvpvVy|eOGAmf16zC|9l{L9;41qObh5tzNojTF`5r6m?|NMg)K# z{U-=!GV9Qj^=5J)Bm8aFjLV)l#u*E?#c3&W2@fkAXNn0lfCd2|9^AkO`p8~0W;Cnr zc%VDhWAmNbdhE_NfDKwHDN#>OE$t|#Q8&C7c%4owClc6%Mqs*ynA%_OMOaJgaH|Ur zWQ8;ImMjYAtpvCU{b=ksphX#-AxGKU z);FGEFl3zgvbX6QL%V?$yg>s_qvK<3xcJ6>uqK4PXf*@k34YVV@T=#L3O~>{{;vk{ zjYqy~eB&XnSVW4A5!Qk_(yFsAOhlR-n5ZMm=bG>JKzHC9e{*w^4*U>mRK2y{_{J~3 zoZ=gcVGA7ct~1!F_{OHDPj_mN2i-PZct&?lokwQ(_YD+vAY5-D-^qBnm}3Y@3Y7B^ zt#Tf_;W?Yf%p;0z9&;zb&K>OA201q9L9l}z6W$dE+8c2BDaok+l2T37v$mW)zhQf~}^+#AP5dL&0rEWa6htg$S35{0i?|XOfP! zc*1;eGaJhNR+|E89Nnq)sFL5c$eeh)R$K)FOn_w<3wXFOXh3(YF-nPYvAkCkUK>^p zPIR8$Dg)I9NGf{+MwMm|{>*NHHFtI<;UD}o8{r?Q1L3FRk(&OtA^eRmSi;j^*Xh>4 zOMLn?65ec02{|yjBt5zn!e?;VN$AXe;;%zyNbMt?Vh#QFzotkq)CP@+Q5(b1Da|Fg zO~lx8LOK%|WWrpEdE86V&f1h~>WXfc$Qf-zC=z*gV}X&mk~rfsEI9LT;+a&@ZTmWH zeQB4X+XiBixr8S_p}Z^4{|Xy#=w<^2apA|-`a+K$E=d+)jO=#Ye}*jpj2yA4%-f}i z#~hQ`h3KhEms`~X_!_kSf!5G`C;D}ctlh-Yce4Tl^O3S;U9=Okkokr`wdO zvZXrud{CY0x>LwTMw6BV`Y+SxTjPO~*VG>^J|8ky>xd&gYBOLkBk=K}cusQux26fb z=2xW}**aC45jvhn5@UeV!ugV25~v@;%_!$iU*YS~&i(3F_|MAawnC?6ZoaU^eyHHV zmCa*(C3%D1P&`2KNI1t;aE@PdWKE+7@tEsing)psSFP=!vQV0 zRgmWmT8VnCgbxAs%u&nk?v6q{bcR-lKS|94IP-^(=0V{no7)MF2Ni|;FJx|DZqign zVKD8?GdHxsoujd#c{5Su4DH!O2KT^UuJ>ZmbpAjg>J}G;s9V(jcM|gJ1!wwEqRK(O zgCLdg6V{Ek5gMv9-iTicNf{3%_^ffvPlC*gGjcHpFwyQwwi#zbpm&v&n+{L)osWTx)F zK8s5()iWH178AaAi+v9y@h6}Ob@3a<`#c>mCuL^qjLxJ13#sOl0)uI6*KDv3wV1G6 zz-gMp=zWUq;$CrqsVqi!kf16`(1E!2{~{^-^yKl|6OA262Ct(jLDRoomxZRw0(9Oe14s@LnLFd+J}f_5nKlzN z4kfGL%S)fmCWeKawf1Z%Yj_1|kD~!hI^JI#~5OEB+Y4i|slZ2{9V`y7s zF=Vh~yj*GwV#J5Jq_?`i)7rw-z8ABkP}n6P$X%&Z6IS&w)}ShsIVH4aoZ>?D_ETtQ z+(v1(kJDC6+s!j9+osY+ezWvoAkt|)i9Z+x>xlPESj^s1NNT+hZvxI(Gw~SXEgSJ_ z-3l=zJ<66a;nl*Hq!jz8U#MG@JP*CZUUc) zf3h+zQJ_#Iuswe{UQ-47Q38>KIZH`hFz_)rL?Na{3XZ}X37C?D)a1MlSXLv&8XV)Y z>NEffP$jQ((NW1hnWO=R&gu?QX5N;Glsn(chLky111Xd6NKIO1kn&%TTcik!q_XNm z$0aGg(uCWT%A&rG2KyI@!L7OvTs2U-PjPyeJz=tV3E9LF5p?n=mt>!A2hEjLfK z^NE;|YRalS+m5kyei3Tbr31`*B9eo;`Nd8?_g`3x*U?rE+obwLd%9NehFV zG?ytS68wb2uaX9m9rYas{$HRWs+R&X?l2#rm_8)&m&@j`it_ z=r_VsKsiPx5G&Sj6zR1OfSnjPni_R@4`oF&?TtlF2z;m`e#`Wcrh(> z#-89c907K6!J$aSc)^Jtz}I36+y$F@(fxGY_<>NA*s3~teRLl3hCSKr17ecjc&zra(DS#Eck)q?>*pe7rNvxGJ z$5j}0!f3fbJ!58war#KR^P2^YILR5{@3FcApP+?~Ep9C3eabJN6#j)H>Uh9ix&(i7 zWObIBwvalQOAB>>hr+g~`!5FWXTa85-1F~Mu3djF`0qo+MmM{Rfy0b}!|bCPTC%4z zV2tQN`M*y#f!200-CcHO|aSM zVi)Gg4v94bw#h>E$sF<*IG1>X*~Dx)HrK|!y>xBLR@WVpXxST%$N{aVx7@Xiw`-u{ z6VKs}1wFGVBy@HKp&EA)koHajX=(WSo})|IADeJj5mIc$xNNH4U|b+1Q`G{@20?({ z`I_~DQN4Z$TnsGsZu<5z>`#TQ1d%9R5`7ZQ=emQJVSC4};PmQ4R=T-git-R~<9auC z3QmNWlWRgPYw8@ZQ6s!5+5B-`BesEt@3EwbD?ib{EFlEecvbD@3a)A)F2eK%G-5U7 zIbjzR>KD`@?PM}F^2fjsm{+q^8h*ae{8U4JswO{Gvq`k8&*E}*6$Vn=dK2idY+pHv zAAyUiC>eTR=o;QK=Wcm@e|ix88M<2J8>qz`brlwg=y3rHW3_W$&Rrw8HOkUk=*Bp$ z-Ww3j#X|4lkOfaY(>`N6v7HR$*kt*K#3OL9V<29s{Lit%fk=aUN|HSx`320DfLf_ z*bA%t$)kpx#0%=j!hSgzLH+0gu*8?hLuBZe{~LZd|G*4>xUgj>=zs3!UGT%%Ej#9i zJ-WdUZyk}$4_IKHqZUPX0?-ixP&fGD*vo_;2EJq{_1*oJQd#&ReAo}72zT@5b(Bsl-de@Kp8hN6jhUPvT%k>P zw4{kzF^4H|B->a-vhv8;?)iYj{)V z;aKNRyRV-%e&m*Ib7sAWZ5XAkM|gq#S6g<^*xf1d(d6TuXain!=AX7#xT)(fr|mfW z!d1v=olpQ^!j-wneXM5Kog*5KNi{*J&HE9M5c3YjY7Vm|kkk@NYONM%f=T@zhNd1( z&v6UzAdr6N&@0-4f9;?RI7c}xWqaYSq>`e6uP;G?&0@4_Ip^`>4OD|QZ~j&>gIv|fy$f*oukh9z}ch_wUo zbLEVCXVxRT8`5L&(nSVP)3Y+Y->ZKBh zPspHUs~m4E|Li8M z$P3sU-q!s<@aLvGnx$2(cVLCB@vBE(kPKEmf%1v>LiTqL%IpHb8#zxS^6Es#DqyXl&n+Ig<4}a@qZATi?vBG||yR)uVV`YrY>?L8v%zksS z>NL_7!)oVO2-XCA0JKbg&(-%aoR;3g04Kfq5;l#A&)3pMm_BH zBy2J>kZZUpC$>|l<({0*tYi2JH^-K(|9cK|fo^^>kE5q+#2*?ZU`Q~f-h}RqzffP8 zx?b;WG+DWnf5(M zEY=)A%bPp}GF_-A^D$PFvz&D44ZzGAESpd46>8yJw#?lo|NgGMdn(ng%Pm z{yI2Z>Sg&7ob$W8Eax;*iHS~=5)@9%s(p!{ItD*7%_1!(kR&=1HiW`RlTYZR;1*Mw zmC`O9Kf${=ej-KW$l20vH{|)7Yek;*B3mgIjnjh#W<&u%lzi;xlMtnE&dnm!SY$g# z%&Ig09=didQ1*}FFNt2uwzLnhb#guTg}^2zlOo~ild6`S8G$!6X%wzUFFA7*czWxE zbKC_V_u^1H@qJ~yPhmxTOra3j;!ZO7h3flfs6dG?IhnwU9Dw&-K&)0iA(SiI+VLn8 z9Kywa{es^ly(%t_UnnCq@96V{GT!+&w~zQ#w;3M+iMasqSP$SttiMET|6)-S2TjW} zj~5VGjYPBDkq_hzlXLL~+#=B?HA)cd|Fgb3-b(oABDs=J)iR?!6(1#(S;TjEWkQ%b z-d2aoIKV@D%pq@*hs3~24j|BKkpY@Fi-~41sQ9OL$i^nXbLWW65irITCyEvB()C! zY+~h29E{}wo@S>meoVv;GEWZhSAU6nBh0<-6K{y@@V!&wF{(r`c{~VMO#(XZH|rQ| zE*UX0cgcuz0hXp6D5q1`wf<}o{}G^@-BEQE=m^?1^hwa}4W~`h&I}b^rwCXX9%$Na zaVarg-meGI<^r`Myx2u0M-3j|9oj{Iwqx2Io0WFW6)Cj)>7#~r6|+-lC!Un#@Mr^O z>`mIq6u!{T4tj^QyZ4VNwCjh$P^Ka3_gE5+E8Pg-~DEt_WBmVf}gtOcQA3?!uUZ{+Z>6c#-@83_d7qV`M z$PGL5-=RmS_WP3-;#za=6ohesKMrJ6pZ`HnP`0q+aSMk36_&ICgrf=Ys9b-w{&{SD z-z8!2MEKks|7Crv1nWG3XJ>xH$mln@;pq+M`VZlWxJFW-o{|P3j05HRV>(cMn&|CuE-&8xVhhui|!W0xG-6ofzI{%BaqdeT_j!@iPscV zmVJa$N4{sAIWCfZ zX}6#&nrBhg#xDA!|Ald9I6PfvlLOP5GEP;;qiWS7nj?>W&Lc;1AsD<82Z9M@PzpRAT{;f;!Xz&Y$;8 zM><$UkdCNDALw!D6@qcVi#3YaRGxzaMiYYr^MGmVNG=%z_{~3CERPM|oe`P}XdBI9 zdXq2u$MYRD*C4ZQsT<}Gl)bI=hWVH+B$A_xYngd?FlHk}db+?ecqo_y`e*N54(EcO z$Z+6b*$wjNB-rKZGgAQFsPf9d2|3_|6#7rZdCJM>k;8uX8IcE}>Q$t!EY-RVsnEX9 z&E!p1odEaX>u~@!iu1_TpGtA)_+ts~%9xLutoaLKFb*Grzlxptd6kzH7LF7pm+?aXQrX1sdu?k`@@HjMC40>jXWU55X2!An(~H_sWUq?R7a#12)7a=f?Uz zjGJipBH8vH?Lv#>7vYgw@)8Y=IPUuMR{8vmG5oy#T7255KfSt=?vMF&5I>Ele|nUB zI!AvB=fCeExUnSfN0%1lpvHn|iY_hzhve?v`(yzF2m~hEaKmE&Bf&)P< z&R<^u*bRE+r3?Aeu;3+89vDst!zo^*T22P1+?K%~ve8@?7`Pr?#CLx<8Fi-(S>Cd| zzF-Iq0fg2zip{A21E;CERNr8|K;WoHSpk)5Akoq{iC+ByspI13YJrNmh&KgG;D&i@kuK^rwFp>Vv1_$Jr2(+HF; zm@<*71&U(|@XeVSZ#cFohBQfZ76HDiXi>V}5vXC}U|7rfzFR^}fGSiIxWea*NTGnL zDDT=(R`Uro8FD=&opixor~ZNuKwRwNC2*#|IAe@xE)F8PIJ`)08j6AMX$EeDI&J)e zwLH5Vf0*M3IjFBOk`SG!)thwMmv90a%n9Of*G~m$?O5)@khyGK;}nhoFGwXvEiM}2 z7jTCv%XJa2*SoqEKTDpN73UamK9H(`WfJZ3IM?k*$ zNDzS`rhil~rb=rv;)S2$|58C?7!RKsu|$7XEQ2oOX+BZ0Be<|J?7gPxFg}ZrC`2f( z@Cj`huFy1>R{1vwn33-Om+@k9P{>0h6=FQqUeN20Lp81Oa z=t)7C*_Q&-o@7g#cgOTzCm52>54my?xstWwtXzqHU+m1f3~6^JLl^?1OSItzAkZ)**A)q~wR z!))|z(3tK8KSiaR4ldep2b|ZI&g#SNtEe zL>D|ZMjsAnM4_79RIy|cyG16^NXBC_!BkEh647bYyFQpQMZ?!0D1#t6p@l5F>Bbu$ zB#_b6SCnrY;i{`6LXD2 zj8|>@9lvE+l3`u{6j9kag@V~~u!6A#09>*noT>uD&Ld=$NHMQ2C6c=3c>f+D7I7i` zRkqAOfK?_tSFH=wFgJG#bTrmy!(2qX{_u1dG<*Gr>-}!#N)eD5b&R%L3nMWO(BS9< zh7BU{wmTRlnP|ZE`eSwsuBEzc=M5MY;#~?x5ch%pMeGB2FxE3O++F=ocQ8_fOwHn0 zag4{z%?c^40s^i|iJT@NM>fD$CmjWQR)Q(Tggw*s)hup^Zia3c2eknIpvtsp=4sdh zQPIHh)h4L9h*mAy*~gi=4_O+!y0vWNs{p6Q6||6@;jQFrStac1Ni%e5lm*e2Kj{>r zeGu9B>wun zEf1o=8@;aAC%5BKMl*0psA5esdb3|+?MgbHOBx;d3NPj-jqZHx2v4u93SL=ywYl#w&K{uui zq(OBSVCpetk_3#9#rR-h@*!9?;akx~kI@I~@Km2-Fv>d+?QHSP#5(XwDR~7hDgQyc z&<{Kli)FnrC}NX`1eh2l(jpPV73fe@63Ir@C*s2SN<0VKm>A3;{$f!r>>#?hbdhQ} z5-?2wO#u_T%tx(dYx|Tv-PN5`8LjP8zj9Z9D5O}F#^3L<^$h+tc%uhEIMlDq+Jyp* zUO)ptL_sqc1iFfeE_`($pciZ*FRgM{eJAoKUkR%LwJGDX!zxf;{nD(CU=JmN8BQL^ zXgGTCy8aT_O^pjE7Pw_F^EfO00wz;GIRcp3Lt{o0EN%Qt^!U+gGR+|AI{q%?aIi1{ zg{pel9uzi7f%y9>fylcFdZ>;_5R=i!V}Ece=l0=UtEgsqGSjIXgbv2WbL8{O5| z5TXvaK=7L!Pm7#DJovDH%m9=zM7hA&<6<4mnqq*lL;xDr4Kbc>1Oi*T8V&pPDhv1t zqc%vac7ZEOO%0pYGp8US1OsT%W>UNH+yM3;~(bgJ@mmPhjD3WL*9Os+L-SFcRYiKx6E$gAd4v(>h1M6PHwjj!&|^sUzn?z!VZM z)zvLa7ltjMb&Xu@s$0a!PbGmzU2S;_jR2V)cO*SdgwRYy5PCTgMr}U?nEA?LCZS)v zARg{w%=&*64?iX~qdznrK3kYABOaztfuj2}M73#DSa1FWZFi~ALgXW;NNS~&2v~pK z2q!gr1bhZ#IPFuzP-yyQw$GTCHpFN>P}oGG(k_0ION37mRO2eCNv46o)L?tj#DY7f1(H9*9CZ`Bh|z*3!c6q7NtY5Ktb4(psmyLunaV70Q=J9lap|RVTgdH;U+y~bp%0{O@LYCsRPH>ve-Q7 zRHW8M=07+}y@DMfN`=V6A9fdfemau^O=y|r`wO}drGASj^-KRc;r%48vGGz8Ml8qJ zxHMO27Xjm8(5~Un3FuG95Dc)Abdgf= z=lyR4m~mNX^FIhMNAA3V9}r;XNK3m6FfV6~>zfDAe&U0`)5vN+zb2z)_~Q*kVJ!u= ziO2@+8pt-a|HF8*%3wkoP2vr77GnFba{nL4n4E@p1>$6>*;`W}z`GE1?cRtYftp}) zm+nf(-RkN6z#;#F+@^3y!k<7sV&Ylg4fJpf)aWrdq%yDWG@1F{!;RxsbaDP7OnkpP zO;3DZjAyy(G#rMpBySY1F&S)LQs1+Y^PuNrY*XE{40aC%Un@Z2^itw1RnUtQ`Y3K~JRLz(v2hI!7%TV@G z$X-e*Mba`RRogBSy-wF1RECb)>O@bIHa=j5G^tq4#6wL*EK-Q+ygst0;n?!{fWwCs zaB=2-i! z-vyPg{@N_XVu#(vKd8x?a%e@_@(Dkwz}^odV|6_`M|xv=Y>A)r@u?W`*Y!t^j5YSy zLX_zl9h)sQ9s}gJ7L471%oJV5Mv(R0gLO%UaE>rdO~)&$TzW-d?#!A(+ZS8rPsCp} zW+0@B8~hrnB1ZGc4F%Y3VFQk4m<&XZM^5y#f}d~rWo}L`7rA|j`;AJrp7<;8u}o}V z_nQS^jhwok&JzpW)!UpW*5LM3A3RbB4m)sBR(-w+UqEKVl&4b46R=5@!BVw5@odO) z*1t)1N1_Tk)@AFlK@xmP@7AQnh;NW+Zm<$jY%j@y?xAfEMXD3}QCyf|h<0{qCmk^z zHfjUeYFrOn<$`L6F8iF0J=HoekuRaR*k>DUs~eg~G(LiYqPz?H0b{DX-3q(jICU&l ztC{ET><=9GgogkWr05gwtFgI+V@JRI2kn*GhJh0yh4ck64LU1S*PuXzKSRXRZ&;-P zzT@{%RI;cTy6gCrp=WA;=b%5Rm2vnI{e{>Dy4M3i$LJ4t!uVUD4kKmoOYh&oKEO-- zCd%@X!`a7!>Em&xO{I27p(mQC9@d1$oZC*oLlJGKm31gAXlMUmHgUmGMSY=c8quTa z+olO4ocSBLzODINDucSi-58`G>Gj6dtb(ZlR>g{GRP&9R1m@jXe+UKLa2ZnVo7=iT zY!I3mDF9~rX15)`8kU1%lL_Nx`w`T1U*vj`qGMc$zI&wrny*$B>nbrcAT~_?A%@UY zIzKFywaX+?8c3Nyd((4pR%-LMu7eA5ZtgAp%Z4gLmP;ufJ45S$0~b{?91x>GJ#dQV zIH>KEL919lu-jEoHDrMl`a9FkVmREqne-qVG>{D%Xu_W49ZKDo5&#-C1B2CqGC+AU z!!EIuS50t)qkyN6Df*G?owTTihHNPCO|BJumwcoRnLt=e@PQ4E0SGUaD38m}hCmsO z;Rt1BNz|{Ne?8ah)05NFqCdrs!6eP<1N#|)>SrBdO(g!1Kweq)vEzLS_KILdYgCR$ zkLxKrEZVLc!~*cfq92`AiUV_5GF!o^sMb{&a>N9a6`Wt;uJSx#J5sjBX_KWxgTIV; z<6)$}hmrcatKyKaM|ne!V?B1XmH1ll32fknrTMPczqCAlQpw3QdSA21bZF^F@4}ui zH8^?%qeX4Y%1G=3zaP0(n34v#WPh!x1vS75ut1YNPvA-#Hw%@6p+?NW^pM~eU3;t8 zleO}PX1;9$8mOfCUc(Cn{fPl=tjzr^0xC(8kb|dHi2(I_-a_?7-2xM{A>=VGAYWV9 zWLlVHg6xzU`}V^?^=F%aM>m-msV)Szq)Z(jkq4wibhUQaf0PzfO_CAcB!43IEP#r^ zUsiD13m%0l3!k?JE&(?4Eqi0aO>S%(Nd^;Mnjb&uwxI=Jq+X>U7*yYZr3~lFR^JRo zV;8KLT|Z%amjO#uE5WJ6>MGrN47wAHn6IuXOrm92Xx{O-T6v2=`XhOnVkVvyKZ5*_ zr6~pZ!PLDrR`A5sTV`%9WFpRac-NmQ@u77wsSu1`nNV?+GKoaB1DruIiJ+M?;V`at z=`zcB+@*TZc#Z|}`bB%q!OL|D0uI{?TIRP{5@`&L`IDk=CQgAZfXW&NzJa0v^GM!> z!>7s;O@XViqAoPI;a(vXdr0>vksPK6)KK)qH%d4#Frd^PSQ!gZc_jUqz& zLJ5~Gos4i}laK;9b z^9cJwT1|k&`ul0JNhWTvS2sQZ%zvs|_JuQZfW$>IHBX}rPnH&;KwUPBX0An_xf*Rp zK?Mq+qFbU`*b*>M7`k9Fe^eO<*w z|FMCKh}u|lSs7bUF?f}A+$&>iD+aHr=z6UJ<$x8@FJTGRP+xIymAM~LWhq{kDQBiA z-|)~**tMB@y{!vu3X3-{ZbyrVY*zXoGgN7=BLM7Sne+tK34=*?@imm$7QD{?sMtF7 zB>+w9CED4;X?c)uVQ)B`X|Pn3t?i3b)K$=@I94pq0$OMw_8oyRgO93$;cLDXZ{4gb z5`_jD5M%rxM0-(8y)V3rz%7;TnNo7xXRpz{EJm#PcG2hwsT z8ynS4(Jz-Rn{Yi}#!|uqC8#-!<{Tr#!N+EfqlWOCI)wraKL?Fzb2yzYoKE+UC2sE9 z+OtOAYQ>}0?FT%?-0M!@VlN#JsmpKDGD1-0)=V{NHw<}z9dgQeCn9&y?f6seZTvTg zf+UOj7+)VF2Q?XzVBcD?f`xoTu#rKd&3S<4W(!TSy%YZF(EJ0bAXeZrl;|k2*dlcD zPn_s0d-bVF>)xDmRW;{!2Z(mCp%=>e6L(CHxd);FPh~ z3sqI5nc%Q&StGWcObRMBT}WC8tO>Hry(~o9m>|*-I9?MSK7+uk26gxr1Y8@K{pv~3d%l7YOqwj(A$mCctZE8Mc@+v4iJP`pht{6 zOwP6Q;4;#DAbz#nv)- z9xspScOAtmpk8cw%R+c?&aB_lkBbj@>PYNWifwV|NfQ-3mlLWh z%w}X2mwBJ+EW#sc@5e`#vDYdFuf|HmAiZ00$l8kB4HaeE>JEy;*03ISI*svcybPWJ z&56k9;<1Y&F`g3$ZsbDSCOqa3P_z+l!%c?o7TI4zUmz9^Uby^#QxO~^^zk7rS+HhvQ0u+^Wegvyq5^n7F z%G}rJqKeKClg6t;m6sT=Ju-<*xQp1FgqibnBw| ztQX7?9fndSty^H9O|iRIo(pzP=MGD{RL)f6uhphitX=vy>O%c=@U}<_+ka~g6ed0M zrz01wI#6;)IG9&${1N%ot?*96&04CxQL>~l(oGal3+Xm2!vHFDL0n^eh3bui0x78*XwjI1{}Q5S@1{a- z>E_JOVQ!O9pi7i=Jr0*h^#eU-I*aTgvHPqey2Z#IKPNm8y3s*;*sBb1zX z(ua@Jj^dan+NCY3-_b-E&w4Tuf1E4rF8{t>Jm<6s%kI9%BeL+vz`d}G%^1#lQf#Dri+y;ORaJJ_GC)DW#jmKwTNA-O> z_03}5ERmal9^+*swqXwquuFieb_K9H@LMq1z6l2|L2vPAe@aqk$$@c`L9AS7-Ft|y z#P66#*kTFFMmq;OEw}L|m>y9M-Zz+F;E6hKsgwqODBOtwPwP!4ume6&8WjhSUX_=( zY7vJ{|BgdP&pB#Rerot9nK_n}!6@rg)lMM*T;#z71owTGjPm{hfru?b0x$2}Ob9x6 z-z5ZI-WX|?zyb2H(rf^rx@#M#&`c_%;r}+;*p&Sis4VUVQ2Z}NaU|dOjEbRZ!^niC zy}ZJ5?WpFfx3B)D3;tf~K5QN$+r-8|lpvc!b+4Lk*G1bQjd8&fd5oG_IMq#@Q3zto zqWGXOA$r1q)o3En$&|#9*SFtw*ufIbm9TZpoeubLk6yUZzep8!>XqZ*6LFs9o&0#; z*@JjULRCHvNr2$f&fsi#)F8MeY$=gABYI}5JK))q2gbrN!ww2)*nGpG)#sW?=8jh| zMcXdb^=_;W{0Ooh^VsU6D}!?%oL0S17s|W^5V)b1+<4y}8X6qg;IuwQ{CR!P89@Xi z*RnMH|5*DL_&BHZ|D^2@)tI2ESjr$sZ4tDjt7TL%AtiMUins?=p@{}9X(wqjCND)% zw-wiAvFlRZqDZx?b#K*D*R9KPMryaNn-CbKt9nJf0OzD*j7ld1nKAFX(gY&7_Gv;5`00%r#lxIpnxx;8YSwO?&q$uN&1px z%Nl$dOEz}$r(31(nAok-fE(qXW2WV3og1*yi`?+?Zyrs0$&a($J81;XGRI})V}AGn z_&lAX?4&~E0*g*h2MI;&(71SwphIE`8Gdc*D>y@)!t*w7T(^6;`AZrNuM)kXwrd1~ zUfg7qOP8hJ_ZcRDd71GLF2eJ2M`F971LUL8!7fyMv=pl+@zL5oQ%(xcD`;G|NBz+_ zN-?)_UFjv|jq65C9)oD_=Ri4q*!>b;xE^-;O6)FyFG??oFyS^xm_^VsP87u~fR)TY z+&Uj@lrPQ>H{VVE^8>rcn*BShgg2}Y_A$f3qFt9>fu>u*$luqWi)l%q!0-13(QBAt z9el<6q#>_yEooRQG#mjM)}rg=YvlK_)DIn|&F_N-bU(}9Hj!8o9zTxhK17sm67O)Q4nq0_-i&@oc>Pjgfhi$6`%Qk4yxVuX!9+NVyW8 zem}0knefazaM3e&I$qAC!Q6Hl%gua<&5u)iB8$wYf|m??_nYPun2#v|ff$r0f^f91 zpZ01(odnd8S_vmde218($N2=|88eti4}C~h&EU#qDYtge#S%R$syQK(5|~Grrs-7F zWa#}OYW}TMS4;rfB$l|EmmLpkYmK^>`sw?wj$6$2-$KVuLD&$8zOv%I@C=!~6ki=- zoK(a(Nz||eW?`k!FiQd(23|kPJr@LU*Wh-!o0ONlvS3=*hmqgC5N>{ikNEB-UU;MW z;FxwA0| zD!VMV5;cc3JA|Dacux>E(5^SPfOkWFW+lC7&5!C<~%&O!tb`^KaY8IDjN5ipYNM3Bn zKVyk2arnsi;&U5+yrLdM;ipDo@fVTPuwrOo-c)Ycmv~RNjcyd->1a4kP*BuWt5hW#G@=3`igpF;h*AgqL^Af30x?Vvc-pM|59mEcH8+diNME71 zf%Mi=Ur}v4x0&&mA<|sPB&{USBx5uJshOOShIKpm934pA=ZwX2F}D>ue4RN)gNq>#o6Dtw_F zTz^mm6$dZzi@a-M5HG>BqpX%m*P{~27=VM{J-v>B%~fn2V$K~03UJP2{Aw1Htazmp zkJaSX!ogu$U@|MSKm4|`vcB$#(m+L^66R*L2nKNQKH8;NpV}R}yC0hz@YrBjKH0+VHhcJ{^HwpI})sOa> zN=*V#TF58T!W&Tr+yFCfzB~+$DbFJ>2{q+lFuV`7o{epvlKCEgBp*;+U@paUjgD9T zm%;|1CDU=;|MKPCr5J+cwn=8rYUs}*7>DlqehTs0%bY(3w!*`ec5a2`;k#lZI2S@xE0EQdIR*1XLr1Ng>c<5LhYYOyv=#B>z# zSs6c$lHV|}m|7StY1gxa*+u;Ei!hsDr{s>dV7hm3`~oOiDL;kp^2e7A5mjXF!{kqy z2;zTcu0Mlf7AUZ>fbeH~^s!7^H+Ov3s&Mlt`a-Yps}XeS@bw!SzZJoKE9PwO#}X_uEmaU|IIzfh=f?MX1OXSpaLMvfR&t0W9)HTOiFIjAUS1 zcw&w02o=bw2V!nIT601s6>t<@;rIU{bZvO0rET$|LN~(EGI%h+3a6qiCh_$;XBm51JZA56P66*ct1)tv-ISSw@T!E^_E@S~sI6cx4Xubwgs=(%XTaVc<)sRo(G=SE6Mot>SfRi)9n zU_Z?}!c5f+q;MPzh#90HKD zdp!G#jEdwrW!YLR{lii|97Bn`fc@m0F!tY)VMWp}U@(JRWDFFz76&PWB2p>IXuyBA zDm~N#?6-?NfuSm@NDWn_Oyb?&E{#jqgWnHO&Qp8KAmMpC=vxS|;M_Ze5zgiaqs#R*zls`F)oa*@n> z$#~~h=pvVabGIWJ#bQ?>I>TC{xOt<}m%EiA*1LEQh+}i}(#X^vzb2fE%!0$R#al{N zt3Vi}ItxwHQDnwS4Fdx6gDUiA2__oJd#(wwhy`lEjvv;K#V+Fo1mHws zS#4v1)NC>LmURF!rV;cxnZeQEzWh<>Q*~Bz<7{NfVmt0hm%3r*U4K+h%)6KvOA7;n zSJ&=_h9ET1td2$6hJ=xX9A{kU=eI!%e(4pO7N$8JWxzz+sf&Ov@IgSjJZnS@vvc-Tb**Aij7^h~M;(V&B9vjEq(s)N2;>o9FGjRs6< zkoHzva~ooTc7|B1u#`KNq^|?Ez(7YaFj@fm;IHwH7v}9cO&P49gJJ@x&lIuU!3M%& z-cTFlO+T803Q9Yk8m5fx6&}ji*Q;5sZ4hoGfm1-2l7-LBkoe zt~~d)-r%REYkx-p)I{3~8?N-r>5p*0bmxJbRJnXDi<2C3m%=#rn~EbL+hJwFU+G`k zaJKRD0<;)mp#UL$ZqNo0V0Jjdx%mKW zm!PhzSUt2){$j`ahJK*!1bk@c$S;ZJg^(zje^)M6kfMchzkHJa$b%tBH;;r#CW%-9 z+7C#BL8BrVoHO`F#lSwlfSXRB7l@+q3O^dio@iP~GS>X(3w1W?(D4`SK=}O<>qxp{M4L!J0osESz zE~YY@jHSMl*8mXE0Y6UWts$Gh;ZFIrrvqW1?~Pq2hD*X2rTz(JJ3be|Skr1e+iU?G z_#Al$;P(rLRA>Sp}S8%Ut{rr~6wBYm6Kf!2uZ}IO@2X5#Fl#aLroR zm?)v7F?xpm(z}anwnbgg9GUXZ(0{eUe1a3&QXe9I>}9;lgIF2$NqgZz%;Z3Op_1Jy ziHD12#yQ#xI`h1#xJsTA7_G(Cat$8P3)jevMPaSnpi13$A^IaDv9&hB1DB7 zSbrGV*~QiJSlZIJ7gx#+2ex20V_Y~RAY?c9W!r!-j--_SjugVDuy3lhSQ2UHpE^(U@9vMi!pyRGT5%+*iS7dfwF2930NOLvK}H5qhXJC zhQdt`v$HYI1)Yo0mrB(TZg4aJ1msDc;0!;9X6KkMKUe6<8?KBJS)+K3#csEsPXdy! zz_yBgV_mPyM9kBeI}Qh)c|0$M;0)#kGIa|xZZSHgC-9W-@Y2}ar4``kGN}W~<=BGl zS%KGw;Y0_78FUOgjo6Xpw6h(gkrEJ%<#{9;{sfXycfnaP3c#o_1vpozq977WVApBpuTytHlT-&Z;k|a1@O6a3U5c!j z4F0!^bAaq|$#^5=VEa@SvI>Q8D6X{W{rWNVz(NX#URNTHrAHSU<<#J%Q~@>R-AQlN zL&>nED&CQD&cC_}d4%VUJ{=Pe&y6Jyj}kRnt&__3`oZy(q?h0m&cSS;MAc2)UYsXN zwV*i4m*8WW{IV^FaT)JM`D9C;y|fB-9h-Qi9GX!cUpuJoL>=9us9;&J{uaVFQ}?B) znlx9h3OZ~TMPVg8iw0m2t*~_yA$~xxBUWpaIvq|jGh=gNG~GFK9y26~;%aeCvNiBP zo)9U0NasH5aY7Q{$8w+sQ+g?kqLAuC0%Ql5%dwWJ9c?6^E~wQOBxdPY76hAQ4wML3 z%IMZaMAhk?6Hp;B=r>4!CTXqLj<9?!f}VA*ErLo0l2HUSjo$+CGXB6O$|-0J%6bb7 zVq%UXQd)ga+&~N^3nz5atv$hNaQl+oHzRwJyd|rN0MQ@Rv{J66waD4$(&n9bs`I|R zbUdL>D08+o*wa@c-(;xszby0CWh@i6^pE*0Y~4@O=JIbye4oc^?gRZi2!nDMm3(Tg-3ONg>a3|P@FiD4e?{Ze}$ z<-HfWdlT0XfU@zCn57AS>bW7%bZ&;v)fj_l5{A&{qC_DX_=1f^@g$3u%CuNhSH@}r zj4)iZQ)+zF)T!~YrVhqOOkGAJf>}1$ERhEqp!Np2+CC^07B!nn6H3F1RH<#ODq+wc z$VTY`*{1X*w_$Ozv60LHc_6)T{-M$n`4oQw-7}Pq9lr=SZDN_OmC&5E5~BXc(t^?@ z3_USJ_me8_fTU4oz$;9(4P`t++g-{KWTgANVg1n$BX69kR~9Z4eh3TG@fpN2S107N zize+jD7R9C&1Jc!KY~`WP)ehX!L{Tsh5|S91vhl0e;vxoP%NN2BK9S)TAf4d$IM1mivWgx@%FV6?9OZ>@Z4N$l(keo6Qk?^Y_X;21-8s4cA0*J zJenn(K*U8YnI)8>3W7=~e*uiNSjD0!F3dkme@t6NeC~FIar0VOSs{R2aCLx3H22$9 zDA*|wk-iyM4&_XywXrOs-|RX@BNXg90{6$q{_7@fL3yEjwn?jBkrYZueszzkpKur; zaG`Ao``?h?zes@6-c9{BvE8Q57s%ikrui(xgs;>jb~SpT`a9T)M)UFEmjkWnoS<~P z{M_3^NJM;-wP>cGUSPT<9wa*n030U1(ru;ymX(s7l3U{Nyk!16|IzmNOyO7`az|+& zU62etjhC3hTZ9RN7%z8rWHhoz7%63q2K21MAzr=ER(;tR7r#cGD|x#It4vn zNc0;Kzty{rm!Lr$DR>$oep`eg79}Eg!8^yPT@ z8-cz@P6p5qT=8pwe#^4%K&P#l7I>~ecd%4dVu(1{YO&ZORE~zvZ(_jjXi6GD*acD1 z20yH!UD$9`km|96ahmD_(8n0Fg2BX{VZ9CR501?{7K!&gTcMR{R;c$ zq^{+4Q16rZ+kXmnBnu<*Gk6F7hQ1moPkEf|{wS6{#pzoe#AmcoNeD?tIFxr*GHkAtU) zKljk^;XU$j!`(}lr3a3CYsG`@wbI$5iftnSbCqrAp_(>Kfc0|o8Z=6akxc10V}rM+ zK-VM=P}5t>8c2GuvsAuYf~{+?LY>`<>njqNps6TIt-z_`bl(DhQ)XN3K{5o!bluR{ z0`vKfEJAcb+K340I_}C;uHl#L&nS4*B>tp(`o_Ob&ZeUuj-+;sRc-()=sF@7obOx18?W%`*>(Wn z>xJDcdNdDHG|<32=ZlO1fMc$sea|E9lA{bAjYgW_0DxrA(I2EzRmBXC^w7~g>joeX zXt;88?rX{yO_@1#^uQZ@_i$z_kpe-^S_)O~8;QKoV+hsrhmIbcWj&Eu5qNEfj;K36 zpBDL}x!_YxkWaO8GfUc;iFDgB+1Li&ked=`x|XK~>ixqr-SWK>eokzG+Df^m%%A}c z+QNAmjRI;Srghb0KJ_oO*Hf#EGD*mjEHQ^jvSi@(u?#bc=Ll+#map2QyiZ8}!PO7Hw_Mw#BB~C&~t=L4%&jZW-p^Q$}?tyjOm*22yZV zkZT!orzP7WN;9s>GL8|dFi4bebAPt`9rzU-PFkX?f`zX91V z{Wk;I@4ehRvR{Ao*C4xSDap@5_8Xo<_F9R=^mR|jJ`dfuWLpvEG;aW5=i9*$Q9~fi zjNF?TC*!^RHFq-rwZXD^{CLeaLKT3PGl+rlO2f@|Hi?R%_ZVJf5b35G^Ii)Qd^0r37D_nK0lmD~5%m0&1`M3J= zUn7deLGc=-3CiEvyxuI^OW$Y8f9WsCU$D`$Wz$k<*@|SQakl)EzWilsa8Ulf#XV7n zHt_?onQDhb)-0(*n<6-9l@$%Fv0RBnF?J|CaNTMmX>K#5Lz|hMc0KlxPFx~Gn;S2{ z(B|Hsa%l6cSaQJ5=w8G)=INOC_#sVbkL%$DBvFBY-wS!*D`X|S8X;GOwKKg<89emg zidr1dur!@Ec_KdC3tR0>J_F|>PdB+P?{J&c%aXX#4ej@EMd0w1CxgA`f4$s)8DeW0T48tg$eF znG7W+y!?BHYHK0J?U!$!r!L z%c1DeXcNBok+un2rOs#*j^Wrd8-(q6V;h73hs-9|ZV&0#k`3|D^?{KBHmv!_Yj$|^ z59}!ThKh?OCU4P8*v?EmQeO}o_}q&D48uQ z!7M422rG$uX3KkZndp(@y%)M5Cooub7|8)EH4mCTXm}C00wST-yfAatXbnrLvoK4D z&ZI<8rp>@zdtzT)RI7@PnNO3{2au#C>(yYcC4%inp zuA3O1{Xz@6G|V7tm{GVLp@6b-SQmb!(oI_6(hF#+ZI+_>2JG7@6Hurq2Ps#vUc|u} zJM*F|+*B9B1$d-nVqyP|;iiA1*5P@WQVL3N1adPsnQvTsPPlnA8EfY)diiD3=phB{ zZcZRJ1eSWS?SNrUxn>iDCe+>(n5WPeM->-^5ZO53h~T`!mYLSlJwI1P4NC{G3v{`} z7`tdB^Y?jA1B)c91Vk_6ueO;~-i$0ZLn0el9LhwB3~e)sH0a{|HdFpZU(rCZ`G9H_ zn8x-VL`ppRInf%uC&7=>*KvO=L1l5|@cq+)_p)BTaqYzVEz@i)Zw%$6=E8n8uC2om zFN5MXN{&i?HuVhwd-tm1T5 z^XOS;KU=LebQ%-XS(-3Nxxn1{9NP516ZWdq8igtX0Ekt-vhDxQ9#jaw3l%0#J)VTx zvvq0;G%-R=q!&Y<&)KZRO7e|?po9(?k>4u5O7s%>Rg(gzx08B2NtCGmzYTCZ(igGnI3~GjAVE8w=yR9fmu_*kW%Uyv1(QNEK~@ zsooh6=pZQ2a?WjNS_$KgD@@8e+`7D__@$v=CdM*t8&=BuVXi}lpx)b`r@lcO&XVM_WTsFn!!K;e;&YEyXgvxL_k6rRlTGxa01 zY7uI>*lq|B9S|>ZPnmL5Lt3Gacx^`n97`R>{){JlvF?@?cP-#4r9T(bou z)A)piGs~dxm~Bva%o@V`;fEd!xaQHb@OJv*S7_u%^I^cz9S#3zv90VmUV1$czh$z= zam6d#`6?S?jDJ`wmJTs6pPvgelKIP*Gs3993VwKO1F45s@Iwd$7mwk+4K8q|vJHD} zhpbqE%-~{+e`N$0JCXD_19%%zh!mxL)AA%~vJu5&;`Y4!mnV}11{CK7Uh5kB%*wwT zQO>bHD%?B+b)oM%M<%6tp-sg>LyJ6)${@}`|3_1%aM1#j=cSk?z(6g+s1uU6Jy7k) zQAT8JSGsoc!vEFu*aLOaF6i*QRaOkSDHF7gO?JS9&KPCjTj0RlA@ecE^d1{dm}&)g z&!2l0T+uRLaI-J<1*iOFRM`1Orrr8*~( zx=ixfJ=}CE6gj?dS>xJG!ZUavLwFtz}Le($>{9{~D6S%GoTsOFDukb$XfS^r3OjMMDF_2&`nwAOF zR@;rKSrSt!N_b&p#d{SxTrKatQ0+H_LzW96X@b5UntpeD@++*6c>-GO#->rIMqmPL z3^5Bk+1C>YDT~Z!e+x{RXe48t7hWSbGH2JV5FZepd0rkXa0w@UfbPX zY_Fc=q(|M@(3jYG9t&&~JIVYNgBcvN1vTPj?w|zskvhn^L%JXAeDhaHlm94x=pI;V zkx9Mxoebz~18@y;kJwTaaSjenjU- z@VN0%>NPp^DXmpCSz1+_rBw~Qhutg1FaLO5=B~ZaQy&rcDAI!+V^Y@M#HVEAo}Ux< z{1mwUSice)M5Tzm4;a5-NTDoYKGV!Jeh>1)l#l=^wn+|0sPC9u1KynCEp^n z$PLek(1)V63P9Z|&Ms&)*iVKJ3(QQcu=K^5BNo7RQ^VHSez810Zho^aLQwjhB-$~? zzPK$P0<$KuaAfBVFXBPRs`2GutKRBvjtME3w{|&zQr?)eFasHpdg$uFALU&($iL88R z5~D?fL5GpQlaRp1#W8``))%ACk4$Gua7P3nuBFO0vLFgElK)$~Zh8^W@`B7+`$eb! za*2~wGAi9`V88446yB-1R$(`a;5lR9@WoR?Wfx}8QuBOT_ zuqFXZS(BkTTXK$S{w@3=V6{(Y`u(WjjpCaK=yb~p)SF1?m{-EfGSk*MY~-edgsceQN`VmB%I@9tyBC)9zC_NLnben zt*p39s8A?{S_Q(z)U^u_RRxuwsF5v>w)1@&-77e+uvZHvCNB=x%+GptnMY5sC{Enc z4aLrQt$)rpUis&Ra=ML|eT4TxLku`Ko0uQLT^uFUZL1z#LL&%*iX zn|g)wo(p_9A8?KjXA4@ii^F&ygtG>Ay~4TnjSM(XyBl@>n42FYw4+ZyCtg3llQd<) z`I)mFoR&x~YRRdu(4JCIa0_iV8{Z0RE5 zuNS)cvvdnnUm-WM!$f5)fJlHO;DKpv%?Q6~hUa+szl8^9764fH*y)b#0`uOD;QhAC z8pQV;nbn_b(eUu>UeU0_(>@wX&*}jUxp@B@&~V0U8EBZ)1~jbTn(S_9Sb0YeXn5pI zhlZyDuLTXk9=glKM5Ox?=Gc4JL)T{ST@T#@_CC$gU@r?MeL&sm1&@VWp}WZ9Xioz~ zjfnC2$8L$1!1b)a^&EHY750BU-AyOd(yE!aE>O7unqpwkpNvn4MP^C7s#>BS+1{%* z0mr=eLjU-H`~pORBm9~N0gtCeNT}TzyfA%U(;7-l3C|m}TjHMSUB~_r0)y!j9RiXY zI1h)Klj_ek*dWVqiX?|eHf5L8s2%u|9EIOXSq>XU%b|^SwNOqb?!}giSyD%i{ z#`0G24SLZ{mi*Sp^I=dmnHdk=G7k=R+7H%6$TDF~PZOwCvF7-rsNjwK>otMvPIv7U zp7v^5R7wy5Ah9Z~1 zPz8Z7X4_0A188t;d1iub6Ivq(h(rjHb~2eRySFheKg0w2OU$J(;Hh~Z+fkbYtX}FM z*^q#ffM?t8ceZM9qna&7H9f}!F4+Yt!X&hC>;^~G3~YOx3*v*k<~ErHoI4BC1V4Dk z&4kUK4=eM5WqZjU<^wy$ll{rd?xbo^lyM%dxj7*l=lj$z*l_VodR>V@6 zs3}IhQSxHEk$*&p$SJJg4>g`lDlo(6KxG#4b1=+)4kF#o#%`gwjj|xgT0NW~;q1m| zHxj3Z;mpf+PU`i(7oj2Bns% zRjf@k^@7wUNMcQ@3T2qBT7jp>A&YMF{jq4D^MJMf6WE@S|3Wvy&4KIbT}6CI@uCRq z$}x8hRE>;KxL}K0L<}|YaWojFhC~xbn0E9hH4WGctWIM}mkm zt%G2vpfS(ZKUiy<;$>te7>`}N+1hWl_No*$zy>@=X$`OePd=}Zs)l6M5`4Y0{-C)Z$Gjk)6t-vqQGt(=`KR>}tXK0VjrH;yfpx6Kq)-uF&yrFJ zi)o7+aSiT~d@)h=d6-Te&rY2jd@r+44!<$8lo^?&U|ZQPbM$vV@W7i4BJ)p?&kIkL&wXt_44^MJ zLvM%9m^TtA=dwc{Lw77bz;SMUM`CVa7}p~)wJ-*Rk36S->_|*ZYsYk;1K}orTAFr~ z2dbOgq&k3FC~4MO3Cxuf2u)i|1}(xNZkxv2myO&cJo6zk#x-0)36z9k4(*=#?k06y z5rU;e3L-?I?rs$Y^z6V_m3^p(L;_ZWp^V%f5gLZYQSaABh~fuW7D&@hmrRnlG`mgS z4-3ZGk6o|1*N}wTj;CS?Shi$n?=CE~Ne>W}oW>s|jyf8;IeR$i3FjNapPA;_nQ()Wia}(` z0?7lZqPQ>@q}-{@CsjdgQ)a*Md%{%`Q9?WV&J`UgbSDt22;4I=2d~Y5b34!TGUfu1nfr?`>x);X(wKb%q=%$)>V44fpF$? zAo6J-f1}`UY?1je4w4x|IFd8$pF2;EXAty$o?M&M3GIQ_FcTt9pdpZxGItC&|CmQP z;8;wY;uGHu39yr7Zdc=vc(sbJI0<(88@xiGO2lEQV0h+p^3^d}$5}3?)`%JA(VGBt zt?VSL-(jyvs9rQS;_ayihT|2;AUtp6UeU&`@!_WPafd6|yp#1R5}tmrUNwf}_hF(y ztV@h2KcBJ?ht|Xr%fn3-e1ZAPZ&ER-P`9gc#TRX4O#{{GrK6SKV#TVhuDe*;jxto) z*l@0`B7zvhVFuLonzwk7_$PBLqYdIDJ62N0I{37}y#0ip&>JOp8_6V~K=MR+j1~bF z=#(=laxf4d!#vf-Ms$X~VJHK~_;pr{crol@oeoOw%u0_8!|~Jb%9W2J?FZywD&hEW za|qg0;l*;xN30Ed3*ZjJaUODn6css~4}C^>=B=O#SG!I=2mkL_zbzO!sbEaYfW5GJ zRv&OzBh^u>sVPi{GwVLcFf1@K^N|Pt_`F@NaLR0x3_GF54{HEskMBbsd)D2G|Hs$O z#{Xy3KQ1M{*l({qSK{Xk3ts84B~F|iL%MS;Wk@%`rF)L)?(x%wn`Kiy(vMXAT`DfS zF;iWtOVat|yA&MuGAFwfb?FqFxD>}S#R!)IQ#RM(0R=SkL^up?p7H>yT|Q*t*o;%` z7mdwbRKebdA&79{M|A+~E<~ZQ6xetw-1<>2F~Jbq8wYG6YW3#ilyr3gJ;SE`m;@V4}gdl!ZYuaFDxF1yqy_KFOz*-K+0I|rVHCNWSLqfac(8HV3aouCsY9&&^Kf^ zD(3@SwjLyxt8nSKqnl;<tCr@1=iQ_LVHm^M+af zUvh#5!HE70Y2XS*l&yMPHBQ=w+7}jm$6+f__wz8<*c>SZ{zhDvN7f0heMv?+<_0Gh zRj~pkz{`7+A)Pwnr6=q*f-WDsE3C0bU?zBJ**W0if30+)sha_Nv-*qwD+|pC$)dsw z%|dsqXjlA&ezE1BSX3iKHkVceTneI08$LFW0THG{_(^Xe3>fk4NSurvgDFcQ%k#Sc69$9p(l7AQ(IUMi*zol7%U|96{Qd zn2_5&p2VrUj3?py8H`Fi?S;zbY3Gi)_A+fdpiv_ItPCAPoPNvc(0}Ug78~ zLV!9w4OrY|R)ulfJWiq>lsATqNoW zOVbn@GnF*4jX;{XrK5Sdd4rVvcQQ^8Z5f@2~%gB$YSzv1mF$#WNQ`vS-0vI)D+0-sFeNpGsW?9_N;(vI? z9a{eq)*ofdf1#?c*<42d!yA3nQJ{W^GZY_a5FQ31hrNvf=n*g1Z{MUzkDa4Q1s>25 z<`m~~s$htM$P2X{K)qzM?(+)lO^3soL*C<7RX?lGP*wkXv;U>2$Dw{bvgG%U(hmSm zKw}m33)8CcRCFv$lRVqPEPzxH66Sz_SKG;Kb~H@?^oK5)@(ch(S$!e_wu0~W-AqTz zL`OtgB6r9HK`B#EIN%aQ$yR11TA2}EjKjqaMn-fY%S>u!nMctWAg4;esnSKWOk2ji zIj9~rAK=$q;G3mCXk4rY$0wj{)E(5Zqc=TJs&xQ!Scf;YhoYkny6}`{maUKB88Rx` z?Yv&F!yOj8S$O6SG#%)$2+wRG4>2ZIcN8K|EXC>UcWD@V)5L&mU;ZEo1Sloom*bVW z;eFk*OIGDc_ZuL+!LN2-^0Un8E{d zOFTdh;byM7?e+Vvk1RK`Sb^O+>#j!GgX$K887VR&Jd+2qOJA2UmjGCO)n{br)1^~^ zC-BPGB~;z2LfUPjTbn>HFsD=cFkH|F>_-$!sEm=GGR7m(9l<0%fc>CCR5{H!k(wdL zb*DAJ97V#;&p>=8eUrP>7bD)wX`4U-Yz;0zf^>D$(v1IESqyy@cS37KZ5SrRBL#0O z(=@;&Vph=!ZSYAuJK0Z2DUX&4e?*-$*-&l9ltT`q8AE{w|4HQ z+JK#lvQ;EX1cGbWcR5QkVl3tj9(N4Cfq_X5zf!WR17FjFDLZz3C&&Q%u_S8PO`Pn5 zV=*Oa5gy=J%h2wQj$x!j#0l5Ng#U$O!FcWfNid+;JRu1}19=ZTH%*rJp^AQ-Xarwy zaFB47HcVO`Y(b9sTOKoaLoYP4sFzlSqd8vTjH6i<_8<*@Vl_F#@hOi!6IVEIHRSqu zA&gQ`b^QBG52{|fD8Mcl`22^TCa3e7Q00SeOb;E&z#AkC!eV*J!d>K5RRNFCI9nne zj>je{fkqzV(l7m=eKo=@UQJ7sCm@RVZc+S>=Z=ghG zfV@E_sa4 zIz;_RbCGwB?GCwDEFnjR5&|$bHc(p1A zp`_FhzHz;%@Hc5@fFwY~*@uC)e$muCc1k>XA@n~7S7*iC_?Yx(PebPqY*Go8-^NeC zKxr)5(g+eU0kI{c4PoESkg`h7TdVS^M~99F$=u(&!L_ic;fOs@@4 zw|RKxXQVscIbiZ7bUAg$$LuKrm+lKUBqs=5ItXG}HeU@a!0$VJFZ6hiPtW>WPign< z;c2`xzm5Ybo7D}&|C`tK>6on)69C{K7!Ed?P5088h~W=XkPOv)LLrUGbpD~kdw5D& z%xu=$4y-#5y<>I6swoMY;tihK!!m%sIs);SMA>Ie15*+E-vRV4&1&CWItsQ4xSv3$%KyNzs5aP;)2d;LByCH>{N$KDuAzHk z%J|~4MdtY$v=tul+X}qMvVYTQ7vigHSOy$D|MTMj*JOa%qQ7L}4ayKq`lIfsJw(IF z+_XF+O7jZq&$0nSI+EMs5Z%wbgyszLKx3KnS0+f-2Svo3E@L5*Kx}Lt-F<|8eQ0Ii zxVDYN*~>5!7{Re~%pD=k@x?V5Yh|lmpkTYIrR+e2R$w;!R_QFFnW*9yD3|SUukfBW zrP%z=&Z+~dMM~@x;Y^q7TV1$Pk7LuM@y=N;qAXmreu=*4QK-A~aTK8ps>!al1n}wQ zpMGb?1nh6HkTNw&oU%Gpd_aeKk`2^i9he@WZz}ao)PK`LKGj+z_+pTm3ET?fI!LDl zbu$ysq1-sn0O?Cp?bfQeFTK$1dw0Xomr2Et<7)3xkG^S}FIc#abBr|n1iIm6~1HB^^X4~31VJJ3s(RE!IwHr^u; zfMj-yxrwm?9>FXUa^v=2Q?2^6$fGY#MhwBMWX(SAOk)-W*V1+Yl8H|cw#y_AokBf1Vnn?nNl z+S@Y#pNnOnsbK-Y;~N70ybG0t>W=3f;87ai9Ob`hX5TimZt5#xs#F$f3Me@_k2Kdz zJJSby9l#!(y5-x+y z*aS&84Z&$55td2f!xgw_3oq-%KBDm+?yU+&Zy8Tb5y34heJ0Qa=S+FUW!j`^v5zsOoq$3wtZvo75x; z2!BzS`@ZH|4z+~jOKP21Lha%85xCp#-4NI?LlLO_Hk+Id_%$i~0`|}wQ*7t6%u=JM z4fKaqIG+6l8ry^^vl!BzCRXwsP6X>ubYE`Qg=zHjUALvjIwW?Y(0s8N5 z&H(yDa!&dfc0XB0MRnS^jUA8$f!?o1xm}wEItu5TFKxV2>jRyI`FOp2w{Cb{8Yf;e zS!j+q6{tPZqBb3Jo)ybzZ+}9rWyG{ZRW)0~!gN(`)Dst#LLaZd9h%HFkNO})k2TQd z$HMtJLM7pf4hNY#XLbaYHggRVH7E{zhj>13M{{^$U026H1CJ4^{WBxG5QsJ_ru*4- z{FOvSn{c@BfMU%ggiNF`Isd{OdJ3443%e1}U+HhynyM4ejJGwC^I|ouWfgLTC5LPn z`UL}R+^89*0v9fJP*nDSV;MayQSuqOUBt%`o>6AbD0JJL;5js18csGGDx>9$h3DNa z)*Z(r$EaPkvBWSK0T;}Oqc9zftf|Hyx?xc|0B4ku=x15-%}nt1V?Q6|(}#FSR!jL% z=0K?(ttLDkYx-C|Ki_qso%`MHwXTI;on17{Yw5l4zJLSe|Lzh=#77Gob(I) zga25i^TE$ySJkxDZGw@9)oQ|jh>d~&m@m)Of3(Xr^$PG?DmR4R+t0e87uout7CRy2 zKmBtkM@C_0e1m?i`2czj+jq-wgG7pob45L&7XX2qG69g9eZNvzzzewv{S`Fs8mz`< zTg!UYiGKWG-7$=-QpK2b&6R3hx$dPA#j~5dK>FD1G!5O`q#duE-G$D@BFX%D`X%gc zxLHnDK)&i;)%>at5c7N6^%>@OsB9IZ(?MV}p~X$Pa%4gQB57sE(QwybP~lzJ^ZA_c zf0pCvvigm}$r8G8uvH9Sd|fo${5F_|l%b6!X`@Md}sdnK$!2eK`%vGTgwR9Lw46%5NGULQlF}L3ELsI7OAmrY)cs64*{# z+=kB)tGbCf&I(O{7wA|S%u@}~vEm)HRPskyQ_bk2Ds?$nXcoP|=^Um)eqxD5sblzb zlz%%$_`E1J(*A10W>IP=?kU6Duw^qP9gcH#2Szp{^`+m0PkP~7AfYeb@zu;7@QM%C zujK-q;(nA9GUM3q|=ok>1Fjf!Q18dz{%w}T2X{${CtOZSs{5#3lQ8xDIHT!oWe z_&>D`{-X_e8}%Sz;hWo2U7SES>UdbB2I<*So1TsbyfMW~)gGbeh4x6vd02%Hdn6zL zA*$d?G6k=o07F*F4eimsAJd$Nj(VLve6DvXHezA8iPJ=hu2o1&b2N+?&&bqbK-?T& zXr^pJJoe9kkBHDRH6jxZK9CXUfGfDSrv(qU?yg1(;3OsFCQ)qqyiYMogUhzY@zRED z$erUZ+EatZD zT6YGfxN0JnfN=vC;AuiLU!@%LTlj;|3dpA-voMj~Coz=TRkR|Aj$Vl}A7&7RR^(=o z-hja&j7qVaM+!m2Rl$a(6W0^txhxxnWB0lJoIcp77!^cv+vLGFM9UKm8Wam^eI84~ zv`a%;+g*jJbZsb^f1JqB^9Wap3mM z)^lmdK|C#zsxltrg}J^}r$3ZXRHZ$O%8dOG+PxmEHj|EqCLaJjPse7wO6#-4w{NoG zjQE~tP`08Nz?lXesH&o@3(U_5B*K9lPMPR7nG;hB*BE5=oO4r zrme05a(Et3C4XU}R7U1ulJuL_QdBC01b!* zijRtocqQx|ff6c`eJWsP4U%B72gc18$ljL~*vAU|T|@q^F*jYwxxg37G7m}V3^P)< zFmrFN-7(Yu+4dq^C4KJ$7WpOlE zf{Ix#rLea@Gy&(SqNJwx!_6G)V32kcZkk@k!@b@|jE83LT)U|%q9b%$G~x|c14zwv zZ3WQJO+6CGAlfnohO;C>LRCscCS~*obM)mJOMQ$S*hx{1^m0U6^27*RZJ49}(WJ4l zxwkkfS_ zEkn(VmuaXfToeY@NZnJLh-Vn+0zoQv|990e(`1BF+&zOr2z;6PyFAOR?^JV!lwmPD zZ84#|$lNg&(C2Qu&Z?#Dnb%YtVd-)n)#e(a2#1xQ945a zB(dTujGgLC`Zh zy%m^b#}b;?oHdgy{Kv(ZE`!N5J5rDF7$St&WCBkWq%DC)RY`L2BS=@_MT;;B(fq0a z!gU!}747vt^%fXs_XJh82nnppt|5rLOGITmd7akR&oTSk=_`{_!&OghUo!MH>ysw} zpAdMeugY4k9fH2jmi7Ymb}93O%C<}1XF-2KCG-^Ii{_6-Dgl^&v3#(~V*P#qhR87R zKnxR3O#uLx zD^(fh___-y9!!E-dU!xQ7&XXW(nb!+B&d-n1Ir7se!d>sLSiU5u&6<}Zy`2qF_Gun za3rD)FFjWCt?hWd0_9Nnd1f1Vh>WB*sR}^Y%zTn+M=qv^01)w+{~V(kRBJ7Wi_{%9i-?_40{m!q*@7t$+Pn?d=B4lheobhop)ENt- z`Coy#du!E7=%VXOo$xkkzpfKZd<16tE(BC_p-< zI98E75^Ld9vn!H=h*@aXig0{Ort-GE?a0KKl?7vxI}e&jBo19!0oy~oAL$KSd89XG zCB9xDz(1txAtHg6Whm80zeDp|2Gf5VBv3MYG|vj6vpTD)yG|!&GfTk@nb#`cNsn!qin6JvNuW ziI8?9=U4pCs8Iiu$V=(rdU{sW70&n12j0tU(h78t%CYn2Ui+$DXrQ72)pAXxoMGRJ z-2+RMr?k6pb^(Y`XMqZb2ymN02qm7v4%1!cxyQtR0)Q(e@7WSAkiUlaXh_h)@{iX! zz=ONabJyPBr!YN$OQ4vPSnibH*>-c?R^3?F%l`&r?=)XA59hi|60%^yb}BbuMUZ68 zPRw&#&C`MXcRL(o*-qX`g#mT=n^vg@Aymn|AiTRkQ4D)SfRZv^dKZiLi1Iq^Jyv15 zJG}=Dmn1{-0!h9=8Z?advOamleS&G7*KQ`I+^*)7ZWin=k!K6+=JIuPn}}k<^X3-c zf;S9FvA@G0QfJLDER)7e+gpsPK_ zbDT(-=DDrZYN(0TYV=h@iODwoL+VS$|szp~p`vawU<`Y@^p=4Z}f-2_ZfQ(XZCOVrpVk1aI2 zow5Fjyp;^1mE<_WRyQ3(VgW$GInp2V0RpC^F4(Cc#Sc?O~8=+TfR4%SP{l0rQzmNEYKGaMV@04Wzrj&W1|2dJvc zq}_BDo}7g`w2?%TVwOJ=hybo)Mj7ArIt^y)8>wRI(11`d6AEZ;FxcvMylD{UI*#|b zP?aJY8zn2my`2DXbV_ynEk7rjpvl436XE8Rkhd_la24jDSB7HqANsTW?S`eJvHyOF ztz-|34S5eNJM%i*S%?Cax2AG)jVMYebAh7}1~s(d1aLn13Y4eq1A&^zgiQ(!-r4Jq ztEd@7)vl?zb}T5Jz^4?D+gZu0 z!VV=1WAl$cPXA*6?Qk_*_(`8sp&%}Q={%CGfmG{|ez+c3Y!)3DP=wlK{=sJp_zO7X zawC}tYO0|C1<;Ynm(gR#ijw(*HB|&I{>ZdHiJ{Vke`rJ^#|1#easkz{TmUmMSq6*w zLK{m`Hq8@+v-ISsVmS{*-TFAD6xOe>F^kY6b(XIasQc@9C2_3`-D56e0i>`mRul@eBm~Vp@V%vf&8yvRO z1V+NqDWf(*O6cB?#+N8d91fg_dYduD=V|M{4=t?UOICRRs`h(u#<%9(^#21YQ4jky zCS#ShRvR?tvf{6Vupwi@jua|jsiQfIWGwiBRPah&DuV1svrP0OL0U0K>_ zqeL3*iSh&`PBJo|LevrR|d|tStd`C+`gi$SFpEA9`boBxaGZkThnwyG|z`(|7FOY@r zQ9a7PT0zSg>tyrvxoUW8NHUAB^+DgDpf7naz=E>9UgG;GM|-?GS#?;HYo8DvNDG$! zQ<`G*X$Y#2iSUDVZ?iVdsZ^^ec2`Uaf+%USB^Y;!!4AeN#p4EO1n_2im~wukzA%6h}q1OvfL<;QM_B zXYp5J`fm0kiixMtFERWs+yO5#aP{fZK)Ay|<;@D)eX+?Os5v*B7SJ55n9^_u&|tW; zOO@4}4@U$vCxTqYOJhUAopH<|pgBcOb3mH2Ax?Afj+%4i!J1tptvM)>nlnt^K!zQS zX5|R5y9t#3&WVh+Cz4+k978yY*v1N<(XiD@ZqO1|V7I4Q0$IYcZ_N zYMgu+jU|42ULB8{_4}eGBYr`?-)ViI6cfl^`7bp8V$1!b_6=|!6J*{vSr?h!#jj8w zut7BQZ+LDcagox^hKQH{hV1+b=ebcZBd*zLzQz~h<>`+Rl?s2f6$7M`p1ABHpsg6- znrc1S#)3suYkgCuZ%(mq3OX8N2{r#9lHVNc-lPr(Kg?&t!I}T~X0SK>V@o9JKlslE z75D?`GRWZy*|+cx&SS*FsmC++!1T9m`#1iG{nXeN3D0{!*0m5?IF!Ys`8WKc1F8Q| zQZ#Avwm}lSEHEEnjKBq8+iBjy*bxh-{23O$3NFAkhaukSm%;HZS*5nC*(kU9dq$@h(vt0Y#JmE;m^bF>Iu71Ac>c5VMb%8Fzz zJ2|7}iFaf1PjOoGkAv#|pw&P}hHL@G_eJI90zsh;Ps~W~Uwnq#aAH!_l>A?0eT?1_4Tk)QB}|V!w|carExHq$<7;t9#dm!ZWAyuE)CW^qi|}0(wRpD6@)h|3ag6#5ANU z&4M$J`(Ida3gSnwzzbbgN~L2P4n@TFaOv46GnAwi^(J3k;S>v+@Lxd&9^ zOTRCIPBcqDu$57ke_+N9z$gGJ=9Aki$#fpqYqah}MMM>=iS6x{vd%HK(y;Gg1xP`1 zu)w;N5$}e*lQADT96yq?lC77)&ZnDk?!rFU^b`(x4`?Zl4PR0|t+NqG2*(HEL4}vU zXM8};Vc~fLa}U9m#3A_WjysS{r%mBe{gxHp;H0MM*Y^-{x9?%oqp8EfGr2;GHou`F z0muwlUg4dNec66Gusr@6LoE%oS~T?bh68f-vYWiap@*}55IC}j1BbsHvDiS<$c<}>=&N*CMcS81@^Ws zKsX67kiDSEJYFT=T%g}faNoo~3G;)4yMHiEKHyXg?*wUi#(XYYwt{6pO=H*Eav2FQ z7u`%HF*Wkzm&}Igc(ae>W{KgWi6(+a9d~4<+cY~}o#{Mb9gc^95g(afH)`aL^_bXY zxuaRH#Cty%Y{6Q*PYXf0ke}_(&#+@Fk4WiQ;-}IN?+kv(N0*pZe#Fr{vxQdXwwpxp zhrE)x)85kZ+%+OvbEfzk=rQ_BXI)e=qT=>iM1lwYA@Wxl?J0YbEa zL#Mgqt|d`DvGy+MWdyiW12H&G)dtKtvtq=1Q}++gTqrP+{s#n+Lsn$cx6BQxmgg=D zY@B;aWq?(PySEl>(c%+ZP|h6l2T2k-_)x*t82q5*VHPF`YO`^5((#&Qlobb72KI`T zWioKOJaq^xggN*|!OFw(Ll&TNI+VxCT`iRxPw2v%4S6BvT^`uW9dfkZoktu@p;pm- zHXfB(xsNg`hZzGo<`kP`!^G}niJgPV#%3cW_S)Hk1@M1AY-!;@2;RrMNrBD&Fji)V zvvt!ykjK#e<0Av)5p6q~?T&MgXaKqW9?To^#UA!Bb8d*;g@ooRDc_V0ftkGryKi>4 zuV1Tu1=}WYb{&t7KHO>>6ugD}57NMfQSYx|#(#*Q{tUDGJiB0Y3TLZU(q;EIAh1?qE@p?eRkcyuWXN!|`eOKCLVkuHd-Y?HKvA zW3+tw0e<9DQLq;#9g1%@SHm6n<_EF&Q_w21rnu6V223&84^w>c6g9==Fm>j$>qNai zlph}hR^sE$eUf3i1ma+#xfV}5Ztk9Xau2EN%;|WVI!Dd&!7$6igKT4l%5%S#`AoX?CbV%1wDH@eVzP^1va#0F22imKlf6G6(cNTM#nfc?B!Yim&M_p; zabFA@Cs#Dt+@5#p3E`Qa5>pVEv}bs5i%f3@-Hm*~zF}_Odt`w2<(!#D`Hsz9E;H3= zY-mk1ko!w{CWBzn5Br8-&9LY-hYR8^iwfe-#}7yxX#sackAQ2oegb}pBb(N!_f+K{ zWo&JEY6b1&#A^k0@5m30I;;kRxe?1){Rde~SP`v0cD0ua8%s!6$dE;uUaXySSG4*| z)r-Lu(AGeKjJ#Ae!W?i<>y4-e+v-wAcXUcH}LF3?r zIppok(?;HLb7*CgZhEK;x&3fhCgEy^3&c5DxMw&OcdhGt~=`lIwgO z*QIYp?1w~(p6Um#x=8#Y3I7gGKoD3Kq~-56eGEMpQb)I#%?tgzgvPk7>MSPjzg23o|g`3a;`f>OR( zR*Fb}gtCLpoFX{^$y}Kfeg9Jg65${o(=N6?g#xjXjTK@M{sLnBrE&q>7|{ajeWCsx zQ(cMc@aBhga&Dao0S5SE(lxm5u97#{FX#|UrJSbXGERfVeVM(F^4<&0%+(Hi=~j_k z8Qr^!B3_skf5LW=*kABhBz=HMAbtI zg`Qp0kS|fv1t46a0k9-b3-898zuh0G@T15Op)hQL6v4hm76Hp&$v2qX+^XwV*kLP$ z+Y}%sCie?uMj?qO(F|R^_5rv^_Ls@JkamT4IMf*HO?VAVr*YDGgyKXdamw3PJuVZe z8wn{ehhGIg`MdkX%YSY?chu(*D)-9T0xmSks{k;U;!{S(1*YTAcH7YKJS=GBkQG*J zO9fkXA|xu#YLI+ZuRIQ825ZU6mv`Z47<4#d$M-k*9a&Y8c&Q@sLW*aN0A8a&fEXNn zQH8ha3_Ps;7Ik2&?dr!Y0Wap{YIn32Kid|6yX9h&Js}sbv=xfid-&sx@+P!{oZ^fskz<-MVGGB93 zHA|zlMtzO&j|Lyet`XiIOP6hD^dg=GThQGmQea;*x~9xqShvm|Ei7*gH!awN*gP1I}lBoUA#{dHb!;irAI6@Hs&2ZSQ&TXi6S?x_>jfG`lLu&v9C69Z*3YK=%8 zQkBBy7FWwX0(rTAuALl9VEp181r0|7kCE(jPAvr~pMtyc33#Ac&9)1nKqiV5&a*=a z!-JlopzExlC6HZp8k>}`!`$BFewh5d+FP26-xhIMrozzO_(IFrcQbc}- zcgSPk-<2Nb;y48K!dd$TSd(M#`6aiTBk?V*#W7}t*D45D9D6U~M}bxLUa*1tYJ2ZE zTx0K*^H3$+gI^8!p@x!gxV=nLH7WU!AtO7~8iQMWk=FE!4%G^nTfbw=j`1s`IbR$u zw>Ck|+j*1zVwC-Ynn3Tyy5z_&ycVnMotVp=46a=-HwR(+7j=oT3tp;;dHwn)2TvS{ zfbacq^OHklIP3z1nxzI=$~vKNYDD2kXABO(l@Wy`R$;8Aw}cy+mLto(f5q$?kFlx(Q-(xmdzl~0B)+aH4v z!h&u4BihAY-ta7vd!XW3#VyCgZ*3;@Y;IGn=q`i#{Aw_<%m7%l%w-I_W$un327VrR ze@W6n4`|rvuwd?_&4S6Xrs4})CAM@B*On3o2)(U*8I6EPsoh~)&6$nTZuIgmm+X8C z?u5u9_e7DYO7WD#kNKri-~N2VrDFXNC{w$f+7{gpT>aSwykYwtZt#`+}%!D!HCQ(%sJ(EqYkKVv8YAD<>` zB@_FGx3zecWL|iIWUlr$gDgo;gKJjaQP;a09o|WvIxFAOEcjRdv+T?v=TMqQvlKr4eDe72&sN@Ct7Ey^$F7Yd&7Yqa9Aw(l))TdNT zw;?JGLz&iD>#s+lrt#4x)z8KUDigzwE^GTw?oYntq;?^yyckZcSetw4YA(O1`+TqV zR5%lCy=A7`PB-%OCBI~y^q>H6lO6y|#D1xBkjxxL!=dMR}TS%?fo zR9TEl{rg*eStW8?i)pHi8rpe>$eV34N{srII_m#1_a^XB6zTgoK}JVln0Q13f{qFp z5G5#Rq5+3P?P$;-=tjidct=HzBmq>8ge1Uh(~62K9=qatthXqN2OdC>fQSOF3Z5t) zJr3@|;=!?!-}Agx-P1jp5Z2xQ_w&z3nLetk-ur#4>aD7OsiJ9JAWUYC#8R{5WE)C* z9`DgnTtQOc4{ZG9BK+VL9~t1{cK+gijob%HPSLIouT*V}X)m>1Efy0Fd%{?k-%CB@ zr2S{CttFCDBakGJ{nl}1G60iSU^oZ_;-&TSi}4~nCw6p_>*W5g+(5gHDKwz~Q!?L8Zg|*_dMwXMVp|mtdit_s)A!=NX zfAQrDlBP1;>Y7^w;0!7HumT1HKLl=gej;qWjKb=4%Hh|3Qg*J{ziSabeGIS9wZ?Q6 zNahm}o^$3#YtsfQRpNSR7Uh-&EHym;!>VgI)xy0CoSZ8tgMCF`m28I4w6c(2x~$W@51p|bA;gW59o8P zz};CXW`;E?GgFkU%#6T+&jeuLUJ7Iq&%n%FB;P7CBl;teNs5{I@bebU3@eVeXKzl6 zB7vhAlfojx;2otyPKuu=7awA)EM9OS(P&Iu?mEq=-G&O(sEKjp7o6g7JDt)S>n}A* z7=+D_h@OSyH_EXsxVoZq=BbKU3>&He8~cMHHU>fq5mGtlxCDiKtDL*2pW<9Ua*lxb zTtW&kuOhjfoQn@u!x8^DD1}jiiCBV%4r!TD@wW1Lw`b+^R(RF>vpw@l7O}gMpd}Q% zBL4AvAW-()@iMAWky7ysyG6LI9M3lfl#7*d135d{vBcJkOj}`Ina%P zdpAIm9V}fz|GlSFv@n0o)c(j7!iYNZg2Hu|1DN56oh@#3SA+qw+9g;pySym&5kZ+% z1(?u$VQeW1O&T>ke{F>^99^EX%yu1w(*PB70Ug9VlLj8!{4KK42^|iFEX5mGSWUW` zWu$0>9j~DH6yhN1spkx@UpIb;fl+mekI=LtU7dHdR_9$(CuY1mz8nBBPGyQg=rjE) zhef!w8RD-`1Z54I*D#`@q4Gtuiu(I2+JS_153J?VgBCUF-tGwCi@{g_IKx^ZMAcT#B*y{pr8LgrAvs;>xITmKymJR%l$C9)Z3 zMkMF_Nqz+b9c4I*o~UF!cl)S@D0J;^ziWYfR^TPM2TI2ur&>qLjES&+f=!f`hU+hq zia2ivsjWLhfWd$S`bo&0MztzI2xuSxffwL~J^MCQTZ9FQsjhSJxVgG+K*p@7s})-P zozu0G9KTVF$L6S6DseN`BdikrDK^Amw8wb?Qp}Uz1Bk1Ey;Ts1OVC}2zPa?nb0vEQ zQOQI~XEjS(fj>xVq-7;%B@wbv;ZcGK00-XZa)KG$vKs`elC2aA8b$W$O`Ww3K; zX}BmH56iH563}{Q1*eh;4i5nh#XzL!0+@B*>L?Y}0T^)Au=JKFnRY!!mB?SPR`^KS z5Uyggoo;0W=98)_b~H-Wp-$gSRYHn-Zc*JzdJafO3G>__|JS zAD{;=A{1G?iSmsK7yS9oMvU~6Ptk_mu@l`SVHEfXk(}x26a%4H>>H#G$5%ls(QR1> zT||H4FDh0#7Q^H$Y`4`%R|OGouZ&|ABF3W;>S~n|xLN=SbxvUlS#CRMI=6~UPS5H2 zU;xN!KS5BNzjSiX@WOm%B~@Hn``s7AtTW#nT)n;X_^8@C4C4kEcFtcq>0^wO91*Si zxiSRGeRdAb9A}krlX0RW!Lg5qDa4ys#hz8-T#eQ$ipBOP%2NkVy)a0*^sDv7#6JbhI-|C$s!!x+i zQT5KVt1chd`$%L%Vt$G0kiTTYDU$0(lzP4EJ#D?{$R*-`W?u%*wmV^1USm~f zqp1Or171$rgn8;H8tkLyw1-*eJ^)sCp3oIyO-8eL+r)b;1;!;yf%_=cHnHCS#$J4_ zP|;UBb^hLkx2l99nnMxQuy)t5<_WAG7(5_<>IXRmfYZ_d;GrEaQ}hS>M9_6tlXOs_ ziBuuzgx;7yr#O~6DUL{7>UP-v4Ef;;@6hKX0uN6fId6ir#${$!n;x*UaK!;OVs$G# zn`+9Q| zb`~`43|lv0kN{-chst{zF4VT0r`N&vj>Ib%r~;fth%20(JsF8d*|>C4!HS@F>|)PD z1BJb|4Y#iKq&)t_t~#3@?xsG{e*<+awUFz$5{*)5boz zJ4*$kUEpMJt|ES@&!>5_8xa9{vm2fI?4sWCX+V9tuk)!&9}d?JY3aLzlFKm-R^B1oF1os9? z*FK5@gTo6e+qA9yc6YRT_haGuH|5=u$!COT)UW~c#uNfDXdvG_zNS&S0EFEMBl$06 z5xzYRJYHvN#X&Y<3~vJ zuW+pm>xDH42hC(~9R)PhAF_@NOBm~{~;f;X#zHh^b$x( zp3w`g@fL4Vw!?*F${U8{8D@&)?QWH|OJ9 z{_*-{bqNq?R%(`2yM0r}nob-np9uXtrJ!q*JNq?d`5T75U_mqK?=iND6#Dq{n{Zh@IU03&ci@ zU&Pp9#pHbYB78!9m6(`A^9b_GWX9Z{fKMnzxw`Y>emDs$2gV|Ht;J4A_SPK$ockGi zT~3O>d737;b~CyR%(;ZKDW|ik7PhJ-OK>MDpB^2cZqKyU&Zfr>70*NAiHKUXByt`k zR;6avorf!Da|~Osx_vsV1!r?D$~n&FWA;1KIvXlVzn__mB>gIw1)74B*wexOZ^}B# z7&#>?**LRONDf z1IdTz4(SN3B!d^&f3`S-d+H(yNNaPctk+RW{5P0bCVrnp?{+KgZSD3zxb9|k6%5y_ zp(ZdCjRRzImR-LUVhD$IKe^zd@QeU%3i>D$R&YvXQNcx3;C(VpAAU4wzX$L3G73WH z0HfYiN39Q_iIg%=qD&Hx_=(^@y>&Iea>~rmUQ#_&q8hPp^nbZSv@_+);VECbT~{U4 zI-e9MX0lObCg7K8sl-;mr$lIuA=^j-wV#2udVr7~b_UApknY6c+*}8LJ$YCt%Dyj~GqJQWCvGAZYXaNj7k@@KzKu zejTV;a7(!EQUW?TTt5ZB@$-blT5Dq5N`6fDlV?I>?IZj!{*8S=4^L_3=LuNi3NaNS zHwZupy&@ibFioT)-Xt!^hTAG^T1@B-{*z;0E%Vh7VrKCH{5aN!qa9wExN@FOm8a6t zMelSJ)e?1yBdWp>S`vOGU#L z(_88ijkqOz=J=uA%7R2G%cb#<*ljV#&qW<`Jk?+3O(1F?hL!yBlW?W1T8cfxY0|W3 za8lf=0`?3p3lRlRk8ayV4S9rF1pCTKD+mgs*$U)n4u8$i$DL`AN^&tyRL|fGC35*@ zc@)ua6w$9xIge&8o8l6oiH^#uAw zHaodA!Xg6%5lfzsZ93W$JFGG?*7JjMej3&Gdm;xYstFf(NsG%rUe8vS!pj_RJGVhv zz83#>z}`rMMF9j#EhUJwOVr1ZH|L_vxhQuoCaMc1dU6f%V#ACv*eHcZH<*Ir|JV3| z*tSf~pucOO07pgD1!g6m=9&eeP*k*32FMXa(qa- z^TH8JQo%ArV~ikNXZ=^g@HBD`zpP3;EhXgB%7chZ9@1PzNFtER90cs4r+TZrZM$}h z!Vpk$*s(Dh?258xXjc}^0J5&E(C2N5FHn&Y))B?r`WxY3uU?#28j)jWy@#^MV#}>x zSGBJZ8=RXk=|Wjy(B6ayC_a&ruZVZMR7T>h)Ui=^;t_$7>;B1Q4I{x$^T>~h-G2*6 z{w&;!H+aK!ioJV;b=Pi=(B8pl;2*lI+=9r24pn1cVW?2IvZ}b?;;Np+66U+3iV~`1 zcFT=^09`gHh|xe_DP%zc@-(H00}~~Qmin+@|Em3@y~M2rA?LCd3l8TjiQfb&*_Ztj z2o1uOAE6X{-cs>s3GqR|iGPSs8SptMTt5vjHBRCBOL4=%X)H{1!ExakU4SeW>77n^ zu|Jv_I`Cj&bT=^ipQk8B1MG6rgkTo~Uv4Hr$q&3M1<2Np+kb3Id{}Utr=pbyxfMOr zT1A#yQNu5+$THrm-VvOTglbZ-NCaU*MrdZ16_o=wFbk#^Hdu_`(Hl`WiATWAEWKPkoife%sIO%v{}kS zr?}@N)X6M?Se8SnD-rWqw;&<(y{YJw!@KdM#>RFZgMIKZ02bL#9>x?|fd@}wazFS3 z4+bq}SOkNU&B!rgKl}z~p%MO&D7kzQrMt_c_XLebM$D`O2-&(Sd^HqsjKnWo-m1hj z?G_K#irfWwu@ZcbPZJ*~kq8|vh)|z*{G=>NX}l*8FStHD<4*v!;7SigA3eaO=txa~ z7G>=Om!k7fF=XxfaJ}SNID&g&va$o$*IMOsFG9Ai>JY`}3dLtc^4ruR00zQF%;9#QAAQ_@PjkD6phIqVkOHtF zaXHO`Y;-K0G8wRR?Zpbks}P04*y+2gcqjJmV#cWz-^1P=?#8K()l0E=Ye^0N`7xgi`6V%xkvM0uYI(JiU?ytU6_~s_#bK3W)vhNQk z@eSA4;l{D&c@)4Qom?F|Vt{Ko4ac7AFfk_fe0P7xY8Cv8I!40fIpm?`MDlyma`r}3 zb}hOAB!gH^gEZ4MLIMnj4C+x*0!I4CaJox|Q%Qy!ZIFRyC_B98Zwmjh+b{X=p$B0A z%dnr4SsW4biK)@i*#9>q==X>2y?mmekIo3Ri~UVdQ2PG=WY-4Y3*WsspcKBVmhUL! zJ+~^8mX~;y)d)+^YH7dinz#S}_|B>DwDmF2jok#2+l~Hx38M;YTeb{-Ftk5uQB~s6lLTV# zB~>Cqk4YgC=o~cR66gR`4GDCss>UVI6c?zj1nOZsP@GDjP49aNbPx$tdT@FIk?KkU z!9xn2I64_tu=}*|jeYdFY!TuDcOohmpNS3@?qOBc{X})&J{q3W7{3-b_7PvhqP*(! zDL#8L{ttdzqHSws$AbMUgVMH5gF0Fbc zel0JqpKw6ImEpQS$aU4j@e6n{E?jpGe=Ct$#owwbQ?!t7+uYZMzT~)8m~^rfAh+wk zC-nC5UxK8scuATfZ!#j#T;42WP4$lbRkuq-C6I*T?LMtQ@wgNq6isnLVHpop?+A=v zU>R@X7kLJcr&4sVuOoI81*bpkKst)r7i|PeCxJ>ziGCwK0|G8p|8;CD_^g!z#Ha6G z;^S=HtU8v0&*kA3@G-ymU*K~^I~SiWt>Lpn4x1-Ff4~xmz2VP;?MNagED(I=bZP;g zMW6pK@VRRr7oTwgu4EsiSPc3N1WqGdd~W-0@9PcwX$g<8NT@!6j6`5LmC&K~LE z0@0n7ZCzack<*H-t(F4hO~bbem*n_|R5mGD+2gHMHq)(ayi}H|cB@x<4H+yo#y_y{ zKw7o?`csgh$!kf{>fdxl4|D=Ju;q@YdF@FKt=fwjE=|5V#-&LfzLxMr52h*pE|CJH z$+O>(CPX7S5_hb8qGNV%U+n}!e6edNw9iek7i-hQTX4K`lLG7hNm#FJ4c60LSoaZF z3$E}~w789n^zhay>f=`Q>eocN;B=&Jz34}Mi>#bVgZjyz0QCa}^%Q)WZI?z~z5Ed| z%SwWJO;49U>GiKr3Xnfx0X0?3ZrhnQ+cVgLybNEzCwUn^Dh;i*tgHDCkj86pe3s>Q zy{fg@DA4+k5XAo}t^L#aES~WQ6~B-3gx#0+h=I8`IIMP_{F3 zJo6F2#@>m6;Iz7RB*1PhpQR=Et32@U*yX~%Z)@;>bCe^W+rCH#|6^OdE=b@%r6u?; z`S7>Hug$R7w)`ag3y*At{&z_M(*MM?@IT>`Re}Fz3__%(|AQa=cK9#x(Ep~LF8vR0 z4gO#CKppyjpQoe$D?a&&P<~$JkQ&SdY!v!v$-x5q%fJ72_{VzSe`SXY{{;fx9&E(` z7ybpGrGr1eIsDwzBrW_${ul69c;Mf$-G%?wBU+K4>!bkXXWOUg;J?Qw|3d#$T7v(Q z_kTP6ee$1#f1#XtzX$r?B?UzO)5GtRe}P}}w$jPZgX?}f{9gNW(=RUluWt?h;V%3Y zpQNMzDr{7n?AeI^zRDqnbnt(<_P4|DlmDMx_#f@oiu}||0kQudr-OfUq8a=QdVgGVS){_?HQ-dM85HGEex1Hl_gt}u)&N?D{I>R%#^@M zgBQN122G_*sk^7X6?*73G6&n;Qs_JEz`^Sr7G%~83hD$N zJVmEQCpY6JYJV^5hs87(F=1RC0ueMrm;5Mvxxk1ab6n*FVIHIy`}AXKF?8pC%*rrw z%uqhcsRXU6E=bwPWror`wCQ9}=zKKE)L>F?{(5lkw@zft>DhLN#`O`#V%csDP=sK9CR6=%&IM%jr^)C4QI#5r&g6F>qvb8-i4 zJ5L73t-#;)=Vko7+?k!xnH1P2K*YewRdS|F)NA{))u7`WE**7uHZ@-VfW-3e=L%C6 zMFLPB5?O8}j0U72YKBhy7o-5|OD(SGL;_66wYwMWA+B zo=*1&?I-WZ?`|I|*^i=I?g~uMefTtJw)j(Jq9Q~(he|FknW14@i7pOeTFHrSyon00a*10e zaLZP>Q6g;P1BFy1vEJUi3bFpZ4z-*0kFKY)_N~`ro5cps3l_^Udp3W#XegH@p)U3* zdgLrfW?*eE=JeWVm(TC!@dIqm6`rvHGyP7wPMv`p`MiTJE7m4QNk43WS|r?wrBE#@ z8WF+KjIXvUZFYD0cv+=OgO@5oW=*BGq4nUty6)bkP`!`o4fX_`c@Z0 zzqCzagNQz)n|E#O{ohyOBg{edAh4`T^q1PSu6Ze*tmiNFdYV!%!w4jm?Y=Z6E~DWc z*I!M^F@4oBNE!nx@K#&31FU`j3I&FUQ=ZXC3_yD1>8f8n9TyFD#=RN(^#?H!JzyZF zzDvEvBIQtC23<=UNL8Uf^T1cOQCyc{cIyXR3~N50ai!i6erk2AIEZ#{ zu9R%7E_NiWvAR@Wn%%Z@NCzvb2Cyjorz<&R;`r9fh_@y|@b!oYwm zz^G(u>O|zyN0E_kWEbVHLRJ*&DeSd@sq{u+ul0pZE8HcxN3O@Bsnh#O)_NWjxXOlO zg{bu?8o*+WLyOG0Gto$4Q$tZquJAyi$`u5#K-xseYulf!jAaD_dVyO$MOH)ACS(!+*ZL*Nda;6leAB?dCTaw+JgMRYJs zt4~5Xiz{*^5d-*R<;FU$@tv)-RF<&AChkiT0yKkaDe2UxER*U9<(<{NS_rAESq2RC z3bAogh$2^$HZb43*ik~Uoa>H8U-Ha4^0fYlWo`U+9r!1u-{SDp-F-{ zRm4XKO&mJT7G{avj&+nXH(;N_}BfC3<^0cY|x+L+X z^8)^hY5@LHTMW&Gtj2hf3+t**HDcO3>cXO0exB&uZltlN;|XoaL#t^^6g-I+l2UTJ zq9xD40d`nW9E|uDJhrcFPg>^0JL~K`2rgr6Ygk4`{64`;(wSwaws!5~GighE_EokN zUd1)@M|l8H^4Jze$%vthm33U0Rs`Z}?|LT*rz-Xc5)kY;4X|RT`BD+m*|P&h7dMwO zra`BJ{{Z+h&{+hae&v+$I?oB(QjUGpw}xkYB&7cZD^$5`!RyA?8W|g~Q+oK;r=&}N7#yc91+zG*d^`^FVG$f`F#!wsn;n3Yv6Zo>c^(=mN818`B&c%j21uwZ72dK_1USGXS;|_GZDedQ z%nDSzWdceL#s3VpLF$Q=^%BT>X@fofIEfi=kRPz)0?<(@En8Z<$-rhmq^yX2{vA$= zB=k4RCV`c7yRZzDH5VrvH*Y~4wROs6s?h64-9--Nan`sXj{bcE^h-h<}z_ z`+_Bqp0yBQ-+mU{%c5&|Vdv^yk*bL7J5l#ZgrucL~KaBr9Bp>8~ z9AYl*Jn|5a%HiBm3zfaS{e431Wr9W|2@v%G6zT@T-mCaUFIn-9BQv&=&rqwIJj;}K z8)`N1M0a(tIVI1iZwlARHd^KsEWE(YeN+kF#0t9GGjNnDZIQ+t5TaLYmgJ#X$kRka zf^0g5JR{Z-$QD6Z(J~;T2c;15s)Sb}aG(ixud!#pr7#wmlr@j_?W9?6OCx|B7C+sH z$_gQy|3bfk{J?=DIMc|7*-j(lW1+=G5da0Pqj!aWgDgtB*y2@IbOI-B*>m}(3|*8; z95w5>$syQr=I2cm>2cXetsEui09sii^XVlZ%vP3hI3q*W4$Up+Ri^!d;n`v4F+vEw zmC=38mm4iUHOnYfaPj?>S+ZYiR3T$2DO8sDlYL(=r4T9SqnardSOb^dzz`SQdF6Fg z1%^ll5pD+)Yjh4`f*v?86ATlfBo6>`G4_Xn)LFN3tN^5lk-&1{DPT-fxPFs_ zuv=uW`;X=LPprpRkgB~KT1M4b^r@GHr(j}V^ZFj*-2~;qm%l?)Ab3tcavybWAj0i^ zE4$KpML}N#K!~;E0yb0Uut9g$EnQWnp>P~x2Q=SqPVXuNCtjK@-QhE``p>y!VhpHFR7|j%TtkCyAb^zb> zSc*ZTo&*pdye1z&dF%(@Qng1C07S~uU-`=0pP^D0A!v%zQGNi=3;J+XkD^vugkUS$ z#8;5}R$$IgdRwAv7p3BK6pERlO&eXDzTcRN(;<7t=@t2aIIUjh!AWo1<-y6mcoBqQ zI}Lv``z-6}zXB|fhe$I2f=lC<5b+#zbOlXw90+kU#{(w!4%a@8FTxA^AA!utNL7`a zygZcK$|Orp`j8_hSw@WGow9Q*LtUt3F!2z~Zmw_))=eDfSV&DR7emFQL8f+MkP(DN zQzCj%xd5kBIZ5K&Pnu5DdNVjH5GCVYWpMH&G5fe4;@B^E6=cZ3gVgb_m24r6K0vq$ zZIpt7E^F2;waP@P3@r$68+++OXK0{ydsF2|RXl&igdql2uXFein+lAf1!pe?h{Aus zzz&A%*p4y7EltLe*k7U@MpR|kL6(m?qHBNKT}*)p8{UJX5*@G-(4|Dkfs0bPa3$Ej z;T53Sg=o5eNq;Q-K2zy`G5L-4LHq|*m&*G1u6*bC72yqB7uL<+g;tCh{16}^EpC|B zj1~)DbZCJOW-aCis3?cq63uv$cZww88Gqpo>2RTEaV)$H2?cKhYQu+6j?r-{N6c2) zTee4q#PD4bsCp(xLXak+AtF(`tQg{>Z7xxQtB}qW)^pq0$XlRNvvY-rN{8#Jjl=`2 zB_mmjea+E|_5=wP<@8(GZ(aP-=FQm|FN50mL)~3s<06IL;#>XWeTa)deptH)PyJZ} zluUw(wkT;r0B8>S9AiO+T8BN*SuPm_{%^^4!{F(hJ4}@XMYkWel>|9GDiB0 zd=vCxHZBz$cA^qe2&{-6?m&OL->s@*v3uF_lC9d0_frB!&>9;6I&9o>{=_eAf!q`1 z3w!p9AUC_5Npkz;ZG0tc8FM*AwXGT+VGB+P{vF1N z?|}BNp-`@Ycw%h~w<|l%usSZp-3mM!wj!dVPEM}Cp^)InZ$WkkF+gO$SRKO!Q|21b z0Y`{{zOew1k#8==QslE%$tO6@z948;qG*Qw5=9l+C4rPchT4!U#efy21*31ZL--|j zz*hF%EXc-^o9rORv&sweSB7hk!h3GP%Hg@_IcC@3Ip*cT;PCv7l|v1)Bk&rP9mFwh z_04l~ye`3l<1h3jskSP6px z5x^dm5hd)PQDtY4_`|AFY#G&=JFsNr<}I!4gf5e>dO(4%b6u%`RB5RI#)K1Z%Xt;C zFT6u-+>ry>@YJE0;(5SNgn-!X1vH8O1WC4MbrVKqJr72e;z0_3s@Qe($#i&OV9W=d z+7x7r7aOTWuxdYhlW=@_U=Utr*j1Z$U_Zw@o3k8j9-OagBQ{w+Y#N_b*q}Zh3?OwnN6Nd{43RcAgFU2} zY*Y{n4Nz@-i+yKF0DGXPjed7|DR$Z3w6Qyfc+AvoEF^_up{;lbJdRqY+t~1I5|4`m zEP_ehXfT4(W~hkYuB^HWM0u{KeE0oY{oR9}?|LM^i^_KgtM5q68hp1ruy9?cHkem; zj3j7wHS3Ex5^&Hfm?dA2$7lH-|NCV;jse_L2{lMUJB0mD@i=}m-Gdd#@V!~ZH(auT zH@_U?{pLBoIaR&+)%WIZzIll~P%H3|@6BYs$;TV}=x3pk*E`cDE!odofxKTou~Zf& z`4jGXI*G>o)T(`qm~;fAu+)`@dG@j}D5a2>B#i=dZ}w=O%xGJIBPR11bq`{njch;R zrhXXV!yG=eZ^UNAnE1Ws832C1WAjt&$@Kpe-huomppT+59dfMhEl~I6~1d-s&F$sGkm}4gnk!Z~d z{5qjI%Nr-9VR^X}q!FfQQaJ1ndkf3odlD?~0*!RI-K@VLy!H9JR`dxwT_pGYmf#5H zLTL+d0D-ly77|44r~jDr)g?ZOK0FP2_AP19yK%f%q6NKQdI@@4;9%p&`XxFk&**=S zzaqs}SVMw!kW55{v~&PCN`N678gw`m%{@3u9gs>K%78S-2}pa{3(tiubM@11d>ly_ z^+IHS`+rDj|G#f}EMj&~%fs1ni|aLIy(l6n8WJ}?kNsDe_xXdb{nd~CAGiN0qH8by z|JUsojP-Jx}!PoxkNB4;T1(5#;Bft;YnCUEe7uFpV{mjDx6Q>!qfi>>xVW`H@jwNGlzBK zQ)feZb2PMFc5utzPA!m8^ZOo)HgYXIXV~L;CEuK zk-sa+W&?sS8jYWa-zZ|mhIDLp-L!Oy;LdF0trRx*2R%g+qzLmVdPot?X0!m@5@x@Z zi5d96R>?&rMMt{b6rFY-GXcZ*L7e+8A=^myrIB%;N&H0G;IQJ7Wdy_j$yzvf+kObd zuT^f|NB{AcKo>l+r1t6uKk1~g>%-&|j3pb}v7eqR`vpSCL?`clpKNBs5I$@-xY+$- z63%w!Fm;mi*P`)6%ndMn?T4q|NtXEH3$+z4bPCOnR?W-!>zK9>gZ}8jAWTCzv>)!; z?T20CtA-ge*(UUc{Bjfm=XHJL=C4#D*e{~8^9)XSY1TaHQH-);R2*Qc4m)q#Bya5( z{|b^7gWklDF#*0*`T>C3#IJ1Fp<|}h_p0{`MapGCYE+(l@$kFqi`4QFr^_g9;QXVmia^|u7ioK>p4kALGCzj)+_ji=Zmu_=VrZrj~w zQ)-uFC+)_GebtNn~9+bd{Y^XXPW&?sd8fJV0 zghy=1=m?aawjG9IeLAIgf_IM4QcJV#kw{^X(Jf`$Vc%Eb|3>?kd5|2A!zzaO>9rUB zZqd6ADMV_0{_X+y9mEkf%Jp~qqS61r-$6f>zoWeaVU)kyoiv20{%&bHn$Qrs!M)Jr z+z+(YIsVQygp)`%+O{U#;t-efCO+6p$|%KTka6@&6HrmMQf5^Pl%bukkmh)y1^2RZoen zx=K97DFIB8%t;BUpilou7c;F#MuF?-Ai|897T9e8nrzVQ`WjyN^e;Spy|Nd3wpsSc zt9&%_#ZQN&zDtRp5TUfO4>`i2pAgv_KP8F0_3)HJFrCyXMrn^U`XH!X5=|P*nENh; zIc@F-1vf-DL)~fT)RBoJ)J&YxvNK%ADOeRub>N3$I7eoq1Ptgz z$=0jmOpz+`BCfDd1O4HVk-W9x`UgpCIW%A-W?u0?#b0NmwULOw%JIwi>)oW;IorT1 z08oPeqXtAGo!RNCNaP8#S0JgtV~RcDlvrz;okygIHaln-cqZd7#8i{$>SMI>5>r*u zTp@YHo{WIjD{A;Io{6&fWPka@HG*Q{7>1pd=95<$hFx+m*fZ8Q+L9ul;pIn+E z8GzLBPHz1Er>>4@rHII9_v}f3!_(`@vu5%Ec0eQ~9@p*y=~rM}Khfc1AQo_^@TQ&3 z=)vY$2e+WgQ0MPGv6>qjzp~mxV>HFs_%ZuLKpOwOUznTg^XE#QC$c|O&i+t2@_yGG zgkfiHT2{A^uR)bkpd}Y&a$yD@VG%R*D1VS3G<`Y?Qu8nZef4)7=f~iGn;R7sA?%PL zzAmK`D?^zPt2pR{co>xj8Dr^bWcE`ToS`~tFTxA^ck6zYKr)9F1(T_P7~u9(f00HY5(0ZuD)+d8HeIo!4agD+J>U#d+G=DMSc5rUE9fFW70 z_L}zqMq|6~0#ieTb0j2~%B~LFaiEaoPX6#*<{Ol{M}fGoijh9XSgY9zF~{{xxhB=j zz_AL%r`D?MrwGXfd;^E6=YQAFVdD_G*aP?_qD8Q~2>aCki~4auTbX)mFF$fb^Ey86 zeK!Ol;HXWCJ-ZO&eUR5O^1qb)FLmLn-QF&2Z3V6ng?+;HAM#4);)fR=P`&f2a6MNi zA%!!edgm44`iIm_+v=Uz#;T|Ku3gnJQg&?B5vttPRfpgLWh$ydxY$PuKO|&ew+FZx zBzy`htw7c{N~XvkDHgQ#s$TR}_MRQ7Yy9M4h; z9+x26=eThF?b&D}jY3JR}6dQ&EM{UJ6d7 zNCv*XK_mlTjuXjHU#aP+?fYSq{7*Q&mDJs=>?_G*Iw;x;&d%6vkWV3g3^_Deq>kv9 z20nf-E5JiVKc#>U`GWS>dR3ldt8`v!bMmDZg7oaNJAnjb%Kuad>>PLZ93`+V!U}rF zO~v6re42BC33M_)5HIJ2LmsXfb8ftJ{`~h|I?MDx5OgM1Ox2hgatIy&J61EeH*avx z@!30Idj9BJ6nO9a8YAm{!q>%!7=?!rw9f4Ez(4otOwDuA6TYN zDGy=+OaZGDwt_-Rkmhu+CTIwLN-*t(ScfUju5q^qFH|YcC5fkDx9@CEcQ8wz@-e6T zVt$JGIem7jI_$$O063zoido*3e=y9fQT#lAO=X0doGF;i(kF9j%G4|)!H^{fQO1|B zMOnv4o87YcqlUs5gY8)Ej^%{wXtF_yN3ifqNOAvcWkrP)#qg1Oc~fJ#AFFZ z&!|ks9&y8*>ESfuh8txZfx7%NW60q5S6M7fN|4Dj%uxCrZTI8aojYD|)iw*XJts ziZ8__Kyp+lB961G>N?Vpr zX=gpJl(sDK1eEskeMv)xHVGSP6ZJ>dK(3MH(`?B20+7^f+2IWlj z0zVGVxQEXXo|1aa7JqzXWMCHqj*(+AmTHCq^5^^2+NTI*E=TlN1pXT=dsFHP{0zPn zi7FNVHVZ~bIS^u;m#fT=NFA2$tmjjhN410t5K6C69}S8atCAyclVI-Ze-78n@ru@K zYB3N5sJ3y7$JD>~k|RWw4Bzx=eW<~3S8KvL&Lh4cxN_!m^ubT}>$pc!hhg(KJR=bd^vM8rojj zQNx<0N()_oxJ=2h6K2pz;zgzbZ4>(z1E@3KZe}ap)oeh7hk+d4pgF`Ays*!Ci#;y*c}N`p zcujqh>lB@`Ykv9(`9knN-(3Lb-?#)OtBs^Dkeh0`->eq2@df?E56!dOX z2SAH_&P)BQ+;bcDrXK}51r~rD0wCiiSB#nxzrdEn-(mzMV_4$P1HWraa}+Z8BT|Bf zv+Z7QdQ1aPO@OCd9KRkH_MjMydcJekqJR7jkUyr3`4^xdjJb^E#hy}`LonuRKrbeF z75goDe`EtYmRyObxNOJ$N&pqOOYinwO5T-e>m9{bRwSBz@=TBQHVpVxXfsTA-$hB& zjr1Tb3osZHIf_wEqYYv=kF-8|N*QeeN9R|cu%^mDZS(`c)moOE>T6aWdusl)!L zNbCDH_}q!K+K6OAO!x}{6Pna4BdL6m){Fee?6#0U$vKVNUiWZDcD?{_8PbL8I!c8I zZBkVB2NL~1R9X8^ewBq-igC%s93`bm8yBQK4uhcGEA~u@E-@Z=5 zPUBBf5hAa7$bAq#k+n|o&bYGsPlqNnHA{C)9nTiLT0Sp23V582n0yJa;3K=9_3J9T z@z6KrdYlD(p0i=8PdUxqO=7;IQ^}p3a@f>7p(qBqFrjL|(}+_>tYC#Iu3=D3y8sqq zy@)@a2GLuD!Op1%E%s4Efyw@ttRH%X?bZ6mf2_dV5vubPr7{~dqr51_uUwSKg%zlI zKj{XdO0YUztON_>aU%wRTSBRXr+^URVxkfv*dtg0N-HW)vHKS+R(8LdP2tbyfZU-B z``kJp*4sD634y;arodP8&7JXi@_4m(@P0p8`$g}AhBFWKzxUB+{AHjG2;K(_=!3nd z0xvu&ndVhzd z4XAbB;TB@fHYE3F=QI$t$|0(c9^vUfkr~a#xAA$pIjV5oy(q3GH`Lq(=S7(VgoBP` z1>&mY+{Iate{Kg*g5PLluTz9NB0a)4chMjCNiKssWg15=f_Dx=QiPa0q9!^-rDVc_ z)6%asFB~rbG3-q>Aj>~sS~R25@hd!C&gJmsW3-a*c?1OV`{_zx)zBvemh4c86?py4 z7`}$?KwN_z_!eh->8-+)@~9!sz@g`;dLk@|y}uDa9oI%OIeQX#?m3cb|9%s^%cpwb zr2_fj9gqgz_wQ7nD0p$m8j-kacr$n>H^HQLu*X+7hZpu@zKUPY=O*Pfo5eRHepw;4 z>0fxIjl8GNeGkNZLyxrk_x#59WZ!Ecu z>C46j_)s*8Z6Gjb#-1DI^BN}i4A<_5ufhupI!CLU(CXQY<@lYa)Fdpx)cyb~0cGrD zHY?*0%NV+5yp;!_jkF5~KbHkC$ym#U9Lw7Uk9VtJc9O0Q-_2t=eCJm9kv!1jTL^`U ziOtLMFnI>=MCqVDB2P7f`3>P2bNE2zq!;KxEY&q-nA`SNf0Tn~^nVcUcB+e;bS1b_ zuEhSqR3GKi0U=s(tla=TWD46Oj%k*TU7T*7mY$kr6siXMq`1T=z<060tm%}of~YIx zoH%pEgtb`GnwVqXVXJSPE{`59#A)P*ReTj*creDekH=wpNpi-YVw8jP+g58os=Pbk zvmYI<(10z}y=UO=gbGfNS8vGRuo{qwoPzw-1R6`1dlOv6*(Fm@1BZ*8JTLosuB+H8 z!$>OZBqui z2a{_oaQ;>0$=E8Z;@H!}3)^K6uHN3a64`U1>Fm?&nq z$lFA;tFthZVRuL)x|fPciK7lG2pq*+LPRxn@>dX1S23yloy7ySi0A@Q*(E@9_SfX3 z-C2IpBM8GI2==ArNh0`r)?sx!ZDlhA`xJUCk8m==4vylaV|o5dPUc}<$sRb#bG#HM zpWP&)nh(pe4Y~&7Gpuu4s(rZbB@B0n+r?6HkoYx4;@YN+aNXnjiBdnzWN1&Ubt45fbgP-I! z#m8sTy$s9yh{}q+4>aV7$8b34n8pk_9F)tJVa_REg=czL9HFxQCg*aF*SQpUWSDw# zKGu!2z+&RbAzb*0?t|j1MQv9k-n5r~DF~k}KO_>B$BQ@-F3jIP`EWtFqj;gJ1H2f= z&qZxO`YIeGU&M%6Wh0>{V2?V(gLLb1&9-Tb*rsc9^BX3>06U7iehN;eXM7>EfV6_8 zSS->C(s3+YhHy6|mf7nz5?{)2-CRC&#Dcp^ajGVshkxt>r&Rm^+@f@Re?IOZkL|=F&QkK9&v7=5`6qAq%_HGnHFV_+{BNfd9Nrz%W z!Tb#qP9s>#rmvcU4H(H4XWrC49_uvHQY_x^Bk8mu@vi;E7o-!W+y2Q%Zt$lZKypL` zfz)FIReu8e)HwslpVcTNoOrO6xNmm_VxrhKPbZH97Bb`lGH|Q{o#lvUIKkha8h=i@ zzA;h8w^7yaRvU*gn3YIWk+nz-DkF%M9U{lVebz3^ZLqHgJc;|gJx*VLd@tH#%Z3cI z*k6hn)GdRT5;RMGl-u5J*f@WC-T@HSg}GVutX>keU?g3?cnZ3(#W<-HOHc2?e8b~}~Z~s&*%U1b8Rn;w5 z<>zO3y6kULyBWM2i$N0PALNk;#RTdk)btk^8Y6}g?(=o3n}|vY<*yVF%5YhkT%bdr z2cAZeMI_Ab2sNN&S%IHV@pg@gn7!ZSY9Lojt&$N+2JCk!zbj*hTh(Wubt7b!N9T%| z_~auz{R0A#27U#^+xz=+ZB%VIzY6&M%1I8Zy@W01a;I?Q^nqQ3k{;HBTpgpBq4? z@8A}jjaOO2x^GnDDeuxS)NGzdT46jzjJ2hIG0L$5&-ur(lQrs6t~YwF*L$wL&lh{1 zr>(~dy!wXHAt5S@(;>XfUkG}pecvFD8;Z~k<*;O~l(ev=q8eS_NDglyhqu@YGT7i$KTA)S(DLF9gj-U7CBR!V;S8e}7PVJ+W@eWg*bWulqs6Sb*HU^}(u$of z(tEc35+Z!gMhRzXmd(S%2K$cnv}&{Md(*ufa2?p53AX#}!T9T83*ZgLk{J94k_(?h zBsoYg7=pH$oGi7GbDPvbO?XVm0UOTXqiiWjTSn5BGkTrKIr(aUM%xsHS{V)YGh+e9 zO^$7%2qxiy{H<5=cLD?Un$1FX$lpBH0r`_(m*9#Mj$Gh;#BX+K%>yXKO8vx8GArqR zN;L7JqN4dGyZb^$d%e3zqs*E(? zbjHJE4ppH|^Z>0g4Frrh^N-gXM$B>aX4aQ{XmzNbs<)OF=+3nheDhW?L)2x>A1GlqmM$bcZs&&MgUY`>1^~h25ob@ED4P0^39@b zfYdG60ynmQ(ss~@-yoLhh7e^@cbSn@4uIQT^9-idsL8l1!-+%jx{ zF61gaWlTwW4#F~!-JbeK<$WViO0_*zsmJ(ayf0zjAK}I0S&j|5+%P-#Ko1*vZP>q} z47dWoKF<8!`ad?G-y8h_t63gcgm)SC=DC>5duc!Xvvl_^>_>SHqJx}$a9fLAG40)> zup8Be2X;BIfZ(V6J-U`>tbXF{M8y@2GQskyn6YQ6+P%4Yu)dH4WiAAij zz>S|usZ*R%wk0@b(<~hu=9ACxbZ*2087(J0%jmPqsMZr@Jy9_vm+eC*>~E0t zqu($w5J|F794O%^*gE(%AR>N^i&30>S*>7BhuX^8aU$7E4WkTl3no@l%16*{>3(nw zz{;9%yeg;yF*qN5CdLWI(>}XG#cKvdu9%LYS_(L`6GWkQSvlgD%Yk~x(aRR_@4HVk z{H;JxCmz^e=&Umkf<|2r?K2bE%o+)~;^yNGbdG?2q7loi!<8PEw<<7BhEXUU`4XN{ z$U==6DkCbBXg?Vb9P5wqKcD2LR)Ode{IC1oXHoyR?BM`ri*_ph9RE@VOBunLI@otZv|U9PArDFZqp zUD>vY>;-4hMcc#@{hIE_;XFN1J$BvWE5NC(ItVcaB*D&NgLRX07lTk{=-wFwe=b7; zC~8L>BEie}<+Rx`oeO3^a;?(nVmZ*1)PSfB37Ua1_!{oAgAr?w@rU^F@|A=34e}Mr zCN>$d{s2)3!$9bKr#_eDByjv~Xr=)+YI0N4j!j>(0wwLHcWBcLYv7ghX?ZxO3FJkc zM6_tam5fz(kJv|^s5AwXKsUzMuq&qUlt%n&M&f=b9=S&0U+Viz4$`snFM(pcpi`ex z>`C+W{%|`bZCoP|==zMZ@mOE=E_*{&80OVsjw~oWMD}ednQb49?gyPM#tbl0rNDCr zxoG8Jg+!2mvVG`XI>t#f%(lP($orvfmIB(A*85)#+XuB_ZVGH4gh$4BxXnm0s20s- z0#;`lsNAFlB2YS&<%mTL+Q~k8KX4Q>>+cdK%kBd>5;Y!whB$GH>YqH%rByYX8GW;V zOno*i{R=5)B#s0aXlpTg2Z$ZlVv>`~5(^PXcRO_vR2vaf{j+!)uERcaZS22&t>FSR z_)G^$hJp}6i9t5#`B5@gs^?zJd$&k4&r5Ed`RaDu6scxox3|i{T+Q2v>QJuQJcM$ec!D zEwcW|hebLaqR9GP#&C@F-Ik@yVMbAG8cRzfs2$t7vG%~U?#E@Z-{kZG-G3Wym2b&(6s$OOCl|&k__(J^{ zot`=a%)BQ@K6;KB#D?{X{J^G{b5gr7f6dfO4QnJwbGsC?I(}|u<)B(@P?rxO{#;9~ zHh<`vJO&E#kKLL1>JlJn?$<1%P(b>fI3RQt9R8vrEA;SR=>Yh+5~4@E2Aq+yd^JPaxnHjp{S^Kon$47;w&`KDHNX~rVvI`BA6cfxkxVrS4n9+ z8-35W%d^HFUl`MQ6qNm<6A|Za%X1UUL(l&1@a<+ru--dDF{D?SfBbQ zh&2pol(`Dm%9w?owsFZZQ35+JITondA=2t19rgJ!LB(I))uBy14l`P0WgQ|2k-QE< zg-5OO5$Nc6ESUcgCE$1l5>Jac&}V_&6Q z&U54voqftH2LmXp&E-_j#qX_LH!fw(@za@?ZiQa#OWy#QW;nh-Uf6@M=8p^!yIMxM zfv9qf+LTE}#*DONg+SjCMZ?rsFA@`G){-_wmPt~i7@4UP5K_Uw)F!Q1x1u?;VqFIr z)|f%GGh?TUo#D}5!v;aowBoviaB^}}6_&zD_K(p4mjEwtmn2?+2zMXth_L9dUxcqZ zb}u>p?iAtpG0i#dX-{|_KS0ztRdipMMFw8cU9`72+WjtsXYI2i*|%Vf?TZJ-b3dIt z`qy0g*IcqP3Rea?6qkvj(`bRY=tB(^9_k1#LIy*QhtV=im`_&2nX05kdtnKjX}bO6 zz5$ohw^@!hC&GPJPS&o|ECG$mOEE9O2jjt8T2ppUpn8CbgC~ch)2)NgO6;5|(9c}Y zHq7dc($w~h@jVO^qb33?1h*KErPEy^7fG1cEtTL+lVBpifkl<(7|f6aQGSW{IZDtS z8Fxs)E<>`q1-}FJcf%e!Jsb6#q<=EL_-N1Z#XL3(S6cUjL=ay{Sb%(6E9;Br8C$%K z71{Dk<(Y)*YH(){{Zy%DwqcTPWD)=d9Y%p?a2%MrL;s++eCWh5bCo@sPn9&xmqkIX zYNeSfns;N2k#3AJKdGGqo|&y;3@GONw{(J9!|zKJuw7z|QH(L>(z>H|6=PJ3X}4y| zk0-_`#EQ1tBK*qw1HAQIC&nm@_0KcAjYs8$R%Kq0IDCNm3S&iij4-UFI>K0XeoBN< z(Fb+K(EhCMLQn}Pjz>L+H6)-=v4+moK|o=KGS%B`h8rge&?4$w#G&I3Q$-P`9CvD% z&(Ul9V~!z+Ikqt77zZq#(=o^U=71M&hGqC!VvhGIQxGCOwE)}vGC0mZ+V;hAh3gh$ zj(ZSHNz9RZuM=~KmlDktFNMCRy`X2SHcQ1ET?pAaob}T}%prr*+a&Ft5(OopU!*O~ zl&H>YtT2~>mv9TkVomIS==A{;J+X#EafTc3y6^qr#zJ}Sh^dxkBi=!U8xuzu?QNcTw4maYLrHwT@3Zz~dEL342 zbkF|h7z$-78mM(VYK?!XVvQ$85*yMqO|0=l_g1k{vBs#0f=y0}=ka0V#2Wq6#u`He zST80LYs`1#5ithklyXZMZ7!eM_3o`aH!fk#@qvsrVoT!PB<2VVK87&|x^Pa+;r6E4 zndTSvO>2~;i%<&7$Sq*4gOFU>JL#4EFN2Uq(;tL>&vG>ZrXGg+f3Fh5qe9NS=V_l>`Yw_6A4$sbaW643|4@FzNp| z{{B0}0$>qG5fFdmsQojebmDK#*+2yk1-#-X0t(i9eYYGCb!ft=99w*=;zmCylMpAN4Iu zBj~BKi_dACfdMh|QUj6 zU8iAAYM;W|ZB0c-eqNM;?N}>S(4@Msu+`T*&avA5VxJ>4FJf(S?P(V&B}Nda2^p&q z@W2GHs)kURf!D?{;<%l}ASQr9`WS*C$IPwdLgO5J&{Mmb%)rDOK|>&%ON7yV(VZrahLA)eI>><(+^jd| zp?Q+}G6_L%<*jr|mk2o1xA5M)l_WFFKMCG|01!&lFWuPw-EHXsC#`{s>;cV$DxceJ>;S zN2!H)B-3upyPbjN$1nW3DL#>EFGEHomxq1$!*w1*Ls}R!kGw_WzgxABs zNi=(4U>#f#>7)c+x*LW$TO?KYNJJbJt!2Ut9X=ecB_CCj7+^~YD@P?FVYn}q`xGL@ zIP6a(GBmLAHFQnB(sCKUiP0lyy#`hDkJr>T{uyRJ!@LP1_=3EqK8hkXE=7A_ze)=- z8W;06{-p#=5JCVZEG71K-Fc*-GDPvmQN+IV1@><-nDzL>`@jqyjAadgQaaNzI!Egn zv1fJp1^Mg7>CfI~_6fiTK_Z&oX`< zn09_lQSf>AN+mv^JsgNT@nw#MJlFD=hcGHmJnb8x^2O)j>7Oz7XnB7GHw>;Dgo5FP zGuHqg94}D+3Y_ioYTm&SsZx+$`;A8&m;@XE2F)tsn4=I_Pl1T4mGXb!hvURsS~J=;gJupnOTUDzyIB_9#xnfM zML92u%sc6jIa&~ebxhQA5CzuJf-jcS`0U`r%CVO#1A;NiVFVZ(d#tM*KoS=h;Wkoe z-7H=g*f?wJ08n9UO(759CHYY*PmUfnVs9r_sXF*MZP5Z{P8QK60VJ9e0m*BFFmv|W zzbJb&&5UWjBqFRD>+gSAG8K2>`X%^xNjw-{xKbt~O%}02{p)Fh!Gb4;xQfM`3HBOD zjA&5*X6oN;{&GI9eVM3RA0m%ngvxg26s2slQH1&_whUr55s^YQp6TgeDNjB7iv4Rg%+=zc5)98o=?7t{} zrYkgug{;6^7ic>)X|RV}NbHXWxp>_S{dlEN<#hm=bPmX$sSWY7L5OkisLWp<c}FhY|;BH0SXa0;DuQRp_kHK2j6WtS(f|mSa2Q{%_Ip!2ZJ|pofOnWI!=>5Irqt zID8Dv9nPm^Q;rhHMi!e{0YGY46(yX_I#Bv!Ls83}+X;(1p+)aeWXaqfEl*jIbrwc{ zcVI%ET@PA^m`r*ZOTNN{{J@%<$hU$+%z=NqoSo)jhXi?&{BG0&C=Y=^1%CeswHEI1 zr$Ij=%ASgHF6?3eUSMIRMc6GS(5X~Y{4JE{b6`m=w?cEeuvVF1&u1-qg8e-CzKANx z9Xy;Rx%Vn#^t_6XUln6yO;a{W5IYBmZJ0XMuznAu?v-Lp<+QS%5*0Z3WWySDa?tFy z`Z93%ld8c0<76Tx1LF?fN@R>~IA9+s3@{hwg9*g2ca!;H|)BtkgS(xidgPhUQ zNkq1io(>_6nwfnwoEln2#ReyNdnXY!vw9NDbyYp|*sozOBCaH0sWc@svz3@^=kD;V zqRfan@O07eplW4kpvrtn5S5Z|*RhPMD}I;Eq<2IKv3@jLA4&;)5I>ni+A$@kLHiB; z9CE6S*mtl`K)ZgRgSIm~K|i6)@?E)0`^k8~{8%xwK%Wkk| zu-X@;T7P|$P+wlk{IpOF^`MU`c=cYZ2o@Cq;rRe0UlhggBkg4?jPV745ws8PZdd5f z04^gElm#cKkN`{1VsFU@r>}*^dl2@)7oPq)nOnQLlrWYMX9ztEWD-V%H=zCW_Y{oi z*#aV}z6{@z9=MuFWI(K0-K$w0ZnEtco>h@Dt8!oiX9Q^-*+7U!5pt&FW8}oH(T#v$ zb!uoAAA%~$=*i%X6Reeh_N5JW2O`gQhNTLK+z1nc(Lf~PE(O06+KkDvGbqUD~Wsg((ni_7Z zL}DWb(Xv9@uVOXSpqLJxN)u1o17At@MwnMd@%&ak} z)v(5N3c{TYf?7pgA*?e$<-~8riRa;a_CML@dnmd|-%}K9 z$@d6dwZC0>kvN_sTz{*PrT$r2W#yO+JzRU*65ypB%ly-n=Z^}L5-ZijDp~#~d85AW zjjyFZ{5kqkE9*j>w5=vo#aGIZ4%n|kg!}i~GrY=C?yKNU<0wU_AWul!iigDZaK6z6 z`B#aeBz%^51f&0xJXBZHJ_}&A!liQTiriZ z-?CAU89IHmt8d#*YE9oByIzUQ9`)@hsfL(z)|gP=UhfZU@-l`S9h14&_N07I_T(fa z=u^+_A5KigPuY_zE_Cr*d0A`tt+;M4@S7&p5WoC^s!ihe18_4;6`r+fPa>qFwkPFg z){+vjClfvPWa58oPX-DqVoxqb^+>q+AKR0T0(6Q!IkQ3$u$nUZ8|=wF>}Lp6p5X*!1?KRKReR(_>H0Z~%lg`uJMSMaQ1(?}yiKPl{TB zSJ{(=7YMxnxjlLM6rTz7*poZujRY{_;QlLnvix+dZvH#GPh|g#>}0%Y1}-LCi>t6)AaK@X!WG!`C{|v%p(dWM;{%Bq z0>?-ZcEHX@n~C-I?!E{_Ti$OYJe{Ybrin?VJ_JSxuvpv4I@Hc##DO>igM+jKoX)Kp zW0*q`xpAQ+J_tUJ3acxR!m7NZ9w(roqxmC&DBMIzG8%on5GAYHCO%-Nq8Qik4(O-J zg&VRmB1AAK{Wmv^?FFRb{dI(ww8xgazM(CHyjIpXkYET<=doS-FDS+-+c`MFfm^2H zAWCUtzl*(hbv|aezF4BFK(C!@41=YDXsL~z6H~D*C?m>_cv#3b|5X*cgQGI{gqQu+ zu?5hJ`8-&5V0}dZbS?<;=Q<(h@3~*lKqGeIP$VhCuh6F4xtORfJbqP8hgM=<9{uXM zERQEJ#xH0DU+7-VhuB`A3?nou`3TrZwVAxIE4{EriAaP%=7=PaK=xAUHnYRW+|3Mt zM;RzJtg|zDfs9)$Lx2e6`7xX&fsYkv7^_uqXCIFWLLeL_a6!cN=TQyA^|gczZxkws zAwviMjnb5r#UDv#9EzgYT?NUERYQ$fvE&K3BQ1zI=A#P!AzaKUQ~LTcZ(-gS^Vdw5 zL5(4EyUR%mzLLaKN(~$^NQ7Sp=$G*_iRW~OgbfpSkn2Cpdc?GgLNY}j?U9ni#@qo> z9wk|{grHB|dbVd}-Eb{wiq7Ao$F@wjXvz8PJrK2`RT1la$3IB_cnLBF2yt z3L3UR&-GXC4LuR%s=7$Gw{#p=lK5M5qCV!lj9(>0bx7ijWatUA|B$qH#<8#y$QpKI zH^y*Dd%^jpp0It8bB+(7FNlAHg^0@@c}6Yj(i2Myd&7<{YxaG3`UVo!zaHNl0)4>o zvQU~lBwZt_ik2v|0!Gr1Z@8S~W6VX$9J^d~r6D>pB%&u7z=*8v^C0XnvBT9X6vtD^ z5CO|aKB0_`FcK{?ja62UK@7oHS?G$MI}NV0x*pl9D-vJ3O(VIg>3v$aOdJoipX@cB zxQkL871>C{>?3-Cg6*}XRS~eCep8y^?$|n>uZxxOG1@|C6}0fLml16-kf4Ko;#)1@ z?O=E#ruh{(piC*RfR_&?drA%fyxI$(AHGt+2V*-HiV6PaC@Pt4o7Na6^$qlAjeuE( zQp8AC=h3p^DPRsfbB$VY{r}i|_wcx`@?Lms>oSroOSwCNkV#0uaS}zo#wJ{3%a-ND z7h%bXlMt+tG?oTSGn1K-FClB<1K47N(&4o>!ZM*m z25d&SSgG@U`0yU+0;}*v@&7~@tp7sO-NI^k+uU^bmst>gf)Yo@ z@A@si>h>vk$amNdHr@S~;^w#5@=bU1MqYfF4R_V1RjUB-BYmR>nm)a?YV5gG)4RWL zg9I+VTu(!u^U)Sa zU|fvR)Oj3o;Ms(Jvv%nt__pP5@c%3P{~T9yPvifyaDN}q3H;xO|D*Ung8wo2e+8Rg zP|}!u%iSj?xXS3c>7M_IK%i;#7^hA_)4c!bH=Pmp5fpF}9r$f3&=X)hw8V!pSKk}be$Nf_;NtwC_GBbu(bbJbuTh5zvpQWUP^)@_&(kO6ZPw* zTP{P_pX;%3sJ`#h`mSSr-I<=75(N&UmfiFVuN`6Gesm&SIN`xo7S2@82VV}s@^|I^kE1_#{S-oVn8JxaF1^P} zOpiWyJ=*+8X^?ThBy?2Po^n2_tURXg*hUZskcXvfciOH$`a#GAz6V{pdY5~L_JMNq z3i}>r7zNs^s+u z$#g3g$x7edn)?ENU)5!v?4LYOmWW zjGDnhb)D|wBgWhG7ecv$BC~(wRn{a z%fAD#WXky|APbfSWdYa;Z1y(MQmJsThrA%ZTF*q#6-EN6+2x)PW5|AEtgFIq?qN5^8Nw|}6F zR`2=(sG8Oqnyb{Y!xaNCNQNK12$>&unTPwQ>7IMpne*tcP3sA|2g4u_@{5$=;n(S9 z8?-ds#SFX+0XHF-bO68y*Qp4UoDmj1T(lI{A?db}^IfPF^X40%>5%qf(*k*Buey{7U zf1G2T=UC^t(tA41szq~wAut~#cV&-A0-S`vp^qaE)-pMn_prUZL%1rq>8@k&*UwV$ zonB3SsI%;Y6d+6NhOiG(>_T||gA|`-={1rUiXWulsv+!+QMO+%+m93e#a$rPgB{+j zzM>tZ@i7QmT6!UP&N{*Eos&!*?fxL2$E}U-e3VW1NNMaHdV*K@pA%vD1OmR8{^ZFo z!6G^SLs}%(V>VXDxL{r?5nn*yh)%wMkgSRN0)l*bdHl@_I(e1&D-k5{1q3}G^X7#V z{vbYl0pXymn6hQ@iGv~edVzF-`K;i+>t61_9^!T4EBLvC%lywBoEeVrHfZhNofyJU zpmfGPvcVhiu^$m_z^Ffws3#vm_ZPp3UVkh2ft}6o8?0E!+Dqm|Y*u2v@-c!l;m=PA z;5Kx=bOZpPbR$cZKtqxg;~kREA)JBc%(@S(#=2N2?-i*Xp{sg4|)R4OSZ`Az@G{8?H(3U$Yui}*x?IhxAQ|Pl-_(jS<5Y> zJ7(;;^ct=KcAhv7CFiuk6Qy4sVew0EmWMWps|B+774B{SzU$W(Y~HqJKJis9B9349 zp)^O*Wfghni5FcFG#IZoTL08RRD?aX{t;IZG4EKBk6%}@A{Ve6$DTq(F4u~D{4VW| zBFPI91z*s3%lU~IGtLB1le(I99Z7qX9lw)s-ogzN>Hf3E4S9q?~| ztSSy(VN8BDfKSXOuS1(RjeiaMgbKUeHv`t{Hv>KcPc~sMIlM#2S{RRNbQx*m?KW?8N)1I&#%vrVYIDJ{Gl++YYO{FZLbb~tfTiw zFQ!U|yebL9ba)Jd>-{+v@fhaLEvKY5SEUnA3CTTm^3l?-##kFt){$pqC4jw2Qu;2? zi4WkX)a!zrcq<@+o;X17t>RtUsE=#q!9t;+;5{ncXtu+3A7r~XrJUrTAunuq;}5kV zma?iM0+*Qxl=J&CTgYulpqxF-37I^35FbG2KF9T6cDMG+*%p$@p^j5D#EFmcO#QV4Y#%-^f^NB420 z3tKON`K)DYBj&R{D0K5!bv<4#D1GW2xxoC6vjS68+&NiV{HN?oF?TUC#T3=a`#42) z&N^F1J=XX=csy49$eQr%)R*Dkc?=dbIiz&P1Ey;$jM zU>{Zn^)RAHuymcB`NN5Ku-ZvzGyg zyO580BNL<~H(0vGR@PQBmTK!pF|%-FB#0vXbJG#thKgyR>K9fmiQ#}4Ml{yKcRtF7 z#}xEubun#x&HpNI?5|>+DUIz)$SG^KEJ|q8+w)8450|ucVCZTg=_vK%=fv$KfV-YM zi_0e``o&Z-0)mJ*ynqc(Qbetn${qPFE9`Q~6KfebRQ}S=W>DLoq0{{Vc7WbCT{@=3 z_Aeah-1$@KR}h=@Gl)%|7zxmxet`CH2l zKv_TlZa*T2qzQ1}DfE<-um|ER&>}-*gKg=yd!9kV9~klnPTHLmiD@E+M6EM zv_Z58CuRI58rvHwqGg5b*#NAwN)pt@il##`iYx|(=$}DPH68hg^jEuVk)48@ec6p>`1Cf-o@J$i1Cra%RzNbzz zT+Zr<*b}9nV^HwlulwIc#4c@%!vv_s$j3~8GW~zQ>i<6gwL$-r=y}=CtWcyrVLku* za#}}CM}96mW*>yb9>T+*kOl{fek}LJjX!$kev2kca zgK&|^L=XUlBC9PK-}xxZ0U1fQYJ7%!*F+P3y;*Y@I{7&$F7Q57lqf68fN`-6agbzW zska@r@mp_!0WO*YA{F9sF-&n$>a-Gt!n3%4fdp?94r??AYjo?!De*jObastz0*|3+ zWB_3tFpw~`Tj~elOxXMT`9z_hJdrDn)J61xqnVCUhn-S}>g9kFcIKqSShKx6?;8Sn z&oBh?78&H{jk044fmDvF9+E_o5?-dAC>9tT2|7x@$5J|L3`N0xy=Z*x1heYHoiJYg zoeQjo-&Gy%;g=x6EJ1-%P3%g5~Urn^aJOefWj4FDew69%a5o zG{s#%J;Wx0?2w=8S3eif@8_UerN6paSH~cQs9wQ)kU*GEFTL+pzCf423lxEwJl)aT z$$*?(dP}DBI64K(>c`w<_xOcBl+Ph>5J3(Hol8&hHqcn<`d>R+0V(t{U7Xf?ZsA+5 zBT)@?j<-X_zX67k?5>s7FENuew>$obeIfL^R1djdx$8d0tBl^v zB5N)+*>z^dr3{9`$4meCE@dV(sEv^m?Br!EdY6utP_jKTWcng2=V+<)`#1bfI)_^} zZ-qj?sz)u_(uZD9BR0tF(BOx?-=Lvoct~C4nZ(cZYtuHHRa{2ON91|ZTewp7J(kYi-($TSx z=&e5>={>+uVVR3ng}uurEOHFSVYeKw7_Z)PmdV2Be;??jNom=(xN5S(%S9X}!Iaxi zswP9*970O`V-Ji4+(!fM3FjVfeE1p_pZCLyT`|cgI+o>x=40`l<}3X~IX_;yTx>yQ zu#@*v`Sps3fbtuXbUfwvc{_*?Y8ARY=M_a&exO_`KNpa6ytMR%XI1&(r9XSA^MR!l zmV8JsunQrKU{5V$PUCAn_t#~T;Or}%B)HEeo^%jEd7$FuhzulH9uVSvc0t{{EilSN z{pK{8+H$wcUOC8NMoI|p3RCW~%|a-y6QJ_mq$;=F%SY6XQFM zgl8|g&Sg)DJKS6U)pXG^V@QaV5Gnu`wmua#ApK|t^jlcD+gh0NqI2AR(a~C%g%>uY zqg0X`%e)o_3$~I4WfJ%9i_jYo$_twAI~%Mjs%a}Yv<-sG-L3_vO(>#=MDbGIS2f-D z6q3iLy8q-I;qQ1m!LhG&UjF2^@eR1?^4ZsIy=xA)Tz;{0!51a?kt{;2cmmfq9l2E^ zUXO_1!pD&$BD6W_?pdkMn!Eq9jP4%5#&?}Bc4LHh>+~Gz0y=xQP0t;%dD8oIiWIFP z$sLQNyM;eek~g|T-cM=XAO2uj-YqU~G(w3XK-P17x`}|G$tFpF8dZOb?89rdEWTiy zOqY?+(E}z4+xQKq`;p)_WI&SDRY?E}7$JUnf>Y&*7-Y$Z)3R0&n-F>tWb7CvK9MUs>^leDIvit%Aqxi@{2Z6^$C{l-da6+b#YC z&x6u-WYo?l!xKCY$-DbRDME{0cY-B_c4pJ+(ugWNGJ42pLqTGt_pEeAn>6izl}Ab5 zQXy;r;`9HM=RuH_`Uo}r(qhv$4XzWOf`Ywo;@)wK%v<069!{T+pY!=|o9*GTpi4_k4@q?Y+q8j^s8$G< z9Al<)3@=&PAxaOSVn{@+OMk0rypD+<&qL~&y?OjqydrY~F}5Awf^=42y5WTxn&fe; zdR@dLev-g=H|$3lBV3Pzch-9E^;F|=ZlnZZNXEJ(P<>#S`kF!&^%IHfPs)^j5!2Zf zL^FA@jBk6H2};2UZ%pK)i9V?sh3hOAQ<@`h78XJrQQZMESzUmJM^-coz#^1Y{G)qT zTyUek>CeWZU+1`+Sv77X_4%6R4}zmm5ormQ4rOxdN&{3Xcl{RXr9j$nosS|Om2A+6 zohTIyRVf+=HgGL14OE3EPs?NkqU27ct2S|`LAj!OMyg_pO3pBdqVhg3eitm$i+|}U zs&^nb6;<&LoTj9bIyg*PX#>e^`<9U$dVNxAK#O5XbrdT%0E9;5Vrl?)bLQ@e>58y3v5^vE3zZnIdYGClD9z^i;Yt~!tf9{WmIjz2Cf zVv{sDrSbg;Ij&)%<@i5c8J6SCBsfVmq}(B+W2C4%AEnU2cTJCo5ujo3GeZDF28Q`R z35&*I8JPZ3JSBa&nXb4iru~4G2nF9LetL8Qz%VATUB&K25u4Mrl3 z&$B^=d%cDkZ`^Z*%6OKKof%o@V_@L%#;?j@8p`-be#;D1qo4d(Y2X)-@fTqfVDsGW z;g7#~K63`&f><9@BAJIodzGmhgZLM6qNnU zJ8;nHp)bRA*T3QCt-r#H6T@(=ewt^LK7}~gn1=N4dNlq>>1%T+)a@W*SDN5>Q09-` z&z1_^;S|`9J^wrsu9@7#iGiw1ODk;PVG|1XsvyIigObVz~Y zrSt4;mDB{nS2&!*#^ZsS9FtO;7`K}I!V0Z6m3bcjT(BlwUn_NFq$aQXIch?oa?1Yr zSFH~kc$ngnKf(R+P_X{~_$~~|i-W8Nq(9092V@ZiORarA)anD>n4oBb;mn2W<9Fy< z+Yn`Pjw%rX^npvqn6=Y|rmxumZRpBQcI8p2Y8sxFV_&&zDt#U0WI(mP#Cc z=2Y}};5yLaGWK19eTSdwSFfRLL4M;H#%S-Xe=MNinmdoV@%Mrr4yYLIE}oD&6WN@c zENdT0Ki+xFlOIns&6gk7-K_HCBY3x<^wl8-Apz_u;=E{{#3>;eQ|g2k}3I|1|zb@Snkd4*z-l7w})i z{{j3T#Qz~_wT0=dKC^hgumu?`+=Q8$g&hO<>BKRCg}QMty7r+A3-=+jh5H2Z#b7Ic2nPv=P^5)Jx8o2rOGv9_hqf{S*f4)S+&1iw3n8FJ?+!*ofkE^+T#u@*kNR;}dk zC}VY}`sJ4)yNk@Ld$fQ8^5jYNi}HOeTfSd@2SC+}@&n?Q z+U3&{rXc<#wnc>$>s3hICci9UA`E9|S#BZNN)BHl~Y28?)JAJld1P^3Zqf#Ug0BYE!b9)JKYsY=)1`!zo7Z z7$#X(b>y>xMl&GcsxA2}=)bBnJIeg7PfMEDr!!!Ls%@zP^V^m#ut?joN%73~<5Toi z+egTMRok-z%wc;rFAputj^qf@jwD&GYDel2qwhe2Q1GYUpJ_lkM!+Ky1STUn%xJb5Z!1(pdQVr=Wvcec56fK&ZIFn zSG8MnzcHC+yqi)<*7jyJ51KsL-;bWC0z-lZtH6usGCt6Yd_W#m^(6}o*_S30;xPzH z#G}ZNc!;Nva1~fqJVy&)p{l;aMaJt#SMf2F1V>eYZ<$~JD7n6B06nG;h8)l$4dlri zRp4rQjFOhBQX&+pQs_;h%mJ2cUwWAFz}qA)Jec&pd`dipHmmlHO74SMp})Z_C3e*y z`W=sa?!!q+ zp{n6@226s7BG3y_R?tXN3OJH1&~s!+ntUXkVO2&n_Ysg3k%$mH@`5zm3@8ilGH7#o zP(D^=L?~84{IESUpaMQbVpU~C9N{5pX0p;9nLK4eRYpVr9^~mN$ST%7o9Sl`kXEho z$n%}@Y*ns*nEjXQrvRzSfiU?P9%W19@{}ihuqwGcbz@adJ0LeIjhyd4KmyBaTO&L} z=2HV~N7E``6RX~ZXLE~n?9TS46o7Wvg z{x`+5-_hqpi`Juet%jd@&eH##h1;&>p4qC;wr%>%ZL<1w>a+QJeRh4~I;rREKEubY z{f_A~F|NjbG!7})}qgtg`0Ve;;~ohv$tQL&0YG;b?dWrzu|5A?7d2#b9?mJyh5L? zz4~msRi86A+4E+7b}iRu><#*ydP@7d^n{jKr0@pG^7_q6fxWV_YJ_D#^=+<*S+_sf1C0B%$GF1sVDT=_6hC(UgPgEJ7;`5ZS3sp&Qwy-XRs&l!KkES(AC?}=6oKV^I}Vf@=={M}{zJ#)E+ z8@olH3FGgXZ)v|z7=L#ef5(i!n~lF)E&n#-?}YL9l;dOL@0itp&g9Xoh07U#kL}d{ zo%|2&mnqY8UB=&YrZ2mUzb6N@yfY@hdX2xwu2A}EHvUc+e|H&w$70nmR5`^^O%oLc zO!e|U3@iAA3Av8XQ8A#aH|#5>U@TW}7)}qu9>)_SLOeGz9-i$(7=g+YhMPRI2N|v% z!C<)aS%5uWy(u-!p-J`TOfipJHel z%x6oxjIFD;4&*s1sot6yNWrqlv$%FOp9LBJt|V6J)n*q`hlVmu5sILgLzl;(JKKl_1Clpl6o^}t>k zv*IbE)9L~C5B*a)4p6HH4yQANc&2oKQk@#f6`5~}{l_Q!kI#I*pW*S$!g{PuscBiA zI*{hDs(N2?bXcDIF#IG==Q$FnCM4ZqK4LHH#V3qjd5S;#9eA)`hCS7TI;g4Uh@}<& z7_#Kt6JvG3EAhlYD1~u9o}gQK!mQ=9u&KL8o`oXDI>4hv<~xib9^VhAM`-U>qgkb1 zY+mM%IS&q)sz-EGglEQZhK7H21`{)k4-+~gPgvIMkBpT!Gbr-})tOvU^2uOq!1OYs zBZKl(JG(lU%qKCftIqYytWPy&N`{#p#}_y7spE!f3^O^^SAE-PYLxFej$pg-$$IBW zr+kiPr2RO0V0rMAauz@ytUm`3jK?SAVJ2itJD)>h{^JSyCQc7-$J`&EoDJkt>W?Rf zLDhv^vY+L^GsE^MU~)$>_<^{vSHl&PLazn#2mLWRk#I%uiQrMr8C4e!ri7l0+mjsq zR2Qw>MWdf0`G@|fAlr{@!h8?t_#Mw-j&u2x_Bn{=Bz^En`Z%ckRU`C@h&9V^xfQfR zhmmj%Mc|6H^nqg)B8g+|YC0$t*DZ+EY$%`sz{fQkQ~QLmYc>kS&<7Qv$gJ6TSf?v$ z+LM`X3XhuhA&&6i*p%v*nG-mM!7=dJoH3uxhadnTVQMGNgYPOGNWQwPT^EZ;kjq=os>@22&8~(>L0`pBz^s5|*+0vm+y%Ag}2k zEy^rLP5h;Iog4ls=TGoD>zuZLBGM3gUzL22LE*Ku8U8roU#ef3L_XI8@-*4DPcQ z!>pBvqMD)9aE>yoCY|A&pg42_2|k!RP@kg6ubOm$nwwz?Dj92rg+$?lCLN@XseuYk zWtcm1l38&&_ES8;K{AG8#1tAFs<~=LgpB!0NK_n!;zs6`F>P0qNu>rPoeZbT*czA~ z5=B>&F-=mFF_B)A$+l;6&}ncK)BD6hVJ)#t4A*1|!y=bzFrk#9Vyi*Vg68QM9?+Dt zxg?}Ad~!lb;>c@ta{W3{SCdQS)6(5k0~Ay>IVX{Ba}~U86!TPkMUgMGnol7*sU@Ep z$qKDP%*(V8d=8{3*lY5pQET#}1yMCMBJx=alyfr|0_fOA?NdW3FIkAVhkk(%mWLmm_#vK}3WM`Ze|26hIR8a~A#)nPTow6RPv zI|v5jtNdXs*3e=4p{96XuguTYj6%;!QAMJ&7?_}f6sBWfZ*r9M42P_V&>`xq=0GYB zM(3+k9wnh8JFLYxh&f0mD1WsON@}qf&K9mt9pYS`VKn`)bhyJXpJb}uFxCQ)1g7#F zK8$8(Ul|^SkP$AfU9QR_7OP!;%L>&waIN%QYdzOG&$Zrj-KzFEV$f@yq;jj;=(WpP z;uZ{5YL|n>Teunr7xd$@%jrT9rAun10Mu;iqH0qYE$CXTIbit!;KN};mV+SA$e;zrTRt(sU>PVXtzsxov_fvX0P4az4Jzy#;@I) z5xW)Pwia%nriM#37W7-~c9p>5%3+aC{ICcCa;9H)phs-!+MS~=m98X+V+X@^?H|;& zh1#wx8i)$GwhKHaYZ$d+#f#rA)dYA;%_L(NxQ0`(j_610emB%-Ei{lWw9vI1DXO1p zKKkWk?V`53n1!}rJ-SExEjQGfGyp#qSd>(4PyX;OS=gXUS2JqaC<9!=(O7_IpbESG6*Pdab(H&Mqw`v-L?r#7cDf_|`4&@kdkACNIgEyh@C1l4ls zMl=gt#SU5Ds-G4BqRS|U3RU};s&X?;=~{?M z;~BWrYOIBh*F`wG&~eOz7OusGOHAxqXmyK0{f@*Dj(R;!E4!8hXl?t0d0OtwO>C+> zOM1}R7}UqL_+PN#&i9Yk5PA5|pRf0E^?CmLSS&6^xFjE6e#<)3!f;XxQIycGsL0zjlEi)chRw|8SW1ieKk-s|LA z97B|1IyVdr72lx}hXF9`v)Q`%&f-uiuhB#mqpuNwnw9f|=F}Yr;=2p867YrkwE06i z#bltbSe{Z%kW~MEO&7nr)dGn3aLg|zN}TKZy1^j68$%B@48*CF90xP($Y!=+bPBJD6xjd*Iv=?WT+rUqBrVq%BA)TtzApYV|YD3CzaT%uwV~SH}|3H1zNQ3w)p{&?H z-b^}$??5|8lyq|1P04c~#8V#H0KV7vjBtc*79{|xvx^VW$3Nm~%{X1kiK0erw$x#`N#AR$H0yEADx-D7i1##-|GLGrF zG(;pg7|wLjvPc&=+e6Ncr;D7ByW89z<&-4x2EK{6&2UKXqIb_sTZa5DL0WvJ4O@|C*#c9>dcv?4}fxuS9 z3MbfAW-H+=9OgJ2DPX`T?1V0)mQdv-tNG@P@MW~oqABq>Mtm6D(H4k{euL1YQ&pHc z3lM=6hH?D4|TXmJ2*0}Pwq3%cdVpH2!E zb&B4CX#`(!V(=N4aktWMA(!e;C%L;SF0+i7JaSI4E5tWrVGDlIi+i&aQw$6BHY5W? zIvt&XGWz%Ta32?Z_d`8V-NKp8>4p(;>NG8!2OV)0MhCKkV%o%ooWw?pW3Xw;3eLg? zwO{BIA%=9(Ua;+`PvaO6n?V=nkhq{?MJzx~SDdm(EiUt&VxGilH|h*i9BnJI4~aoF zy3PW^O805<57ASq*JTQKeEG%AUG(_G%DSk-JFh zmiwBkj$>NWcyO<}MgYUyvWlvbI#1kwnAL&sYZ!(q5@Ez`;nxJh$f(%Dh}*)f3xru8 zaNp|2+eq_PH$tY{jfd%Gaj3?f+tL?*O&<#>nFK;DKp07-eFQqLZUY$q@Ceuo?sjMx zTL-G6g2t>WwOHMjY@eIxr5k!jCVlIuf`u{=hVHGL;(&WA$F2Kh-n4FOVOMH!6sr^P z-`>te9Z`pMJ2)#m3`GHdC}KCKTh}#!Q5KX5WnB|nw?Iu~DtLskX zK_tt=LLw3K`$#g7w9#X4LtUs$S)ULKO z{V^{q@94%dP^wGIAWB%*P2itOL3wg*OWdyRvOcC(ejWDnI$OAoqedJ1!HpFJP$kPu zwTxjijR$oP%jCDZRlU_QpG*-}C&Hu)HlIQ_hPsp>tc&E&LW#Rj?4baoTgQ)-Z_Z6| zS_c~#vvo3Rfg3uvTZ|pL_wPKIp?DT|7V~y=>(Ea`5Zs5{>~Gyj0cu{2iMq_j?(SWr z352KFXC_TuCUqd$KPti!?n6bk3h5_9qebnwI_WOY?P=J$%;<=&M)-5XanxOFjDq13~G*6);3W~K>39m z6WKNF3yg6&R-$QFM~lg|ruU#eZ#q2WG|!lX3UjO)a>7?KeX z+^}0!O{trjQNqAqHzU>|HD@o@(Q3hnoBQSK3fX;FCd6QiZZww27jc93w<(W{vJbk| z?5Tr)zPLf@Q{1R7*2C3b=Q7~tY%Jj%&1aIx3catY3ahtEUJ7R;+YmTLDgu5{Uk$UL^38Ho@9pu(H%V{fS^JTLZyX zt_*@;YAb^YXecUXCJ;<*l}wmhaRAJoK(JMwk{6&IBnhmNP%cg|wbjA0tqzu8O%SXN z7Idv=lpvqAYUp4-p1?Cj2!aV*69nr#%LKvJmA_$ite~10jSvJ|9}IS@%syB!0KW}x z74mm)1XuzR2+YpZ#H7*n1OT1R=ahZDEFXXxIdrdIp3b%iw?efGpeaE;FF^FW08CkQ z%gCK?a^S?4E@8*|cMeE_2O0i;Mh*C((@n|SkEm;ld1wCn`EdVtE1K$7Ya z?l7R@+kkFOu3v5oE-f&?>QVd*)^D)Wga8%ACJTs30>~@qI1DEM)JPk^AOb+GGzYM% z%J!g{SHJlXn39t!1Tq7%K{rL!W2ruc$ywPMRKJzWBO^$h!MMzkPh)bhA3zuB)j+D3 z85gts>N%Bx`7c=@uV*`}{6`$vW8Q)bfw#I*k8<_zcM0gKxY}xXGXQ<>fo#s}AJ~w^ z)Ce09N%v6Pm>pWb8@uA&tc?M+*Z?TERW#O%NELGwJ*PmYniXv0;Ksd?0uqR62LS~= zQO{`?S_>3%^?ies<2pX6x77wQ3+mORQ@N->GD92;L|GP@!~wuqw@VlD>$wbpP?#8G zFwV?CfpLvhfeq6E(!&GNjeLWZAGdN^&lLj@qYM!1)u1yHe#2Uk;*1n>N5q}i)xP6!|*m*s=@{d z*%zTknXR=)0Y4a$mev2Q84PV4=st*TaRTxMs%vgtLNK%+0Cjgg_Gt}b22f6S)uWuG zHd)yqIIx#RV+V^FW_DFQR}wh+k!NaTzf}H4sA~aI&kdaMs>d`8=bJ#-0$_ZZ;eUB?h7E~2P8U9$9N62 z!>GT7;eb}OdL{`G%revNg1q?+L7q)Ow5klLX+{Hz?-bE2Ao9%zLBZV3R-?^;cPm#1 z^IN&bv-kMUH))8<>HxD$yIxXJ+sV~$%?i(ELp(E|tel1{cg@YkTUXXD>ogIIx6ZeL zkmjxatW<-VI+$$aI0Hy+9kl8KAeqfEVrdZ52h&`#ISdFR#buXs-iPttgkHzGjOA+>1~pl1$8p0(Y!vIn&B7kwH~K2~o-k!w#4IKLby%Z=$G)GZc0xx21GY(TYC z&=Sf1+eXva*(a*KLHN_@wFWf-L~<~s*Z{BB9jpy%1kmWg4u=NOgtQ81Ei{N0XTx#) z*dWTQs(;JQC;E-@c~Fa-8drZAdMnGA2h;>ZBISJv$tIQK$RI7PK42z{=4 zT9CJYr(v*PN;878A*8Bc(Um|La+^knNNN!6%5YK#olP;B-vES0>etoS2CQ~4yFAiC zJeebLvJ5D@pRxxOD(|=`zCC%k4|2OfXF<}cz#B3mrK8B?IxpHqR|m-VF2}TDax(>svdQ#;E~AIiTMtxKojgeWjDkJ#-4y1 zWYaQaylfg@yg`(wyjX@*J2<&X)?MsPtjpZ%Vv+T_DVT-i%sMqxk7&Wg zD*GYxFfznjPTaA=Dy;y~BbW)Nyy9ETP|C!q+yt_i3WP&rorn~e$7HvTmOXe~me+}R za0f(*z(aD-s9V(GVjG~DzF4fIG8Tek62QEQNf|jW&gg2ssguRJO`2s(4OGRv6-O2K z-omCq^u4S{M!ZEvkYU&io3SH7i@oV-tuHhH=4Vn}I+|Zh72rq(aiIgC(A_u+P`2fo zR#kWi^U|`(2~dRnDB2sN(8W-ADYgU-Qebg&v0I6@h6RE3?=L_PqwsutxWK`n3^)L7 zIKGP;WdLOg)hr;Dr2L&-yj?+^K1+txw946if1$8ekBUc;S+hYWWa&Kcfg_>kdV!()br3?DU|GdyAVkm36c zj~SjceAMuRh9?Y98NT1}Lxv{}PaA&F@Z*N349^&T$naB!rwz{D;1;ke;thMNty8eVF6o#BMxHp9ydcN%Ur++}#3 z;XQ`i4EGxDG(2Ru%W%%{9>a$W_Zl8EJY@K&;hf(5H@wVnv*A|5OAW6xoG{#Gc$wi&!>xw946if1$8ekBUc;S+hYWWa z&Kcfg_>kdV!()br3?DU|GdyAVkm36cj~SjceAMuRh9?Y98NT1}Lxv{}PaA&F@Z*N3 z49^&T$naB!rwz{opv1aRk!*RpQ z3^yBYHN4dDI>QOWZHAW_?ljzLxXbW5!+Q+38SXXQX?VzRm*Je@J%$e%?lnASc*yWk z!#Tqfh7TFO-|(2>NyA4CKWKQu@RZ^E4L@Xf((tt52Ms@Nc*^jM;fD-AWq59{w*Tyn z`i%AJbIx$H;n*JQC&SH#TMZ`+w;66V+-11UaIfJm!#TsfhQ|!&3{MyyGdyW{!tj*g zNyF2Irwq>+o;Eydc*gLY;aS76q}AVWv*FlHR)53IhFc9M47V9>HQZ&m&2X>bF2gy) zy@tmO=L}C69y2^?c*5|M;Yq{OhNleA7@jsfYk0=+oZ(r+u|BK6;bz0Jo2~wan+>-b zP8e=8+-kVXaGT*?!(E1RhI((r`gDZ`V7rwvaTo-sUac-HWY;W@*z zhGYF!f5Xj&W4BoS4L2KZHJmWqX1LXGm*F&tp0|Z4aeSK^*7vXxYcmNaGT*)!(E2k4EGxDGMqEq zYk16X&hUicF~gIFCk#&+o-{mdc*^jM;c3IOhGz`V8J;y9OIiI5Hye)KYV|kVY`E2M z!f>16R>NI}+YI*_?lPP++-rEuaL(|A;W5LLh9?Y98J;veZFtJ?jNxg+vxa93&l#RI z9NTC0H{5JE_C~9};bz0Fh7*R{47VEYGTdgk*Kn8NoZ()>V}^5vCk&4no-{mRc*^jk z;c3HDhGz^<8=f^hV|dQ+tl`+8)!%Tl;h5>kgyCkxt%ehZ+YGlF?lRnFxYux(;hf=K z!()bXh9?Y<8J;veVR*{$q~U49Q-)^@PaB>!JY#sy@T}q9`psg;*|DIQ!&s7#KZkJ) ztsDa_#lL$W5533txy!=KHT8k;u~>82d-=R+;5{a;%ib>zVazd=y?<*6kA-loT0LBO z?+m>^62kX{@Vz0tB!r)R_8jqX=}&~-zbAxCq4L}xdLOG%50~Bpq4$#^{GkvATtF`u z|H07viBS4yhTeZNgg+C)(;@s=2%jCorCRlH<@svpeJo!7J|4ntA^gS=9th!B>|#mK z<#%op9^7aT|fLnX>A|#qagfq>75(G?)x3?{j$*eMH=0U|FRHH zgm7;t{-vS!n6Q>Vm*4Fnd|wDJ3&sDV(EG=m%F{D;_R2dM3coy*-iJc(9}HmzrK@3B}^hFe1K*M;7% z4!v&+VPj7(zgLIizcCbk`n>Y|`Q0P_x$?d#gxln;|GxA)^>E=ggx>QT!e26Oe<5lU}q=zUk{eIoQe zwnjCSOD_?^M=#O@-1}If9QTCMCuEUb_})-{!y&vU6u&NnZw}!HLh*a;{nVmzd%)p= z(0gYOxc7Wb8S1dJ2OM_xfWyunaM;-c4m*3mVP_9G?Cb%D4~5F->;d;Z?JJ>amj2OM_xfWyunaQOaEe$F0n@0~s1@MI|bhe8-oB%}-f zVCcQG2i$vS4>;`X0f(JE;P7-PJ!cQN_s$-0*x3UPJA1%kXAd~+>;Z?JJ>amj2OM_x zfWyunaM;-c4m*3mVbU`H9Cr4A!_FRXSX;d=Q*#izcd%$654>;`X0f(JE;IOj?9Cr4A!_FRX zcwMMJoIT*)JA1%kXAd~+>;Z?JJ>amj2OM_xfWyunaJVg09%m1@_Zvd*oju^*JA1%k zXAd~MF%-W&gq=O$!fy(_clLmL@9Y7Goju^Nvj-e@_JG6A9&p&%0}eZTz+q<(IPB~J zhn+p(u(JmocJ_e7&K__$me2}2?Cb%D`Ih#8!_FRX*x3UP@6qJE@Xj7^@0~s1u(Jmo z?zQ-_SYwKZd9l6VYVHjM=Fab{xs^w^fH(SErewnrad1x&@X9rMF3G)LyL$CHZ?`Yr zuU)goKRN|`tG7D{dm74c&TwE~G2aJwtu`*#-83z-V`2f~%SOu<9P*SMuMTt91-~cM zDEnb`gAljOD8^>V4!yS(Sa-}oQFl%0J|yfj zHLQnkBtI#A-(lI4#Q1{I>N~Mz(8Jt3h&{B7kDXN8u)W6i5(&25lid5;h?7ahp_bv~ z?T4{Jh~aGqNsE5$#K*d~&d1!1#P}{e_by3%JKWTPddqvmeIq1<;Out?kUxs$i#9V zCJsmI4LpthVVvFER?{eZXZ_1E8nF+E<=1U=@;*Asz$!Rmax1XWooozFIoV^=XE03j5M0V2_n{?J8wI%7Hehlupm6>YkyN_x5fs8GCYp2u?gDrqJa-@{WOMn zMl%>nK6z~qG z-c^f6ImRuFyC0Xv6z-Eym|hFTU)%e96rQe!ek zlb%w7xN^s!o9t{7_Mw_|F(08rJssU7a?f4trs-H|ybbgSL#xbPVFNqNd{D^C6M6#N z_qmeCoi1O1Fm8jp6PQhEeVGlRc|p_Pq7s%>W-M1vrvrVT5xcS(KCT1p8t#A(D2Qk0 zd>`)c=D8o=XP|Eo$EkxpU@EzV(hoD(&#m_5Vf5xIKg{qx{UVs}8#fVh3_#JEb7Drf(~U~(mGZb)d)s;Bh$)l!<%mNMu8qTX{3e{8r&-ZrN0~UX zg54n-tzUHs6!s+u6F8~X0osC(lX(!$dM|KO_Yltv7mA*>+T>Z2YJVbkZ0;7)h8@e} zFY3eNWgXrvbxk6{)(II78i^8^um>wS^IeH_hRse<$?g zHo5HvJ~kL}^1DgxyTH+7`0&J42ftUL_X#!8<|Dbm*w`p~vPn1odp(G}al;kt1Q5pnqyD7u-W!tx_1;?=DjBm~G%t~%{7x;F7bSKkXf z!mlO-y*OgSxF_g^a;S9oBa*5^p=btf;1^#5q2T30Sp!mJ%NP-%0$$Lc64AW8JA?gD zLwdA37%EtLi|AeO>qkVxs)g!%1?y-LQO9s79H8q-_VomFgqMEc(oYLsdeLmaOV88= zBL>^ca-@I?RXf;(F4X)c(Xb9+?OH>~JUJzWOS$lRPtw zevrV92W@BsKgh^(!&Lo@9L+Q>^D|Sl%+HL`GCxuisFr?V^OJrqTPKpl&$4x(oE}gm`(zQ49dhx7-AvpOesXe+uq-r=OeXbQ5aghbG67c}cVf74iH$F*XPT z6mc2O^UL{uDIU{zW~qgPqF%L9{T3ju=z;FTI68mG_|5!014G+S!hyeG3DN?RvWTA= z-BEs~YtC2>G6@*A9EzObbvVo319`);IKtST8ew{10^g66q{7no<0oH|gEVn{ztr%) zwW~KB#-Kdp*L`>-=!Y}wGMXy)J0u2D&~MN){r&VfEucoS@8@_r7FHn1O#NBPK!WquKH3%FE`vLF~vBpDjL+;6{Jgjnv!p|;i7%5X5cy|F|CvQ;vh@tiJ=jrId?cGgYJ|hLY|^~=8dov6qorqv z0npD2={OIIln}1mPqf1sG=9CYI*nfgoh-uU_YlZ2GK2RT`CCS{`V zctCK7XIOH;bLBiSCZ4Vpoh*Xq>XqwPuU~u3O88g-o-P~owVHt9Y1vQ`h?N%fj11`+Nx_hw9TWBxW00PXtjvs%mM{0@ znfNnRoPvJA8%}nfsd7@LwLJ6KJmsu?*i#5H;298snldvAc#^YuVceNsS9HtdMGu!s ze9yjg@dhv_*I#^3xkjZM(_TSO{WjF~Dck_!hm=xL+KQ*OJJLMhr)i!dMmNjX#1Y-~ z5SBW4QLg50o`e0I6cyXh4~fws^sbl-zUPPxJZ17c;F%iP1+Bs_dHA0E%=c#fETZoz z?4-Ac`JM*`3R(N;!kM1TkseWj>U$2S_K|D3G;^kBKDJ|I<%yGKUz|wWL!O+evP0(K zz{EQ1ai%Da-8g7J%y|X9CiG0XN+l!~&U8cO0+@qB88Bzr4W*4Rx(_#5s^a3*HT#HizFwfPzKyQ8IeNB z*HXY`7!kF=6-yq2m{p2&G0ho~Zphct#Vr~UVMD$a784A{ca(P`+K?L-xg$~t`C1CN zS0p0rtz{xxYzL(4*Vh}4(>LJn_onz-+00_suukYZnNQz<Toibo#3Sx2>TI2x{4jn>Y zvCuD1EQ6H4Qf7%^qkFzKO|HXH^Hn8rc|y`*SZOi%VnW+fE9Q&O3&K%C56Kf|kf;z4^YXMO0(>zFG{=*E&5p@Fpy-=)45Nny;$= za9DpWnZ;Ga{e4a7rJJ^rgr&65u4f=|Tv9XAsuHMd}sw3>H7l-)1 zIecp<gZqreJQcLv%(I*0P@hzE{wf9o{SVX869cYD1e3R&>Z0<>fsn zzOT)!pbObU&bDj!=q>0=4a5rbKGm~4y(Ve_6G^<8^(>u2;AAouCpYp=RgA38vT-_= zs@ULSH+ySGbewIyay2L=h5KcOuSP-OJzpnL7{lB3Vz9N(rdDbV%);t~r+9m;=IJnc zN2nlrwdnPpV(vd}J(kjglP zw@W*u2wdopw+kJi3Rseme78in!znD_5qf2G!}9j%sL&yAD+#WliVPiHd0uc8m3D-# zK>=4q7clH?B@v6lI^L;sCK4*QwFz#-iYiIi+oc_oWgsaQWLW0{a?XyTOwi>omg4g7W$g#0$vl{CIPYGnJ_2`S92odiF!M-BHK%w&^v6!NFwvi81aUFl<9Cc z_aTX_k8VK@&x0*!wJfuyY>^9Td&LNh`GVeoQJ;8QRWRA*25v#`z<@019T?b?tV1S7oFNU%iAMDZ*j^A-aNKW<=d-YBDt*7dmn zC6TVdh>BbEQh8D6^maw)7E4N&URe_7tv0F|Qogs0o3Yr5{cpk0$PMP0pNO@#3=iF) z7Kxa**snL(S9Am3oTEi?#8ULVv46=Qm;2soi0sr)didU25+MpHpk*mW2TY_cuH5*c zu}6>JvZ0B>HgN_#%$-PTtRIIHt3c4SPubjof9$U;yQ=;-{Kg6b>hwf`a3^xE;!%G7T+I} zq4G&G*AA{E7$ebSx7jg-x7Lx%WOWG}O3U{j?3ZOs+hiW_hhm0Ou(5~lpW`CmXv&rZ zeSa+{5U;w#QyQ3eJI6*R zp5n6c$vHBA-lg{%V$%rr!^qa8bGeOUtw*5#@SiVy{{W@)g&#gJn8b@!-isiu;KkY% zQQ8nM!bGjTh8Mn-p&~l?!g?+^UXmDP+$w{(Sd1@d-Fp4)j9$J7(2}o@&UMPzBQ+a0 zoh!7eakf;Li0j^?KFS+!3tzLMaC^tUU@G4*UD8 z{THImgkVLVod=oP%0Gy=;3lhBOy2nG%pMWx8w^WaRsniIoK>y9H5;&M@CGt5s_pS6 zU|$A1Sl>i-B;I)0m-8~;L~+Ri)F)+UV_JG(Q+ien>thy|BLQ!}jlIG7k`_)6q+}~1 z7Jj`r647h)!OQ(O=$XqCE{VdHm8YKUm1|$Nty|Gw zsy*ec-t(PJXDy9peCjEA6%Yo2U2RLFyOCDYDPGY~ImIi@E6~S1Tt@B#!^_uA5X-th zsD_~HBtiFz)+=^kRo#w~#yTrui`N3We^(EfvJoG%OUJyIq?X|-vq4T4;;?@l2 z&TJ5IemOUKEloS%e6OcvL6?i#-h8jUE90*1whnrJMAta!8}-f!V0}lC9i#=dG34DX z$WA6j$|a<}E0>#$#jZR56dk@2{E2rye`3}h6P;WSl+N?t&EI6@zvF%do8&c{@xP30r1lE4bjVj*aeOc3ZpsQ&l=!_3xdrZmRtIA zUYn|7yTEIJ!Txq^w9IpE8pAh8SmYV_%!Gb59B07z6{{SCzy)Pn4s_sD*ul^AU@ZI+ zr5kV1s|y7w*}k&?Z)G&QRX-%;5uDMZz1@vZGFVOhxqQZT4afRpDws#yvTlake=Dpb z3?)0>M8m$s?-{O5hRXa>^o`#wp$>?}@Os^f^}dbe^QNTz(y|&~neeKv?QE|>lAb8K zGC``(74s0AFAa9!eA3s~0ZS&Bj>W#kBXeJIE8|G)TbLO*Ct$&u{WR~jafB^;U0Ake z>l$CE77P=MUFbxFm%lTi*+JfWtE*pWw-j{YDXXq6r|(&Jtw1@GGks^wmA`T9FYhB8 zN7H{<`2xWF3cgG$h}?ZE0@i|WnZArAC>L1ed#hjO(Ja0@n##As_~-XDJJ3+1-B|1* z%|h7%+X#7XOI`#- zALNuA5*ehNOA;I?f+P}ePINfFzBZ9AKn|er>k^nYyx1eusIn+AUR*Jm6>Bw}N?EO1 zdHOJGSBJu26>qj$4b6$k=1yj~-0MzdW)@ae6T!#sqW}TjEkB2A5c* zEQ2nyU>-R*b*8qVXFgtfx^`8LkYGOdiq7&UAy6{aGLgajnFP022A4(1Y`gdSu~ zFM}mUf_GItRl8kg(lEGnA}~_&#y1wuYZ7%_Y4qwdiG?edWst39^8sk$%Ytp^+LsLh z^)3u!Gv}8@R(J2<-cWsC5t8bI^YXN#fEKX4K)&#Ik}no}MX-cg-DriP0q4nu`E376 zNl^kCyPT?5UKv^Ie!tFg5|sTM9Wv#Ilw;VZ4k=@K4vG@Iyh6olbee~dX7ETrD9vtF z9@V0po0P`GL$Z+0rH0vr1h)`tnWF;dsEx~u#=uuV_wT3*KlI-!khRA^ti6e=v^dj)axbI*Hz@Qt2WJic~j^G)(5`Igtq^T7{lz{I0^-@iq3 z*Nl44PwZ-ac~tzrKCUr(PZR&{liz=PRQ$8<*7%dBiT{^J!+u@8-Lv*H9UW2eXK`qdf3siQp$_|X@!a#3zgYfMRQ%7qOCwDF zsB-y#*12~{RQx}Fv&K)9D#t(b`` zm8kf?aP9Y}mD~T>$Nu)`QSld!Sp9!mx&9w*T=ToA_#d|Rn|-Eo{QmdsyCo|A!^Xdp zKdT)7laF6G78U<~M}PlOx&GIE_g{yj;$P|dZ?1Cwzy8j@{aaN0&sqI@e_c6#=GWJL zDJuToSovrFqjLOz{@LilsQ90C^?$Z<{HMQ}{CHISS6TfhyDPU}>e}~5^54pr8vWE& zrr&|pCo)m_e{G}2k8P|R|BP4t`4^+&pEIfP$J#5$fBstycSOa1oyq^%)5PETil5yc z75`}~|Mcd{`5*q1_MxcwW7ht$>nq3q*bDnlM#cY6%RjNLa{RkS9{SvqviENOOjQ0q zbn<^s<@m!b7ylqC{*qNjf2WBbd+_bwjf&qor157@6TkC?-#!=>|G6=Z-*!{w@-O<* z{gM2?V?$`XM zPZR%7fAGXxqw=5py5^rqR?h#H>VaHT{O67SdiyKK?>Kt-;;8sP8n^Zvs2u;{!d16L z#Xn~D+hnS8{DZ&y&o@TJ&szJ%_EnC*c;7{@j*7q2=)d-j&ggIYH1WSy z-~0Qh_y;Wi**8@#f9=U*eNpi*c#XDy+y2V&|MAJEuaAnq#pr)}xN`iBFP;5gQSpyj z`?uXzIez^WCnD+ReOCX;)5L$pzupnae~*6vV~UZ*Hhycny>k4~^S=Ci zRQ#tM{lB$x{MVkixHc;OU%37ss~mr3_ojD8#lO)$NHKYu_`f^Ro{frs(#k*f_R9Hx zf5pEh6_$%*t+n1x_-*57NdU56WbBnHzoIm-r(_f91sdD_OD}H<+D*nZHX#b6!F8)~?BHM3`#g8>t&cE+(wyuxLf70yV*x8li zx8MJ@!%^|8u!&gy&Z!*#B`bCvjf($-ejYN`cAEHac{c)dw~H>@$_)x7<7R$*B6z82z@L zCjWoA;zN=2^GTCGV^>zr|BN?%A#(oVaVP&y6aVuU-y0c!i`73-U3vbeWAE@gqU!&W z_gee^uyXkuTE25%RQwPBxyBzmP5e9m{>n)G_cO=;KdPMn+xGnZr=#*e_7=t18Do>!UYB&fl!D_+zJufAbGt z_lBta?;WxJKTY}ncMz`ZV#+ zt9|GdQTadP_-}RP^8ft1U)~!P|0&a-ZKsL9v*|tWi;CZB{U7^y<@|s6-bAGR{yn4r z*iS0QU;NFZAB)QWBgVh8Kd&7Bm4zRDFe?7fE&s98}2Kqm;T4m zwNdfEWAdZ-e-rl}@KF@+|M(`fP{f2H9TubnL2;&huP(Zg%&A{{G*6z4o5ly?frzGtbOC z(`T}+`A>g3F|UmOKI(5H|9q9S!7~28q5i1+W-b3=cDvm&{>2}P{G&~?&VN%z_m=kG z?gM^xx;6jf+c(~m$yeVM^4&K4!?ty~BjZ2xj^Nj4Sj+E_J62kM9j-(8U$N$Ia<@ar?J*Ev4<}i_repYFqP< z`=qfn{@SAaC~N*hp=Bq^^nYy@gx_V&uf_i;Z9i0o_|x99=4WSDy(p7E9^y}3WzC-* z^{q7j{15Esw5dOrIrBjqnfwJHUrVx@$oPvx`qxHS^JnbuAniXZ_lA(K zrdsnak6biFCZC@i#V@VCHUH{Yiky`3R|oyoHP-w|*|k2C@z;m^r!=tUKk@SoY5#2t zkgwbD-y8kx&ocSbA^*4?ah*7}d$m+z8H|0h}fUt|2rD(m!9Zp;(X{;Nrl z|MWC#`F;20lJ-A#0sFaZ{BP*X`K0~dpM(EY8e03`-_BK*mcJRGzr%)qPo8|z@uSfY zf35@8;r}Z1xODz)o`oX)I~!T^PfASrK^A{)(f|Bv%^z{Iu+)FXf&KM^*8JxeJX|A_ z-wWEGP8<6z-QkdqpAG^2osF&2UuxxSY5i?B*x&huwf@Qf`&`<790T&z#@77re!&hh zkgR`NiScj4?_4}a+JAK!`j519Yx(Kw*cmeUQA1h&|Crrptobv#6iAct?*sp-HL>P@ zKWzI=8UHrOKT1<;{)Ro~+?DZXg8kI9*8GomnbJtc9|ipv+D7a2qrG-Y+I|@X=~q8( z?LS7W+TU9yzZsNYE}QgUadbuL{DXZg{2GftcP(rE*Z1u3sZ9QLjK3&r{sQ~&NZT)O zV)_rUwtwfJUy}C!bz|Yzx&E(P%kL8Py|n#31nj4dw3gqZOoNBA@Snx>_lC9n>u1+U z=U;yc;n!`#-*j)mS~B^kA^j?itkcieCoWu-@fUns_q^VtTTp*;G_#i9=iBPi{;P>t{@Cb0G++D%nf|%o z65)5-q@PZ^+w_<5S3rIn{cE)9EFHhkGa2O9v9{k&mHSKmf9Q0uKc%=DCDZ>Z z`p*{D{Kq!72$k_4!~Fl7HUBT~r%A(q4f3D1&^r7tPVd`YCjSD|-yAmir`V*H(*A?{ z5Pt0$YyD5uYQ~nJe{}br z()Ppm5P$k8Yx(uojgYn<8ZiAemjAWU*8B+{%iAwEQGQEn{Ym*t<8KA|PaR{;KW*r+3Nrq}=_3BLcdYrhpYFO{#;*du+eZJ!k=?q;_#E;{>AREZz+o-M&y?05OMw4$T(=JY{ljlb%a1*f|Mjuf{Er`eL6hm<0rJ1o#((w5zgOD+ zn27N|&RYJst4pQ*e-X@n{BqgIAD{eiu1x<*jNi@dub#7(|Mv1v8p!zTLi%^w_^$XlpJ1W2MME8Gi_@-&fmP^EbRWB#(@LY8#RM z95(h_v!a;Pf4713qvo=f-{8{s#bol^Bn$a28~r<<8z-&*9>DtNyVmkge%`8wOnxhf zKYfBV|AMcUzANMJjq%^Xn*aKXC8Xn@@4@)F)5iWoYKI+?$-niXu%DjKTK)&?7E0GI zCTte`YM3?u^PSjE6O#Uu4KV*mx8WbMx%L+_{%?R^&2KG#)4I{p{^tsr5Plo};+HNx zEt5YU_|*c|@@E%(ZLf@f%?BXghQHjB`psngAk99t@#K1eL*_@(qKJ=|1oR+#CL{&FVp`8;8zP<^WPnJH@A#`BFeYn zAJV>ba~b~)od5T@wfw>9&q@0aU%>f`HvB)jiigPL7y1zFA8sxG&X(KpGX8hYLHha7 znt$exuSw_6O+x)`LuB$C=za4#7*iYGE&7VCg zPMUvuLj0*Et@%sFq)6LuOLGbR)gP_-Z(O-iMP|RRw;I7$)Kb>`Z;cO;mcLm$ApI}3 z=HJuwyJa%@4oH8>Kx_VYPtB0lUyech!F|Mr3ljKS2A@ z{k}E77G7G~|2z)r-+C+S_Q%v$j+d9|{}%Rtw6NwcQ2V-c{AdicU!2cc^Is2VJynwW z;{~X{yKU^ZsKJlY`g11e@3N^s4}YPmwEyrm7=O|yTibvB+e_b&>Ax4`Ya6Zk$K3rc zT*mJX7x_nNV%>hN^~Zu6GX8DQesI|EpB#Qrk@0_q?GGFNJL$Eh>E{seyKMM3R6X~m zO#bcStnczuW`m~I;U93|wIwqCn99O_4jcZMA@S1r3&XJe=CqE#TbC45Y`JE#C zuFlr-|BQ7=`%lUNzt+W?|I&}G>dNGQ1NqPCiT?)tXiekXOR z3*(Gqvb-B0!+yy4hps8_j>i= zWBbB-`H~V1Mh{;SKUxx=IG?ym0u2MY@cM~{pZE^Ox8fdrijQAMB@){jsS2Z${RfDC2(z z{Fj65FGTtK4OJa7{(`W+-etpIeAboUW&FF*f0F%)sQlNWZb<#d|3(P=)BSxY|BxL! zr2OOR3x2x44&`suqIn~k{wL9XrL5y`<)0I!{^wPYPxrT>@;CoHj+5~( zLi>^ZIjH_o^%|{^@vjDcy1z#N|NJ;<`sMpWxq0}>{uGpd-r&1sWb*m`Q0fu3zJ=`1 zK=})0HJU2p|K~{&|8#!{%Kt=-E@?7;zQ2^lvfke+J5bvVQLn8ULs6 zLjF5uo&T$Dh<{wh-zQPr<)zRbH)iRK_34?8h&4HtYb8jj4myG`*ls|NR6Xoyt&QsF-SA3?>pRP}${P{AD z=9kHT3i#F2*7jRIzxWa%pRNz0^7G&QVUmnL8q%Li)(27k0j`x&|Me%Nf4V-0 z@_)GK!!|PcPlNt$vc8D&_d56bd>MZ$u%C0Qwg2nee|>cse}SpOey+yW_W!nUq%{2x z0sHA>em~W}>*RsY$>g_%@YDI-lz(-xU+c^G>*_*(I=`3l*RS%twEUU``qTNfl>c(G zHPZHP;n70AO6JE>{=*X&?UdG z^6BFxWc>AEegGYxr2O-$YHMWtA%1jPiFJUiCW}{{>e6 z=NBCxqx_R^U1=)g{~YAg@iEGO+c99WjDKobA)k(qQT|`%T~cNI`yv0(@iEH(&HQo| zWc+-8UiB!e|C8}8%HMK(f>i!_kWa_QDF4MtwHnLh^Zk7_CZCRvQT|Wrx%$iaH(~qV zGd?2hN%=2#TCqXK{{i|hGCoH6Tb3_0RK`C5{I5#Jw$ck*@|h8uRkw%+aVuRFyv&DlI6DT_YbkN6B^=m{hg%NuIjGZz(>Rf~dmrOWT6RRO z$`6m{|EyP+oyhKg&M=qRxJJK*jl9Rn<|LMyFjk+@%N&`P^ZJO*k%5~?4IFR+I5ROD ztc)Gb&Wkn1B#rYY<-FvO%ptMttXq$nV~z7NnW>se<+8(2{f@A1rVjKni{qWSoqd>P zachj6_N&{lKZ;H4krI>CnIF;3n49J73}2s9euq?7l;%>sNtjbSN76F8c@B8x!sYDp z|2I?pU^#mWuXI_`#DjRH$ES0C&$*uHf9ChvFopS_y7YX|uVDOD-6864qBf)`NYO1F z$osHpzL1b9IvIcF`@_3=`2`nyG%l12kIKS6kWxlu6Clh5qUWb)^#L_Xi2T+j0U8TqOHe@|Xh zi^-oCMfmytLzpIAGhscMtXwM^KWc(7t*0Qr!vn0k7u6@lhAjd;K zKt7~DztY4l5AfqS4)P(5nJ_;?#vjh)iwoq#I12J1eR5k_K7JlxKfb@Y?yEoS zlZ|{xA8!2eCmH{(nf~(iyrLb9d`Rb%n8wGy0^~P<_8ZzyGm-ySq0z6(_`ikvH}bno z`2Tk9=_BL6Mfhf{s%8UvKb@efIr~Kfm}@QSOcC@t3Up;O7IVC-Gm3g8o0$ z`^xxs+Hi9? zzwq+`+!B7YC-PTwBhb_Dt!<^q)!f=lhH55`L=xKM8wl%jEO@LDe4uBbd>(cLW zS@`+>BJTeM@>BW4`i(jxlh4=p>wg9E)9@#r3q2$Ye?&5izdM2aRDN6cfQB;pe0{oh zH;|u(|Ml)|cgx~$Dv!T=ijwh~@B!%mkRr~ummazqf5~j(zxeuM^}fCTs1o74Bh#O+ zuh8;^C?y#Vzo=aCR#A$K-g%12f0d>`zP>>X^I9AEssGjs|L-RA-?K7_{(OCdCgG>{ zZ*k?hET;c#>c9E=23^9Bc0>JZ&8_o_%>I0RgImJy4Us^2x%D%HW$A~nZ&34l|Bd0N z@)w+Wj>rETYQLDuEc_Pyh;wZJOJx{;Q_9ch$7^`Tvrqgf$}`^XkCgP(nnrJq@r8A3 z)l~gH8rH9_MncC}O*JkxH95692S`g#6?5!;y5x9=oY5uGCnh1ieQNT^lxFH+wFXX_ zPaYJP+HPc0EboM9DFsMO@%Hp2vTl=9pFWg9tmmeNPY<0Bf~*_FzhlnZPsf7Edq#*3 zK_K+&k3B1iaq02NgE)di8j9p$YK?)($-|qe$-@Wvgos(=$fWdy#JF0d8e za*id%F?(L!rZ8{+%y$y}%7E{ge_2e_Kh1E=-fuhmBJUpv(Es=d!GZJB93>tN|G5{c z^Y%l4{-+j#Mo)=$r=#Sf;U8?gy`xNjS6zXR?K+40X!vWBU;Ryn-=Vp{$99{OoKp#* zvn6?VxXy-#h6dQb`V7J98DFXrr2Y*G2}Yp#=iYdi>EA89PZ#6;&L;(}1M|N;<2TTL z(qHlVbeZxqD~Pv9JKjCGis45@0lq$^oAHNJP_C=EJ_62xy@efpGH~{85P5$zxn%Cp zkdXQAu0n6@|LYC*SD@XD^Qb95fm04WF5V!Wvh++juD{Y#;5(c`|4ukR4(4Y$$_V?% zQ9$xMfK&j^cHVT1$FH-Ozy8-D{nPlh!&j7weiFye-BFRJPrbW8{*le_H=LhP5z-H> zVECc22l{)rlS8@vvx)srv}W~>Puc&8{R8+ZzUu#?R>>xOe(8J%q#umm28rT-0r`vS z=MSe0BKEJ-x#kIOf1TJr&mzG{?LU~{(Z`_#|MacG(>Q)6!7pcmKZF7XKKo_Bqie!) z8S%@uY2z2#r?}4QZ_NHU|It|*{R7s-jK51id-51_`jk5!SQ+Up9PT7 zgz7~9w=bOQ!SNlv{q5hyME?{MTzvf*!QYdRI>*qT;K!NZk3=97T9dr5{FmO5$8UHC zfBnC2&FarAejTuW!U^?F;?@b?GFt{~&aPr2M7)Ohx|-(|q6aBv$FaAKwU#CA>z*89DBW-_k@{8R5;gEh*uz&O@!HVM+E?5URB>>U?1^qpL zlS?PLeOx4crkdD?^82H+^-%C)C(zJ(ueRg*tKdIRPZa6L$?$bvKEnPS*uE%40m(D{ z{j*79rgHsLi2mPV{vz>9`3bzzfxIYR;=xItKAptBbpZcB{j(i@G~}xeKs#OQ@&va} z6xc_B`tyC3{@oJ$K(mHu>3w{HrXM?etmUEHWm7X2 z^Z3mo@%yq#{MzBKKwzL9uKX~P+b4zi=TU&~hWeEQ>Q{F78N~k|{5jV;!~O(+Bb2`s zAH)(Zy^q65`|`z6As-s)pR_Lyn3V4eyin3_Zg`9I?8GyCeoO@R&lH04eJ&`9^ZOkY zM9dYIqIzG_-kSw(gU2t{fA&NE z?FEjE*57PfU&Oy{FB{9}cLdZQHm??nc-9w{d)|0qhp!4Y&u7fDlfN_4Kk=U{pnRnM z(+=O^K^9-SBK8Rlh(m$@h$MF|C`$PeLB+zj^r!VFB8l?YJ z(EsQ0Ebs1NH>^)}LiuHfk9uP~?B6+%uRn^&CjP%L^Zy#dr|mC0e6$bZ-+#6qU!NP1 z0{Ub6jEZOZm*M03FjuAE?2r0`d6Y>Bm&Y;u`A&j=*U8d9!}qKogZ=?K{ZVhkkGRq3 z0LQ24vka7vE?nOQ<5PC{^!GXqzYOE$uTJbA{uF3H%3sQldLpIzzZo-cuT1}gP=BEP z4|e#Zd7*s0BtFUTZ=`-Q1?q3qzuDmz!hit%@q=owasN!)?{5G;Enn>L(LPAWuUfyE z*{2ST-@;Q^-g2?@5B67J{LT(vC;HEBGMo2L&Ucdf^EY6BntqBAe)>p%51+JQ22VdK zDZe63>Ti^v;+$nv`F5_>=t573K5pc@OjSlR@xbGQk(M8v^3< z_=L}Q{`JuH1-rO?GKqZ}nAnH%6F6l$c~N53XK!--vxxp_Ci>gq`%D=!Bt7us8wTU&SEn83=`(})&(f^_M{}|C591du7{4fij3$&#`}4c*9oc)2 z+b5gYXSIoa?C{x?IKL~S%amjuzu6>ye}w#{5dTT}{lM4**01pW+N{|VIer$wZ*7u( zC_myLbv+}#Ed_d^?r6S#K0*ikE7L^(=TbKJN_R0I1nbY8FuwdZ0-4Y&`TT!~Z#tt1 zkKZVwzaw7!kNW=y{_KHI=s4k*s7f*4a{Oq5-(o2%e_bs7;Ql4h|F76NP}N`LgFe6A z=lGc@QMCI3lvP3>0cfCKdFDV)t|_JYh~s`o_^@~MYc)$ zw8IYr{gHOByMwP^j?lpVF6jRsHA>h~%kE-)al!nM5Tc*IwH0LvdGXPR<41Y^jUwgO zPLupwity7%9pocjc{r1=zlczwe|S2y?|QTJ!!J61R9d_?{mcaX4M6X2y2aN=M7SXR z3gdq0WJ-Zh2(b*jvdDE=R1i1 ze{u?F2K#F|BZ9;CM`!c<%V&+`_^3a&FWP}2X#3Gle-+e1TJwdsdH-QV7NnnKXn)OO z`OD4hL)(vb_|bsh80fH9nshVl5BO66KbfU}buW_v`$xH8eAW&h^)3nc(S3iu%JH)S zKMwG_vhqt~__Tdzhfmz6a(7l@{OSzf1><*4Xy4i4lkPD^J>ILMk-td$ z=p`tB9nk*5@n1W9ntoor)9^i6`bhwM>i=_!zv!KhPRj5LwGa_R%U?Tu+CD1XV97{s zAKE_JXwv?&!^d<3$w!%ZJHD|IzodNMXVU(%!*`Ji-baatM|1oP(tex_^9MB8Kg0#? z>!=XaOin*0uTzRXTbkP^oA}QMCjPSm;ir%3ME)oFW_-={&m{HpV)Fzit)JWBd&+;1 zv+av&y#5n`^@ngMzs`aE>G+6B6{gRqKhPVuy72Xr0r*d${y%gv5O5!2JA5aRx3uT( z{@gw~@&BV({&Mg2?vIN7ly>+EB(OW6|EeW-`ToNZN=Kn*2H2-G%U|lgK>uckPk&$W z!ov-`{^lg{I}Q8;ZC_A+g{}#`o>;2ap1I^os6Xx&BU~e=n2z zXB^Rwm_vD+{C@7+I!Czv4l;k^RTKT6q=4iZ>*x6T%f*EUa{Ls6|CR}UWn?s=SMvD( zQ2Y5lUmE%o{~rhG$4SOd$C2>+qbW)x`Mt`%XBzSJ8BOB1EcV|5z61K7t587l{5^S| z*!SK99=|RUzuQgHryV{m-^<>7h3}si(7zFh`oq2n3XG5BBKpxs#7CNyU9%Fy_l!>s zf%<0#_)pwl*$L}k?C>=Zi1cFfrOPYw}AJyxuLah8AH;IzY!0{lpz z&z?)*_KAoB{4~H{$;&T>PwUTi__Y3ZtWZcJBmI-|@jb8)O`mr7Xm?OwiL6$6fGmDL z0(@G(wZo^s@7>k?0xusmlK$&s`XT*qlppm(O2PFV3GPybmY|K5c94=um!@TvcZ z>|HI9+g~U8=XphFMC)&M_@w!(6fL8x+&d?zM@{^X9lo3R&#Wy ze((EK6`uYTlD`hEVfDlP?1ufRU8RM8;QT~I{>tz2ZR7m9sFq93Uhac(-&i?GqpK^)EZ#YRm_e|m!vo)6^yJ-Eb z=d9jaI6kevMZ7M!Y5uJ#1NC{gf@HuuCA%B*Z(YRx(;$CQ`yVIa_klLP*7uEE_U50a zuZI}*2hu)`1pTRhs7(RMvxDH@NZN3i<3|(xmL~XEJ`q^YqYB@Uwu-vP{eOfL;urg` z2D0?SFWP?0Enb^`I>P*adcJ*1O`g9}h<`|4A^wN^-@8hQ{AG&|@D8A(7Absx;|Len zXD*b#iBP|#{lmfH1H3ZR(LIdokNDVr>GhWQhiCt7s6PaY-xvf$WUYOU>+gX2!!*$U zD_(!tA6S2|!>7MbZ(Xu1_YW@8KjvT=RXxCzAmt0?M>`-@@e9!5&7UaG?SttD?GtIz ze`Sa7>zlcVY754s8Ra`kKXst|rT)PVpXQHQ+n3DZ`O8WCXM2lf_s(e4*ll=?jKS}{UpuAKiJ{3VL!iXZ=pX@dHmA#t+O!wll~bye7gR1)b#vE zxqY(8`tC%?zj%JB3)Xko;qQb$WCFdpeELQnzZ%4^2Kj6CQdYJfU~!D+2f+Re=$8D9 z;PZg^_-e!C{&RTxOaXjMpM6+Ih@0W#`2fx!@vjj7_Sf({M*h-?f17UN-(cDVsuw_M z|4p6;Kb7L?$3@c5a=@qMOUnR6{})%t1dNS^XTNO3FR8ypqk|&ppYr>ovnR9<(4Q+u zea+(+%NHH`w^u>>r1dvP0HFU1`g^{Au2<#y)B4Y^%s;3H886YF^82H+C)6K)`2JKg zzP=-%d|ZI_bHK;_J#6tw{r~Qur1L!gx=8xjVv>IB@UtI+;y}j#7BY<6MDCS=J#r3nMF6aecZ%>kK4yh(*GTk{s+oWC4`amleAfTpW7#k*k`p#`mw{O{qxg) zt@*i8|0MpwZQ>tVQ-#TMNs>PM9y!&6r%yLYKYy8|Pg{JjPf4H^i+w7_@4)_tz&~t% zMJR^n*E(VT515T;?R{Jj;{DFQ^=fcX%-DD?{S}hGx&uD#zqP}szu&w1_H#V{ zMv?THr#@&v{6FPKJ&{uVLkHLBBGW$;fT(}7!*7FvfX*GecLLWxn&@AI>92ml{zUYr z`~*&+?Z>J^bA811r|rjRlles?`B8X9gExJFPHB3162p(kg!K6q)Xyt0{WYdP9bd4+ zr}|&rJAjXm2k5V1`XuFx9e!mJq6c5?D#ZP#PW;0W$SAaaWrvUL78G-0*J-2u>m>2} z1K`vCH#__&@SBL=?z@<&+&(ViANH_>sB`<1@#}WTXhP}uY3Flwjqy7NDZdJ52mopy zJA5sdzu;yuwT$uE6w?1$1@NhTsD1s>6ovM$HaNMZj8VTL_{~l5#Vibp>U~auuULJ$ z_*idaeP0&XUx)Nxlcj&RB>m^}LP@{XAaB#ojG4pJXB4sjUyy#N{q69368wr?e-iz- z#6FL`D*j0AZ-=jv_^nxddpo24N$`^(|5E=(`H8yh(Z7JNT@sqJXo15g{?W}&H z9%5+-&fjx^{(UGQdDi^RqYQnfRJfr(@o&elf2p&m|2U!jj((lMdLA9{4QcZ=ReAXy z(7!!;iufaK-;v-0nwKChzS;hE#(u-Uk@~{~?4Ke1OLq7!1O{4jeBXQ=KbzS9AoCBJ z#Qt{pPQb-}zFs}%Jj3myJSRNM8t@P8n19e2J}n>Z@agZ*+>P4C^B0}JIuq?f>JOBk zm?NP6(5_j5B|QDm`a=`&57htI;cG--x!GgNa{o-%*LOAXKX&-FNcng?|F^ri{whg7 z7r_5h{reOB=%a(+cl%+iF@K(pfBj*CPs2~~JCGN(XI|^T(yU*$|#Sb>jaQnWRt3PxWs|UL4xJX)TZ6 za1y_9Ch5}-za-#eI#ajb`HAf>UBXGmr?Qy;SIe@*0Qn2&)rJ%O=p*7HUG>|T{w#h2 z&hPjR#vidm3imHn;2au?i_eIQw1_jUpA>&4a)<kM$eHvE-R#6`O7tD~D__y^V_ zr@(g~hxrLP)W2h+foW2F7~e$u;Q1;!)qi;I>eBOnetK8v9|H9aefOj3-{;M3zsmHF zSm}?io)_hCPUCmLvTJ<(OF;S=2@9c6fA^k8)BnlX-F$sV0RCyHD4{!4uZZ#u+rt?9 zlw!I;TB7wuU50-b@KJx_ma#8F7)m{8zuGGW@Uwg296i^Ye3R|Hry+;{7uL z_USUwAK!xu=dqcn@9AAd{by9oZ3D$nd9u{i*(V&Q!4W zkErqm-~TPZK3{_UF@DkhNQ1>cP^6vIJ~1SHdeTh})90jl+pfv<;@C&aI0B9e?&8h$CHUDL4{MID?*%Plhv`>w{LYy-FXHNCE54HnxT7J!L zy(nIWpKq24eh$muF84S5BExS;{3q&<)FgTX{9BLX>(%Zq8zfSDu18Rn^!4KGu zeR!$HG=}e)U-2>2Z|naq8p?RSy9>sDJ?Y6rfCJtm?OOTryT151zpDpUv|oxA9FK|e z7t=Ms1Q5hUitTHxesGJ{lYIbzp%Rt_BYNcexavtZIR(01N&$Npk4*@f9&vG zhE|G_33T=AHB0&8ABXfg6w(jw`|Nr|{9B);wv^#d0el7Q?tuA4Io1E!4Q1!a@K><) z#l{8uZa5zie?zGzvt{^8(LOLQQ-S@ZbE^NZr{6I4cf$0E_MhECsE_R~N09hbe%jgw zrFi=n@p1mi?@xk#pgh6-u_-_N%R?OS4e8mBS6uM559Z$w!9LnIkp6?zA8|p9vSit* zJPbcT{})aAAMEs35g2HLp`U!m`+ul?QlNhT>m|6p(hlE2@Uj1p;y-Htp%d_teo?Du zwy*th|IZIG{cjQW$Nkyt^haEz``6ByDZ}3j_*gG-!TO_|;=fdS{C6_^pP_$PiGp?o zoWEm-?|}YiqJi0{XX=c z+u=I_nfBje`uVs0x2i{T@nzl2S}vLXJ)rz@!uSI2k7}pCgW!Mv)d0SKU_k!T0H2P( z2aAt#syKcz_TNMMp#ND7 zpmA}j$tpi)j32qxNgU|rVT+BANlItOocSDFAJ5;hqu!FzVg|?6icV(7b;YIDG!WPc zZyX376s7aOLh~FaSKR>TaI(YV(o*W+xpVADv6Q;L5B0ncfhVTaCqDxL+xg23d8AF&p2kSu`s#kr`RFF z^z7ub;R!>M65|Yg8`c-6pLyd~B*clgM_pq5rvc}~&SmX?$44PbG@B>JT}C*h+YW4l zQWx7KA@fRJ#dSU}y!8@_zwPerjtqY)9sk(E+E@C=3_0E(KbCdyI^GvfDtvN5FED&V zJy6b++#?z?{DAW%7mjBAK|E*(=Tr7VEwEwf<>_Qw) z)jCES8ag%zs#THqlOQhAkS$MKk>S_$^xp|x-LZg&<3;tLUP~;5xJb8!w^|^>|G?9J z6Zm+JgU273w4)IhsrL4qB{KYTnL@EpBlWPj_*3*h<`jSW^Yx|urw??29|99XJ@r7e zi%B~g^+q~+?Ni)82E^~p)&BZ>@Ub5&HO5AboGy6EDc{pZE0tiWa%^8l*=Y?+w!aOPs}DlHsRN{9hjp z|FI1TyJYw$w~+XSe2eup%*Wzi-cPg(($6Q(9V^4X2IDK3KC#~g&tvrTH+!LtZ-|Su zQja}~4FB#1!AS8v{j)))pC9jcJu1V$^MM@S(?1&|e&XUom1X!3HVb_8pIDF5e;y=-^Ij9_u=Hd(LjWjjw z3EsaGfInlC_&@58_(;w2FP4u;f9a!_WcbDC{?t(kZ2rVIUge^p9prr@|Auz3m_JtVdv-|4*JSJFFkWead&L4Hg$nfV*V)YQV$q+yP z{omkExcUb_Up+wo3mpIazsFBsw5y*Cztm)gf8pQbFR!$;f((BoD}VKi{~kYk+TD9H z{O1-jeD}Y{U-;w5Z)Er-S^uMJ|G&o{|Ja~qGWr?=bbXbAE)eq@|OaTXPW+7ZY^A#=^s%4ulx*S{DQSFa{H%$^bcC`FeUoSeC$s> zy=|bh*!Z|X=?Sb|#hXs`>aw;Oe=|BhE{UJ;+^{}-F_xW1J$$(TpTs-w-(&|tLpV@> zq*F&Ud_E*BtRZc`@b(eE)c1s4tlCMut%MiiB8_$D+abd*!_q&$)W5;*@&0zgc9`q? z0t&zJLR_Sghwj{v;dg=hp}P{aD@^d+F$EQV@g)UKxJ-m4ZY4)EYnQd;x{ucp)y*GQ%&-l;L;P1&3~Df2|-}qiC*w#hS%? z%J7?D{8qNsUt_lCH(sbW(vNlwep80O62>pp`||XI?d*(|1r>hdg}6u?jc6~m&pMdD z;xf@6@x#{?RQQb-;v${xP=1o>&-(}X<%IlY)lVS)DLxSwY4gDclVtdbynezi^?|j0 zoUa#D_>C9hB7I7G?2HWG3HZ7VzM?a1e#3>hNPlZLp_dGQCCqQotIE?)%}T8Nsm1oN z-cZoE&G4t>n|V-%{{^O>f2{43`DQ_d-*}$`o^y8RSP~kUT zh>P@z&{C5`a z_zf50B5i#C4W|sh?Z-L%HfWZ3-13vrQtGi=4LGW-ly|L2#wLf9vsefOBfB zG~FY^?_F7NXv5_AnMH(uaK0F(@Eb4uhP2-KlRwJv_qGrmYIT8smb7Eg{?X}$6n^7{ zxJb7)`Nl27e-Z6-N~9l(AIbZnnSXO`D`ebe_)`iG+9<;}+NX?3gLdx~qCeI{c{`Qg zc%j}N`dP={Wca*&$}g7&OWi8cC&f4GC!qQddFPp>GW_02O#fZX z{?(!lITU{rE8iV;xX1IqD1Q1km4?gk`?2;Tzg(^5_NiK3{7ye9{@rq|*U0dHoh>-E zLvs8mR$j_3iXT?AOamD{Z(s8Z*N;*A1Z)3EA$Kat@Ok^1U#{){E`D3}ZWb!T-^Kb* z_@%=7u`o7YLsou8waBaR8!u{~Cf&C+mEre+_PgFu*uMj5XQwhiXI-{NePABrHp9Pl zymm<$ep(yB;W{JiL-Fr0c@9=*p%>MEZ~sEKW%%)lf>S*!@WY$?+b3B3ZcnZVm*E@z z4@`s;`ZcWjA$VT|Uib}ZyS^=+li}wbCpcV3h5ac$`seH!`4oQRg}6xDe5_{4`iBd> zCpbbB(IJWB3zX7v2E;{L63 zHwq5Kr~T&i*$jVV*#7SsegmA}fb+N7zbiO!eWL>NJhf>eKJ>o?4PzQ-7&%Y;AMJv) zdc<75|4{&b62W)C{1|n*z;)k2{E|wz&!ISoi!_&ea8Vil%(X%voZpH4{cgZl?;(DO z($_-&ugjm{<0Aq34_o7pkK=;+41uftjri8~>C;AiONRgQEP;>nJ8}F}dqv>t_YvRP zKDG9i=`O?Xwo2gR{4*REQC}6f?gxVAX7QV1VV_NFD;AgGUjzH&c%TCFB;A0oJ{0)j zY&Y0wTx7sh!gxjc_3t$!Wcb^b3H?3zFrKE*6u6oq%KdPr`%>Zh37NI$2b{|EKQ^rOxe`0mi)@c(YUnx9V=fIk8J z1I};5d1!9HS92qNq>^Qkzy4}`jn7XFz<*_fun*2Z!+Fm7YheF80^ctE6boy0S%$yu zZLmMgZ^L=W+8nTdUeur4-x~moSEN6GcZl!r8KA$C=8x~O|6H(tzTogb-K9zW!#V7~ z1^pEm*LMTHnm;)FR|bwKEYp7?^xtB6h3iA~d0_tnh#$`Vr>7!;c0u~W>R+nM@Xtg4 z72+e+UI+UZ3=Ur}P;H_N{}#c=d3tIF*uN0sTgUH)TSrdF@MnX6#&Q?unY#gBEiCYJ zGyjuq;ot7;uK1S>|6PKQ^UU@6VE@O1!_S-kZdn3ZUXO@38;je1RbK_x7X+ z8DGvHU5D#W&u3c7>i>EHHqH+7p>Te-s4cQ{CSZQJSO4BM`t|qBh5Ro^+Io8j@Y;Fj zPNuLaqkhvp+1MSQNa~psY0O^qKC*$m9_caZVxp;-&Dd88JUGc`it6BzNwK41hO@bl zsY6o8{8B@pS_4KBQ({pTA03oKvstUEXBz9vd=4waNM(#9AjyLVBba}vIP?oO`qgdF z@c)ge`%5jtRFqhIP+Gd=tuc_wW~B0v`UjQk9$3F=_{RAwEPn>n?+>tl>n9XwoiN6D zkzOMOQG%T>`E1EcCs_Uo7@w}k^1qtJamDyFp7R0lUIKD4on!t-dhu?JE;9Y+u>9dZ z&nreE$Df7#j{3VJq74~ZTS2j%g}6xP-pzeehR^#qbr&zzMA63a`L~j&Im}POeokc- z%lYi4;kfqFTYoeBfcdX^r!o9*#rzu{0_5ZSN4a7CYxbvM%F-uLAnQxn&HA$85%pj8 za-q&L{2OfiSpQDUKk&u(v}?c4tz`F9l(ua}KR`5lcC%-Cy*K~4VzT%h)Q0JEU15G) z#IFMV43yu@599yh+T9;1!!O9{XYQL`d@V?PYM+QzZT^(mXCmwW(qaCM%s$R5zYM=nZ}H^)tTDCw0~tQ=f6*C! zcyod8G{NWnGWt54j8sHw94mdGv`9-B;d6ypc!3k64J$@;IF@(x0F zsV7B!jn8lKjVJU=>UVh+e)r|$NgsqL+UdN;Ew}?eQ7+PL^G}YD$>;uyUv3!x;o}d! z@_qdn|DUfP&{XnyFGr6eUE0h*@beE zwt4YricCKDul#bH_Vz!^sRWc>DHAnf$VBej>kIE#&EMX)*D;UOSh<@5aT&v)w1kMVe<_?zuAg zPviK+I=TD~75pVRK_CCOflnwG>9X`{~Z|rbGDO*e`6yN-&tRWDEy8ZCZ1E+cYd2)C>Lqyw=egX$$x^+ zkL8!o_?>U~ar`So%cJo7L##Kk@jR8?W*5pu+OXQaW-|HltbWEX^?eb3UXPT?7ynW` z^6}Y>qFkht7T1^BKQmq+IGz*oc|Frt{w=1Dv$ogHQIH=s#>Q{63*{nRUS`Sfvhefz zDZjAZYgJF>byeSbs*63FT__jn=r0cElF9!Q@}C>RPvuu)QS9&u|2yVU?xzaM_0Xcf zY?H}%WBTtT?4NV_ao!59Y$PuRdH~uu}Z$Zl< z#eZPh2^`kT$#*Xmb_k{%+`pW8$}?pulS2eSSeZ5h?hs|CtM z`uXMLvoiTpS^R50^0h1S_^0wWRc3Wkwtma(Lb*tjc4WOOlkbja>CZ>LJ4pHHXU*h$ z{2Kfr`>lS``4jUuh%n?fN)?u;eiHGZ?-O>waSI%G51=LrQ28rdH{W67BLV%R7eRg= zMd)ECAICX7dYH&ZyCd!1_@nDG`~O&-$cBp9|+}F ziG0^BlYf)RS5JB6yMvV9gOziwC z{QoBWHBbwbi?rg_b|+-=@3Zi`edN1?l#l%^fs(}=l#BF4#n+_%_wQ$!{ZD)Cul**^ z{~8Fw@b@jx(oGJ+|IW#+V`bq_VD%gAwzvP)Z6Y80cTv7w{&!#o1ij~Wa(=<`-!giB zXw6OH57@sPeO(^@J4HnPaE%ea11uwhz4aTPVJ*r2DDmDdz(lqINDAApBPC{t&qx>V z+>0F^la_|{q2X+_D$dyHBcOtV!9!X+qWC~&-vIwopN%i5$9SDNm!Yx?5=3JN0M5rj ze}eM|Jnv1`M`OA|`OUYSeu~Kt7=I|xhROev<&$_Z284Vi%Xuxxzs-#Bf5!NA)hML6 ze=OktqvWZOej-xVe{HO9_>7HzRu%E)fOQBI!fM?^MlU+rO1Tx~(v{JhWb*m?2hB&m zD~IxpbrBNzXh)W_}LkB7Jr9F{yvg-+lq9d8iyI!7D26@QrbB$oCeMTKu*x@2#ib|sZBmrtI}zdkACV*2n7nsH z{{JtTp4k>Yptsuee>~No@H78Ps&q;jQbMn4|8v17$$v3T$X8DZ`P@(YhJP^x*Ht7`;rBIoj%MHaeVhMTa$&fU z7UN>H0ywKMB8_KI4DB z;ZK1IgsXEdh2OINcxMpnlU}*Cpo}d12f_aCNO|~wsV4N(j<7t+?!?mK*;$0G31s(x zrY!xlc?4NS#VvjfoWGQQ^4wIJ{Drdt|805v_h$C>Ehm?3CEV6d?ZQ`NVn< z(l7sc`VCfpDizQ_yqeWt+5U&vKk9^iAh4!{l$Q(qiWEdymPfP~ab7&U_7Ied^xHhu z!esKh>MZQLyz&(&2T(53oXSVDAT3g0S_+fjgsz|A`$xEaRB!W` zEd0j)5TAJM?}U9E(C$d7{q4e!a*_5a{7QeBe7=8#<|AK$eFji2(tj&|&8M}aWb*m` z52~?$CZy+J!;Y@z1Y%>3v@2}w4&Emhfz*8QI_8W#9Dc^U2Uy*_+ z9ihF4^ZntqhoD@f&gaib&!2HM6%z6)qM*b6R}Y1G)t-J6c*b=S_&=N%>QR7v*;XrT zo~-{sVf9(Pe5iN+BdlY_a3jU`BZj|dX<;wbWWOd1H>z>q`-#tS`E>p}Uq9_;nGE~K zoI%QO3gc|@)fc^V&WSt{rSjOas?Ou zD_H(?lczuQKS)0~u*XfUgU{h@d?uTqsH0>|2d_@6O!0gYh-c5z!*!KraRT^~bYTPLKa@r|w7Bmqx{2)>OSnVK5s+v$Nnq@>1;N=P2bC(({f z;=M|>#4kR*5E$=B4;H=0%fEp5Z_oSBk1NU{n1AlfBhnv4w}SK#&U=FRpIe#b+a)2& z+w2bx*01&!OYbg5JMj4_D_Hv+{)e={C(uRLLuskK?mZfV+jsb+Pf` z6|Db5XY&-InOsh>KNaO7J@{*ZA7%1CoXOJv*9;5#&z&andH*@TQ2sa`UKalLtbfMI z)*0}5x-PcQ-!*P9_MQ{pt4nn0zHI%{Y!@m2Bik@LmJ2niH=GCc&0ymNyxo;KlI;(e z7^Y~X|MD5uE^ztGi@|=}>~!Ywhw;_k{?{v&yYl|)fc{fA@Bd)sFQ0epE58tL=lP6( z&ne}_%cz!L2_MgX2b;L7=U3uVyw53-?05J((!1>o^Yx3R+z|eOFhAwihb;W}*`Hy3 zOLjgH|IqAKkUnNo-bKKB_b%ZFG2AE@>HjX);q{*Y`3aj@y77^p6832F9UoiEuX6Ts zl1%=FjV%57$j^R6`N}8O@;g0wd5BE@H%z|zz-#}M{ErrX%|`w&FMrO@-w3dOg-jOz zKJv34QNH@Ab@;d6`YA>xe>{_~`^Zlz@Mz(8+Q|R=&4DLn^4EO8;-ASs3;s9zQRR1v zHgcR<`hPlp5#N75!2a*C@be4nzbOSDE&S?W!AIo_bapt#`zf86{AHN`asP^oo8TXq z{~u94?w?5IhXZ`qX^X>T;qLHT33RIPaztD#){uRD{6w-fq&ca^;@*h1{h^GH5 z>R7%%K|ubS#KN!p$j{E9{2rM9;oL|JKiVB>yR{vZMV|IYi&{yy?kB61e~7a;%P z{zGQ+#|=p6Ba=Vmbb{K?Lt{94ctfcrC<$)DHkz>6~Z<5>9lh4NF1cdti~nJjf2}K%|G@@-`6P^Yo^|#|8XPdn-)!)|anSy%#L}Odi#1-M{*_W(9{%+u1U~v% zfLEd;{NH1IQ~$s0r9+Lm{gtlb|F}M(32T38KJv3o|cfQ(f{GTJ{bQn?O8#(prOLgKPeU6Q-ps4 zoIf}n_Mb!llWihD63RIp`e#x8io60(iS^I_D*OTMv3yqi2ri%2KQ~lkanCN4pHe~| zelz)4|5M8P%SSta8p`;tZ`Nez3kLMRu4eTgexdwq8~M0Tjo?z0qYy8+{|olJq`)7d zfOgn*cN-6X6vY2zi2t5DSo+KD?f*|HDG&d;YQoO?TJbx|kAnQ~oGQYP@-W?@{lD#W zjGtdsDyzG|!TQe`sQ-JyZz4Z0gpZswY#u{2>*c}rpNafjnE#IW+rJ6C zcOMb*F}zg%vKxo_`P-iKkMgHCV{?bP@%}FnzLe7P@Y~8iWG#Par;OqOaI@^o=`8O zH}-TmAk*&&m>=SZ74f2P@z)Rgp~J7T`EcyU{^%_Bo!{6mtzRpo@EiN5^_WYee%P#tbp10Q|K^ttaf0(2g=4*nPG(`#&3( zaIo+EZVmcm9${k{?0yOax(|ma{5HE#FQkhuhn|z^*YqvWZ-ZRFVR^md68xX@*fYN} zYveZW^VP(23ftR&-#t-ZwzfZ$-DVf+g>*`Trqc6Edb9CWerXehejOO3Z~XH7%dhMa zd5qf_Ph;aM?liVvHM_U7_~qj)QR#V%+X3@H1ef_I>V-69=~v}s_WK>yKkFX|{rLPh zU;S|XJxY2=OyXwaU%u;faeY4i-;APONEeY&;oXjgCo3mkfiavyGTMgSUJH*VvEAtCXU`cchm#b(zKNQ!4s7VTWX> zKN;s+?PTGB`jg{HVILefLyGgK9Dr*!fA1~q&w_PPSbqgJ55amC#$U;`uYb<<(?CD$ z-{Xz5)B?~Sh3#atlgDuI1@%U%u6${*p&yKoV*8k%Kjrw?8^3Cm;Pe~YNTd@w zKhcHrM!pet#rUK8dD0F1@Or1Pe0=^?CKj(3J?I_RfW4bFb(KeXlI|ER=sm4scfy%&!^5E=>3 zD$s6fijhAuNc!XFTe*DaKUND)zi!|UY5Jq{0?pE26w$9vr+!m??Uw-ggP&jJ^qC*2 z2dN*9i{XCaAWn&_CG6)aD$<{sewZ(ie)Hsj^-RBj`75Q`u=eYBEPBx%k-~mZ%qvJS zo*bYE)=N{%u@`LqeqLUWV)YiRPmSW`E_;50Wdx_sJPQnm3SW>G`s*z|zonGYNrW#E z?8nbPa_$N7=;sFgFn=MX`jssY>5TZlVEr@dg*0l-)$h1|QAEGJto`F~v3eV{f1TCk z>F+G7m-5SDd@9UN|4u)Q_b|X)u;GKYS3fL2qL_Z}3*PZf?Wy4GR~78!IhO(CE-fnT>LBB-R6o9sieE^x z-nci?&=2BQncU6zeby=#X9>AH_ETyGr=O?aYqtzTnstVpx|$@L=F z&jtEz0Q((h_H(3r^>fzxkL(Bi!DjJ02JDBlxN}K;u3r}Dw*~C?E3=<6+N+;h`@hjo z$*{H`^*ar(Y(2&1F9!7AU*z*gzxVnVSCIO7#_j71J-{3a`W;6D@t!m{@oxe13%fk& z{DRvL=NF;>Ys>tf=A)k$6`cLLfPcnuZ4_KLO!z;1Pwj;N!+1wJv16sVT)(JZf`2;1 zZyufiUh>ATQYSe5E~g6|t#UMqH0W3;KTy9YzhAu%s29>>rLS(4>GvYDpCiVrpB|)s zb)5fBKP-3AzB{&+-QpX+SU0{b#p2iP_Uh*jQon;(57_LVKNKi`b$B1Fe#PGy%lA(&<>)Np1;?L~ zdHvu=@A#Xup4@)8{=@->!1@c0yTNPaI;@Mr^N{THL%vV@Eh@$I3z#41TEP6vC9i&J z{owT53GH+2CqOw*!+bq_Z>C>KU_e@Y#FN9g{WP#2j-L-_>vz?kz52O=)X(GpNc|qi zxpf%N$Ml8zBgOYfXLmS~$@QcDuYMBipYzdAYY?3MG_W6@7ld-Le(HpLV`e|p3;7;X z^^3CjZ83?ZKOg;+hQaCQGKt?q@ZJUInV9KEM?RWWSTmZJZ}fbT$65ck`?5EF^&s_| z1nJDIevj+M?8-N^-{UebI3q<-jMP!F^N`WL(Q5$c6>ZovuC{4s{*5A9d4e$K|h*)I&r z5A`=;FVrvC{6X!yuxRyzvij9Z7QecWerl88^h5umH1aP${=)ep;CIZ@AI2|+t7+_r zjXeF)^L_U5`qgh<`?-SDubo5K4bNpoIelTC1-{4l!{3q8_xCzBT_DRJ+n9gWee~0s z24_E9--vz$e1)kdAKpJYWAE;GfU(`c+q-^{>r>)2}hq1GL-X|EOP4m?wnq zX*$FIpJH}Zdv{fozDE9kAChT^)t)A*gjHh z@^52M6lvxBI|p(5(e}qx=3mtRdF|(fefXjItRSWJKh(orB^pg)P;7r-y&=l)SMP%g zUojo-Ju%~Ht{*Kw`1t_(1@HVU^_k$}7wdnt{4G@#{LYgiUD9|&4NDUJ`aP=~^=GY% z;K%aqKDXcRUi-O%)XxF=m)4&#-f{fMOh2?6(xMH@{oJ8k8{c)XL2aC0rnL;t zem`P6@^=wlv`bTX@62KSul4Oa*O-0*_4}Kw{MG;P+K)LyLlmYvq%{4xp?!||6!rUp zytlI-^8HzLLaI!^hs#+0_0dlcQa_v*iRY%HoVn0{fO-e3-}sMz=ldH6*iU8i3-mv| z_H(of&VDnR`j=y<-vaX9PCxwp>AI_p@egc&pnqP>*0-y-z52O>)bBoy{}TWFBd+@o zvVD%>nzEocAKwbFA3uLX|K96goNx{YraPoG{b?{>g6&9@)8cFSjPvXFd-YSF4K9Ao^n3mh^;4ohc~+($KR-mh=+(~^q<+WHzijib9|T+e zirF4$J+?2@jO}^3e&M}^{W1OV^F36zS3j*yaQ4IT1r_EMp``AR{#;Xp-X%>c&=|i+ zt9)DOWu~8}d_(`7#Qd{**PB0-w!!K5Z~KR^e8cp)?84m@Tt5ZY2cZ38Soy26{UNaY z(1X;^3F!>WF|^-`8X|tMTt@rg??~}I(ycd2uH^cme?j}zOJ@1^t~Y)i?Siu()}P(C zA-{rPtUu#>v=8d#q2!0qHai>g^cUUTKmGCZRn#B6`niMD&y)Vzi}0Y_lHeCL4bmU} zKq$s9zD^0(6|Nu7KgakDd5zVded5;%^3d-grT%Xtv@;ZFPobRk@E-RI!uZ4Ak>Y!# zlQuLL^K;1jmo_YZ)xTLC2HV>m^Fk?y_tUWeZ5k7 zJILA}{Cpjqr9V7BQG;`KFkX@Jd5QdT7@v&7dK+3l9Ru|j%)ch?Poe#5yAm4yBkN!5 z!{#@;4|w%co|DHf)eqa3xb6qkR(fOo)TaLr;}z*{*L!Pt{5oNM1o{_#K9ByR_k2j* zL_a(q676@Slt>TiS^xBh^LB8(5b8}S>V@ye=|>9k{EPk%^DjR?M>o!w6!ILMGhp|Ozv1(iC+=LA>BrC4QGeq5GYkFP|5CqALF%W1 zVyOSX)j#$&;+M={qxMl+C{D(o^y@*?Sk+)ARnOI4AdLmWB$kAk<#~* z3%pW7Hvg}jlf`dAwuYs(h+mh9ey-L6*#QEu{icxmJ+|NQz1jRfj8~-P8@E^`o8NqO z0tkFs#M7ZNio&LLdD1WLV-%HINZ~i`XB5r8^Beay(%5%?<32k&`_6CN@5sr%^BXVJ z3u*Mc*tIhK*6YC0Jlgoe%UNIjCRAlELcNdqA0~ z`$%K)oD~|X@Hw(KSBes9+~O&4|Jr7=8tjtkcbN50@(b7HQT^sTEq>1^ z7NYR`BC{vI!b>xs&h9--e}3s@LX4a4CmavyRw>17$8WgMZb;iV(?`qn5 z{@piz>HPXD5&rhvRE~3aubu4K*WPCH?NKkJi`p)f?tjeJzwt|jb!Yth|Al@tv(h)p z?8n!~@k{?d)^F|8Etkmj{ccoQAwBCRMi29WS{oE1aJ=ISI zLn6I@v!Sv7LNv7Bl3@N-4AW2d(J!TU&g|C<^l<*_-<~W&^hP^@S^@3LFXujAjN31T zv@hS>%<@NwxBno#PtNrF3hK*xn7@9wZw0pRsQpl1eBXZDx_!p_U83KKNVe|JN59M* z>WA^D-|^RPChTj0^+43a%zpZJL(cf7KOCQFvQ=`l+YRZD?tfAr_0G1=zo>WfuZ1dMI=)4g(wf*WGl%*WfOT-#pN9HnLjMuI_qHrW z3PitxG@`}%+P?9N`J+9_AJP4DWaf1%Lu3+bb|UlmLC}da%R7^7{BHG z%eS7jMS66?JOmZ=K!Wx|`a`ExgADsY{ul)MmD|DUFQMN0LDb7R)9);lW0()neigBP z^^wpM}2XJGLszaRhp z?Aw}tU0wC+)wf>V)z2n_`Ahlsv+9r3ddfH1%16p)pZm5h`8Ipxkg3JwyUM~}EV_RB zv)cibkM$ed4W;CxK9~MMvQg~|@|WYgWxd7z1@bpkU0lBTXy?&hFx;s-n*2*z1@pC|f@cFUKK$jsvU%RM*r64t|f-%&%@} zs~xA@5$>Ft6N5*&AJx=6*PIEze|2+ny_^k@{g9x1-%hyh?($7Kc}2c1m^=J^ggeuC zJaqPK`OILzdrOQTv`Go=fAsSa>dt^IGA#H0|&7&YfRQJS;dW{%EoOxi9Z06q_uuogxy9t4 zFy4fae#po#;upxzeah`}2D}pYE2reQ689}9<+l>|FURD!68AADi~89HK_l#9)h31Ir1Yh9ur#B)ln)J|N1=B+BHi%>|!Je zpW4+?nuh!IDP0|ww*3B1h4^h9Q+R*D?+WiH$$2=z@%fYYDt!L^S%vqd5ezNqfvBl({ z-DE;=Up4aUJX;VyoNo!e)x%MW&NcFd{vr25Pa%K&H+wirzrg%MO#CXnqxmD{Kl8SH zyG`i7(0@eURVsCb@t^|kAAj*nU0<|a0_Qihp#7D+TrlyF%zxqg5y?7}4vxFgP0AdO zUegd>a-gxN_WGEM`xo+Q$A)9wH2u2>r<6na=}w$J=X;eu1^G{g{Bg0LZs2?ZzrMKq zb%==apO5w-<)Iw=vK@l;3zXkJx4`8KCERlG>0Y~e=Ur9)4CH6~@_OBW`lWt9!|2UB zzGLza&$QOxP=DKET?G5%E?+3&@;Tkz-#aOL{y_-)laB{}j_fD4KY*WP z2j#zx`DN+9)cWVcac)igb(7CbR|)ZR-)W)0yRQgk_ouUe$NhWy{a5#^PI68G${o%V zV7aBsa}1^-Li?N*%3Yw=Fd$wB%2K^m+>W(SJPYn8RgZ@7`MeO11{Qg{T zUUB^Jd<@DzW|2v+y?^*}7v%{31=^1&#+y9whu8vJ_YvHCa0mbLgr!0JpAY$;T`KK| zqx14RjUAK!%ikB5|0cB8-4{$alz%Jm{c=-&sb5R%+-*62vHUJtKE~|Nx7PPvc%hWv zxAOaYlO2?QefJ;x><6Q~5LY>Ytsj)1{to+m--zm;{Wq>}x>4kJ(|P&*rjF^K<&=76 z^xPN1{pZwQC)m$Y<1u`nu8p5Zub-*=gLC6E#Lv~zeoNQn@#DohCcl5y`r(J?8Ts3- zAAXn*5A-ua48ip#I7yVUqn1Jo|V?RPU1g|^^|Fx3$iZ#6F2nN zXXvuCv-r36?++FE;~(Vl3`S#jQzCR|3fDf@|pjO#~Qx-9bCv)%Hex_zV!iDkJs{RuYc`&rPN>l%FFM~@0k4i zVIP8xAMQV~$HNE0u99DR)w|>rut|7OZ)R?qsae7UVi7qj>*3Oc82zx zdMdR)>Ui4E4z?etf69OKnWH{Z`F-Gr@(*1o^;batWC!JEIgNf{@Id)d17$-wc^1I>z&nKr{ILDDw~XJ!1N-Z|g&mVW*M5VYVf?g9+`mgXbNK@OQ!c(|yDk`X zPg-!mzAAqb`sewQkBI$={yVRKXVLn}Z`+@8lxvRTQ_jig?{hwe`nBcez5TrPlnW<_ z{6C!k5d5SA@+Uhee>>U(w*47_d0+CW|Ccc?L_X6+d2Kfg2HodwdggZ3e+ctS9RImb z>8bh;Tk~Vjiu}&) zopbVgCwEN#VJxSxGmPgJ%T7}Ny@4OD>u0+7p6%NBdGp&db^rYj@H6%-DZk(5_YXOz zbWHxUc7xrtH3A&qe1uY*!8cTZ|=LDbNh>uCFJM+9pZ=k zW0Ef$d&qd+;W*nNg?xM8k!|1kK3x|-m`}T2azYoyKgWOA{@hmfzolhsydmv>w?|%n@3fA|?~OM2 zAs!fSE94}f_~-mG`P3`lvt1VqzQ5n~L*7ySC#?C|^JRW9F7k8#jpG-WpZjm9f7V~L zGmJl1PgyumbZ}n|!;xvff@{Xn`~F(-?^@$ObG7{T%~-oade~+V9aXk6u-X>t>#>0Dcu-n2T}f=u0NN#SF-D zLuUBFq5IZn$7jDkP5DRS{MW}s{&+zC*jYyZl$-94l|OooNtZ2u9P*bzPD}jUI3MlB zfNswZ3+g`!{ku0x`3=Y){^gI8KUqTm?zP3`PecBQEjaFp8@k6`efjo5`QL>6D{heT z`?9`d@-y=j%bzYGzx(p~;pZ=3UHExWe&VMgF8B|~pE&!+>EDkR$A7W}exi`S6nQ1h1m%M6rJ08d zz8^gm<#)zSg8zX0;l)2r{^%b{$PfL~&QSg|Ay9 zdItV~V)f{`k7&2d+}Y*K>(QLHUpF|6c4*G$4QCS3gew=@Rm%A-}EvDCA#Z z3yyorP50Qknu71Yeh2$gFY_1ifc&vv|HSf_D8KRblz+yG?zaT>Px)uc`TgmD{NdmH zwDQMMui5%fuS0&eJLzuL>*0d$zwZP5TzH+}|5eR2;QuF<-$A*y<#%5-@s(;nP;R$(7e$HmQ2j$P8{C+C!=X5~+@Na*d{2t^iL%g(~-ql9_3h-$^(~y4^ z__jm2>H6=C`mUJ#TP+j(zou^k|39((@e=a8ubKEt$sa?4=stbW#kU9Le-!$kDedQI zK>oyqKTiK_Czm1Koc>{ds=%lIqmaK2eA{us2*JH>z`{+l@=r18=J@A-t^HxK-xZg? z)c)~O`#Z}x4q?p~+536QZNYKx!sYXte^)P5`P(u6&-F7e$^NW(V1HovqVPTD&*XXM2ldbOll$X*3+|uEtf%~|A;0?x z>^b7K_a#w&dtXvVnL_zfn4gJS``@jdSA1#yRzGmzQ;wi#CiJuLj7|;6z5AR{|lUV+QZZfln=1WImA8P#L^?P=Rm-Bnhhl~MRa)Ib`IEArM9)*o{6hBc2>sQQd-)zDFR!8S{+0s^ z-+z6q@##l}FT{&-(|uyjtwW2+?}_|+xmbr`%m06+|2iX9ZXe$8o1V^|AJ6j3`J<$G z^oDnFR)h>*lb038{|W#~vLk!h>*T?9xc-XsjKp{AAe0BJpLFp;4eXHzdlUuVv)l>y zhxgX`mn8O&oCo{UF8EJAoc}(je|d5FsSnCuYX8fNod31)0a_X7t;yP#dQG*lee-ZT0 za!vj6dwTqiG0VG$0HwOgUKelmc~_O+!TRSjA^%ZVi~O(U_jh~o;_`F-JoW!@8}MMQ zU;1xTA)j)-Vewta6>2E-PrbYODkST3@c}Pvs`&TN|04eXc&>~;ypwPLI9GQ}{(e}G z6dz;!L!A7%!dAa)3D%3oI~)Jh^V!&E&wMP0+)N++bzeN~nJj)FKlk5#DC2MLyLtJO z9hBe2Iwi(S`JWta^hrMP!}`K*kA8u2LH{{<86ez#?>~1_vGorFWdB0+y}bPXH67D` znsx(vW^}3Tjr^S*Y#QJB3uRtcg=oVD*k`){iSQf{`mLhzaQjX z+cEiD;51c=r?4bNZ z(eGvZp7C&B3Hj1o&R$i(5BbcOmw^GCh`ZrfANR^ znf`g6hkbrN&+{Ok`mI7aqWqMX@*^3}==(F97sLOJqW|dU`SR;s-!b{;T6Tu&)E0K{vxe@0q- z;^%D23I9yj$>dw*n)1`%%=h+OsQ9t>FKj03Kcj*5^T`g%UjaMg_AInNS6T8i{<<*q zzsUF}&X+@e+JEMY{auc&W^8eZ>OUMY;ZXlO%l^Ccnmm5|WgXN1_GqU$mi_F#XCWRa zKg+M({`m^!I(?8y7xnHstT_yVUcU5$kjkI7@H1TIU(!1V?Ej4&lfRVxe6oa{`KGf; zS9F{SpL*tZ5dGg6`CR}$443J@^1SpHiXXfG_{8r8Ki>w{KjR!&;+8JgpT`g`&!@8Y zzkdO{N zR=Z*(a7CO`uepBZo<{%7mxPs$TY6u(Sy28tsDJCE{JQVtzrWz$TpT~P{D19Z@L+$( z;9<0X{A~*5=>q-pdkxfcn0N#J!;rhma<|y2;+UZP?Ek*4^;h@6`sZ7U%g^=O)c=p| z|N1!ZpYoUL|GJQ$?qxgm{ZCMSj-P)n_TTN(Ik*1YxwT{R+xkRw&Qsf>oMPOQI5`~l z%KdL)zMP4ESy~ULk&AdIju`IV-o3vO`IjaSHR02KJ}UT02i9*VOUTdl+tmLm^gB3? z$#|9k|7<@~{^jIjoTn#VNLu_};PXAY^Y^=Fn_}Z{3+I^^(tRV@A4y5LzQgoyzYPMU zBj>XRFMb~&u}ODFsk)mPAB^?x?kI(}4ElDQ3*~um{8P{8NiNOX`dhXy^k3?Z>7skZ z2X`ckr7ycbMgmD=Uys_+VET@h^~ZWej_#hN7{((L$4GjFULS9sw@14>O7HbE_hEUa zv|ymQk4=~K3hmHl?vt~-J4*Wu#`{Of`$Cm2?vImup;A``9?*Sj!h#l^|42_U_~ZD+ z4X?=jht!p;uwFQvFy%+ooW1Cln!n`yNBk`lF7?Uz587Mef&1flz5&aN%l%NW+b-fS z0ABdWPxad64}6IMZj(b5ZVf zrH|?Stah)?!SwNb&EHz-%dBVmcs^-#6Jx*Dm49{U?=fF<>D$HVhvz1&Z~9)I-dy7cKc3Ug{9yY2ih9!?580CZ&rN!mK8_bf!C&9>eYDB=;lcci zA$^1G^B?b8zx2Hcd6^$f-@6u{_*`xAnLc}7czx5CTH4+tn7&q|@4LSh=3o2W>zBUE zP|w-;oW*?)z%A3qeZ_YBm3Ak(+~jLV(?|VW`O7o1=f@JC?EfENr7w2R`lT-?SFL%E z`N#DKwtdOX@4!w{KHJ`|D}B_LgKO-F&ySS+Tk2ZvlV=23fm;CeglN zxNM&$n~i;8O?@TWP23O4e#(6GlgMZNbKXuS-|TS(#$&q`V9-7C*e$Z_2bq7gFTd|< zMiOaX!hbBDzEb@?o}*!(m%({;@~Q8ApeOQ~f7ft)ZB@tcNqsTh|L|_=EaPkEC9U&E z2TA+HdqCUAj-zcp%26)uj^H_kXGpswc>lii%YyUDM@u^{_TwUj3g87&dz3TjX;srx9b~g8^R3}F%Bkkv)-u1jkou5xVZ;0QY ziaaZONQLB6*V!v6zm+n5%su~4miV*pKPT@CJvGAI^Eq9ni*Dm*GtMuTzWb&BrkDGa z$vAZdTB@FKP|tNmLmWBBPBnD9P}p= zQ>1+^#Pc!zgXFmo+uP9rl3zm4h(6paq>a3b+zatyy6B#gcC^J37tcfd|D_yO z8L=G??&L0~bkhEJ4D-*6QNJH3^H<5`V%6)6-SQta`AEA>R}PrWUW*Z4721*Z{^O-= zSNDlzebQcSiheo!yDq}H9(;yV0e%GY?c`U2PbY>SWpH1Z_VzeUU)-8s_rxx`ZWpH& z^W{;TGt6|+ZAHb#^l`q;-NERC@$$R0(XCAS82=FTf9!V4=4k(r?;@aWIUjtksaKh9 z#Rob8-HmkNnf~ljF1U>j%7ti|1b*!dnbCH~((U|FRvzd}96`jq#Is zcN0GAy`3-)mORbq!$tU=p^x+^!)H41*r~z~^7njq=7*X-j*p&!^!?{#NuQig83I1t zM~bH}gak5uA46W^hw(CBId01Il{%mD-4Q4k&{G%z-GTl#^VMSna80Vkw&H&GUcY=_ z(-%Sh{R-*ZQtAiyjr{rpCs{mwTz|my{hZ~@%D;A;ch7V)eRjEYAs5dv;raun&qw)V z`j}sM&8ff-x<`I_*wLCkw$J7xednJm`S)f%ed!LSZxY5!InKa%A4EIS?k`nf9U=Kl zx4j;NxSclG;ahY39(>khQR3X1ucLp?EB0nW;4Ht4OBN$Mdwd0KXCnItcNUIUa6T#ej>#A1Q&;3G`xBIRK5#(3)y(+;J}*!1^s68~ z7a)C0&y@1_K|X!{V;xIhZd?iNeLH>Z_m$zn1IQ;EpBJ+qjQ%6j-39fP`&i_5pvGm;nT*W&X|BSaB z^RjmSor`%{JO56#_)G`K@u?4&5x`~o$bR*@2jh~yrL>>4FDEV#`}tuWpYD?#OW%KX zGx^5;Hsg8RE95i(PT#MPPrdI{QOIZd{s}w9@Lfg#H*DRHJSTptrq9RvJEpHz>}Pa! zK7G!gJC;7$b$k8Snz2S+JDVQKJb{)|;WmqplzH|q(*L7GQ5Vg*|<#(3IXTBy7jyrAb<&W`x z>6eYy{7YH$?;lC|i$0zoUrMg%SpMbgy|sSeN!UZ?AMyDD>OUX)U^+^T7jj*JGsdLP zWkTTceX=j=vj0(9zh|uU-75Huf1S_2_+L7fKAvOh>}%p@JpWtudnLvJ81Km6UZ?n6 z>RRW=Y5zTXfByV9AN_dti|A^kq=<`@lcz z_r0w2u>3OKPP<)lgXW*TK1aV_>rKtCPl!HUJpVYq&-AfB!1;Q{bN3KqM~Fk>^JA1h z^4Z=x4)%!kA8~gW><;;?7a5O>A9TCK_RN02!pHm{_YXZQ`4^Y{H&yI^KGU)Ey^Ve; z7t!mg9w6%ROmYL`o{ck?lx&Gd1-8~JvAMG$Tk+;ji<{VQre+cAE9IqYZmMS{;i z=g&uTF-}Na(&hX*^X~$jmb3BTuXS8h##N~Yx^>_7G5b4Fzn_BqTlTpLkmK_yq>ud+W?CnLOShsHgRXSvt9VN+u0T1)8+dY4QYEo=f@J({=>RYWPT;E|1j~q z$v>uxZmINf{@vbxXz$Bq`ogULt@$H+-7nL(;%C4W=5_iZeeO_Wq3AA2_SsR=ceHzy z@xO8x<8CYSE9oxz{%yN{^hqwJi|)TsZ`=KK&X1AL{A2x3`@r-~L%)D_k@~L(PRU1g zs|{e=I5Ngs-VLznvkiHmlOf7GR7RCGHmt$!{g@7mS}*<|viA_=N7vpFOSXhkuZM-G3LqG{1h*$38r!n=bd|{Z#39 z&*V)_%}SBdFQoG$l5r7nK2hVov&Ci!2jU&64zi(sFIH%tD%D)kHO zum88=_*VO?S3LXQajpmMoDT}ycNc*lUv9!7uGya8chZS#jz@BSmGau(F$yEz-7){~ z>~G?&1mAWdU{t~V>eN9GX!<>*|9Yf9BKVJgA-Rn4RsY4}>F4-=9O2pN0s9AfVfsJa zx6lr`c;R)7!+FDv#7zIL6O4b>-?{Xo|4P2ch%J}?8UKo%zWKeTpZ!msA3j~jU;mx& zzxaPIo_>yR#Sst3LHPY&M!yW>Cghjl0qvka)Z`oGvim#41;^pp-f|JnU#xK?>WlHy zWjMUQ_u5aNko5nceSDaX551r7-}ovpiN4=W<2)IVX zQPd0e`SGmp+>eca%3Z3y>&EdFwAbwVE;`-d$Yp{pH*DSSJMM*vn*YQ<$6pc)WNtc` z{*@g|KgU0bPezyPk0bw?Z*O6~g8rHQJ{adDpZT?`#di?_?JoT@pBX>hO8lT6dSANm zu59^7{eLR#U*9Id|C&JlztXYv4@LXaL;f&cdtEQnzc1E>+w*E{$3`zV`N{O#%=-`L_NSyPacxq!dcFB%hfbnm+`94@xLLHD2Q7015$I{Cec5X$IJUdyjU(Oz_@-_`CvWBbmFn&<3|kc-+MgQE13R!k^azYW&}Bx{x^%K|HqC;Q*P>o zf zM+Ni$m&pJ0N`rrn&&1Nj^S{*i1?zkFZzeye?^5`;&xK+>J%su+x(fLUxi3O}!tg7= zpN4S|?nerPPlxHI|JTQT{&q0^Tz_BH*Wf>w{4^GU0GN>;B7z?&nGRmwMLv;3Zw;+xCI= z!LfIWr~hu?+JzhpK8JU#4`%xB=eQ#H9N)gsHR*A{cM*_>d?tS&`J9i1U1Yv4v&OYX zQXsgLgYIKPPwiQ({_~{&t5-Z@(yjem9T{VOHT26q&i&(h)Xb*69i>ghC}@4gtCAT9 zM%f@!fAM)I2;}e7+fhmbxc(M$FEmdKf3|+zrneIjxI)h#QGVW$x;r)$% z;r;%*72c=k7T&KKT$tXcCluZlas!`uZaZ~g7*xothf6+`6}|jsGg}oqWBN(I37+h(j0$5{n8Z=?0T2wzEnNU z{=K`(q?(!yR0wC z|LEvl-R%6~;YL4fzrHNxEB=07Ki=w&>F4DUCLH!d7|(Cf-XPz!jvVI_)aT?ASHHIS ztPUD5f8<-^cW1#r`C6CgHQ(}|)4zHAga0;u-u!gMg+cuAeA5FOWqfaSUO&-~I;J1H zyifoeS1d<^(0=vrGIoRV4+q|S@Pe3 zyTo!tdy)1`xh9`@i!>DSIi76mh4&tQu$TUl%6CU-k4C#yF+#IIQ?uWXN-|nAPfbYyT@iCk*_;$Hx`uQ4N z`e*zn^!mV@uaET)++Vtb&aKJC{$=W)>!%;u3Cc4TOK&Nuu4HfZOfu^rc$9*gl+r?O* zU&Zyq_Hzmm9RT_K)yB>+e$J<|T}{1ky;>CQbEan**HfUq9frJid%F^R&OfmI+|G2e zK1Dcj@UJBw?MXSVI(yYY;3(YTq3gE}>SsC1*T*tGn|@wAK|e0q|HJ`ZTR)}7=iB!* zxVQDQ1Lk4fTa7-cpUp5Yz;-WjpBv9Yx>!zf^PJfK6+!ymMZ64$=|0A?d)4qi4KCk5 zbj@R%1od+r^y3SD(lvSfc%OF+KR2R0#BVOdPXpFfQBLajtNoxiq?fp|@j$&Di0~N> z^|QPJ;Q%Kd(i!4YGp(iau#$DWrehyOU&D=#w=QV+{v#~tju^Wc96q?h_hfPY=3(GU4|fZvL7aPsd2 z|D0V5{oe(CndSbndAs+Djc;5p>+keR*Biam$?wgCLdulO-Z!1r@*CLq%>Ad4u`>T5 zwB=5P;}P2kG=1@(l(`Y5`u^rV8@T+t*V<=&o;(j;?V{k|_|o@%3-3EiLtMk>HF)>J z`zmYv=xll3k;~TKUs_Liw3z;GZWP_!FBn^B@?HC>LH!-z7smF9jF$z^7f%e5=OTaN zdnZe`j4|Ui;Ric8O5a)O|BxLF1nX{B82%9J{)@K4=c^YL-iI5EJl@CR3JoA|;jQT; z^F!ANC{4qD=Fmg3CsC->6~+U)FCFpp%fa#IlTbb<-og+Jjx+x@IP3{FU7m~S!EW#^ z*58gb-_R5FBl!&H8QOpJ%X%T81!xDbUhfV5yW9ta?_IK7Tn2l{?~u|CT+Z+zkBe~l z-4?c2EH%Sd-l5*;j{acH)y4F8qNTs^*Bht)_`OqGf8=jy{oS$Gb;lIb-xk+X=LUbV zZ#GW-@q4Sb{>b0Z`up`K#}?J!FaJ=ezr?p2r~cfRP5#>YBY#8d@8gCs{fgo5kCzqd zFZ12TslR9m{gJ<+^|xw^-r4hu*neXEQFU#h{=(mHocfEG&>#65T7QcM9jx_z?rQ- z@;9{pcK)XN!(#gD$qqK{U)POOf9VqXBY#8d@9bOMkBaFpVwK-Sw~bSO{NA&TKk_%U z{-%F;f%*O>)?c&zGJIKK`OS3SIQ18OrFi?9{0*(Yp%a#FSqy&%om;5CaM{MGzjz7# zk-wq!xA6Io3fBJ-e-B+!sJ~dxjZ=T=68a;5gX{0Pm$Um{?f%EaYYO$3=(Ta`kKg+a zL0pbsk-wq!_x!wux?<(`jHQM8%WSf7>M#0g3Ht~BhSuNq6AxQlOn;YI`U`Kmaq2H# zLVx6MX#I_j-SciS{VlV`uVR~Rocc?b&>#65T7S>>+w7uZ`g_{aUt;r(Q-A#4d&stb zul?`zfB!P~_x~!UzdCFDDihi`^~dkc+xjE_r^cT>|8~=!+kRYZ{_TrBkfDbgy{(k_ zx6Oq`IZteod991{^HkexTX?@l9_e~>UgcYw`}n!N9i;>1KX6hub{_5n;*G=MFT)t12>kC#P!0)jxhV%K1XCLfqBR_{stkWT1 zrq#1onYGSBR^n%`m6m_5S1q&7l_EUHuP6dC!{lmC7 zPm}c-OI>UK*_JYY?!J>>ALeXha7ew;<@#^x&t8Ab=qB_ra&g@j<>LNp@>x>0#<&mp zv>V@G9W(h{UpN@)CZBfibIU*17dBe*xDfPi%o8<~+Bos_?^u+w|vwi-YT1c)s33 z*`E>*oZsMW+cEvw=PNMYO3Z_M*oR2{aor2&uc@a#NO$zp!g_QW)`!!-iwG{>&iLaz zdj}wo+7vaQ#%cQjr zzh}95pL`Ggmm&Np!kGsCRp7_pH}6HkcREeV@58T_t@bsun`>)Zo2zSTUD?gP_Ym1W zKc}gtuC`__?`vn*Hs+tssmVT^SKXZRFsCLauQwM2GN-1cuDQN(ZcA&m?B1U}n}G>m zIWuLae0^iS&VSyn-iC(dlCtDe<#q6x6{7JueH@$uDPjy+%P zW74W$bpM|BZoYg+v5$}SCtby-)(IZ+v9q;LhS|&SKGS|N{Nj(w!TWDe{*O3KWcxBu z{&zHQa9tH$mVXBgn%w@XcT9MU*WM>V{ceVJj&}LC_lvOn+w0g}L~tAGdxld1{;Q~G z$Pa_hbG*r~1pmEljojpW;C~8!8tJM6-*%{1x_!^xM8EI4T^#!_E`)v^>A$4E%InwN zxnugZ_gOIh`-U62{WYcZTL%AhAKdJireggc{XRza!unior|TY*5ZHg-S8RfuzrkyT ztk2Xd{jZ)`x&{hKbnfLSRsGC7cf0j+lqL=~_o?o^9Hp1=e)y}Nj#32v!(DngN;f0C zl)S4njnBUm|3dv-6JA1oE8PwMVToJmU4$R~tf%a2>gm|)MR~q#WVOUCGy@soe%jMf zipl!ew0tkd`?hD6{w@6{y;7@sX35;;^+P>9yZzMVg5Ry22}ftW@O-gUy|hn*`(Lpx zerE(km-}D2?>M6Y%evV3cyc=P;bdF~58BAMr3 zD*2`Ta(Vw*dEZ;o$(cM_`WXp1=d4wp-`dI9UY={Xr;E3=_}@+LH9T2zn+@l63D1-8 z@8xK{Z20Xv8vpa< zJzf9Hb<;nW{7Vk%ToDc#m!p8C9<7k*n1H5f|;U^e2o}KUoxBJBH2Amo7ev8-3g=7Ee+>MqVBgp;T>$=(sL#n?2!1Iij0dz| zZo_ZS&FUZhhc@W{Ezy7cxGuT#Gn4&Hil}$G#5eU{s{i#m`irbrXuo()9_?fZ^2OMW z9%}N7{nR?Na~<@jFpT7UyRXSd@&(q}i~A7CSNQ5R0r`?noA;RSE74x&zF;@&+i||b z`HcLo2lclC`xiXOsl{Y%m#zQ(|1|mPV*1}j#t)*k`SzW+YjORv{js6+pTs%m>(YN& z<&V?9`}O+ipXaXI`ggG3c3t|9B6C;{{W)WgRQ)H=zP<(cKT`A`e=L7~WOBET>Hlz! zA7LFnvCt3gJjdEMO?%=4&%}R(?Lzn`KDPuuSzb6Ea}50Rd_oryui!Wr!lB;UEk1F% z82t1Bhh{^lL^w%{Uj@FsAC`K>;~zK)seknH&_Q|VuI;k+-$DCuIra}e*&_O1lh?mD zpkw;K7yW6DKbhF%6glA2gPzOq;0ddJO#PpWem4D6|1U2xcqQLOI5F5I?`&hQsOL27 zw!hHuneGhssWKcN`bf1EhQAp6JFIxy!G9e5^kNhK67ZRB+l_+Z!F|8aQC9`$Z+;E@ zN0-3^`W1=YjsAOsP4{)!(fAuE|9CzS`wQbw89wzr3E|PcQr|omJN}ySPknQr3fIHB z2tR~+k9_KTJnXS=jkiTCK5@O({)PJX5PpR9Il`#|pW`XaH=`BDnT`Gd`K8K%i*T6k zzrXsywZZle+m||j;r^_Pvl9IXZ=i{Z*-Lk&^zS#5Fg=9Zh5G%{lwYu&h3wa%J;VH1 zpLvh=b6=DC;d4A^)9}a{6%ZC*DKOFoN>IJsvr+|Mr+P5C+@u}ed=D@=6j|AVvxeyHJDDb0j=?ok( zq+0a9GzI;0{_m4B#r}Mn*MBnHG5!CIb_RN2JWvHfTV@-N# zXI=1jM?Fh^1^6>gD)i5MFP~q?XTHavH-_UOoEY>>KJ)#-y6~~{qwx0_`gj2h{mzoY1BW@gJ8O-|839@C4Q)X z`OP9S?Cw64-iev!w))A@9O1!Wat9aPyRn-Y)YuSuX&z$PtqsUFxK2h z-xc|Uz5xJY|B>_w?V{sAa;2XzWbS_W-*Zs$;L(65?*FCQr-(KG@%6c4p91H*Mu(bw z(zcLZbXh+{Q9pc-_7QPyd^>X9u)#0S!6ZI%^P#X?%>Q%H4`aDu`PdWl#^k$*fa4tT zv6HhLsK@z~;}EmRH;TWC;b7dT0(v!;2#5YF!N1b-KOFpPEdL|Hf6;0`$gpwID+;a$_wmc32W$H*h4RP#;haV( z$E)-Cm#*ws{;?hATkQj$GeSPgANz~xPmF$;uk0_TmzsVK^NIaMhT|d~x&Gp#ENA9H z?)(CjKju@ZeqpEWjT{c-uR{12p`5YY90b07Uc87^_!h6f=uf8YCi-0us>rQhh8|J5dWr|qclL~1A^BS zxli6Abx-&1S=zy>@0JY=`gWY%EwhFAm-(#rZ@XoQ^AM@8 zyE#g&ct0t!DW&B7WT2nGP*a(;X`I?^CzbG%QN_1^;2 zfB&oield^9=$dh^EZbwmPbKUI`NYROv~S60`Fj!VVe(x>uqp;UBcos zf0J97@aaE<7rOHtI;$S6KzqdppX1LrA$;;(gfkQ8%&@(p(~5dcMEH!Cc$g2qjfdBv z2l9!BEw(Al7cU#S<1}FWF@5l%Sq|~A6~ZT<`M%ilUx#oi(SGn_25$?%FXd3Lbd%>^ za85D%tLJxRFPz(@^Yhvyr~dC0`XvnY|pPI^4IP)yq+O68#Tv2N|CcI-C8I(GtGUY)oLME|>8vq2cI%Bo@nf zlF-KpFLk9n7Yey1zC=HHF0?)FJ^8KlFy40u%lZMKzR1AT0C`{NFL)lQkhBTyiRWH_ zd0%KG?xU5x93^is(l=1jCv+EmJFY}i!%WpgE zvxj*E{}6*)##>?W`Tk87{$0GV4CR{T1<7?5So|>j$1Oh8?L26O@4^4o7QYJo6;?PA z@Q2~Ms+4CM_$OQZDEKd1;n#uxoW+lUpXpa<2Nr;zw&d}_|I7+!G5B;D?qy37+3$aI ze5M`aGYftv?cYHDrpK9-h7b;2JAa2FUVi5e-knE=8u`=RjGf{8J7YYJ?aFezaGb?w zcm8|o6XT88R^fbM@ntw8dwokiz(38>1+a%)hv35hro*6T_^$x}0N7Rf4};%6(D?UP znsgCYe?WRYv~xZ9pL&4tPkt5nt44$0*Mt)Re}=`c1OG9$A0Vd>ewpQtzvuJ4i`nNx zq@s%cQEYG@Qw}v;)g|+#Oxl~l_G3uygIBqAUqS!VMFOD{#dGkyJg&P*$hVP{*j~;| zl7VsUC?elu z5}J(qg3sCB<$YZ05B~}nF<~aO{Tygt$JoKf3kMOHxR*~rW!u}a8D)-ASBx*k`pdmg zHRg4^0cDQT3Cu{mzg*@cw7u>eD-V=PT;nZ%;>t;(&hq`{$dLwLY=14;zDw38*Uu*o zG>Bui(!Ht4yvOzpgYSZVKKW9eXRqn#-;qyAKSO_>e9mvYhVno@@wWi;zT{KA7o&Yl zKJCTn7N6yOT&z%j7jjOu_);9Q*O6|a{|fL|Ru=NvovXpP8s!PY|2OD|kiQT3caAL# zhxXzYjPKL`NcjI7#<9rvz%S)c-*hj%YrAKPmH#_1|L5$AdbrMURAM?DF5y{&7m)Rbu~`;g{+k^Evy+PNg7Si1VTG zS(`XYC!jq@|GoN{U-24wE)$_8~KS6Gy2W6`Xgo%xwzwMSCuukoSd3UBm_5 zdBCroLrZf?yohV3)LZLP1F+hSO<0Vl^fKt5HOyPsEUd6-ulcrHO6I4&1n zvq)FpI476R?Dm!Y+h#{vn4smVP=_cg9dj1;J{ZqCq~JqaVhU zT{n_i-Rv{9dS>oX_BBaNmfKLPK4hEFoECRpb?g}PJNsEp)q}a6QhP!!ZMy5|sHWz* zwapW&XVx~fxX0|B^F6a|_QWFjE9}C^jVem-+%drMfFHVJE@JW~81!*}t5z5ZC> zpS{-CZmrEud19A>cFO-huv4~OS|W-Jwo|u~ga_NHE)@ZNJZjmUgDtyLZrPoKEW2}r zWoHIzeA-SeaaG|F-P?v;wW;EV{m=1OAF1a9q_@c9CyH|d*bbzt_|YqaaQ8(&&F+8J zvcKmR_CJ?kT+aia$+?i@eOPzvWn+;!J&sf0`wbEB&p?0G|Hy|JHro;5-igZfHNdSP!=h{4+3)>2@>z6X4JEOgZIuAd=u; zVa~ZU7GL0>y&mAa5#~Q=XS*SM&Sy~mrV+3wm~V3t z&Y@g?VeKcZ;<`Za!|=Z=>v!;3{8Ct#&v-rf->fg#~HC_6_`L z@c*U7kAgo7^Wgk0S{?XLLl5a?#;(M`{{r%O&l`E#fe#1irToOre=xog#rI_6@c$|1 zllZ;f<=}H41=E#e_=uklizVF;A6&e+n0BaL0_IJao=D_-c{oM!Gt_h z;y%KN#I3~n|Fk?);=aPnav8rA;{L+){qj9`A&z$@|AExA8 zCGJD?pO})oP|A&e$nUri_bbN4uhL?y-!mw1oRNL_%ebdk zNINnxzPUgQf$n$YwZks_W!!1jJ@-ZW61NgB;*xIP%&Yqq!)Lbz=8brG?f6XGEBPfv ze5UW0{1GBP+vS-O@#!uXeG3tv?gMf!M0`5(TZ#CLieDw-vt52G5uYguTZ#Bg$ulM5 zGjyNeONjW4%5Np&Gbyqv5uXWprbK*t5|$G2nU-ft#Aim+CPaLOBrGN3GxA4~U5NPf z<+l>?nUUX0#AjIERU$qk@>_}c42xeS;xi`Cl!(uE`JE-~n@x&eCE_zCvMLdup8QrK zK11SH>3<8KuEedxi@2ow(qH!eM=^Z9HBaVR|0r`P*f(0rer7Hf`yfPo#$K24ej(yB zd69fyNr?E2-za{Ch|lPoWsVZ@>AxYrg^17eO=53^h|lOP;$MjPbS{zKLd0kCR*6rD z`1Ed<`3524GntU*Ld2*0TA8Cne1`8VbCh!Ul(;=1;xl}gJQpH9LlUA?!zq`y)B0j_SNPI%Xrz>G85uYh}rbK)u?v?n2Xg^ao z$a5j$Ga-4QM0}=xC(nh5&#MEjW(ze=>9G5M`T z`x%nBm3Z+N-P`Xuw&?i&^fS#H-d=0BpP_f8ya^GX-uqG>g^170+hQM-P`~^C5c?rS zeEQ-yOQ_$Ya<4>uCdIE3@tKj|O2lVa;#ML)!|%$y5b+t4-%2@r%I~C54xbX2D@1&T z-jnnQ5ub61ONsdO0OBp;FTC`5cFC2S?)GxV60Mz|} zLhOMM@!2kMDG{H(#HU1jhUK>s@tKg{O2lVc;#ML))ACG-`1I}+JPQ$@G5M`Te5U2M z67lJXEK0_}cOo(44;xj6;DiNPy`K?5JI^tL9e+!=> ziCc*maY=X5$6N1E44X$ER))vHM4<>jh6j#HVw!#3e+0CghnC@#!rSeF_nu zp7>QFK3(~(M11<_}c3`y8Z#Aig_RU$rP@>_}c zjL5r6#AmxaQzAYS@>_}cOp9M7;?85X}vHa=e>fZ*Epbayk{lk@dc z*;h|wQ{qM3(w%nU&KDNL@3~i*H{yG&9lx2^1usIxuPe4(iTF*)GbQ3T`ljehi1>|) zUnSz#liy0jZ(RH;5x*(ubI&yL5#zrOw!B7W22SBdxy{Z+yfB7P$hwi59hk!MQ8Z@c_f zB7W2ITZ#DfBrYZ5H~cqAj}Y;jl(?0M->5uOB7S2Mw-WK&F3*&R-;_L4B7PkSONsc6 z$!{g%HzDsT5x*(@>_}cZI`f> zHWvKGMK&c~#4X)kPuK5X48Jd2X5R1zt=;~H9uj>C5x?G_L|;P0Z{|VKmlDSh9u|BG z5x>6p%@W5C0{6-{fCE~YT-c=%g6Y^V$ z_-&VWm5ASzJX0cmGxA%B_;n?0CE_8QF zeq-`miTF)O*h<82LY^rRzZv z8yCMy#BW4oRU&>}`K?6!X5_ch#)4l*WXTc$Ox)7l=1}j{V)*?C_BXi>{Kg&=eF+i2 z@juINA>ub8&yubJewB#dr2JMQe%&WTze2=sM1KnrzwHvX67kzE&yAmAe%&V}JR#!O*SLj<-z1a@tcz0 zN*fD)(~k;1gm^8%54y+IjX6cv??nzX>oK0f`p=siWp3=N{Qhlsky(i$%M7v?U0s)@ z7ti(MdDhXdjNLX*9f#*xlh5+Q?^t+;8vh)hOYLRk;XbQ!1oQ^JV?n+PejNL>-Mh^C zjSBE%Shq(1VeoIT!l?xR-`GFK^&TGhuMH*--7i#(JxGR?ckSk%J6{hp#7fOwV3@rVW{z#Jk8{2L>4^DlGfb#@uE(JG5l5A z$AN2AC~zY`e=GAJ!K-YW;GN^R+^_}q6%t?YI$PrloNwV-{%1;fdVV;sezL(Sz9fGi zmiyrMxSrGS1K|zak#8FJ^uk-`6bV1Lo+P31%X!+o9`DCr#!X0nAQ<08qs@JMJDDFB zx(4^{+sj<8&=abUfIQ2s^i3XC_zi`G zVRE`!E_5pt?OU=-VR>h~k7Aua_rbCJt-?Cz_?$xf|34{T?KM4|4OzazGkZ82Q+e`V z=uuFfB7g6(LCaI3S}<+l@qb#L)>c0JXL~s7Q$E_C?%@Q>NBeUx4#?m12(*`hyJw&Wo<|V^e+c$HQ~q-BYZpy22|@eL1^;o_*Yq_e{0i_tVK~r# z75HJ;Z=NqS5qxBuvurQ(YYE&lKOBEsuza{@nDU|LQ%3jhlKZ|}6z5d38l=nekzPmn zxV*bbU$V;RmG#HTz)^g-NnaTr>}2_uCP4P`fm8Y~N5Qe%>lNUaWBoUAHxT@r(O&mA zH}ZtR522k+eiisz5ihfi|0wvm^PE@?z<(X><6JoafAbTd2l!8d|Doky&r8$m1>gAR zIZ`R`9qdnF_$$GmZiSNu|2N>fILAHLzGZ&~?fC2=)Dmw9`x9s<%CJFUFwPMmpZlu! zU_S@pl*507b_IMF{0Fd4iTxbi|D#uD?yoop`2v0%b}^0bT>4?-zX9=*zXJSCml(Z~ z9|GQ+&M)Lo1K;kS#KCvE49)M;)vc(xJ)dUFs_rP&J)yDcSz-5>Vf$paeO8WeXD)25 zZJ8w7LS?fq{pc>yX4#KBxpslsW~=*d$vn7eW=qzmG8<#fO*Of@R@tp88*>p;3ASGQIN@AscFC3rg}R^3=|uX|>LjKi~E#S3tl!tp98HZE&|3br4sC-qRk zoH=Kbun(6_y!pMsCQ0T=Hbm8KR*_A!YI8ek=hRG+TiL|i)LPx3+p4L(`o{X!`fA-! z9Gh4_-)K(rueznBzNPiBw%WE@-QU|*)9Rk&7TcGto2>KENYw5z$1>M~ueY?Gs94B-UvOUaf`a?jDJRy}#-`Rb&tnQ(Rc8e^1y2L}vt!k5 zEwz)U&~Ns(U_ZB{H5SgnSMT;JxEoS%cVJUBOGoKl%>5sjgZ=a=q70JHk;$6C|e?sWctO=QLXcyt#dCVFYV*RrX>R0-QxpWT3eoyk* z4x4K6DM#HFh4EG(;*mI?h~dCIIeo2g*xtGi=Sr2jhb$6Eel;6HE4xd8mLt$2O#8!Y)3gFnRb-wuAv(&rNJyIXR` z!T)fZLOm=4|7?q&0KXjVGp2Vr{UcxeYE%Ct!QX=I1@g-o(f5BV=3oL!KvxNqcS{l6STI&`;vW?}NVz`y9z%4E}Mj zC*-$--)x1m1pJ?&|3m+A@I%(P_cHKv-+M!QDgi#fE5>k^gI{OqAqoCsv~%fy1^8`N zdoTt5#Ql+vI{|OtFW~;ltqnf|{uhwnLHnBf(EBmJb~OH7;59TH742D`GY|#;!3mHP{$t?RR2sg!x9Mjr27fW+BwvOAv)4@Shke$>y9|8JkHkMU z;U&OFvYim_SAp^MD~IhAEPo$kd~S7%l)umNzl)cftRVdIg`u#V1()E8xF@{S)|?;p^;Gf&Ij^ zi(&Ai;B!2r68!fOKK*;(&td)}z2m{pjWb|8qze4pI0N`b+p<&<<&Wb7)8PMYlmpIJ zM8W?(aKv$jI`CJcJ|RB_{(Y8y7J%Oy<%Z$=;B#Dp-)~(E{tEVcI~n}8gU@jrALBDi zz`qE%rrwg^f6RU4$d|{#e;a&$pI`;}Bhc?u)0VW#=XBant9*9uit+}22;oo1I32?&2Y;5u zcfoh9efkyP-vPWboG|zUEqhT3{&L`k{yp#?w!*0bKY?)q`Zro~oHE)Aq-z@dKXqVX zdZXZf0{hQ!>cBtMEA$@&e*x_a!e0RXtya7~_`P8-82)1LPq*5E?chI;@=yOuz^^1O z5pNv)h?OtPz<1BNYKGc_U+QH|0cfWGZs$lzkBJ9I1IzK3xLi-TCDv}L@?O3|3|HCqmu2&d(jN{xZ z!Xcw>_Ru2B3wl)5v?;zj7Uk-lyZNskspYwq3Cx#ye|8LMc!>?pG zDF4n!22URNVdOXcF95%v#rMJQ4!h%_U$_|jFHqhXP8|G~fLHRDfghngvih|(sGnKh zmc#$@66N`h?k4@jSrY!2SvXz+{=ZNj*pEzsKaJtvRoISQL43mwu7dx44n(}*e+d5m z$amVK)!?6k`jGsOz;|Hp$p0ApnJl*m{}b@XGk;)a%4V-uC@1`9z^}#p zCd=U(@E=0F?3XzxKVP{feBzDv=&ziAL^%w>|Az>l<3_BX54Z3ThW}$NKJC#O;Dq?0 zJz9=@C!h9cbzdVV`4NO~&x6w*oriuu`(Lz2z0nTx@qJs`qfKacU}t@V@1tEz94-dG z40@%TI(Yu(#n!JqH_v$VmPN8Z^n8;E@+*Y*kAuCzt+Pn(gX_EO^P^9<{P(5-Ljdo~ zf`Z`tw~sHpA84%~%ce81-bv4&*YkFHeZvI`V07hz3f$}Z=HR94n}e6GXAWMvo;i5w zdgkC2wchuw`+G&S;QFtrl72rRe_Ymk1+OLYeo!Bt$RE7t`sc`1vffyT>z|#ttko5I zwO=qa$2rbQzpjrCUb;RycyT>+{AyWmEyVTDDG6Jtm#kk4UP(*-hb?{eJRs=XaV`~k zg6Hi`$NCETYO?OTVt${`(^h&$u|o_G+X#Xq?y}%f1BdW8whW(;@Pg zvX9Pzh4wKd_d)xZtm;`{AKgRD{*hq%)@mOQEwqn`$?LF>k)BS_K86nK=>+Ygdw98y`^OiqVWCukot@_cRf(V4Y=_Ay*5_zBoYe~!ez7W67a9X{07%W#_1pFW&dLt_~q;eVEt?Ye0v@4a`2-Z zFGf3^<3Hos?*Tsv|2v{z#eU%m@Y5WBfd7@?UxfZ*68zWce@jz8k)He_Jh%1WWVrI&&Wgn>=!05zU*23!V7mb{)wM25dM?w z_n@D*2K@7S6sFffm%v4Th~abv|92Qqi~qyC$A08{2#4cuA^5+NJ_+Nc%*PD;M>)=caQ+4UZ5U_r!CwRZL%=`zY?#I2-(hnb}W38I3cVXSB{}n=yaJf?n>iy{hNUiPaC7*V5S1)DoN5EW)(4oE$!R zuTy%t?t!j5$rZ77uW(1Y?kLxtJIb9ms{e4e|NLIN_1$fdT+Oow4<5YNkfFnd3>`CO z%-C78#>Se*w#^w|TXVpn6DHKooX}iqSE*Vb@wTjRv)rirzUvcPas^}jw~t6Xa?~hy z)Tq&}=Xvg={RhYzP1mh%b=}#qQ4)gd*2{fE^KiFmw(B;@y@cVm#D)uv+HJ;eyA6<3 z50EtPaZuyzJtW3~ZlgO$eh-r0gXhHN>@7(j?#4zjim`P~^TyRx&l_LeQg`5?2ab~@ zFO)Rb9#Y>pYhrCn%S2hFDbzNpzPd?Pm)1|NJ+V46c4}2b){ag&u{t)juDX7zEH$0c z77q97Id9alZsRBsclVjqEw#GrwMJIw)>OCbB{W26Z=rpJh6)X?;cuhKNia@j^%k=zukZH$QwvHDo; z32pVQ`q7(~nay)sYUa;rscSk>Ru8x85?EQ)TC3|-v+IW?=X<$TznD5o{#EP0Iip0! z16}thy%k|xx2Camlv}5_|Btt$P(v5#!YZW*anRbBl=viqe+ zTaRwkE!*HQt?H`k>O$33MLi@nFm#)66JYKTCy+5A8PX&Z!ZLRfA4cnRd-tqxsznA;Yg>>-uvwL{@?rGrx*ElaSqXJ z>MFn}fgh}v>z1>xKju~v^Y|%XQL4;bMdofS>cK-U8j1Au_e7!uv4KI%_ffofXf%~e zECJTCxv|7jb!iL^$Ct*ci`mq8u24=NFO~8I{1i$jOX>8b$?``m z`|;Bo!%u%a$LU>SH@FV)14rXriC8(8O{T?jo0C3x1%H+)?REo>+uiOf1ZC-yi#0DD zbCd8^#&6|nW!OztOPKDZ!w+Fbi-#XtI_6$Zl#0g=l!3ct0CAz>9-$BLk=~&Q=Jn`d z0?%kEF`rEWd#mNjSShi%lpRl$vWYwZ`qENjys(5Wju(pfqfQg)T)L75ZUY-nPMx2c znmt*lEM}9y^Gr2&DuKU*ls}c8FQu=XS}rc8^QYl%zL-6|Sa|KF?3r{Cjh$IeqUJNp zDg0sqP|vyQ(tNsfKK)wMF*APZ_=G!?&Eylg8TlhhAP2}ZvyA>EXA{}EGwE5jRhdoa z&|jcUBA#hF!eOREybs zIbEt;%I5Hwv6ixV{Qa!F^ao@movf78N%XOdQ6nt9;)+$v`d6IP*Skz7YH? z)1bGBRN^cUJdsTb3W1&j$N{!zmlOG=L$VUno`5srlteP{6D3bmz5@D~o z_^uR<>LaF)UVX&%(I<~V{<@_heI%|*Y#s}X#CeS+^^wX-VoGD_1wvA3A(uc$N?9#X z)+}X>Rl(Hq8RO2cFoy#G1x!y0t4=;Z@B#&`<}c;(_uH_PL>N4g&82xd<7B!} z%Ao#})z<>JD%q3O(o*%(V)j(F1Q^OE9!XqIu-((-4~U;mEGHJ{&ScM^^+aiI)I7(| zCKeMQJXr`K(msgMiEKKTn##?MFJ>=grxT@edNN;`Uc`#cO(!6uR7-$HK!%AV}PUk z%6xe-fj{%-b}tl4$#m)<K$c#OU=Bnfm;h>~F~Wj9%@ zg4YwOP~ZtlP+;Y0h*1kJ$tzGm{~95PS5Gdxlm*n4doa!l$yqj|?5eUTqK5GOBV_yT z75N)@*7*+rWVz!KX3Fwk3 zJ7vuSYp)N~@Zv|LK((*j%E*-J*B7~Z9w_rTSC4o}4Siy8dJAk}^CebncokfvR$l6L^ji5asn@ZFWxN=qh zmwWQym`mkj2H1OJHqdJWaU1Bffqokpuz^7v7&3u)#0H`^U~7)sn&Y>xg&9B*e34L^BFL-3JkZU_(BF5O@dI z3n2>eAPm^?Re{PBZ=UgZk@ z8t0L6x{@gss>O0N76Wsp^wA%U^!ACw4&?}>lN@OxT?DKE`%@EX5M_{OsD@K#M<1U) zKQ%sc608t-0up%|VnU(32*M8uBMVRl&P?S}bCWoQmrXJ>4Y6E9v(?figepMDxwDDN zqF~Yq^8M+>0vHcv%$Y>B1Z@m#f9@;~9!`LSYUl*#HBrteH4urtbOM69!J24n(1;Mw zFpU&}P$o%9jz=Uj1q>T#m3A{l5VlM6iPAA6QGhRlCxdUMvguSYhf|ZHjgZy>QPX*{ zZR%6QZl(-^pAw;@jK8Itg!YBwev6Q2fKiDQC=6INXHBvY6ev3;)0rg91ctn0kswie zOPEQD%*j=kjtQ-UB#vi}L4WK6^d6E-kUZetn0vH4^Gs#N; zNh%U11A>Nzy4rvIp;y8Q;A8sy@o^74K#nY=V5)i}ebE6`;)dOYQUZUe7J4@Ra_iM1 z#34ZQ$te*0@#ABoX*%Jd`GRK8;1ZrdQ3jbYmAyPq=>{4dlsU3? zOsfkyK8cm(aOam@1fj379gkN{S|0U3kYF?ps$xHO5~s=qedSvt$Yi} zjQT(tNbSueMWg_0xumcwGH-4H3z)oA#PMCIsuc)^TzY8u;7q~=3_b6eq0(=GwJ7tH zf>@r-DUgazDpk3n=?ZWP_;gqE7$*=Ie{Gmdy+=+YAJd?cq9+XZfN{r_GUJp^A-aoj zNyA4s!7`&{o>D0Y;1Ozh?JlSZIZ2-+{3Y_9?7=XBmIQLS3|&_G zpg{ZB4+^%oIStX28!O=FKeU3YF~KxkLu)@O&1+JQS@;a*==sd8N2WYZ1a3Bj_+J zQ-=v+*v$I!e6@mUEM#Vo4x08r1i};l7X%V~NdZ#i3KUL*iX<1axfB5t zfK2HE7}+yBH8GV+p6VLMi@IGSx+}SG#)c z!Q=HXn*jWPaSNrw64XM_M^7+?aQk{_Xo82LMrFaCMVAV8g`zEIF$a;-z@5i~b|GGUYML6c4_8oTPl>&m>VH{gp5V# za3aPtB4Hv7RBBpD(k?$l9_!mo#hYV2&40&xOj z2+~{^$O$zE3;;5-dsyMc5Q8J>N>Z1M<5Ei-tVau!v!g?if!_FFf3GOWu-5bs#CxOt zMnwS{l@czoX_#OFXu=p_;K^1HQ`HC~$7+w^djnM6g^{QPG&wOh!;d0N!&aLv<>zLW z^OeNaS61=;f(lFnpf9CMSpLzm^H_c{nMe(kDFpqv=Kh>BM*1m;Dr7@eP@sb{48Cpv zyuUmfJ6;o;6hx^M3NF}WChgA`$B+TLqx2*-mBEd$co5z&t{fyugXGd{P=N%5CpH5p zxs+a(cHJu_kVS>F7>HF4#K%IN#sF2IXzT;b0gwOzsZc>gA>9Whda01Af}f@U!-$ou z$wjEWmtkZzYOIiz@-V8XK-n>1uH&Yb0|pCIc%iuD3D$^}U}7``lIy0F0=n2TCxHeq z07d>1GMX54&{7$CrWJayQDWsd1=ec5oLETrOsnYy!Z;Oo#lVzsPx*!jb+VwKM!E5#yoJneoZVIZvxq5IRE)1j$cp^a8DM zj82z1*Ckj!7IQS;shA34OPTOkB1J=D7HtTA3glqg0U@M`5{1%^n2c%ALHc=i_I(c{r=FUvPe!t>aK3(B_SeC){h0s-9Qu)CyFeP0G zX4vXDd=dx@0iW2w1rI=&Wr=1X4F|Dg&P01M1t3H=>G2nlVIctnOW0Eq0|@lQ!6on^ z8COx^WwAgA&$vZk80Gq9NWC;g!~Oz>rnFE&e2Id3K!&koMmRtjyHQnGF(^}w@$)c{ zQ*kU=nw+#GfT zmT2Fl&cto2xk)jR`|0XEX;P1lC(@qD-DV2cy?8x=C4} z*lwp*unJpx3xF$E&Fn6KfzYDU3JVHYg_5B(G`Sr3S3afCv@{Ro#HLXW+zU{KEiMQn z^J(bDfYwR@N|g{92y#X?Au1#Rlc{vEkjs%4nU&693jhdr1r`?}cOXiOCBav)D+rgg zfk4u5E&5v|0&#tdZ-%47fqhV~WEzLpVy?o5bJf6&_xm=2tf_xrqx|w0u%>-p3;7-wx=b?U0Ei8EX zjjhIula>YFli49oa3MqpdfxV8Xby7hGK(5eSHzxBJ3OLkHq`q@qvLp z-QWT?T1p}sjyql`(Xcg{FIFqZWuwqzwp5gWsuZElK@DFdCd@;OV!{lT%1;ox1Gp~5 zds^23>th#YFdNnohlKH|bKtgwLX%^XanG_gL%A4`IXA0{e(pjZCgU{B9ajJ4)Xrw} z%M{YbDPA%mghdd>?s6_lWKMNUqc2m%cU=gX}@;aly!*!rSf6KaEkjqZh!lnD7s zr+|Y(Cq)ED_frc1(yLbzm(o?xFm5=KeTzs}DrLcKbGh0C;10AVVjAflxD}W&WH#M0 z14{(jCvv3zkf$Y?k>^-8FUm#ge{o%i&?F@Oh6g8&{{F-UPdItbu94&%Ty8AAobg*h#O=AdLi?xO5~`ZCF}9I8m? zr=gY=E4k%kSuvIXK}td%FN59ZU2NZhWhE_4NjGa|BTFnlg89KiM{21wq$c9# zf#x+iF*7%YKxuhyN+!Bcf=&-?q^44S1^WoPCo;<149!5g*ONYGb)taH55yVPMgX8F zKO&qMD<4eZWNU>5pw%4gc5~2Y)A`F5MpR@G*ALMyuqeb6f$Qb%=96_zvhP1ZBYTl!IsBz3=S%4$q$SvXEgb0`i1o#WB4AYU{^*e1ea)p8DqKD=W!mCk`9GdnhBpxq z{1ga!A(MlzP?;D$i>0hV@j4xZe8tl{0%d{Gqi4>ag>l0-(G$y$GYv#uc2Yo^XJAwG zZC4OffZw%gSKzdiOk0_3ZkkGCRav8M1c>>6&JYUXwHXxUTrmO)MS#?&WI;tOrq$D9 zreRe`!{)2tb(Nm^;`+2D`b_Dbu1jVh=758Oy)0={Aj1c^F=<$ej8OIkMEj(uqI>~8 z;wBQr7g~!oEt8ysvsH%b4tTbjJ2C~^05wcy6;y*um_hc_+L$dz#rE~Q@IV-!umLNI9&Xb&}RN)sV@)Vo%#9EIIKyEWTl0I#)EF1fLUOuq|=^jQ6DNr%T z=w)`c)x${`9eiDt(W`z2M?vr}(H|-0gA!t6#MjY;`g6mdTObhdA=JqF9RmvhK>+ND zB}?3|Ajop}h&wZvvjyltzA^FG{!>$Dk00qF$wlp{!{~A;9UbhC^~d`l4a9mQLw&k; zJk%S7aN9Qk($N|r$_3eQ!WyJ4<`QCgCX%u5lq!VkWR50z}H(N2YRH{Lj~Y8CSEkKqQdSkHBH zOi2Scn!$a6K~=ac9~Q<>Mx0OC%7#^6c8lI-SWpbdwh1?Iflg?WHe%2#xDQ(OiU0;g zB689AD3&O}kTPua7!e@)5+y<|FZnrEiixmoQH2Wjlg6sUg?w&V37NjC1$20Z(#xba z(O55Q6KB#Dm2K@_jfGEGQ#`=NfJBSn_NbQ#4-`dRunjNKM*;U3$B=fSYrcn!Un_XFqS}Smc%PqQEVrf2Z|hb-;V%?6PJWlir{DwRH@0h z?uSvrAzy%p00@t4QMl2K5@VOMC3<_*?q8r?@LO93*MkRj}-~2isF| z><9J3VPT**GBD6PWIUx|u@hm`A_$Bb;I`n1Gqa~poPikvBLX!PU4ndaW){*gZE%G| ziKG%_UN^Trc@YqX0a)7?G%ipuYuN&7!)FPABA5ZOPByWHN7!9142i@t1(#_xz#37) z7(gjTiZo@VJ0Ue-vJ}4O(_mR(R0xW|X6$mgKHd-gL`|_lL<5Xec&N60(1$c zed|!8wrInzgpDYeaZAa=3nAEKK{8|uGngFM<%l;lq_^Yr25?qv!-4jY%q|Ex6Vr7+ z*?j_bmBHRff4sN9uXnJ2s2?^(@sGEYTeFG}jZa@tEm~XvJPqqiAwz%Xxv3IlC~%-8 zbW)(;Iq(K+Zh*-Uo3%nCfq0WsATmd2IK6^Cs(%2n^i{Ma`Z6QUM*hx=WgQqpra(u8 za?h9;WgzO(*379Ap%Da)8}=K?jkODAxE}BXoCb$Rl0YkLV=1Sap|6)m2f#^X9~ig= zq*O8j0LVnz*IRL9eG&h;*3*}9@JnvT+^^$ibE1+`${#>b%;$ig2NDGCb0Ki zfs2FMNINFtB(#hOb7b=BSX>NICkSB12Oflkc|OhSX?A{JA#_> z01a_cg*t#)iP|?t1=-0@m;DaW1F_=ARH#&1Y6!AeX#wEyxgkx3OpYz4E0o_biQrwn zMHQ$3MdR4hmx2y3ouH;H8oEwjfk|W z(pY6i=F`lrTEn=3rc|s9sDB+KWO|4&xL)V-Hw7_}1&ZLrNcbp<9~ul>6ayaY_R>LG ztXYL~<8wtog4*;&t6s+e)kKD4b~q71iakpC$JezLgVY=uF!i;o00^HL_`T!!2ly;} zVufzd9s_}l>U0JyhLg+6W06Sz;YjpwBsLrE8;-<>BYikG1HbVYwt;)W;kZNG+Y5!O zAIcUFYKVrU`wMgE2E0!V`Scl%<$-Xwp|A`hlYw|>IFyLS?n!Rx3&+wprX#SM8UXhU zWJLZ!5d-fa-jpFAkQSk{Q+3phrhtwG`pkX(lG4iB7x2!qFH*EKln(n8{;)O#JGKaY zp#5O5hYhPEAX%e==Z|4Y(R!#9Qsi$X>T+R>Ryjc*&Ay1T5>F(o<2h!J;llYdHYLuRM_&ZO zp%E5EK1EmLFb!NcsPnL5*pPH%%DxNmB~h2`I>8N0wn%`kswxRplLd*!`}$!0?2AF9 z?C*ymV=&UMZe9bifj*c!`lIm7=#AsBUZl6zy6kvXQiU$Fxl?vUYny_8#x5QL+6z-* zYb3?ivl8nL=Arfgm>#`7wrK#6>^*RL-32*RI72p`fn><7Dj*ajFr-jYSKcPBim9H3 zytjFqt*{LJB`o#B?rR20Wt~mW-vps(2KJ6#(=Zxb8`%uxqTr-0EP+%Xj6w#`AD@}T zIJwC{q8CIX<6=!hhgN8uk>y22I7uyg(}!WJu2Q7exM|aP*mTRRf^-#<2SI+!L`mHA zksG(Qh%uhXZz6$KyfW$|}LR(txN2XqU& zv-u{-Ekh>DpsGVZ)D3o$@al1>Q}C21R#7LUY)_rKcT;Y5Z@u%-upl0UF&w}KPk|E3 z&0(A;tN}fo?^xpbZrw>$p$gzf4rCnfeJ3Y%dXkN7@m4fs!MZh&?_`pcd4&kk&Q7f__p6@QDdHNVI4gru%0}6?+?5sm6zS^W4fmcA; znjQ*VxQ`z{H~DzI4ZZ+(JL)cgIu-r=jWWIp3T#GLCrHV*8mJU77jS`z_DhkZ&lZen z@NA+CGHy5YYH`kDmNAD2(8CfJpu$LkG0wxFfIvVaDxDUr5Epo*&b`)v_}qt8t*GH8 z5K_eb%xd1grx}K*LP`ydWj~ApEDNI3sh-RrQZeZ|p~f1I^Gm+Xv49Ugq#vXAYn_S} zP;3YXLFGpMjZrPwA2lbcAX&4E8Xb%d4h;^)ar!FWH`v!7ALxUyr#?|bk)ildd>|4X z7>L1FDhAw+_C?e^>O}TxIyECzV#zoJ8NlJf!r|E2Q#?3y0&IcA|BO%`SbxYXYB$>P z*Tb}|5~b-<8b=8r0?<8*`-L#!LqxS+$fquF=iN9x0psC@0F1>+d{BbNCeMwZg8dr{ z35$qKE73WVo)hQDIic6mO`vTiqCzA|jTmHs?IMQ5!^m#*sN@NSTqG}m5d}ZP@Oat_ zelH+pkmM!oD<)tuFi|L-u%=MEDX^jaL(!mJq&A-mvOiWTra3rZ;|I^9L!zDwFs6PU z`qeSn{!{(1BC`OLLMQgs^n5oxui%xuA(UA%WAFiH79XUo?CWi^VMEN$p}w=Fp=5}1 zftkdyHfvf@D6Ez8siJ@a;VvTM2)wp5@eu~fD=p;A_-YybQTm zi^}7@Eqn+BF>^r;Mg2rK6aj7c7d}YRP8AT1rI+#9;_H<3Ab=a#Q;HZ zZ-ea%U9^B~z+1NTdS(=yDP!@Np54hXN+cN>&Xar2A^1oNj^;yN829amXBA8@fUr=a zRg24GbT1~|w(uwpfBa|>-6((&#Ae-hhhOB}$#MEhE?|CZl<98LVL^?9w(}}(6SCAu zfXzHuD&UUCO_d|Yi^H?S(+LbGN+F&LCuVh+2pY$INn80oPo5TW=9H(4t=I~|iC%S> zJtV^wu109^l}$TDU^=-wA;QC~1%5VXSuo2}y*w15BOFI!$5w+sQ>w+)B3BTBgtQp9 zsClqL4->LW)`G6`EnTp@moyubEXj6+@zwNSilUN8inybWqt;oSh6#AA8lvopEVe^} zVV=i?qL^20xtc0ul)iH~;;P}jwEKp#D`jko{xM+7;$%NV8wcic0KhPxrFw8%V``;Q zN(==2ZWQcA8#o7%Jge1Rz=`uH3bChyiXvF1s*UrhX7u$kM=UnbJAgw>eerlNwol-} zhh2NCnI0mRp);7Ca1K0kFrq)cN9uXWwIFmoQv0?elblMSdkdA8X| zMOnO!ZTvQdw~x-MGmza}4b*(WxIp@5BA&M=CA)Z_e35=0nLJILq(zjk#Kg;$!{7tr zWQ`!Gricxx!;JWp!rWuj3)G5DO}pXYxn{0Yz2_ifVMpHcorZ!3`hjkdwbVPk;^bzj zfKT~A(sHwfWF;q5Sq)tl$2>!BPzY$ZZ!PCHR!_hNCBj^xpg02>zuxM!8MhZj?4U;p z)F?_6mtLu1#v=u1sFEnRRIf_IFJA|eh%=v8cvz8tRM&_LbUOAhs7~zDqa)s19SXqQ zAiJ1xjakU2VOV#frl!--%xxN=n6;xU(e<6P0ZCupZm=C8dGN6^3O@L3oTJg+{z0DL8i>I+wjah?Y~@2tH{a6f>mQ8w!eTVo z9~s2ID9#WL^$!jWna`U5;%APZd=#WA=qC(EoSew7hC3^4gQSc170}6uwL!syQ_AsU z+dQMTMV|V`VJuKjEFTCRL}f-$T;~-q>6xJHW=CNDJi`QByD``GTKmEh7@wttJR$lD z$`ambWK5JfEdZd0sNAj9v2zdP9sqCL{B^bFHC>i!N~d4?b?K#FOXb1MHE2bUT8*Sk zKe$>E+E^m&SPr}nZfX#m=%dHo26e@z|0GXk0D@H4AyE)Kw9LTjJAhcM(qT3yx)|mG z;+gnA(*yoP8>Qe^ydMM$ZrOl#FST(+@0Rh-kV0{@_N*npudkq=I zL+o?arAZI915z^fpsW(CW>&Z`n^QmTl83woG&wwMMFXA|;6sZ=G@COPqHBFfyw@9X z>|r-H7>`9^&x&IY1pgv9dmA5&$A<=Bi0fJG-LirTF(RfohDC7bwoKRY`GI~AFw zo^9~OR(RqXS20Uc4KQ5bmk?4E_+RS%d5GRt%ahf{Sk%PtYq*o)eL=(57&%6H10~yel|m zf#cv1b>#4nCJIZja7$tP1WtuObWdRa+#Ig+TrhENr@FME5GjWiH`fawzpCd0k9^>h z3-~PAGVsciiaqe!#8SBVdp$1cy~o)WoN5|{t6+l8HTZf0G2PeNaN-rT&STj2gFjw* zyXOQ_>3_K(aNJKy20Vnt2uB)VBdM=&!q6fameR!RjB`NV?DuVE=GjDmhd2BFSk zV+Hgp8j$GXZ5^ z&Jtn7Fl36{twyet(3r_{H8h6w0|EuUP5~l=43D3fc{QliCL8&f)u0=y6z2C>DZ7i7 zSZ{Hqyg9!)VtMMNI8$RE7M=)VX_SL``2Im}Uteqh z5-vBCB7G5@*BwGqe=G_=1og7pNLQ4d80j=2QumgQ!%?J^#__Hq32L#%sB^*VS zGwd}7!XU+&G~H9hHpFi?SOhwOk3IpPi0!no2DY#5HW^>w6BBysm52zn z2*5)J;n{{6s*2w*$8zSz)iEe$QQM=jsVxpwDWNK15;*off7@ zmY{C+SY0&)SdjI!6H*(|;JG|P`F(?yb$qDixu1ki(SNOy&MhNLzD(zAOjSxoYYhyh zg6j}mtP-`$0LLM{=guJ8qTv&bq5s0`uhiB*g+TX zDoDiExB^N`rv*@gx(_9sodI^1-OFY7Yy9#P=t7iWwv36meTwCY;JU4{4I{;B22cCnX=b#(L^I52q)~axNU-aJJJN z(B$NZqe$Dgz8=eE#WYxZLY8}t5bAu%*n)pCc^KFUMFWzp66^JOXh@=z zGFHu9vh>cjr4qIgp8=r!(45&z^ytV2QZBdtxqay6QQMZ!{(%!#I5)OR5?UNpw-XJs zH55wn7-;$J7#zORWc*`2qpgDJRpY*ZnG-ucaK)2Cn?0!p4gahP98 zvlQl0@tKpIIt#SIctu=%iA)#-P*;xp)|>(!*PXHYkMMZ7<~iJf=t1|a;BOY-8#=B~ z0uSIewu?X%N)&xzGN2f(a}*&V){kWA=B%~9W5)F3M6e-JT`%D~*490tMvz#-8GmYn z@Ku6hw0_?}*41uam(?l9Bk;n9tuox&_)|a(h>+I~yTKZ=Z;HWYi!^eR7u<49rr99RXg}RQtstCMb z07L*J^XZ_Ma9=a@L`S-ib~DTB0&b4z$RR58 z)fkx&dI9Tpmtd4fCWP0HEuVuC%#x*`)@wN&bXJ-S=1v-`4DAfYZWa6z6c@LSN$Ps= zg;DvxZt}EIZJ&9F7Si9JOkk#70K$2*jRfbzQ9sW zzmZn(H^L8r9tsaxnz_-Iv>dN6-XQb7pfFuZKSqZHnl_9OOy4UIk$j~rJEP<*`1TG? zHT&Ci21p`e-(nTP&{d8^UGQ=kl2vY(s@ zc+3UmRAm@4=Qxlv1c3#vr&w=sn8t1xJ{mKKvv~u9_!?@j`F_kTbS0TpAWef&HuFXaZh*PG< zb2~_sX+NYA!M44X-i&+@0{9NVH*U8NK{m({v*ln4_Xz;l*yalQLz2`mML#x&00nRP zivZrcNirItY0Otv>cxpb$$I}YepSK~4$ax^Oo3m1hCe#B34HS}`+8yMn+zpTImV-? zhE4-3)}0p(d;t<>29@(Yf^wdwb7B$wsrhFUfS77b0~QI6ZNyhkK*-sM4qBTuCsI(5 zrYWkR1(DKw@cm4cnXGSe9m>HP!-0bfSl$Ty*cdz4Q&%+V0l-Ggo$9l?4c2_>G4QQ- zkACqB5FjhuehoSc8t+Jf?pmiMeE$P}viM_b#&-rCF{fs{eI5fga5#eYz&~)MXJZuJ z3iJ4AJRNxKff;(Uh?C#~KWvamEsYbf8VZ2H8>~zJig$2}OOORCzJ&%a%(35Od` zxQZV$C)j%;uL-Doh-v^T_m_y7_6Gu_7u;L9b=`vbW}{`(+%L(` zWYdq{pVR8ReNe5P<|LN+Dlh%MjT0`h!}`lp3o@n^;sr<#4N`<-&v;#9A;Iwg<9EQF zK#(50n~doWe$qxa7)dX+GdM7x!{3Jh8d7qCk!RE1%))^M-XNZYGVCtnDH#Fcljw+0RV!xNO+(W-iV(pp++!{6CWS4495mIakz1|5VzEN{6)uIhLG%*%jpeEp zA!Tc;#^MObwciAB@4p{_W53)2Q>1<2PZGJdN1ON;G@vzb4@@kX#-Q?$8}SOjQUkwq z-z{BMA@y2($m0yQVdbxI$&nRVU;o@3zmP0RQQ`MwAEcQ};9UG5D`rl~035M{G}ZcI zBMW@7iD>99jHe=;fRX5jt)+-H;d&%QEfR+X0fAWMOX({jp~LtDzA6|%=%+9SL$+AE zXj{SIU7j~Vjs-BwhwH(QdnNb`sewGtfi(z$8?b+Vx5fX`jys15 z2HQ6VN8K#^KDZ84EuZ;+Uve2_clkgO$*0*H0@o>2GmE5lNxNM@qBk?`wt0-7?8tg$ z72ugoV>`(zK0Yd{W58LcJ(C36<6nM();~k#vxl2;=M9c;W{!h+>a~Wy4K3gMG4N_; zw&$cs()cTWzOCI(AO+VcoQ}2M?lhkF@}U;BYW77ujZgW4e-2`XZtf!bDvJORSq_1Z z{PPp)R^?r1SsI3lb}Ik`cUPN<2Z^3RMOc@7v_=RcgvX|s6&8fRc4^~@b6L?7K=Yb<#02jb5rMLX7T5-;GhVd*$74y zG>CU{YTZ9oML?B}F)|vO0Br*IoM52EafA=MsK90vn4DAN0Ci5B0jpEWs(aXOWMnFT0KEC-zUCntbFm z{z(1Q^efNL%wBl(vBzKaYW>#!MmymCF8Rxk{N2hQo_i^mY5cX568}W9Qf%;P+QZxf zuOogJ==d~t%7DM`6-J?&}ykEV|=NnS5LHIo+<$)i!-T+p5otE&3d3*5?hA z|JofIcg%C-c8#yT%shAM^V$xR&pg-OspFddF?~M&&&@dBtIZl&# zHkfC-d4|n%t9dq?XQO$xndeh0+K=f+PD#q@YxQ|?LZ6W<`n+~c^NoC5pYBiU^ZB>w z^Vz5Lx%!+wuYXjZPyN!Qw)B2|M&7H>=YQ5b->1(TPwR8--THLR`-}fdLQ zJpYA0oi%-S{k%S}oA}x7`n>orP299I@+&6)Z%#=6BA?Kw(=x7c^L)Np<2U}Z zKA&nkF7KZ=Pq$Iy#qW$s`VB|pPnmMh{&!7xerHtPKYQ1RJg?ub&!UMJP5k*kF#Rz7 zy7nJ5K61a-`)tUx_Zymi<9@9t@`yg49oFacH?`g8zoE~OZ|Sq^D_ZXQ|7+r={k7d% zZp6e_Z_~K@R#VTnb^NQJ)bguKI-WH%Z#T^I;-~a|(Wd{ImVaue_Ivd&^u1%!FTTw5 z_YQqNW#;eVt4;e~GWD6~weKlhT{KVU9oi4)1D&sFnWGtX=0dC@$lcbfdW z^m)z1T@zn5&x^*@?<`jB~kM4w$Zbl#pf<9vRPwi7vM;N-gI z8!^v|U)1`pecixILElIIT+^@rhKUd9`;ny9@BB-%J|EPl`^zT%0d42`1Nyvf`nzVv z;l57mEB=Z;ZpVm_}^Sf%EUESKBi(~qnKB>=3nBz*58f@<1#0xm|>>x#LY0<;>ECx z5kFo!0u0;!@=1R6aokL2oz6B5vrg8#Gf**!?^Wu|r@v`X+2r$g~VZAnt zVM$o##Pnarj=?hz!(2y(Wh_XrVcQ4x$Bx&|Kl891_Jd)jJ2y4VK5xN5na=v{7+DYF zOlR26KhtbF`@oxdc-#7Au8_d^7Tnv-d$wisFh2|N$#h#MpU!SgXFZMhVIHR2F-p7m zVLJQ9g|c~U{W39C<{a?JJhs0Kvwp_; z&f=NP!xs$8SWF($gPM6mLFQpwHl6t`oG{(aA=_blwoU{k%(xvF>j;@T8Rq=j`kezB zW?$K1TTe?M%rxF?E7%{~u1&Lfg7r(kQI2VL4q1;)=aU1qWtoS4;gc8BSwAaanE7pc zY=03q^8*#Vbhc&T)Aq&I!@0Bd1mD@Q+kAZTW~DZb?bt9o!Z7QwILL6#xJ+60b1!b@ z=h%q@wjRzi$HP23u}BQdoZyFHxlJCXhr?kn5Bp>DIH3j!Gc9E5VOz}@F!Qi)ga@0y zDNv`gb*rSaPc`*mQf&SfRK_spk3S4Ef3PiEr}P2un1|zXcJ21^+dgnCO&BTju%9hx zfMNEt3I7;o9y?FW!tb6ZQZ{VI$$7p5w{4FlY#s{_%yZhL^Ia&Ahsew{)<+)9F#FtM^005VpM2*uwn!e< zY5OMW2F7%ZY(eQL-+6VKak0*DpbtPhuTBdeGTugiENqYU@VRrlrn8@RUHHyv(!R-> zhPHd{+VQeac7CLv4SxM$gV&PBgtedAF2lASE$h>Y7Sn&`aheodWnJ*Ybmp~Vm+{{1=MNhgle$q6^YiA#r__T5XIRF9fK9i3 zU>;N>>3mmHCo*|u`3|>?eXGtVVTp9xrgtL5u)?e#9u2|(dcr(xw+R!*u=LH8W&IFU zB%NW>d7H=11LF>eKA*fT{nvD*hYZ{NT7QGAkHA|)QyZVW!3#osvd@k3&(3*B-m?#^ z$IFl2N;#xMkP0)*JbU+S_wsK+r`e|R-;$(D9{`7b*#>EsanNlEGY{9r<{_VAnCT55 z3O0;P5+;r~yLU-hGhRQ8SIp18@g2jwK_|VooCd9*=}v32SJr9PezINA7D*S_a~i#} zc1~oik;&HYG;EbH+r-rR>8Qr$X#v17%sfs@qo0l_+oT-gI2U#^59fnF409|kI6Cf? z4K=keKk3;4+)U>UYTfLG!wr7eakes@b@FCet`Wmbmoc{b<0V~Xy3iyOW}Ike>p@iV zur7{>=@JepTuGmsnh5IJ2I{eW-UEv6UM2x2PKcBhuYe0 z{;+{_!3BfwGS5zvjF<4kF)%-GKvbso{*>ou&`6*2JUWI$HcVPTn{eMR+Nn0%1wX1pG3GlA*sKg2hICDzG&Ojlau&y}4+of99|C@V5Q=b*`i z*#}OVoj1oB+`~M)osLc~Kcik-h7L;{^{^~)^MlSal815Npie6T?NYw7^|L?BOWb6i z7$!^xaU6q``4pIe+|IHRZVBLfqv9#w0ZoO+3G5+@ZOhU$tw;HY{0Ot|!4*)-TO-aP^K&iOwpSK3fpMk-ms{D6^bJqxi-{|Yh?*|%8Slh}hs2o| zl7)1Qb;ltq>x{q6YAVbn#S@1nn=b%G zi1r$m7g!0j$9zt>ORC{}&QEau`C@&0ZBoqU4}bQv*FJ@OjGL*4W*>-$uz)7cJZME| z62o#swr3l*yqz=q9u$_Un7r4%)UHRkLD-7C*MT&)2jSfbx9njBtWP?=d)I^ACa(RJ z?)v3hft=<&`@+_2Txp)pGV7C&p)FniRLa=9l&Y@XPsujX^T-osI+osL3xCfq&b$)+AAXew?kHHS^oK zwRx8*&pOTUBtPdn7?=7%P*|^RA3Q-oj&bG(JrRVmai_7%TMxePB-6yj_q-kF9$8j~ zwdb|-3EEsUK078aexd!4Vk`D{{J?Z21d`t|L& z^KSAQ`<}yLzik{rxfs{+D8FKy?FQ$Q?}Ovf{x!-3F~7d^$Io%q=SLkL{1CpK?nB)# z$HVp~1oF=^HjepZE{V&;w{IahNL>3H7Fo^qm->NyFAbprKKY(EpthAf!{(>WfEVLZ zUsI#kKdC4b-e=#-3uNb$?_~TPTZP~=F8IpKxL6l?eoTie`K5kCubE%!!;_a+UsFqS z14d};b3(hi?%1Jm_SAG&-fMYXFV?L#-Ve&O+WI=%w`{TfmG&uqAqU^<$PvKhwYL|B zG*{yspU@9vwBu3gsqa~@a%+uCo#-IzwfSuue8)LveN6M>4B%pZ@(o@WF6euv8S>%v z*TN%<@x9YbO;p3`9}#k%fq=#L>>r!6?MYz~*W`*y0+lyfW z9&{=J8JoX;d``z*U3_QXv%DQI=QFr|0*|d7TkpXO*3X3tj!)YMeq&r3wq6dvk$~Gd)fLxY=q(2^2jGcVw?dxe~e3i!+V8*u`R;e zcG+nOv>$Hq-c!!yRX{~7&l@7=_LrHk#18>}F+SEuxrwc^UA~j?G-`#63t+pgLLlt> z;Cyj@osMmd>?hxI{rPL_llQIQ&}P1Mz8XbQwE4NZHb2uK&9w5#oB25(ct}{`_2p^C z`CjJ7>FU^qjLggT+J?Rt!i5fnzUSx1nC`ge9*xWTr%(u&UtfDe6BwS2-_hlCv0lby zJk5c=qxZ{O_+wt~k;!22wDqH4SEHdnte@%ypI&>79aJH_{HRZ6 z#Fl3iul@W^^EPV>R9XF}WA;7kvGO{@gje2n{yCqZ7x>ls1g;Ii_Qs20lK`+h;cYZ9 zUiNz%=sgjDWp(}=eh(s(#HG&^2=I>Y+1^(Ca=?tUJbuDkz;dK*#$hjMKn5Gv-f4cO zIpL1nU05Kmd@JEs%S(NsEuHMIEiW}<u=mE2+sC(emZG(@aty%BL_lQ`QG_&4)Q7(-_o8=(TQyv`Q~q;1*$F@^6r9`=s! zIoC2i2LRC^EMCTgcanqe2*2OK{Rxv-`MI>n;l0HUL_P3qsg_@4cg{^Eym-cI%qMgZJ ztdH}YfnP0&9~jw#W=^;0(&t_u`KJm2mg5SJ^NeVAHL&d`@a_&+8y}E z{L((E3b(bIv7?TA?%A{F4qSMz^T9cki`7V)^h2!2k|b#|S6z4RaL&hWqrSkh%qP+g z)|WYL8e^2Y*;l4<-rCRyfgO`(`qs7;;w+LRAJa6CphPf@S>&>91iCEw*uN&QB4I`d z+jgBs*X;_cPQd;Wp7^wvm+#)#@Iw#l>@tn>=lp1RY`)>=?z#&>rs*8qb@8IJQ>tJZ z`&>TPnS9a)jWSNMc+sS>2*-;bgtR_R8c8`X zn`ZMdD=+?17sfSvq3OZ}0+#Kw(?}#~Cv^IAb>!tv&x7~IShvjw`w{BbMhK7W-+dUG zbO>*l#`VS33Zl|LgCW~dUQT#@(0S&;U_Q6`HrOZkpe*x|W>7}7aw6+vI>&2Dpl^}%f2+T7T%gJWZw%pV&utuW1lKb=y^$MG`C zA+u$#K41_DJ>M}+<^bDG_xIm+Hw7S$LHozD?ani3kZGLPc7-m4G|l>L2ip)h0BySM z?#q`Kq>O>TkK0I;|ZY9gWC`3{3ND;!90qKA9wf0y5aLw435a;gF=U z&wH`aYx~W7(k}M;+75pG@X)f~2FuCCjSA$0dd}+&?{Svj!vO0det`G3eX;Ee_^16f zwCRJSue?}RjE#6sEBboAQUZ-KQ(7P4inVq)hn#L_)ypTz<|j}ez>6`(KhBFzyd+6k z8QaLU=Nd1rPM=zA#m<(F_hEbq(TU)4B2t6t^Z5rH{KsN5AJ-i9$x8BvX&ke&?|`#E z(%NzF{re+~YoDJ5?ziIoHp!!DKMp$6;M|85BW^J77H7+rwl-U*?r#Z>I1M8sp?#6T zqj$-^6!UXDSWMC=gmlH2E@N^UT*v*&_pbfl&)>L)G@FiGtQ;wNFGsm!TMRAbFcNZI6oh{2VEIK zip~Y=xrEieh=1LZQ}YvU7}|yzS;g*s$mG|0{wnlW&NyoMhV!S+gp|_!uCuRWt<&v% zsB>`J#chO7&I@#gW}%W|o+pHAx*0PPkPDOZ0TOClY(v)vJPk1yv}P4)oKwEz4QNKX z{f7ixgb~gq+JoiAr^|e2>pTN2;Xh)F4Y3^8rfGKwzr`x#RIZp@dG8gR+B7yV8exg4@G35twUVO)X>I?hS9DK)mK^J+8l+Rzr z`Hr)0M&^y15X3&J2I_#~xJaRHGtopI%6Ga(F7T=w`L;ve8R0rLa1Cfj;&mwPI7e`E z?Rfd+#+-A`xyEy_0Ebb-4p?LPjyEsYi93DHuZ0GjUf9OM(w43}-yXm^6DRB{X1Y#ifwO5Z{wdaVFRg^r?}P+lrqNME&<1)7t)L_pj}L|NdXW zzYid!v|Y#7iWWyvygB^l@M?GsH`j;|t!uTfH3ax&&qlCc(&{=RPj;<}jzj-0T-SFr z-`LUo-*+_s&5q`;?`VEuM>A6P;04!B`o>%vTpS|A{F(2Chm~#w z^Wc<;<2>&;Hymg60vpFm!Xf8D=K}N7{5ka9NUY5OZ^(*HYeZ5wCm+B_J`mzR*3VxX z*D&XVbOzVT^-$(|=;RBbzeq6K8?T41-Uz*ML5j%SaE=(G*1i7U7i8#clQ@qH%UTRM zr|^HDGYXm+cE)7Eop(E{l7V@RjE{hyVpiaDj_OE%lmSN{hZ5#h{@TLK`_LXz_P7sE7Hu2w1 z{nxmY|M13K7!AjzFr;ZNfdtnoX9vi%ipB}e7^}dt`vwn2ULMItmLvZ(vM=H|3Fo3S(l7!H zzZSZN+2J6$&K!4>^S+S%$MNg6CPDvqEkuYmbQ~cp>f56uZ;g&PF8@y+9tk1PJ@Tr< zBd<9;@~R^v%ZEpteIv+8JY+j<&f7w7L#_PvL#v@xr19S9B8*v?)rmYk7=L=O|L5_0 zH2&j9<4^xq{OLEwpMEI*2l4oKqVW$$;*Nt1eato-m$`d#qe|DM-K@Jp0@t!JYVs0x z2^Wpd8u<4b_#$pRJ8(O=TUVcHXa%!h3#~P94XESu+9x;Zwq7nC_u{7Gp^JM7;lsFz zN2FDp29~$HhRn4E2`xbM7DVE>|2-zNg69No+CF(T5+fTQX9ooi4E;cb=sEMCm)DpP z9a@bzpNKf0y#nFpM`CbzAp8+3af{;4xTJzr z^M&35Umh)C?Wp-^$bnTv|M#LWD#7yJA?pu1+AN)PJ01L&i}OzSskzuObhHb%i@E9I zgkb^+pbfZJF+ZTV&Kc(8?JA8oG!O|&^Y}{WgfoJF%(jZ(E@nqDa6!mi;A|uw_>UjV zEv8X$*z41u;oaA8Ctm1ZY6XuWLHrK_`pV~helHce8!+rXjVK^$k`%(xJkYRnlKkp*Q3aPCvq3Lbd z&*3%w8T;0xAKf&4?c4_W&mQgCF#UHoOMiId{GWb!({`nUHT^`SE!fZQH1cTwEy1hF zkGF4oSSjWDbW)D>^YFIK`g3SqKmXl%pxd7H=`#P$s`@(Cw~HMMw7Po!(YpCJ)OcNb zgCXSg^*B<``u_X#@Q7iHc7C4PaJlWKxCZ=e_n zqq)RuTEprsY|;&}(pZ;CL@@?$_^Gu)G-1ny!RJj*O_iMErXoB>0>OwE4s#L##V`N$%}_(r{(Hg)LI)ZL z_e}1%5W-H_?h6;v4TVs(VL9}!mZu}{Zh800&$PYw{$J|&{l+hcuRr`^(~J9V-VANK z3n%&-oynit50A4D?hDSlZ>~5mh8mm~Z-#LpP7CCdt!&3NpQQLI$vS0aP4-M{^-~6zX|zx-Q&pPrp~tJxp3jd zo8`}=efCK%_JJ4s!Rxw4wX=xZXp6jsO`x%(;k6oGMc2H`=Ce;*uZ`RKZ2_BZpTWAA z$EF9Lwk)3zDL4A>W!dN@OK@I!1?&Am!u9>tTK!);-(Ff9-J1Kc?DuDU`in+@}*(|Ij?!}>0z+ZXeskJSIBm&|~rGj-GQ!{`rZ;D1_|g3@o_>6yZTC~xo(zRnzdrtCHyG(%Z|-`sq2q6)$jZch z?!~U@@RI{8kQi0q)4EVm?Ij665lGuOM z*l2U^UbT;lD|PZkai!)xavDhohQng|3#t zYlXfu!E5DW-L-P9_8M7vvi1tCNaKN@f1rMh*)D{h{D~2|37Tsqu+R+FEcVAfc=O*p zxUw=k;a_igVE@Xgx@+aB+N*12U){AbR(GwurS@uEX{)c_w{f658^uxN0Ps?KnHh3{}ZXf&N2D|IT*x`fFUs})(b!`7iS zp{_^l8)&l+Uha`Cl8+4h7&aK5A6fkucbtCU4<4V#60RcrS-X~w^Xx_eLNyio+MKfEBw%Zu-sAN!3kJ`*^3|W&andK$4;SlZ4~$S12umzZVIk?6=>jA@w)6kjQ(Sr0r$Vj{uu1RBmdaC z_CM91Z~f}D?Il70H0&0k;HAALyYn{mR!PFZ{apmo%GKrfxjhy13@@fB&xK zE#G;;Oj!MMWX$Y>eC9p6&HebvzoBo1v-aze6W{M7``!IV7y8*h)A_f4n)Mz0tbwP^ z=)<)S*REfE`CHZhq2JWeVy!i0c zRxPnJpV9Y1b2oVZo424(ANXA@Z>adX8g5noi*@wjkL%*^t>d@vtBe1BUH<91`IxGU zpR0@i@-4=HtNFdv`>+0i&X0P}teYO^8@Hg(^(AiBC3qXuCLMNxnjEwf1QWz=5J-@C zAcw~N1QYiXY}_Vzag*T3H6aj}gkYQrHE|@=#cO7vc2xQt;mjD-tz}uTQ=@Su5 z5GRR1f_hE(3C4}WOR#h!I z+19mv=dRtm_qzAqx1Wh{T5d+;t@vgU$0RahGnK<9E}`E8;8-^`F2h7GO_7*n6mOfzgt?`+Md=(Lt_() zwzZ>Z*N$gQKK9LYx%ER{S!q~0_-m#jP823Vmh?GELv@@c)QGG7b6#0|w~Xt8>HdP2 zmHx2}PV9eS8mqS#TK|fcwbLYH{3_E-&vZ3fTfZs!P>}N}v)tVLZBtgOlLC$3F=@qPGA_ak7UV9&U;%He4q)5Ta-XCjfuO+)<9)f7 zl{{u@+6PR1gfq0+u@&of!sbIE3qy}GEzDYoRmiq&Ti2qbaVoc9$-25=gx>iErU~F` zvsi$Rw=zuukQ3j+Zofeo6ANZC=F2#>PLC`Vb^ip*{fW)~{wtZbp5$ z+S=hD7wZ@`WswThRFt~NwuQCmlH3^Vz1GIH*|D?%hIw+6dVOro~EuYqW=%4_LjP3U&9|=|y zM=Qkgk2Q_0$i?~k^V<4ktzIx`#B)H$md@=vcK#1dYiK0KsO#SCyG7?^4;n!d0carm z4>Ao)LD<{cxntL^+xOggoM`~bCLlG(O2@xfF|Db&T}IlqGfLHfFIGJv1wKE@iozil&xdyJ8W4b^CB4jw3d}wVFfJxZj%nFCbv z6`N0c%`S)km}$~~Z5d17@)wd1lL7dHtRocWyG-Mx2?SA&*t)Haj;0{?tz`M;xw(?SohEXU6YBppXT`?N1QD~3!Q zGikcCvQo|CHSOy99d;l?^Ry$C5=gys% zB_CITEjKn2Jl-T}00^!m0S27#?NS!Ak4$9q_!4N>dzdCGsLRxWD*rDn%T!*#ndaty zCut2>$}Ny2!Sr!Gr}eS>M0RQBv!<-{TDb4FZGUL;>FBl6uSgmSvcp^<5Sp)f^~p#$ zn()`XvVQ4r*nHA5*EkgVCet)%ej6J8(v~&wMlk%YO+zj&D8|-;PmZ&!019V?lf6}p ztIWc#p&*2vy~g0mo=8y?-sk5dX(3;2>DDwU%B2J$-~I}w5p;=HpzU3tsXRNuG_1we zoqJxkzxz<{;7>5ErE}Nbd-uOQ+CMyYd~*8H7bLBt^R~O(1BZL!!y^-?r-r%N+q!l8 z?Jv9M{zK8eV-HW9o_+_@TDI-pd-s6{5B2mM!4>(aYzm{p3LRXf=1=HGF*;*#9|L@z zY2I)Z-2PDW5ns`79p0bVG-NmP-SAbDCKIpA+wkX_R+(5HZJIz=_(9tSpweDPBn?9o8YJXk%dn)$ z;u4r;)Z?ZNwoE`}`lLzY00|33xoIg&3{=47JUp&xQdH70{r|)(Yscm|bCRYl7%*zi z*nCVDfN5%4lKKb~x+J7*Z(y3tJSizenC&}vzQd~z-Q$2Ul%LkJ0;VFRgP#1NmKB_& z`~tD*&W}kxfpLLU7XNKc!}vv*!isO%@_DAo#l`_1psD{w@-;{pf{I*U(=?$!Xk4yu z*s?MdzG`g#E6FEwfK<+MQ}cJ3CS!%92Vv^A+i$;pyJx6Fceoz7c1s${a_Kl)Tz6_d zR)};$rs;0|qo;yDM(*_F3&lz)m8c|~9{rs!mrbe(Rnk3~LeG3Pn@eR=PER_wpczXA zeO8u>>0CB{$?3^f67w3$6w1p>h&d=)Oy=?uv`P5e;}TD$=c}2y#Qc0IeHpE5tdz)S z(&&Lk$u(DKpgiP?(4YS|A08|HQd*6yT6Gz?ls)kal5~T zIPNvv*KxZaK^*rQ?(4YSk0OqH4fl22?#B?vy@vZbZuc7ExYuxB$L)R`aolUTuj6)~ zLmc-S?(4YS-$oqw8t&`3-A^Endkyz>-0puw9QPXT>$u%dB940v_jTOv?;wtQ4fl22 z?xzsPy@vb$qwGH5+@`X&fnR%O5@*sx5{N?*P!h@zLLwl5>7qMS(M?xK0uH2zBrIl^ zWknyBCb|ht^r4Gxy6C2hWr3lKZo240|Bn1T-te+7`|c-xC%S(>NB7F|jAzCZoLEYK zTrA~F#ZvkcVyRe4m%kxpOZif9x=(MD7f);{KdrYjvQ9>scgVh$Rl58@9n0g9$U(nily`y z#8SRgETz9F^^Tn5*Rqz}uQ)yDnw*Qg2w=-TOvlek&z%|NO2tyXWaeFxuO{nCW>1sz zm3=Jb%kAoJ$)rN5c!r$kJ#ws6ETzkRv1LtPDo)paNi5|{#Zr2&jHPU;SW16c#!|ji zETz99mhz=yDg9Nkl%MY9hsikIkIkx3uCso>lw42!H93cGvdT`ct=#6zK2G;Dr7yjX za-GwEsK}PmUzg*he0gkr*}IpusW83$K{REv}Nzh zn!fDySLGbi{oAreTC?PK*~e1)JF=I4{X02E#(ruk{axvk@}=|xvMNsZ@5yaazEmuw zzb}^ZrQ&oi>*ycIZBo9>=gU5p(i?J{l%JM-T*tE4Ka|^~%;n{}+$rx3^pNz6V=4V3 z$)xl?xlL|2-<9(f$7#v+&_9-3%9o0z^iRZ6zEmuwe=3$TcaY;`AEzbv!I$}BxlR8} z@-^kU$=;WWQ-3SBe=f(qCf7ms{$lBueVpEwNG|0|#ZvkgVkuvGec8uS`j=9#%l-de zZj-$&_NC(V_BZ7AujCjha~F9GWgkoFU(0P$zEmuwe} zKg!3E+-Bb;AAd4dH_G*peJrK_B>SIb9@+cpSV~VVq>gkEGzr8#J=qPbf4ZX70Wo5+w?ZMO-gSU%ifl~pN^$;d21{Zio(@|eo;zGQKl=j3)NUn-W;2Z*J7saQ(y6ifM1aXKC-w@HN) zWxt_3=Sjs<=0?&ZmA>VQEfq@XrsPtwl)U|?@}<%D+f@WUn76JyNlhS(e+S)NJXI3Z?XeB$tY% z%!4JDQgbAi3Z?Y9l1s%><~+%z(tjAimI|eGM=~i_$~;7JDYZaysZdH^D4A3&WiFCj zN*yY>R4AqYNph)J$~;VRDOHhNDwNU>ms~2AGXE^Ol=_S0QlXT7gyd4Ol=)Z5rPPs< zONCPU-z1lcrA$|HDRq?OQu05tDE(;3rD7@b7|Es7v64%LQu=X{OT|*=@sdla6C{@k zrSxverD7@bM9HPp-zAp{rSy{|mx`s#lO>l@r${apO6jLcE)`3er%5g)Z$#OA3m04V zp_J}Rk5nvWULrkG>Qb3QDwNVMlT6CITyFCum%X||j*;7J*@sg4m13z-@>urz>C%6d z^h&uhj#Hl@$Mwi<>HbVPRw|Uz&yt?B28pHAVCj`|r9vq+L@eb>g;Hv$Sjv?OrP6nK zGo@UqP%3?+UsKAJO5X%d4HHX+Qm$0`kGPvsZdxOyMo1>5mX_P4T&Yk>EhCn4rNXqN zUrC>t_R4XlR4AqLGL~|sLMb&$EaggtQfgVTlq(fVsnKF7S1OcJW5iOfR4Ap!iltns zP)aQ)mU5*+DYd*<%9RSG(szY1rCg~{N{tgsxl*B&8ZVY|r9vq+K`iA;g;Ht-v6L$n zN~smaQm&L*Np4HWtIA$VO_D4vx!pWl9!n{8jy#r9;c7CTEVoO!QlXTZB9?NcLMeHR zCuK^xQlXSuT`U#K@#eKMpOk*C_G$mhs=^wiCs&_fL}X z$#UB%Vk!Sr@o8dDEal5D#_Tg>|DCu`ZvR32qxdJW{9;M}RjlOuCZ?m6-$}VN-m`$$)$YxC8ytC&Q1PV8ed8uAbTlYZr9~sUh>mgO1_WT zO)T$D?n~LbOMNEaYn0@+;qv{`4kb8Y?wGwZi%;Q?-K5U&2tyX3q_hIY&npZ=qALZ}hD0w4Gyvdc^sF}^g zIs*+h9nxwT^2(XWHM*BJX!9)OChgM}t$EcxwiY9g>5#Va$c^)nN2B06ZH*8k`n55b-=R&qPCK-IG5Q0#LML=Y+hZ}G>7zfQ1KL~;xqb<9e|fk@ zt8sAYQslvSxQ|Zg@@2@)3CJVbql=d#Pv|;rtcZT=3g#=peYDpFSFc1K(CR8UTm`vD zo0DL>2f4l)+@Sr*?7tehI|Vkbfpr58X|+0Bz81MT6|P)IuLT>|!~Qz3bpvdz2Y1~F z2XvLTHb>rj6LNP8*tr?jwuBqBPusU3Po^O+-3l99!*x2^8P4B<+~1Wst#*UW8giYk z(k7kI$?oV6?qvTSuyq%l&=GC#iM)6>a)<7r6FPmpxw-9QHh1}Z!C+swmyY&>-TRR1 zHrz+6>2UY`$gTZhJ%nxAqvM%oGbldL+^K{PXlEAkt_P93v`71NLMOES5c;Dsj@KTB z)j@DKog55zJ%Zes1E;TZr&}`LZ0@5+n>+cL5l&z0PPbrz+1%&r&7F!4gA0$t#-HK* z6R>{-+(#!z!qJn+!{gxc)37=bEVQ@riSHfm5a+j{rA>H*d@`!fngzlxo9?aMC3i|zP;L5A8a~)iK z4YqE8^RL6+EwK9r^BU~E37hxBaSU4_TzL!DAB1yn!x7z0yALsc2f6Vu+)b-TVC`Mx z!J}}Mb{>QC?;+Rg%xUj&xa)o75$)05lgKL{Ah(}_RRh+ahFv1_62g|8~RK3)B0C%>09LLYdE1jy8Aoi);Gv=eXvivbn-3o^mXBM z^S(2i`}FnUbhE!VoBPra&7E?7fD<~V%ReGFe?*?XPMmJ~PiAxP{M6hjlTKeVPPg!9 zv$?PR+}x??7r6Kf9Me6t`z!LUUy-Z!O_~E;Wtw}7_Gpzu9%Ybg1K{o~><@%XZE!Rg zF0{kW5V%eUwAq2&9Ev=oy`^FKXL4{pqhMzM>@ExEI$>uV91nu^@o;%C?9wqEO+cQ$ z?vrlb3UGcXtX6@`8mvu(wWVNxRXC!fNw6~vxw{(NNBfiE?(}sY*@7vsmcHI2o4GpN ze62_v(uMT3BH6SxkoV9IonHodxF+%%?XLxwMk3b>a98>ol58Peqm6Zu8|iCGve_HK z!LqQkCG#a6WxaNj7&I=Cr;o^Yk^QblVONXp7G4$c-J@KMqcI zg^lsByF1)RJA1&r6Oe2B!upD^X~PNa&w-6B&O%sCgssD2eO1{1 z3*2b=2)KI^a`jhOTMdqngnMbth11u%(#@yU6xcfoxksDFz=nZ5I1W~;!(lfZ(bg%n zypGk}PK8Tr!p>>1J{3+*hhy3}3l7&pZdKv>+Hg!;>%jJ6BBR z+6?v|hWlE61n%CP`J-@t3s^k{d$d!BjV+OfPr`k)@f7TAg()6KuSL+@oVUzcX_4UFNh;r@s?RH|;&-E*&=D(yqwE58(!_eF_J=A$Pxm zo!w#kYdBYegKywE?R*DU_h9}5?C%MOKf;B*nEwPvw3FGidER|{BadlkAK1zwk7>ID z?%5Z4MC<#(em~>^tqp?H-_@m?GZ?N+r!}~1e>hkQj_7C@?94!(42QLuu(=HTX*Umd z&tg6rt{ecXF>vlcIHaqzu^jS38M(JS+)KxFaW?WmN8X^FajGHSUZ91?+jPzgx0!|`@10bXl++m{^6tM zwUw_$Y} z9MctApN_mid;7zI$Kz+h<Ygh1{g;bV#SaCv9%?(ceP{ zw0;h9{Sf2=OT~(1Y1=&I1G;Iq{9C5kh_P&eRM)s79%(Rf;@LV?9&xm9f7<- zyL9^d(sZ-`hP-?s?6_Qyj_Jxp$koxvwToes?xtf}eu>$fKR5>c6}t7lcL^PyfIPYc z{Sj?k3hUj-ecCz^E?kD(rG45w33>YW9MUbIYqWkc@~$h8+a8>|5{}M-wX5KSF4M-@ z$a`srF7}{5rbAjk2mQv?T#xRdJzBel>s8So(!pZbxfZ#50i4jrh0L!*t}cet-=(LU zpy|n%W z{Q&2utp{QKDdY*Qo`$<0V*U)QKMaS@az5I98SZ)vx%~=UqxDzeVjX$%8mu0N%^236 zfIYgK_TNTsK8akt3rDm?TTdbPTREN3#ix-c4bJxrY<>s_wD&Pwc@}v@C$#kmayR1f zpThcc^yhF)2ek7KB%(hwh~ly7Urq zy$}5nozSITYn-nitX_vBx2-|jQ)I#+!_M+(8f^Md<%I@*J(G8y!Hg^(FF%F4NA&oR9YD(pTt@P2_#F z+61<~My_uPN3^*aT>J)kK!>!kIr74{$lWdAkWRLQOWz?6r@>u)u(v&2{2n%Tg3TY` zco*3C5w>@QeLC8M{t3ChC!GHoc4&_d>D({K!@bcT(lMR>{j_vT_Ca2wt^MGl$~N4-K?MXm-T zPfmyPLty<3*rgLXHxzkvKJp$~T?m&nH)x->#xs8i{kaKn@-Q5<{0MBVfLwnJRx83<9j?;eQ*do1jTxuzClMXf0tr1-VYw>6o?* z&i5ty_0?hTYdE1p+Fk>>`yFy~O*o-zwB3i?n2J26duaQ6uD2F);|DmPW4f?5^5{q8 z5$*mA`|BWgeueDN$9!+`h1366FWsEA;Dk2T zhAS5GfL1%gMge(12ei2p``1IB+nMvP52yb>Sh_{Dz6+defIOs~4dKGB%;|uRH)6gU z=ie9(=!n*LM{bzNtF%XJCC*QG)7B>FS9>70H-%kV-yF{GiQJ{TX|)B9--|h2p^Yt( z_tDl?aQEKm59svohNqifMDEhwG&r{}a&2qobWE%LkcZoIemb_`qRsgahU1yAI~Vq5 zaefD`8~|Gj;I0GVkgn3kLgZQ*d3-1ww)`i!I2*Zt7;`#09Ci;v?i~S_4u*rj!PXqu zJPKBGVfPrgMyq3Ca~|@9j_Key4YvGi+=MS%vYy<+B^=qaW8Y)x(_ZNk6gbWZqPPeJ^{J)Aabi4_UVYW zA3|O_kvSdF#=|`R@5mjxm-buvNyrnrP8*Nlc=Kc)PlvSoD01f%2?bGJz$hD`ChqV7RTsZ@ILMOEK4D#}s$OAh4|8LUG zc^0{S7LR`p?m8PbpNDI-{Q_J)2YE#2&xQ3Dk$bd5t19wqXw6 zExNQAx%D#gUOIRMw$JDBukm==qU{TitJjeyv`tqozu#bW9g}kQ*PNzlS#Igw{Vn?p}?4i;n4tE?&d@ zQ}hS4`V7{uMIO=~?S772U5DIEV24&;z%d=s*7fN3zeFC=&R4K;1Lyl1_G#@KSi2E< zOn1}4x5!n1-2D!&&{iLu(E9gq`6l!ybWDdoATQmF-1`xZX!|F)cnfmlXE>zQFL2>j zr(H?Exj{cz4PbajxgLww?1$3B&-5Sq_uG2A{yA!!; zL%&U%bVz%2*IitXc4^g)c4+M(*rjbcpldBJh2#B4&>ztWozUi^$o1jqHy(p6 zx|??CnD*$dI{JOup#wUkLt1;B=R@0cOb4_Yf%DOxK)*(pX=`cZ)|1HNJY0Pmc1FW} z&%oArIR6jkbeVSP9@?W5I;4xwb3NLpwFz90Hfigh==bOv?bEpzkcV`Mj_H6_D`0;0 zBKmdOqCGmKwH48CzJz|0_Gz2$qkY=$MSnzxw7C-IGhRlnR)%|NjqZ8{xkY!=0iDn> zU3``Ebz#0LZO{oF(9UbgKz~FBv^A0Qy@}kTyJ>S( zmrXa7<4z0b5JfU6M zGtl2hYpe5o-b24n$F#l%^3warJvySzHIZ8%AP=U(y|l3wTx=kZ=^AaXjlAnap&o(^cBq z5PAM{9#4C;wGr~9mDAOP^KFd0_yug3?5E95VE;?xK5cykt4)#j(KcQC8hJ=pzJc}4 zI6rOC*0;zbx=uTrqu=}vxw8cv()O0j`?wx$e9!f^LY}^#Lb|zhOvkkUBXYZl{=!eN zPuFOD8uHT5oR3c5qaod_t(pG<8{5DU?a|J!$P-#qZO!AIZPDLNC$zjrGV<+^_s{`d z$RgLaN1nb89_9yq6AXs~^|f33;8?c81OV z%;_2((Oo&@)-LF;(rQ;YC+}~OZZ2J+jopwp=zuPDqTk*fd7X~w!a(F+33(5l(E1>r z&mPDPRp=}MhvoG?94(Kj< z@5FR7_Cv0Q!2#V%8#Z!lIP!?D)7Et4l@Z82T3Z^{_D5c)9lE>>a(f2ynD%GF_DJN` zEZEG$KCMQ<`T;zi_UN8vktei1n)4lq{wf{O<{0E|8F_kE)4 zbWC@z#Q7H@*H@+wg(KQM46b$|*A9n^tH3^8r}ZO{dlT9JH@LhiY|*`RKo=*m-$j3& z4(QTq$c>|r_tFXNOhz6bgWR0L{$t@<%g4dCf!wF-v~@gkV|C=giLhD&j!uR{Iyn`t zu8CYb9j;7;oiku#EjT4>&2L|)tgc}Rz}eld^V5P39U%jWY=Zd=&zguCgGj%jZoa%VfP zPsg-11bMJMa$_iL>;P*TT%*-+xN0E}>HLncyEO8M)|P=wJ0Z76!U?S{3)gl=?$E|A za7+huFdF^FuIwKJ2ej&fyLU&fO@#FloU8^nXm2uH-UGRs0{7B7ZS0BMr+qr6`)Jp| z@!nqOx7UQ7y=9A6GIoJpeXvc)@>ByZe;mZE>wy-w?HnxMc znasCmPA5CT$t>jV9? zXAbPlf^&1>nD%J*0OVcsc>IBIFKx|+d**Y#gW#eA8wbNN9nhsiINv`k}i2-v69k+5Dt9?(@fJ^^{*&z%1x`Y-fpaQ+DT zOt}14*k25H9|=bn!Oq`c?GjjXVUO;n^-Gbfqma9FnKmv%9@7zBI-31G$h(iBujYKm z!pZe;gVqA}ABWtz4=$eo$8<04-jCesMy`i&L0KAG!1 z$N5g-{QrQBQ(>PDX#IKSry;jqgmn+rUV?jQy%#Q=jy#|PI(nJ&oq^nVg~!t#oj((K zLVL9JD*Dw~$RoN!+pi%{=$I~_jehfW29Q46;+W8)~E=3;E5pDc{ym%RM{YM^8dq45`%aL0@GpEB}VCM?tUfWj9 z=b7@Au-gG^SJD098XXN_e-CnV6kNI%4wr=!+FA|{uj70=Y+ny+6JYHISYHv2Xoog$ zWWE~mo&b(${U+F(jJ!$*Q{b+fk!!2NAsy1iTaa68Ag|F0-E}MHUlX}cYg1wEHs-WT zYil9zqkXz^JNliqnbYPvaODoyIIi=qhdOf_|-zJfL0L-W7R5$F%)8`u*LI_tN_AaPbMQN7ra;HuA#L%;_4f zAB^052Dv^D)}Dop`EU;%90Hdk<_q9n+FQu{IpoRNaG@7=&x6&=u)mo7bWDe|a{=IN1LlxxFG>`2p5ff)m=O?H@Vc%E%)+pv|9NJp*|U zt*s90S>z7w(g~f={u=1F+t9DC2}g89o9)Q`smN=zvld+FKyI!JtA22@A>5#YP2isX zTyIlY%fa^MaGefmV*qk(3*=Qgp|wur{+7tQ>4Z*by@=cyi2j(4X?GfOYY=je4(Nc+ z4MuKljs6Pl(+Qo>_7L`OgZ_vPX>%xYV_W1kI<{b6pat7?LhTLBa_fBU2`EYRx9MiqDc_DJwK&~!< z?bYFkj%oc;cba74O+GXeu>4+{)MIKy^JfcI|SPOY_1&^oIm9V}x=cirT zpkvyk&2`YPUyI|d0@tT|Y4=v-_Ik*pJ78mdx(0`|e<$bL0J(V=9MLgtZHU~y2YG%Y zIJ_73Y4d*A*qC_;hqUn^Tr!ax55WyOq05^f_a0_W8;`){O_4`*gAN`=?rerUehgNd z!$}?X=;#T!xCQ&^fKHx5UfvS9{WKiY;j?hK6>{x)xVs3OFTjOqu=N&fZ3Fx7!p636 zM0>RT9`f9F$m5UTuI*v{W7wsgPhfoq+Ro#6Oe zxR18lrZvBB%I%8W?hiNUcp2C!ArEx+?+IJ0v41bvU6bCM`BWai5A3f6Yx}~<+OSW1 z>%jVc$ejXnI$jqp*vPdF;FykRdpdGsL*x;yZv172G`&c8YL* z7VJ)g{g$_ZO9vn~w}aJz^!9K!t#*XVW#raQaBeoN?F@UgOXm(k9_)&|MyuW7(!o5Q z4(PCi+?s=2-wV#o<$U|XeYC$H?9M|j|HxqTk#De zEVx0N2f+3MAVgJu?m9~y#|6h=6N5T0cVC!hur=4S9{jbP_W8r{~j)MzF zBKJ;&)!*RcB)Cc&r^9_Na_tP*I|`2I{L!#~CUT$l&Vu!0kb7q{Z}}YN$09e+g*`f< z)p4A^io8O*=fQonxfphiN56hPoX`BOh}JHKtrL+epE(`V z*58pwmoTUOOX1Q<$nDGFg!Zn0D<^aQE8zz1(dAQk{8h-~mV03PROA62(dugC=4r?+ zI-q@8_mIcepua|2*Yfz&IX_*a!|Rxzf!w{G$J6EwuyH1GkM?QpM&$XkkXy7%s{nZ) z9nsF&==X0z-k_bEVf!59<}Gk9t!{;_bCJ8Z!F4*O%_@(-9eF_8bpAZ#9$ldWx|fdV z!eaC%bd}cb!2Ifb4es5yuTNs-=qWDrnQTZyL5#P=w3RZ z3m5Zz@5KB*?b10Pc|<$3x(odgZP3Og=(lK(cIZCZqf3{fKcH)LOy@5{uI|QqF0IoI z+N7<^(Qnf=I;M>)kh}L_z8>1AwJVWFbcIgnnAYya@x`mqZ_oj4(fJn@(t-E?tZMn6A^t{g|(C9deiMp#wU1J&&gyT7@{im)2?X z2K1YB4{g)hjmSN^LI-qAN3<27KcPcfdjRWq-GtnrJ=&)GXqPVCjDDZ4(IK6`1$j)n zw0aQh#k5WrZ$-aJ2ed=yZ$lo?E*;YiT6+ld7jH+uK?k%&=kGx7(iJ+Od+C@i)X=XU z#{5-Ur`4UvP1>eyx=wp^*InojXpfHQK02Z8yV0*bg7xdPN0;tFu0M*rL7Q~(UgQql zLwj`YKAsOvhZ@(|65L5H+O>yM(}p+bG$Iu_s zJ+yif>uGi5I$fbnI;KO~ejNSoQ@nn(PZys+9?=1v(D^5kYfs~Nmp14IZPBHt(C^S8 z?a^INBM)egj_E#He+KK7pFzJxN3=^9o<;7{J{{6pggl`uwDByj2kp?-bLbE0kk%sf z8~;FV(pB1_)$_r}gKsUhW01M^|W@ZqP1WdJ+9TU8nVbV7}r@ z$YZ)rtLJ(DdXXD+m9}X0GIED5(;gks0d2m5{)q0O6Iy!}x%N-2U!hGprd`^44gCRK zqhnfs9l3e|^L5iY-A7xr{Ra9yx=u%Q;Z5ZFiz9M>}-+L-hM}M8~xG5pwNS%-=(swDvJ_o379<-Jk>7`UL$6 zU89ZHc>bRvcj+n}(Yeo%tJl%*&<5R0TeSH(`W?E5_Gm3Z9?%s!rej*Yf%U8}(67@W zZPLb<$ZguEV_N?Tx&J2S^XZVzeT_V!9a@Xg-%A^``3?Flx`%e?{I|$G+NA@!K}U4y zJM^o!uwF=;w9$v$p{uk{tM8GAbeWFnURrw_^P4}Q-=ceHkIw&yJf^#8;~gB|N87ah z6Z$>6P6xE{GxCV8(h048L9V@v`OCCPN3>0wzoOrz1KOu`)zN%iGNe7)d=K+$8RY7H z*rRp2kG5z#i++c$(;jWKArI&(9nraV4eS=;PD?~{tE5U4LYQ)PV^^qjn+QG@%ljI2Hj0tbV56H zX%PB-I;2C|7>qooeOi5t^|T?#b=swUS`9^Re}aCOcIku;=#qy1hz{w5?pg}D_9^D` zXoFV6kXv+_cIb%qXmdFFL%N4npJD#|2;>Is(l*_oUD{e2{XQMi5#6;6a_w`TKW))! zB#);ZI-z4)PjGxOkA8~|Xot>^LhjMsbU-I`M3A8UJ-STWbVR#!p$q*!?bG^qn6I!3b2_5+KIG;^2xSP3E*u8^e+3ry|#v=KOR- z7uG@^ErYyH`=jZ#k%wbpcOBSU4$c)|e|gxWL%Ko7w7D+&T^;>3IvfX^>miTE!yz3` zfD7v*4_1JKmRE$kHekLI+(U;e!^Vcly)L*$o0DK?Bjn~(xV$mvqZ_oj7IND}ZWZ9d zCUCSa+)Fzfz}}|F^^MrS8EhBf?#wr)6vb$cSCO70*AD^ z6*hK9u5RP;v~@dNEFpLAfFnAp!S)`={rlm{o^bR4T-Xb?AB1~om(K0Y`5!{=($2$h zZXeG72<+3*qp-0r^7t`0q_t<@ct7Mu1ozmmM{Cnz_j%+EI;KnebN+uar>z&@(hTGQ zU8k*=kUKMxhp)nwS+M;Y=cCo@obLe6_ZDm%2s>}X0d2nnn`Pt)9nk7Mzd zdGH+^(bo5HWdU;a1N#@k=FhNN1c$%CJ#^H*P4nwV@1Z*0j%q1_LW zn>QdgK8Nia*-yuG_%(9lCieHieY8c}HzN zf%CV+VFz5i12+4?b=vL^mutv_9IW37y93~WwmM<+F68<^IHD7}d^d767v`&9zPaVkHHD;((X9+*O6N* z!QGGZ_%7Id0*>h#?My=MKgs^daOEj_3f%QH>=K_o%P{fTHk>A^T@T0;FwNm`=301W8?{)(C!P&P2}2(a6I2=sr52-8ay0PeZ@Zi~E!j_Izq zk;mIHr`;W3;~nJ6f*W)|`|lzTc0yi$4>op(yWfYSJz?(y*tg-Z!Q*GZ{)hBT*!l?e zX2I%X=Cn^owD}2g>j3ok(lOorDRNatUiggj(S5W%8+q+>k zbT=IxhJO7kR~&v2dgkAO?xAUFQXoc8_(+utG&UAT`9j)E)S@%W?R z25r$+A99-xXqVQ$NAA-Ot&YKby|i^KT>b(5)^S{q_PgQgkIYYm^`GE~uF`>ryys`+ z`swWd1vbur{g%&z!(Wm6bW!zdeqDDi=X@DBqV+7@gS@K^RyV+UJM7X`THVOJ1Gzme)~l@ruCPY z=aG9a!^SB3E!bTaHs6J<(Qx!W+%*O^8gPSFAH%h=obOAxcRASYgZq|;weMk1ha=h; z2m3!Dk6Qi_cE%&Oe}c6Ma7b5Z{b%Gctu(XwdDwl1Qh6C2xW$CbWiq}}>T0QUOW(<} zvcZncv9&h#3lE<+W6JbJ^XJZapQ`+}d?RzV8h4x%_Nc-^i z_V$i!M;8BjpHjAFHs?`iE?IAkjMtP}M=I@0*E>MQ>DIR`*2_)%59{u{X#Rp(a@;*CXdON=E5*dQ!&ENIl1MZQe)k-_LWi z`E#A=3ubLHZ|2U2O?P&kJ#Ue-Xn~w=hw9g%_Q&(0#`$w+Et!9!j8~H~q|z;&KRNBc znSbr6GW}@PZ?u}1UVORy_*3TMI*!aaNajoL$B8mNS?V;YbW7K<{+D%{mpMKCHP?{o z2djRA)wh|BYFH(~rxCWSnl= zCU_idem*QZ+?h3ba(Vi~^5oxsYBWDF^z}uB)B1 zWZg+JUPo#@sn)t1$~fJoZuGycJL{1DeN}ty{WA9Q`}J2jN3}aj?bAMp>srIj=6tTq z+q%DJ$oOojD%VQyZ?rzvYkl4?ICS2k*>h)2o;z!9dS?x}Zv$25K(+tC=5)&Dyzy`5 z{Zhu?OZ_C(x<75_qW|~T@ptnVn%8b4xptjv7vfgGg-dbuqsn&YC$oRilulbqvul3{~vHbl7jk%sL^W|m2^z-*t z8Q(2+pHyqTM`Zk8thf3ah2LJ#BmZqdb7>RvoVR4XaWd|bT2-pG-kLH_w?Dd`3l}X& zKOUQlZIXVt?5!TmjBPKZAMP9c=HtcZdalfum-*8Bce;#ysmrBW>)j{gbo-K5L$boXNkR$NH`Fa7LQV z`8`>ubv-VTagWrsQmym2MaJp&N9Qr)U*|F0+;wBQ{*F36JGOn>^!l%nU2e(q9oJLm zFIjJxj7Le0k!r2Cf{g#;dh(Igdca!?djHFUR^DvR=pIMmaaro%|Brd`ggr@h zPEu~$B>8+FV>ZvJN9JhFdzXywl?tWO?LVEbJWn)Qy+r~GKF~^wAy}EeG zyu)O?bZV(|`;YUkJ+(FO1l2h~o!mB|d5pt(OTU@-AQ{hC&Af79TNAIZI@ed#w)NAA6V9voORmFs8LuW~NVT2^3NlW& z-+%wt`uvcuf34|<|LeOxc@n;$ZESYi^qVGr>t~NOoAbE-lJ(A#@%d60NwwCyQpV}_ zN9#48be62R?SArV|lp|HS;C&-b$qm_B3H ztV5((p6zEfpHe3_|2$is?d7R|Nb@;g{*j*>+Q!MxC`0-U=qEo|O0C+ysyyHKAKEcA zeV#98dotM#> zUhUc6p4kAN*__syVLdg@Y!0eiKfP{O%lLMwyQEs@_X+dX&jYP}>*H|xoC9aio4qK# zZsv`djWcGH*;u|fUfQPaYaf>z*xpZmU|dSRJf=T+=iA52Pu*kMvmIly*|ss+jzQzI z!}wq4%5wE;nQWYqpWtN+#+&I*6)uzKB-y9ux4n#al`2WK&TqPm({0Wld>z3{77NoC z4CLpbY`d}kl#Ci=s>wsLqqBpvvepXOF>-t|-jqM(`yiQ5mwme4?J~YsDwJxi_n3^+ z&Hsa+lV(g`h;^o=>uj&q83z%NzU8w+oAY>Fw_E1b<(BmRT`S|8rEZgI zt$VMG(=GlF>;BKzH-2*h)*d^^3GAzm&!lItR(h|;H@^zX_2v4xE0%mdEFLB{JG!a`LsUn z7cAOu;p_va&sa2j{=D?shw{?X{h3Udk$!eEKaV&t^mPL0LUJXt^QTVLJ?&+_7p$M*du_bE(n&<(s3|GyT@f>K*xPSNnLZ zrj*xZHix~keojW|$5TVbA4`2E)jGd#Wt?s~KJT_Zj$7w9Yu-#bMLE4uYS<`sdv^Gs z=4*$;TQBbiT*tg>$vV5qc!t!0Qmu7PlyP$%ejguh@jpLqcpdhiKI7m6@pwIn$7>@s z?9{A!Dmz5}8!=?XK?AabvV+=(^vkyo8{4tm@NDO*UD-jM@{x2%zm+nFsc;puxlSbO zweI%^GH&Zps=rk0d@LEK+upq2$;N+tKC8?s*- zz=~ZR%Xf^_hW1}-1Fd6d=fEM^j`Y)@)E;ItJ78 z8Q&}QfK==Lyei{#Ydwy?zdwi0J8bs6nRC;7Vw|0sk}*b28K{Ommr-tqd|r00knP_& zctmH;$aeN0(69fL&h&@kn=X0YUHL|y6v&*FG`jgFcry@Cz*4L%aWZZF${9Gf|I?t74oNlf2 z9K+|4-<;=WqgQ)&Q8jreCqO&XG2uHVS! zhi7MIz@W}-XTQnvBd2`bOdr){v*%{A6J$MiikU8}99h3h_UYq!qKq$)@}*kmcZ-bE zt-$9shp%h?{`|I^HFxg(Kg~){&Dud;Z&*ue07{LxD5D&?iv32WFQ>Op%61NHp3I8b zk=c!#XCsfRVK&!M*UGh!QF=b3WjsY{O{v!T>>=ZH+kl_9m4E;IZCgSijNzM&`2F4*6=(k?G8?kdbHOOj{l`fSm|n6~ z&L=H2+*m{!}CG>nAT_4QXGt--z9E+YKHxHaoF% z<$;5i9W38Jjm{3z$D}VaWX5LOGi~X&pjvKtzY%RqXS3OU1GB>h4H(?fk&_SK!6ULA zTEA?2=PC!vm%+}F{Rb~A{qmjHs%08*fD!gw*8(=c4*uC z>HSPMbE?_g*W~`{GD@$CoCc!B|9_;t37lM2 zmH7YeeQUkit9q|qs+V*+Yj+m15t0f?NWzjdAwbwnhorMWNSZ8!O$iWIQ6i$EqC`PO zVIYDcqDWN0pa@YA8AU_}XAotK4k{|j?|a^oP8wV1KmXUCQ}5K$@0`1zd$y}UT$~wlV98n1v8i21dnDG5x@Gk>j1!BJE+!OrF*tIxp#{=(N zH-r9m@|N`**Ggl;JahCnR4^|u2wr!DZ+3;ZeDGP~=ZGU!1ef2$j9u`nohmQknN9+s z+;i!Rj-BzUSz{dEvQ5)BDY#v2Hkt@*zU`&!EZenf2$nP5S^kKGmF2%EUGQHS?K#dN z|K$$;m+8y@ByBG>p_J&*{zCIOJLxBaS@w6zdP3tMDEKbQAMfu!4SqlH z6(Fvk%)Md#SZ9XyQ*~B&kNf#~E6?p;wQl7`sg~X9Dt()5l6IK4v0l~Sy7(TJD<|iq zor!)bHLBXHtJQT?DP~s7&$1GwYBNrR@2uhyU?Jgcs6yDv206s zFRC(=cDiJj67i zCpZmGz0RfTQDzo&Lf4tK+O-=j*JXN7W_8J`-tJyFE>RnfQd%VA*>!fU?RzpBGj_eL zie=urUPti0R2RQ%=i7{3n#*MTul}bo{vUZ_>F{^9Dqzz+l!7h2q-?j^I-r@g%^GcY z*zLB(`;oTE?>l*?Y_q8CE-*9rY_vTp_~lqc-6K=JmvH@BR{n(cm{O>v_LFp7HlvrO z+2*hC_9**aY2|=IdwRa;2jES>wFJ`?c^jZ~f-}RiYXw_MN{XY1G`P zjGtIdsSFi2Li>5hpJ{UebQ>N;gztGLfslbnup zcMk7{;=%rRU{NI~&@GfJZs)te?*qOJ#N~b%T(0M%{man(o6KKQ=M!YU?3=NI`Es`L zVfH8^WxnjOvf;lQJ;zo8%=_}7T-pGBB5*Pg(|h)T@E_ia=F2BH4XNjdp3Ikf^q2L$ zTJ6zi2d^($!R=lzxXlP&Z&1N)Oz^twUYRvNS~MPTf?0E><10s(C51Bf<*n!F9Ia0qnnmW@?N>{U^W*TvmUaeVc+Ky}1D%g~6l-{&v-3=;8k&L^1H6HWy#^j-GHsOKGQ~FAP4)>V>2iHW zr=7CdVCi}~>IvSLlzj<3+!Qd;{y7?X+btg@vu8P;J-1qyE9Xdasvb+%{H&R|)SIK) z)hM;NI#-xrPS@8cJ;D5gQq$B$>KauuzIB1+nmCMYbYYmplcTA!(1dnK( zY>%kR`CeJ)f`x+=4aHg~HHm(|*_UZ`zI~oGU*&^IfA`6ifDiA%L4KRTM*v+w%%eaS zZj5MYez9<<{(rP7oZqHW-`8^i=RNxFCuBT6d%heIBKW`4P-*%1OzHl)N3g|yx5=lKj=CyF9c@1rZLrFwq2wjVgP67Y2(;!pae@epMJs(_gPx!`ie`tedVxGd^>-0)Ma7Xl9DfdUgZv}3PK9g|} z(~0i~>22DwwRiKTHS0I@&s({5C6txXpp4(JZ4a)2==rbmtTLa-^UbdtMiR&Xak=Wi z<%;*q1CbsprqeZg)xfrh(5Ue%SBr30+@V%o<{1s|G2V~yt5^Fn%GX(0xgCh;_VL_U z-*XN4M}bcOF}3Hm!vRtM3ub1i2PC9>^FC*H{Kq zHx-^$Zpu%aVs_G5JYSNg?d6>6THWX%N@q;J#O5hw(>L3BXR?MlzE>qa6Ybhx>GtXB zRzK&->gcC)$c3Ke%|=zB>y+oyoC$X%<@~a?#^{eKl?jW1eX|l^%PChGOzL|Z_?5sl zKwR#}z~y=}D)+z;J=fvo?!RDtAh23}pO?~}54c9d=S<_1XoOw18f9Id(<+5J#$uhf z^z0_Hxt3DPsAKP;aJMrNs(aLpP zoh?$9qMOLd#D2WKSLuUlS!4f-Nf06sGN9sJ=3oj zZ`!zEQ_!)FLuhR1HEyso2(EB2M})?5UnO|nv_}T(=Xmf_fir-Z?xo;z?Hsy(MShD5 zmYgtWdGFFCb5DX+ZDj*hvXCli{IN1RS~c1SJEv31rA~ZZg`!Y9^-dBG=BidWnXj*n z=PhGpC7`npdSx)Fho68S0Nwy%e)4;RpBeL__2`BncB8eM*7k4h-x$aod(`{Yy-Mv- zmjthE>@khzr?gSmDl(|krmIzr-{^L#ER(6W7Puu@W4@uR)w(U-N%o#y2?#FVJGg(@ z34RT5Js_9NYu65Auk0Ev%B?wDw)AfnQ`Y>=n>TG9HGXMWd%-*YUm0a(OpziQeP>tX zX6)ZPxNrCac;TCdQ3J@2gx*wexh{5Wc{8m-SwzuQYBY*7^bRaswB2*Kj``7Q_F30xD= z()?n$@(pZQxjt=0roSCRCoWdCQLZ*F ztq%Ux*d0B;=i7tNp9g*%uo#Hz?-X#k9vp_wR(dr)GBg+b6e~v{Ae4KJ>v0hsD>c@s z+e5kFKtyjh&x`BrKJae?-vMHJzXg};(G$ade8q03_jugT#TXq}x@z~TZ|X-B7W4VR>yeM3IB(+=$d~jek1aF`%`r}$PGoSX^iI~6 zMdXGx!S<_XW@m~_*@y9FgZ_?+_&acJ$lp5X$L)9__?5ubK+NCG;BpN&4i+p~x@5^R z=`+3a*(@~UTHJP-@f31bI~##2t0h72nV=Vhy$3tnhDz|fmw0X&Ovc0S!2b^D#|PRqfWf^?svQ^6|~_ zn*6fY;+Mf%{SL3)@31D?^Ig+P`WY|nXZSqp7reY*u;$rIT$(9~{ue8SXDzl*!<=I} z@P;?RDfap)(r16{;Ev5bybf%t1W4{XgX>i{_zYkc5VzAZaJhPhS=YNpufr2$)cExq zS8d*ifpYVj4V$)0v-K>;_*}&J+YqRanf_lqccuxif<95{C;zd{<`IU&6<-l zv#FfDMX$#Ag^n$Qn#`nQ=GY(BuxoIvED9AD4ZVoYu7e3IJu2tgD5gd!%}kJo ziThPG0!rFTqV<(QXL?q%y+T(QwklJuMxe7TbdC%Z&l-^q&D3_GBdCq4gqQZ3%~3X+ zD!aO5*HqI3&bRK;Y=CrADA4p=9F}i6{KxIT0elCr6NtM zcSlgZ)1`dm0e;^8zm=~vO!?}El&=()Z;#g4sM^Bv?Y^`U@ICE&gXKFOd=;=3h|Bj) zaJe=_>&$~g><|ar?>H&nF7;I%=u++vRVtMmS#&!0TgFpPt8SnHn{^^-rs~+=CGd|z zy*}7@EqDvkbh$tlZ!D$R+q%~Hw68EfwZu)=d|1&MW!_tDeNpQ#9$cs1QwjLZJvrDf z+rcLT(}1{KbG{$^%=mhL*luqQu{TJ$w%~y#nmH8VuZFts`_X+favw_@PrBVYUzf&U zT&+8;YTueTwck!+#|jga7L8@$C;O^9JhI>n}NIy0b@lX*c8fwWZpnQvX*d>nW|DRGH4? zJ<9yN%1kytr*xG)RewOaH>unV-9rD{dsWyjcT(?lRK3g>Uju&<*bl_*GViIdU3T_{ z?efOb@IE-74y;B+yR~1s+g^27DB`?kigeTYpkv&V2*;9R6_6+rBh4;pm1^xU0+*nIi~drIIlh9My=b(zCj<{?Ybazb>!4P*8iiNcY5&-c;~XSoBg@hH{`CWK>%?_55FD8wL(6%<}mVT2|? zsSF*Dg}Mg6i6-5Gv8>=&r=bocOYc$GEJoUijDtVLXw1H@ctCfjZ8^A*>u$53g5mBGlRaN?P%KW&}t@(Uzx5m-4M_kK$ z)EL#NT2(fbNcO%zY?q$>gYwaQ@UwuGK-@0R{vd3ZXWtd}zcV9y*^qYG*niIAm11P?QN_!(S(DH$sj@#A{doa5BsYaWOO07=*1HXP%UYr>^MEoxpuC%u z`CFymW!|C8uPI&Y74o*5(xdWhcXCnt>q>nA*96NenT;775oDB$tCL>h_Ler=JjAv; zycSGr$F?-mb*w^aw6-@1qlbLAL!ta`$Rk=57-D&ya}ilvGYxhrqy6fRmG(w^lQ-bk zG{SM6)rg3d@r07+Vj$OcyWf=O(X|Y&oYh#dXJ?MZDyQt(uA5nEFX49zYruq-=9x#B zhZFv+GS6Tk*lf?WyS?_1Q)eAv0cpF{<3V_5)w`#a#Qc1(tuG=1%lo@ZiWApJ^MeYP z$s3g(sivDhRjMuQ3(~@SKOFXl$`1$kHA}%)0IPtwKYSist~a9n=_^C#C5fF|usINs zYX^QVj==Y+P4s~KS^Lthe$AgO_f6{wC({DQVCqwJ_c{ezX$sWjr%D&lJF$fL0*pe>%8a!^MNF zh4)i8Z9Z3~)ylbO@!Dp?{k;S|W?G%LD@}K&*@_72n`~jw-@(rsJsDLrNO0|m__!82 z@qG6&@VkJ=ftZiup9_C~X=LX=aNgnbd;bM1S8ZDvOz$oG%`2;(Hr0M}hk6=9oj+3A zRGkRMPrD$`GgGNwF{!A6u`}C^^8wyZ7)8yGnC>km&bzu$g~?F+O;(xO&04Q}=6yb6 zCC|?iN7%1>`m+hU$}V~Z?^rwMd6%ASyzFgU? zr#5S{+2Z`u@AHhEj_Chu5B=vn!^CV69~@zKl=qG=lei`79yS8`$-z&K!bxsD{{-PL z`sPhOlQpcfv4r(p#CoG=o@_3M`Ke~By%^SO?K2+J_GB%55BH@l zOeguzgm(l(d%bt?|3(Ka5A#*P@Hk<(-5v|G-O+!($G+V+zvbH(O+ez$Utljt9gF8; z!Jf{qCV9=?ID0(pgxSz!xw5y79dA$du27WpEZH8ow2UMs!IDkB@8l8%%TKfRmuge?uaxH^NJtV6 zW+cyi!nY52Ov*AOK4bguGqF<~rLWTd^(H3F88|B?pVQuU?`;)0hxFZ13C9cLAO|LL z&^N*N0pA1SaqtJnt5sTLu%lcY)srd>M%8eiK}-eUU!@p#A6&y0IKyBr=?mUSPZe&5;`STCx2= zk17WVuDuc6-1CF;P&@c&U>p$BoeD13JN#}2=^m6bL-l57uWD>h`S3Lh7^zR>}cZi%<>|G`$-DLa)iVc{3tE7Nk6gtk- zup^@TCeQVFuFy^YJ2r5j7KrJ#g3A@h6}+<_4G7&xjwzN~TcA7BxVF&5q!5&}Gbria zh+ZGhi~H?X@a@3G5e?Bx59jB=eoE+^+kX)qC}VVHjGGG?e!o9@?t?rde(pZ-?*UH% za{Y_v#_kiHO~xk+ekLLM9OFRr+`69_Mw$0PzXzWOECk~E`3SgNuMQLMaBzP+Va1x2 zTf$5&wUtkb>8}U)kr?N@zGE5VUXBYr*B( z{jbV1@zCa|!f)I@ zw}XEPco2xoJED;mh-XYM@&VZ=l|L!tyMK-yT?&_Sp)4 z7jQ2SmuJ(9VR@`$Lpg3}eB8nD6ZSVuMj~PEQJ)Oewl{~jQvw6+xxwq@R&e`h_{}lF zn7-XEdg*$vVVu|6>a|UB*dcV8Bkg1Au2c5)YH)<=_3k;@gNnvTSA|?) ze^U|d8`BPzjjhFqgS4n910J$ojoBV38RvA*FWId!4*sC5-IjVtTMsDRg(_~>{b4=t zr5?*sJ^ujwkHBAmxSrSjJgnyz)`s=GI=aXEQLNtUx2`;!%5B+=+w^T(?bfxy>*XrA z-5TB=;Va)5{Yb)?)vfFOn%u;C-6>ITVhvBYnaMNQm7qH~!ktD9>qfLsH9Cz)VtR}_ z$)AG6KgwN7)QD3z!fi`fD3t5HQF^r5Ww*L!&J0}D5l$1`J{s&st6sm?%$H=;->&tU z-VI8frt0xT+~$v9CGEf!KV4nZpc+)8YR|g-uJ^&PKK4`Ics=+9`0s%~0&#tO>ZPzg zdLq4D*TCWX2s|L-`q*neYCmGCz2^V8k3eDcFVe;yjBw(HT9eDMQ=p(VW*(U`pMa^d z?gp@o)ugjT_mbIcx}C_Sv&AufuanB2;jeZGjF^m`FQapI24$JA*s%5cOC9HZrb$fA zh|#v~OhCZrAxYYO|tH0 ze{0pcRbEB}&dMWUeU^U_)>p6&g3kpO0E&-geO(VOS1cb4jWd$UBvdEXLOmd=mEEdG zv`?e2)y8L$#&R%J#FLj$sbr0+QEmfzq(m;8)q#uVSp9EGkBAq5-o2H8-h_6&mTBxKM@vRo-s{>d zT7lQXF?4h3bY7L3%qF_%R>l03zf}=3#=@5kqs(3SISqU@unvg%xfoooU6H@jP`~_D zn>JpsY~p-jrMDk5V~L1?(Vtc%|7gu*&_y(1Xspkc#5sQw^);2fJ}7d~w<>Zo_VN5O zccK69;I9C$0x|u!z~y=+imMtr--h%T3H`o}Na-aUZb#pxj620DmPrue6>yL&N#~ep z1ssS)V8^#B!E+b>$Kd*P8u&V30}#`H54c=!3?p9%{Y4W4`n}UB|Ky+!lE&z}6;|F> zc2jAm-eO|N2SMYjED4h3>Up#xH)9{qkJp>d4>GH$Q}77EQ-(j(wp*P3XR`d??A6nBKjDgl9B=)~*zD)94x zZ9vS&PH?&Aof`JXoss?Ta6aaTHL*i25_{Ie`Z5~hPSdzYxbT{+diP=CcG-;K2+*N1 zJXSfA)EH6r7<(SC$m5OYp%d4~Z@~WwybZ*B|fLee1!FJQcxFBeSAe3j|TNY zmq;}yTHT;7W?7r4i-GS{f(I|>`DHNakLQ4I2QC3(`qzQWbwd<4^PAXi8|`a?{2B+V zp9;-bfKCA z!~4Kt9*F4d=b0YQlX`y<{I9^V7_ z2mTE3V<0Z)pTOlBuAJL8Mlry(J*#j`SVYj(_@|WdtfXqwmSdyBDG(|t#vMOVO6GB% z2+Z0yD(eX0rSHi~@chcFgM2IlUjeKFVm`Kk%QYMy8#it3-;S++o3w9jWg2^_HM8Mm zuQGN9Yoq1miOoMw2bD3$+7?wr`TLdNxqErO2PW`i~Jpjt~)}1 z%ZC0S2}^D7g~6-~`7aZ$4S6C$>1as=yBu+=w1`Z4YphxE>Vw`V;$z{j2G`?$@NK|F zK+MPIz~y=}idQj05ly%MI3RAoBMTHppCrn?*be@Az% zbd=t6;+FcH3OrW`UG`G6SV|Yej(QXm)WWE<@Zi4vmEidYB0ADvtY4Go3#bQTK3)Qs zE7qs&jO3MgUOW#!u}!NYfe!Q4br`HLUwserm2dR?odTN}xIHp3rQKXfCGa3mdFhnh z%brU4cs>;`K|{JVnaMk@!UKvRdiz{^174%mL`CGxs}*KrJD+R=Gp|yK&X&iNeq8bY ziyAtsEtbAI{^Mz7??=_17*nm?jC-toTJ5oHBC=+6B4<0kU34-j=_4*Chw56lqlmq! zQRlK>VT$f9O$z>H1cq<^1p{S`eU-AWRL3)YZ)TX4>VthpML%NdSCy*4G4XrWLBr2W zKdJ=vGwnBn?RgUTPT*P~uE%k&2R|FOA9amBZ(YAQN^QAl%N(gvT9x?3>#VmWKJk*^ z^(GbE>VntX!#A(%;9Zr(FZR6U8#g!|y4#UG$%vV49mSLwaubLM{w4OMm>Ebfsf*Qa zjj!wL-5NVlz1_YrQB$QG>pZ90EY(Urpeky|&G<*uXX{(KFo*C7@pgQB0$EFB=fQ5I zN|dx+$s_HV_K5ass;oiWX=Ls3TU;jjD)!9sBsP6XyW8%u+v}73R(`+0CtH%zr|Lgw zwO8v-wNJx)-%rDO+(A8cQB~3(Zw3E1;EO<9kN*WO*UpnddFhSFz908T>T%V|RqIH4 zEvm?4Huv|-@YqedpW9@k@h~?kYKLuHi($UY%8-Ak+8bvjtSTZ0h|Eu6g^@@JD~~~C zlP;x8^}J>^!O3_!klWQ-%dlRjAJ&0*WxVvWO2E&w|2B*=nDBip_$FWr5cA!6Ao!WF zF0xmB{T+TH(&%fY*>MxOHVlXSjCrqwP42OR+l|TKRub2do-b7yPkB?YjORTcmjlb1 z>bkfQX7E0&@@uT*8`}N_vS7xkA&4Wb(&Wl%*J)*1xtW%@D5OXLj{Qn>4?VgL55*-q zalUz>$rzz0@S3tx%k7KpXSDe(9LbLRl-B>P?OFD5b}Cbs)jbwDS=ioMIp1k@j`f=C zf}{UK>ld{C={sI)JNV^n&#v!s>~;>EJu!zzP8Z^mcuMA`*ll*b*XhjlXPI}I8XpkT zI@>&puU9a#v-J-t`z~carR?+A2|uHp0o$E|UIcHvR^m6=6yt+p*;CRQ6^w8{&K*B% zobJJ)!F)m6Usm2#I(4m1&G4qy>{Rv<_VV~a&uZr)cXl(DtiwLEA1408?&b-Eg}7E3 zJ*(T8u&PZWUp}P052KC1B1Fv*OS0k6f4y5d5lt@{~<*`7U3!H+A+~Y%{i+hsDgSOzZk+@^12_tZ`I!$c*E{S@@w(o>ebd?JMB(PW)38qT zoMh}Lg-W+roF*N#IPHz-?c#Yko+sn#4)D8xdw`hU1K@JKgI=_6*tT)Y$~FBf7WZ#w zWEFeHbVKkM<0lYo6M~&F!Q5+=;5o+c2kW~4-UPG)F}CX<`H?_v=M}n4+%J$F5>|_+7xgKuo{>4?>;se)@^Q{n69H z`!Mt;1pV*^la6?`IFpztza9q1ZXlQk^t@of<&_pHjPw~#`n{sNQUI%;OV<0J3=ABsT)(`(E_12 zDnica`O_d@OTkwFtALoVOTgud>ucz|F5Ad@jQHFs><-H>Op>dE;Pv z`~$iij!~>B_P}f{W6%$Zx?}I0bC8l{M`&L*MVrC8Sgvee!My4Q*vd-O;cGebG|Y0 zR%QGUfxZjfxNo;xjRc}O<5X+-yj_2)1jtJ~UofHnCV2iYtaU(4e-XG`19QUqnKmR} zLC`K+B)Q$HFu9$(OTVRV)M}Sr7`(0zUX#W|3}>eCNx*F*VcPqZl563qx+*GS&viSN_K0rEg*Q04i$#xd)PwIo~7wXJsN*%N5d z9m={gjN2IaOC_M!^Vh-gKOcNCa3T=%wE|qOH;4AOA>(Y-hRrhMD^qF9QO3l6;~`cj zb}uw#n?+|IXN^@Up7T;f_fDQ0&xhXz|1R)-Ag23caJhz?cNp4`T)1*el!0#JRJ%o zjeWAtLT4lH<4!aB4WCRFR;FO#$z>_xdH5CLN(=8x05LjQ(ILM_|2&SJ-}|>p!0(&z zT?Ui!mH#{W;eZw(F4r7zxpqbCYVVNz1R{kjR!l`)yM{&A8( zNdUXHCMkB|v@Wp{+}rT)nS+v?9{zW<+UV{7UJ2;zfL*P-W?Pz>bg7Lt_06r$MXe~@?8o3S>OvmOy3JI=tuL} z(0%P8^q0i@Nv5>Zg30XW(5gHyc=H^Z05m^KMe#HF@1AiJAw(`}kJ(CMHWE%5#|+;) z()Y(7S+dC+NW6#lvf`tXeZC%t6}{cECrM;KZMHDMOrC3Kz}n<#d_}BL*xgL!U8b*4 zdXp>G*zalU{YqV9>i3c7Z*aUC)|{Z+%PCjft`~t{3S1VI^`EtCTwZC{AmODnbkMl- zjLGwiZ{Ypapq14WkJsLa-u^@Ay$;?$B9vwzuII0U%e6nUdsQO;o47xny=}v}QQF(y z&HX_ZT-usAm1`M8WI=u;yj6lX;p>zDzdp>iSu!Ty?HX^9l54b+b&AVJ=|sO?hoX=@ zkjVf*-A2w$lln$Qk4B2{5i5~MTO{17^RH9-!b5)Qlc!#Onlf8ZEjkQvizFGiCF5`F zk$f_xPp;ApHBGvaEWt$-G#>HTsg&T$uEw_Ilrgw*D$+20R{a z#lc0gk|eD>&cYU6>FBU5QAnD_>}Y?SU6+#xBxMu9;o}owkMOIQ#ZYxw8Y@(*n`73% zk7z-_hLKBze4|t~%6uf_>zCkv2L1-be9tjMzK@UEd)bh9N|AG9d>=j7{=)fg_2F=A z%?}3Er%hw>mA3JF%8+qLo9AU6S`ghF0cm0iCE6>ME;Nu!8gHn4G03bY$za7NKIyy6 z3#G&lc#-Vo#3hU+8f1z(-t2UyDC`(=?M}`K?zg~iJZ|m>e-zjU#N{bl;qSLb`rvty zemL&O2gi??Dxw*ycHpzJCvFEGlpu@AcUZ=g0_>D6gfLjCrxRU#pEHky5-!LzHK{=x^m^#x`9Y-ns9s~!uH>*&CSkz3L&T6?C=3b6s)^dnW9PgZYf@ewK8>{H=%iPipfM+P=_P zjN|emYYI^}-yjSPtB_rTY5M~HlOU&B%nb6mYhK3^Y=2itgycx4-&|LNt$^L;E6V(; zqHkN~D6^BrVVb!Z7C)i9CkQ4aqQJ3IaH1XGeNCC~v(3GheLvM_?a=09%KVgaZ&vn2 zrPIxm?Ga})BiZ{*^E;+@mBQv&JkvZC1HeY}Wo`bCDpfyo5EYl{@5WOU#CnO<7eb(Fkd#!UzqkYYD$}bmr9iDEWZjS z$Jk?w973U~QUXU-__F7E#A9BZqCP`LF8bfD>ad^QNk5#%dzs(A1O7bl0ucAp(-VRb zPafqJ8M==i(oYx6C70P+x;RNuzH2=#2X=f{OH!1{54grps#|rnU!Te6##tjg*J6Wj znJ5G?ZU@~X#p-T(S=u6@>!VM2hic2ywZZ$O`~vOL_)OU%Y?Rg8Zz2Jg7+3@nyiRo& z+BksPN4m+Wy6QdNC4uoxG~<6Voij<2%84PL3HP2-uHO2v9`;bqGVi4xz6btO;O9VG z4}SxfYj?DtAL{RbN^b44_!xo{R&F_0>R^}pQ5bhV^+u_Jd$jRpO)F~b`LN!t(pJtX zN}7Z4PnzX4eY#$(+u?RcL&(=cCboD!KLdOXa1Idj^`lhC*E{qu(Y}~<>tLH$xf?J^ z=6=FV@$0nlP;IJEmA5}>nO9j%1G3C&%O(8>cSfFt>@{wrgfItC;3z&I!V(qA2Q8{O}isU zEAq4R&8scCGW60mo%$-vULMl4gys^Qe1&F{80h%5@EDFOop7zIwfQ#V7J=a-%Dj&e zX)@ON9DdP3)cE)h5vwQ!z5=h3iH=9Ob{F%~pOpEg%K3iAKha%AMipAey3D!)Q)R>{ zKO{xPUYRRc-$ql^FS_o1tk%pae_)zC$aK5lS6P@Y9k$xSqxETtKiAdfSaS@4rY&ZN z({6Sqf(e(D%t04heqSYi=eTb;RZlXrDD(X?6WK-gDdjLDjpe<5uQJb< z#PRkB>!(3kJ|`Pj28Wad_ivJbBl=ZgXqVP8F{@g9R0wV{oM3|INUK~W zfg)27_CAKERZceq(+W8oRKm&XY?iS#R*%*TLSc#LmfJ!;?t~7?vS8eQ9sJwC<3P;E z55eV%{j7%OZ(M_Cz(F>Ol?r*MrksI4ca!cAcjG36>iJP$Zcx zANV*B^L2DCSmfuFt=N%Qc+d_0amWF`%? zNF<4$#(|M!X${C3`^Sd-?SX#0FWv|K4De$h=I=M)at)_1T#2%hjnk_B6;ivxUEhVM zU#n5S&fJ4CoC@{EXgkqT&boH3Zpg}EZOio1czo{|7xFQ!I4JKN5562Y6NvfP1}@ja zXx}t+UX=6VR;*cnVW85g9aznt{Qa^gpLw%3PH)vmJANvgY@~H7jBJ9hE!={IktzCQ z-C*Wpc8uNQLw@!_FRquLfd41(8W8j2R)zdL8`*b;@^gqAUTC(xNzAr0uh+)Koa;q9 z;pn(22+CD)0edD-iRs2VAb<^yTnz^2Tjj z!fNTeUsU8@61Vf2*O`*6a9%YV2RmD1rJC)09STjKBU><;fC?GpM?+E9+>*2^dj-s!Ry^HL3^s&4V`rEkMlg1n_^wZ^&(tC zeyeA0H!Zc$c##p$VU}XWX=N@JD-QF_#5uwJRh}2O%U^^}jWR4Crk4Si>z}mCF)O!i z*vg10_RS-3e&z~}K5jyP90WTrie-m^h~9FZSLS)LPuT!|8E_>K)B7B_Tzye~tbb6x zrTv7Y1V?<;_FYClm;;FUzDCCCcd^_N%2}t6K(bGu(1I<9p-#l=+IwHN=>LsClG+v*n{}Te`X6?Y` zjFf>7$jj$~5&VK_+`;5lr(Dmeo5Ff3DdcexsXr1u0f`b(vm@6?zLm+=MS8L7VYwb@ zo)$8=`-qUgTc98Br}lt9415!a`773i{5>1V53dZ7AA;oaYu4jNzW(AcujRlG0l9S+;d z9&*0T$L>b!;h#(uxJfrNwl2s7SK>srq)QGz5}%aqQEXa0?jt=8c0rq6w#h}6C2^Ne zlKwU_oVi$p-Bc&STcb{#L1?c0nmBy^V@={pJ-gn`N`bUQTW) z)WTVT((DwOtB$d&IPOW=i7_d+NMf+~lRRb*teNPOCfF10E^8!tW%Bq2pnLGP6-_^Fdc~N-)Ic$|Iv4a^*(P%{wnmG#~d=MTK1a1vw|Sm?-L|T ztnANKaLWd-B#AbY#;jXJ`TP+y0cyW%?6PL8ytHCAF`-szV2xg6Gnj5Enf zj89K+Cmu5aZT!+KJ4EWpA;s*EmG`{z!q-IF@4=fmSMUC}c3;=_$b8DN5_NXAqwHlp z9%Q@ss;0?P%<#>Krsni0cem-@#wPo7ig;IdW4g4>y8ua7=c-GSy;1h;x;inxYuiPk z;IlCYB=0!T;HGjVJJ*uq*wu|35rdPVVO(bYr?xoUvD#g1O?5`-70GsMvsp`gG8nI0 zlaH#*sPr!86Y0+b$AtAiK>fz`zZ3kUz$bvX{+|YyYq)&0bpF)`4WL%;T=Yb1fRlhR z03+~4ZG0V-B3}K4KsC!5i=1}D>_F~B2Y)@M!>&Py;UqFSkHoS|Wywo&7nW+FyMIB* zXI<0adN~PvF0cTI`MeHXuC6$KZiqdpYc#@Lu=(e-gebnDc3>Hc#6`f5WEMX9G1It$ zSvXJfS_z8woUEBA*;$IDrU|E!F^mLHu%%d$Nc<)yLV^*FWR~;D5$86whlxfnw6^O- z=6oj%xZAxb$onnV8Mc`d%j^V`}u#-+CB+vEW2nZk5CgM9rj zv*=!&+^)?%gj_L4hWlpfg|*#K}XwhTuA@<==oCq*T8=V`~isR zyDcI8*dJ`Dy?rga@0DkVUbemOCJGj}Alf` zo*&CwTfr{{b^tN`JHX`{Cf{@S>i)C0trg=pTG9T^q6(0j=(%5!L3qZGl<@$pkQEbw z$3|D_vMQ&6D!B2o5B3SJdLlH4VPccpJi;QMS2_r9;D7lAXYRETTvEViHX(OBX*mJQDPTrQ zFkuuhSod4@xTI&#nJ%^bjAdOB8Y?J&&xv6@FQ6k8kgKF zzq-N;>=y4+Vz-#_#f0%3y0ctIi=K(|MjMA4C(zJ)j^)%Py;PG|jr3{bnui+8N?D|? zWT|xvY;$vMK$+a6Z9o|dVH;4WcjkCU7aI~%8$jVCZ<$YRl%*y(#}%pHD&P`L4hLPa z{HDeRv)(S%$Wk@R<4m}jBdM7il)gjjKj9u}95^|wmjTKh*UQJj?+3mD#P#wzxLp6A z`bGc74fvo-8op4}t-K(4Y{mk|1Bn0_HaD2YZxXFF1=iVw?qp3!BioSj8RNE>Lhx`Dn3@P*Joh=9+w9tI(Y$;@v3HwsTf%re)9SbA$qX>lt8O4?mZ~F; z$!WJcX4bgcInw@;wtkFpgV5>*J6X?pvmDQfoGLzoctwl;LFYKlht4)$vi)YJq$~z? z#wIfIMV0VUj+}kgtchfztKzxeB>J$-UzN85GdRz3^jAoCL;kxoJ+>ABt)}|OdMk6B zd%T`wAKlgD?b7}qluJkP=j)^OoDk~5JLh=n0Gh|y9A%lVv5(+b!7TN6o6>&_gwEW% z!g}nB>Pgn2t>BjfR{?Q7{#W#Uy#B`bcphB4O1#?UZQ2-2c|Bjn9@q19un62`8F%Mf zt$ODue6v$lHb)RTawCCpl|)UhiejDYp5mY6o`U?a$sKTXdAq$&`Lh$UQ6hmxF6Gke zi8XT{P>GK#_YO=D{B%0ogd5qq%8EjPj?ljeB)CdnSe~BFu-&CR$AO;-^Z{{st{)kG zAMamw4~hE=%d@P1^La?oaq%TdmmmdmyB%qHLAIM~ki1hFTh>=C$ooxu@m-&NjYN={O?w^yIzonhBjU!iiB z*)lmDr}rvrlb)_8*^9mJn|g%$i?UXlAJNWY99}lszfunQ*_#!i#Xm5eqwMBHqhD|v z2ncI9xGgqzZwT8r*EQI_1` z-;xB=p?t?gg)pHmgw&~Q5mHiWbmino(zoqC>i#8H?Te?T3Z`Xyh z?X!Hh+F~m#sf;#R*C>6tMv?U`ZQUeWGrU7Ol$?uoU~^bcd#Q(5-uxN(OTd3bbt7`! zaDGJLc$C_ibHU2>8zPbSQe(!Y#*X?Hc(xpwOOYa&9URh4F@5qlV_-{2w=#OLeR{!H z0IPtweY`PY`wXYo3F%7@*`dDWh=Jg@78ZgT&m@iA^(s}?{3kTN^EZ7Bzu|XloQ!1@@EqPzko(^tz1qfkSRJ<#Zunlb67p%AXA1* z=#S5a3Y*q(WPmOur`IxNN+hdlIaM#GvGNRV-ZLlW*?iSjvBr|2LsU$Ty`bcR$p+w9 z{Zqxv@db}bWqvGdBL`m;)=wYhkNfZW;8y@w19APl1TNQbayRSf_BcDmYhpHiTwX3& zLKQt_8IPBwigHwkj|-8@oS3X;$z!HWwn&<>ES#aZK^f$yBrQIbx5QnXKx@k{SQ=15 z;3MWDDI(ixQrjk*=U{P_Avi-{FH!%yFA2-hH8$i^=KZ6=7XwRyxEz;8-^c4$d>>rL zM4cPBXa~Z)w7BeMRL=<6S^foUb|ZdX7j0ZMK4Nmk=Ki%3%ec9B)20n`u?BAp zvXT^gM!{wy+PxWl#*QY5@AOpzDp1r0O9Q38Jo()rAH5MBsi)Q8=L6e-n2*Pz?*}6N z-q3T10yn||=m)drz}@1oiEf!H`nhRb+tf;b&f!~+RRiC+dbE29sw`dWmN{gT3YXz(e(3?MGY#_0RF9D5@>*I;|E>)$|dsI+tM_odHHl|K7fZ9LmVpQZoVtl3FK zG&#&7!zn&F#66GxD4}jTZIdYjm3}pCE{x8wPNpkwM1>Zd#)@5IN66>ih!5fO$KWpm z{|Ur=z8QTV_s94?l+R#m3A4qXNwK!$8g{MCq%^Uz*uDY{zUaNqVBO@lJEC8~_EMqw zh5m`)X8iDd1~voZdy5S{RL3Aa*ruASPd*m%J@RFv@!Vw(WIJI8;&vz zVQt~9h}@=+P`Hq}2(82cDXT%Azw7d_KK4T|_LKV$@IM2817dzg^o0DZ9vU|l`C+X& zZ|mZd=4?6PBx$%^>Z#B#Y-X^}zEn;nnehee&ds8=;+P2XL_4J8_KEH$jggt~PUVb( ziOS8I&IVb}A5az^h#*Gg%8n}R`&IP)@bZO77fUy7;?&cA0`>y2 zc;G+8v>~y+^Io=$jj}vss+i$$sVUa$20RbQScfc0+Mdo#ais3zlUBDa`XrZ}mZT@j z0St4rKdHNl-q}F1@g%38!TKtFtgfhI^~;L=mlP$q_FNT~r!pa|Pbtr7;O77vfw(+h zkG}uc2pc-rMagsyuUJJwoPa0VLPa zh#2ph;7(5H(h+V4lK?xb6rMC3eOl*LyDg`OD#L{&^w_CL4nJ6)z1N22$xR%TBig_x z0aJmvJokXhHTkSi&blMI$Ky%DG&a*Z6r^Pr4jw^t;BTB8u}aRnCcz(r%A0SV=$)l&63d;j_79cXY&Dyk zt*&@J>3v^R{z-#&w~^ozfhj;-{$6mo?igk~$K^jdPOsIwk-4vc0&(8$%DCHVO^F^R zh3?GsFsxy&VkBkZaJv=ylDt3U2%-+)xbvqgd2O0PV=)^M0X?m&jx%79$d5v)RqqSa8y;4r$46!{Jycpuvl7If1UE zrrqt7mBrOXj>r{}fwjdI^$x1WBRJ=~M;~o3!tg^Lyc@%E^ucE=mu?5Y7PtY3%drn! zu4R$@zIsR;LtGB=g9%EoUws^f7Yd87nxglb_eab4u-)2-#}Ye3F<91|>7SHqAp6Al zYJ6`KD&3hmwd&|rzvxWJ+F3v6PR};j)mwC_y(HSZGd0Sc8P-BI-+VNjsservd?4h% ze8iw!F%|qcUG94@P$Sj(4nsoMDPkfm>OS~ThEaN^l ztIbXu$5_Mv(Mq6bHS?%Jqo07OO?p>4Bc7=jO0{#+1SKsRQo@CINBz zJ`XO}&5@mB=s8_$R~=Hm2{L`{R?7lc|2<}K`y)4+=@Xu@!)tZMqHHAx4>EkTsUls* zB=Xoak;AMhH^t*TlL|X3M0Rp7A!4N{t*B;`mS5tWa}Kho!5Sim2yyxnwKRqa4;S{4 znHqX(Z8a7!yT~?b6o>1bV_y^q=o>6j22WA_YMq{|vJQtTNMeJnr3_jul0yXsUd)UnCoRXoS( z4vZpkBkSV0RBl`^MSSdnPAtcM7W@I=At2`CO>nt}-!Jqs1BXmVYxF%Q172JwrlWeB z_XftX1X^M*gUnCR5_%B!qA7$8bR0f+k-cqQbA(HZ;tsy>F_6S)~2#wX> zz$R$)eQZv^M`hX|zo&t(0nPzpejf*yYxw_&^r zH%V5{#B3JI)#f4{{0E2Bhw80k^>%#@(UMUsAgA0KmaA_1;J6qAz6dx0h|BeBaJlwI zcE749k7wK;wya{ll4+L`we4{y-s`G8?(eMNcDWPWUQ_onEayF(HttJGp5mNS=eHLU zUIT9H#T18G>U6I?pNs>{0c78n0AN2q%Oj{s(w&VaTS?todmZ_ZwcM+FW^{W!=(8ty z6D8kUGMA;NW4X{Cg2^l#-cpT+WFpdGexD zr2Wq2p9YmCKTTg_IX_T}AONEDI<2W{ss5zm<=aXvL0K3~D7T08);nWRFTNi9V&FYM zTyM{T%Qd+#T(7L?erUa|*}U>R(k4aPe8h;~gkr?!{TnrXVsFZLAl=QPg@Z-LLw!FM zHHALYT2wdMuTOMhrO{5~7%NvQzIr^kjtG0cEXdHhg>V>U6wl_WU+R4gsR z;h6}gdTq$7(9hi+@_Q%z#B#(}!5;^{3&i|BbX3Ui@x%C`uU$27Gbc$0Q{syj)8Q|* z2tdDdjq7vl7rgpZCY7odvx1wGgJ%gAVR?}w$I_)_v(xU>;o_2)7{|2hrm5-+h_N`Y zkjfqD9^*LmVh!fto($4wYHjKqXQDrf6&rhq=yHktprS^Gx zBL{rx)JIh6V`OR~$tq;s+Z8{ZRqb$i*akhGIPO$H#olPz_JT|cC-ziO32!5%TcSqP ziBRP!wTFCOn>Z@f1GT06Zk)ZG|J#;sPuAJja&D6SDHUjT2s|Z{v`g<$Z2Qp+hlZa$ zVLj(&4UXS7@NQrd5ZCiH;BpP;?;q9kVyWofn>4cTzbiKW^WJ9}FXXA{T$(kV1JuP;Ir@=kobJxkYf2eTyOh&`J>@M(HDv0^rP%G4!vd4=AfJ$gmDPTYJt8Q~ zuaw0!CH~A|F>?2X<#--G%kU}d`LDtM3cL-(<(NM^EXNDO#4*c2JUf=*UsCITF2Ubd z>z|7(^8t>$U5XVC|J=*8wO-tbwN9oAOU!@5G)P9fhQ=AiBW4EAe6#tFX zQ6?ty|3}%G07g|^jsLwn@6DT;OlBsTB$Exu282Bz0t!eF1VqFLh=??VB`iuvWKp#C zGb$>zF0oaMt=4GW>Sr}o+Yjqf>PqWEYOPXNY^~MSw$y5Ct*!sxdH3B6#E$L%#xw6E zBk!EM-+NYq_(epl@f%y+toNRt`!wHO@MXsNE#MCVKLQNjvl}(vbAo;6`hMqr;kz&3 z9FY}+Sc)I(0E@#Vmg3A$!`5BtF(vWD1k43kL^1s$E>^s}q)Jt1LZvP?e~Bh^5Owaf zNF{c5^aauBGvU%G-^$@EI@O!&o)}tyYcm8bWTZQ^!H4 zLUJ>6qnOm_s$rq!p*8u_+3ChbPQYnkFfH(76<%Qf(RSXpL%ywd!~f}a*hxLj`gA+^ z{{asIrX5}amy+vTv3cE!)xK$=zWWPe!J=w4wJ??}!7_-xLQIe#x^XhB zWUZW{&c&y%wC_C7uuJn(KRqkwnF4+?upBV_>;ac@OOCiNYd5u?-PbRfrYmG-TqI(# z7ejnRfk&0hlO@S;>K_qnXK}St5FYZ2RQSadF)WF}Fp+sN?x^zRs>R{VgGIQTA(L2? z-__&_8&^Dgh{V`Kl{r_P5gx@!yP_zAgQ1fmyjge{Sxk{7C1c5*HZc!JiUsOnewf}T z2;`u?se>@Wf9hdf-_oOPtBT)c{)`4c1~?Wl^}P>VN?i~)e0*>}F#8$nz}B{oK1(g! zEFW_HYunY#S8i`x_aaN0`EJa*7Ei-^ZZ#ef{LSnYZ{zqFKAr<|F-d_4s*%8uAuodbuA3nX2|a?$DGRAbi{K}Bh?}lC6Gdr-^v!m-D0k(o|o6kI!WK2 z?Y!bR)7{@Hr_`<|rDU{#Zlw5H_bbPjr2St5! zn(mi=9%9XWgR3tQXUoH5P)mxXHX)@^EvaIn0gP35`!8;JO!Kibpd;;nFZiRtlYrsl zo#1{_BI`6kP`^(rZw!e%$psb#Z7&PU}#Xnj$FqS{s8D)z$ zA+I=Dn#jmG-@3_mmaF={`10M4YyKw9^x5^tM-%vRU=?8aJ3IKkBalyg)Gw}-geBPd~P;?WNURMn=k&o(tnip&|!66ryL@1iY{D&z$r__Y<0*Jpnyw zuQ$OD03QH`pV%>)-(370>c0Q)8M^krV5s{^&Cim6p77HSekO1>VEEY)d~fcN=4s{+ zrXcG#uiGrTA3xMzx@saB#%3+B<_(A&txl{M0WewQ#J<>iO4IG-y=L8f6Z~D^4}hUN zaF$@X&!H>V`ZQ(x?%1P{sLtZtxu#kTWD)YzD1<~Kk*Z>ph`Y0Yh)Z|~g+`X~+rVgn zn?z?RT{D-siZ8LV^{t~Fdo+I?&^P>D0Dc{C17P_3HMo?V>$RZw!Pb4 z>VICMegwH$&xWmTTTY!=Axq#-5dx)%>6k{7SIM$b5h)%V8p3G`QC5cZyZ9L%$C`OK zVZT%@js*X(C6kO6$xX38l<3>IN1KZ5ep=UK((G(K=7BE+76Yap>%b4LM}L3Jwe5a8 z>zbsS77`eC)y>B;TcW0hxeNHdk*|pz}tYK8=0f&=DKI# zpN0Dqaj;r9Zr-}773E@wf9Y=Oltn5N>_w7&WfsfT)dU%isw!@YF+4L1aSU*6Y`-MQ zYE;q!(9>tLIE+8&y#B1_a|wJH|CSE$^MOkN!)NJS&8HK{kEg6VRDRjVrx}iex4SIhi;yvLK8Hh4UTd;qx;!byVWWNGva$K}7FGM~i~_7!QN`a19Dg z(hHZVk`HZ{FbTg_-ae9Ks&|!oU%4lt?TXV-JRy{bz+XJ8#&biOwhD^lqO(>yNOX z?~|~0yrjoTC*#1JcfSdKJMh1N87F(erR1_RTiv>P>#8jb1gYU0au*%Jt$Efv zw)KfiIEQ!!D;peJ5qEGlPlrm$;F@1StW@-(vS4xRTq<+CWuNA&^tkLin*e?^Fbgnz zEeDs9OAfcGb$#2)t(!K>3_F;$rg==U3)Bg)_Ge|?5r(x0W)^I4FVV*&wMLpQ{A^Mm z`fJYqUuu5tfSzfm$H9LA{1PzyjGU+WSr+8E_#lu+oBc%W4SiOQ-nwSkXp`2Z$G%Oc zi`%a5q4sm03E}vTu^ld@gvE7bfO9d6W>5l@k;hlAIx5ucw#PfTz8{nCgm5lJ4e5+U z&BR5bWTYy_gCA*PBsQiZoGd32!73`#q`s$|!FDCnw&xXHpKb7K>hm@5Zvi(0raljW zOUdPr)~`N(dKf3wi~_YLX^2xK{DR4@D)L(OvEx(h)U0?^?GE_Z2^}*&?g4)g_z__E_z+ym=Zz1|N5@uw zgKM}{T4*^fH1{jYdd99sbs8mFy~L#`N|Cl9p5$_Y=|S4Vk{;cADSEGJT%jt!J=W)1 zTIsts=HExlI??<3bWQ(+ET2ok*8^>U;qw}BDMo+NKku0Ir{;6Zrn6_a`m8p#VdN{8 z%O%s`_I=yB9|1P5=)TCFXGvTQNpl2aa;73GKV3{-0L+r$>LN+9T&YHf3e9i&oJ4AN5Vl&mct~M9iK@iVlF0o_iO%kK;N8e zz72j4a35g!djnj`e;#+M*Kh7<_uUjSRX5s&~#fI;HY((7cKrH6?Cys7!CKQYVS4DbcOV!-fsCb*Q`=PuLFD_3k-v2m3) z=Uu{(tN@0vRn2`^qM*Sd@z)4O%OS!aj(IU;@yJ|?eevkAY8=PITGPAO;r&YUw+H&B z{eB1jA@C7k_;VKgC;mj>zEU=aRqI+;oxYKiX_0N@9pLNhW@X>{{Z|M zF!YlPHT_)o3r4pgnQ0k;oOmf>;<>luz~NS-Dnr(Qm)1}T1cAl|BPEHhnAd9R`SCipwR?*T*iZ{SjLjZ^5Z+3JTt=_C92za!fn&}&?jrMC!tIj|Bi^frM@ z$<^MhdNjEq*@#%SF+psax$V{qkS+J!Sc{yb>=X4!OzLIWNlE=?y8qnG`%Qg+2L5Z{ zw}7F4%t@b5KTAB*@sALC$KTp~+$ze)x&P}~|6&WkvJSC6u|P(;!{Rk{vUM>*$zFSS zH0n*@Z=AskDTG|32^lVCwY}xRiZ?9Jqh}zI7`$u5MqmMpo*UpNIv!#Ay#t0ydxYWI6O)$Rc$X?5p49cJm90%rqb#5Q)YEF%a_ zK2g2uaAt}|P9P6c3EFd1jhH%?k_(ftfn>tro(y=6PJVtx(!=YB3J_MSN1?r2=FU;e z>>&=CYvC*P2VIW?@M-R)-pRIA1e5}%9xK765v-fVA@ z1^(km;CmtbbpA#2-vfVUTs#f_67ULO`2Q!kl-%c{fPdnT^x4!j-J&o5dDgtwvChX9 zh3I083r7S!IE>}vr85RO9A`&tM`4X~&`>>KTRzZy%~_I_7q0<78~74n_<8_b$}>6g z_Vl$Y17*XC^=s323qIsgwRt3b3O;yFJxyp}? zjVm0LAoPWVyUehWN(|#<+9|?q*7hn1D>e+?Z?K)2_G+_(_I#-MkDQWi*BbC?zzo3f ze-XHp|Jbep|C;w(lrVpad}I?zdQyuAL)Lz;8kxR_+3O^`Br!h0I4MVUS5b(wODq(T z5Nd3+ULrw6UsT!zX^jy!m#Gy^|=^a%3HxaE$TO4`}$*r7%u5-BQ5_FAFk^{tR(ZUV+SlO0saxP?#1trqbLsT z#ifJU7SXY@K}YA}IsSXwd(STMKSzY~%2{U0NSk7-)&yyp#k7I&RKB{;k5^ez(dw;J z+z?XO$CZym1r;qGtxhQAFA|9fh~Tq0HjPWBTkC5t<~m=qQS5}v?3dBExwTk8>4xa} zShvG|>RClSr5!#3kDN+708)Fo*9`}kV&Wyf5Zs@$_vT=}`0XIQ+J(T;H_sd-)|vCp zSJtahk&;Q4n=vTFVkoy`33E-i$xIgU-MnApaLl5EAqPg)HEg8lRB7-swD3h`e&Zd3?r4-z z|9+zRN-fLsH4c0>a2#OxdKFyC>OkMHyI%+*u27NlAuS z_y_u(lvqebF*g*iaV)t#{}u9@CZ+3H)ts&8MDY2* z0>ISs8gMCQJnYLg9!xN>Zu@y{82BFZ7IhENff)v030oiKRma3IIE`Iwv@(eZ{~p`- z_sn3mClMrz=`s$2E+fRQEKA4O`U~CUm(aGCB9e}XqtqAFc;^X)a_lkro~Vp}!95Ww(rJGhh=f_&8P^wTRI%FiLw8*hQI zzcBta$JDd}6!K-}4c?50$^ghSB-ad_04Sfp|%oSDrVNd0mhgbcteJh~;51JDd!hk&40! zS$uzQt4S<#3vkO_a@f91{G8{#qO3n+u~lFrWgbU_8_^T6Fr`r7g;3u|;yb=3R#<@u~!IB zmv>eK*HyXFFm11N`pzRM&F?z+G4tRe@T-7p0K@MC;8I=)^1EFf$z9$w&^X^BTjVTv`ee9_uQ>Gj(I5R~_qL7a;l$FBY_1KO_vb)I7aJlj5 z(o>-MOs&fDISTv;U@BnvTnaA53G&yEU;G)pRhG~78;M}1hs8;ZirXcS-MnvMa}S?& zn57b&fnzMTPhx47xflh2j85#)Kg(cmq2{j#`lcO!2L2lGCSdsc7x@1te@AO8)lAD0 zc)ZQ$v0GW&vDT`KuprZwvX#a>Y|e`fkC*i4@jzPh*R(pj&aMXkB5)pH_wtfQ3rp79p&hkkMS}= zj~S~B2RdP&4XdUC)IwL$8v)}t{x800V&h;fh|F>rO9}0dH za5P}}KNDQa>Y)GYPCb-=Jv0xgLXWOO^TAcPACv#WgQ`HfRlGu|01~BGVIGG4oRuf4 zG!>C&QI_>l>QtxMUTt{qEY*DPfv*PmlJ($q@DG8%1BUNY)@Z(aTQ$F(!PCqy+8vXF zY_zy8`)z&7eO7b7#$VDOa;=?dR)ipKag=ii(Vv<3o|nx8pqv-5H#cpGpAVEFkmxRhIR!~?-M zHb^PDax3R$f6*ZBP;i$2ApwN3TFbUOu`NUhE0Styuc7$ zfZ?ZZo#tmpj`)&t+&E|yw_GpV+IRiM;rHk*VFm$u+~uqtG!PohiemAh_nWK4SC`Cn zPE{w{r)ujfpFOK#pl+{i&^PPY<>1!=Hvoper@*B&1%6ij_gyTkj>pkKQnvWp?&HE= zyR5IjVC^D+KVGr07$d-g_)&V!0QQ8u0r)Y6l3~K5xyR#(@3-FNHUXU4WnGZcHAwSU zx<1R_Xz;^HFN5!mosfB&`77zgf(DtsiO^NYbhNKpCoNNTo#;TKgJ_w@k^cEDgXL8RFx^gzdq>&L+N0zU@~AAbgy zlFL31K9262U@aHPs2Rbing6`)2O`Jb0vp463_nB%NIZ7JUc-&ZT9&B|@X}PH`IvNi zc6`hSKLuC@7(Pw|my%mvr04mt(QO^HN!qvbui*YLe~q<+g-5PDgmV^g_mZrZh4~%O z-^KgQ{CN)im%yulq5nJZ|Bn7jO@Bh5Gv+%3Xmyeq%rT(9K&=HkpO4$9^$%k8StZ3;fUXwM{}N4|)cBuDj5GrV3+Xxxq

X^->3r8MQR4{klfPgcoLa8e7fV#o)IlH9k?v37>gFdz?4*zs6G zG84NAB!5n^|2}J|roSh6zpNiGgZ~P68!+_a8#R4%59q(1w#n|ZeD(~PpN&sRl7ji~ za)O4px0fAuJ|V>335{criQCl>xT$m9@Nii~u^Yhk zCO!k+FoKr_;|z7CI*;b_f7w4w^Vb1=!{2uBuK-s7hQFJ^rQ}*SG=H<$o&8l~1)9P6 z=UQFJTZ!uh7sk2JZ=HmiX7pt(!!`W_yx-7wI&3Qmqya;JFu0Ul`dV5{$@V` zx@3CPu{lavyGD%BT)YJra*$5iG4}ZyWQx9R`(mumV94qmq1)jj=v48$jL*~=;6NQ< z_*euk<^CYQbpQFXnQQ+cZBf(hKB;bW?QVC*jWSYx5VAgS#&JEVK&~Ih9IzUJ72^fx z>fs!bhxtyRDIB0kDS%_Fue&0g>X~W~%7UQLpx-!3^Lq#Un0C7#{71lJfZ_K|a4G%! z&5v(l`YYq78(kv%-95OKqT6Jh^CZ4bjC`UhG>8CyT=rZ~`tEqO1U3!?^y@ce_uVPr z#{(wVNDfb8d+i&%|*OAF$RjZj*2pS&Mmb<%bku=P|-nF_&L??P1(UFlq9m#Fl zElCu+<)bmuK&Ca+8_ujpr8*w3fHTkoz@j*um!V=Ir@R|FDx7xj@3SxLYS8VrAHGbx z{RR9J;d67A?>cZPb-_KMrJw({&$k?gWnt{JpH=6vGX6S0P)()MpC@_eU9|0FTbN!Y`Mr2_#!UC=Z4+dIMU2JQ`bQ1Fq<4yt1-ngqX5R-0D& zy=^rCA4Car$#z7NP$roHqJoqTWPOT8bp7@puG^#Z%#7-l;%BqXSHB&- zV$-Jet()XJdb+jXbgPGyx^W!;RF#OO$krE$C5MZJf?xIrbUUG8?lU)n-vitSnEL)4 zT#C_4nDrn_|5))e->~6e9;C%nmowE<75XS?E#RiLpM9|~QCNoud7&r?L?0Ma#5uLS z!HF`?lwY--;XW}wx+m#&soItuhtt5115N-8e`~>|%nbCV{q>Y1JZ!uZ#lS>-2T%|o7QjK zvXE=r3V)2V8NSQb+i8DCofoqf-0xaH#dxunI~PIa@TgppE+k53X=yrKfaQG*cTg3r zbz=Fo*hVFbxV;fRuNLDSt~8uJz>yPT(-TL7qwSD(*y?|6wIDPK8;7i%wq;t-|L|+- z^E~*gz<$8g=da*Wa;;BmSDm!+EW+&`G;5v4D~a&b=vfQCiC6;5oCGR_(X5muWT%X# zVj0fV8MQI6=x)?}G=4EVKTZZ;3VZ=De5?YOlFLs(+4u;wXf0^8{)nMp1@oR1ua-4QNiEq2 z1G+nTuj%Jq;12?i1hf?YU+%b;%%^`xa;vpqD`tHIBvU6x1hV9Y#yQIBn6CRX@}+D& zhk_3WMgdZUUhevxv=Kv@&(v_HwP2>zMHcl5%74l3fKJCjbS?qE6uA5#I=RQomJULq z%dyKhsz_OjQr0e8n#eD`!Ta~|F0(%V5&UD|Uw|+n^{D?JU8jd~#If3lJQ_L@hF@%e zGcAvbsH}>s!=mlVdW5M?coH?36EE@8kquxz&1S+UR(aTqDKd{J-xF{#Q|Qd>{M~=F zZs!i@8~%2HUkBU}@Fe`@vcC)X+S=!w?^K$8 z^QyumQ5wQ3T^dW1)+?RP57`jvnxXlLoR=MEW#GerQGjW$9pF-OodW{CXsVjdvg<>i zmfD?V=Y3k5XD$ATV{I8H*U?xQ+XaX42a4O^NH$+oz(wKkCOi_OWEvw8i;9F|gJW~! z$Kv`oWxxQ5?Jx075VDuYE8MEW0r{o4+Kj~Ff&bM_ia(9SSSLSt-+I6Q7+s%z@N3%l zJ@9`3p8}>nC7rrHx%S63*dK4(yaC@Os^oOpYklq27Cx;dZ%PVCjuJ673Fk8cug1zq z-%=ror@r89*YE9}rTJ)qj+wt(!M6iD0K>;Oz@?aV`jfzZ#hh<^J|y{%ABxlIwio(V zBeVImmUQzjO#G&ZdNN)w!3czh>1u|m^k2$H$862VJJ2!f=fA)U&$q1-!0^!sE+yBz z!%i3p*(yKVHZ3x#x6}TCy_cIh$Y7p%){-01i`a7t@kPW}k}II?7N~*rAp?;_)^?m& zR&FT)TCg{Q%Ps0Ax#oAx(fsXzzGN%tv{*C}&2DAW%zdOODR0Ze2{`xlZWntqaC%>Amg3Ci!7T8?{1N_g+ zZ2yt;KfNot*Dv|Rv34M3i-w7^ipitGUvWfatct{@;6j-|?&gG$L)utI5*VzUOKzNK zp{XkTEIHyv$OGpVRye8r)I_hEYMkTz)J6@ZPZ9g)>H2&Gzg6%n_s-~rwp9QW1ExL` z!KE0xkN)Rwsn6DJ61Owcas?@GtR+3l`hegBLvSj_tTCL(3<`(Cqv5bPFIk!__R1>< z!OWS+){nQjng

njiFkKu`GD34SARGhq0+EBM~rf6dd(llIMh{#MmUOP5TszJVZ& zJErXBTsv(ZQknvKAMrl3J|vm5HNX(S(3=&^<6P?l^I?IQn77Sbv1Ns{LZ^MUoCa_5 z4Rs~S)WVw)GU1q^==1>c)?Fi+DSYuj5lo+-mEohnY!9u4eS95OH}q#?)~W7?xPphx!ezV)FT zd@wK!F!ZK^OUdOof&9GH^nic)m$1f5c5*PK8-{a;jImIWVM1FG){#9sWyhKS9Zf<1 z2k)2qejWTsUW`yH{m5}iqz*oK(~qa8oH-}Zw1Z<4Bd;trR2)fi;dU%ReoTQ zJ{?S^aXibE$^D`eETr9wbiI3n_sh6`3;g%M9|1%EZ^8Fw zJe#K(2R?o7g{|9U?Pxe2jqK93)`S6gTMd<^W4s#a&!p5znqK3Vb$x{1BJfjzX28%} z8+>o*nCBt%jOwqC-ptR?>kR1i1n(1iPk=uI>;(+HeZlvJj(HwJZ}s{!*Za|t`Uo!Q zPw+rMujb?cheO~Lun>9p_jxA|`5 z9s3liL=z-Mb4wz{ZYk>$0ax-#JS_$k7!Fn<-kBIJC&Y6JMg>k7dq+H63c>}PP27qK zR*+fhSuw$>@#*hh67+w-kF-w@_>X}n0K@O!gYQkdm}g)6VDIkpyqWx`zQD1IlpkDQ zy6h)-u$KJRv2Mn$phA?{q`o05kXX60PlqBaxSTopA=dp^c}()lln^zmBL6a5^eEp_ z>PLQLB%j}=Q#HSHF4yfR{4N1s1*`!KzuSWE%{j9F`CYnl^kFi3nvO%KnmK_E{gU-N zPK&;S9&C}9M|9rp+8U!bpu3y*ntpvAd_V9OVCYUl?;vGnV5d51?V;^I-2NfyDeDjkjyRTcRO5|rRblV5hYJ3)M2P`22_ zinR-gY~mIdi7`c{t}r@~-zt)|+=VRbc@;@Hlk7ApVr$fd&~TqS%c^SD?brpsX8-&) z`1gSC1ExOjflD#@URJLgX zjIgp;Cx))EZE^$+tE-DL90(FJ5nhQGlph5w>oye|5^5nQ(6RPtyUwTI-J3j9KfD_oLlV&yWU~PYH+)(wHMl>gs-lZx*iAM(~PgkRh&_QO2E`( z9=H@UzQ*^V|clql|uids+BHH~~Nl3e;=R4vw9IHYmmLbf0tS}Yw@`gBH zz#csjN#r%eW1)crrJ6*LZ_<7yQ{t~SUQLe-cB||W&YI9k;n|!l`J*n~t2N(uz?b3s zVep>-&jN<;--AoZbwBCHbi>yq8pf&IQI>Wo>t@2x6h_D=%EBGU>XWFlCCavNau_za zi|uhNn%D!jYJMhtHM{N{3%(R+1`I#TzZUQl*cmU`aOgZ;+inIt&cJ&DXW%?>244EB zr1c0P@^DitAvr*t*w2Xual%#^Bo^c$!tPW|I~{KRt_)=RKA!lxroW5b(%W^%<-{fVub`0N3NEfrW(cDID^M4uftVEe&VOP&6VL|!iusl zM6i}*`6JjB#$#z)OvqRQGl}Ee#j(6XeDE{4m9dpYqhwcfkB3ez;c}8LhR@O$I*-m<~vh_vW&@T-z=l;G6^b-xgX+7h11lkBgB|gm5b&=TvF` z6;^7a=6`4KPFdgX0>2OV0bs`0BfwfT4FdxD=ybnHR+8G4xjVjc14KJrLVseG*A?rVw@iFvR32 zRz!VtjFQ$vju+7Fa4lfyehXZRk&l}5gKyX49|Eagx}i=EfJa$h#loOm zPJRu2Hk<9bJ>TIyhR)x>KLtY9X6a5gTvWynNj9XV7@fLNx5-5J&pX{uqOCzQp`gd4);L0*ECd zRyuLw(ZmMD!1A%nj*Ts2&8SuQH;ReVLpFgy)s3baR^w(}k6rL-=Hb)euLAo4Q;*4r zo}_FD;zKM7o~A#8@v1Aa+rCHpef_`>p}6!C&w3QsVL8JqG*4|o+Y^gjldlFNU7?OB`9 zp!)ssifA^E0-}iVmp!ShyYM|ukZUP{K4d!5YYBW2_iC^{^kXp1#z=F5I#%0QG=5RH z$DD6w+v61Q7GM=%_-PBiH|=1ahqT9L*>}_AT8~)EP9(M00OnaBz#kRd=eq-XyMp&g z`~L*I7x+0~=)D$vZ|IokA@nwGIGEn^|Bjw@uC8DG_1SfNGWaauSisOb1zbulxu)OW zE6Ho;Q=GCMKq7sowh9HB%yQYrq2&LEy7Ba#3XjvdAxQ9@lf zRiRVeW$s$~m-UexZ(Gr>adYX245d3LiFJRi?PvHNt{kL*) zq5a9I@uJSCk&wJx%dSw?1)(vjp7Su$50q%(5LaT`O^_rQHH~k-{-%g%;I5-HnE&6( z@-r9wBwz_(_&E*yKk}p5NfZ9eZWtxQVWV|DHvTadXlWKwa*Og}gqjizeqOjgpudav zoA&rA_{+fSfT170@xP$I&X@Ai9Ixu;DE6D3z|j2_xRjiF2D!wyuE8i>s@t$# zQfe=|&9>g7wrA+tR->dFWp>_{?V4`GP5QmE?j8kx5^xG&=sp~L-!VbocSrV%C({-r zA?dbXb9}YRH98E&ED3|r{7TsOLL+u{JTFc#yE^#Zyx%;{IQ8YE&xI>z}EoN4&MyEH~g5V;cIsLW|$He z7=5{Iu4l>|bh+&e=++AbTb>ZIp!%Ro*Q^-@u%7%@mS5^!QHg%4MS;%3VK zgIgqB=6P!v&xH7Nudu^#e2VjT+i9^^*uS*xib$DPsJ?C!fS}ChmV0uSuHPKiPE)^T z@C`r*VCwg0a4Dax(CcE)%0uOWn_9`YOtkEveqN{gsr#v9Y3~YI&A*CRmtjmLqI>g$ zfGks@rc!k5U!F;i184fo>Z=qzf_PTPGSaPmP|E^@WmpD zGD$C;MdYr`4@rQ*FB4Xc;NUL%jyud>J^5Gu50PY4xLy_E*;c6LJA_RhVxM9kVGj&_ z$FErL)j>Plp4|_ZfS(F915y-Fnj=2bnynjG`3AsMR&$m0SL|b4RmA^)Ab9T`yu-Bb z55a#7JPw%leFj`guJiZG6|3=12?Be{(Ytw?Zw1>=U1&92qw7(6N0#0Q@NvN5fT1@P z{J)_mu0dM60Ktp7RP`g+5zyNayieAFZt&ZII{`!Q-r#$4pM5V_56pT<{Wi6(+0eRb zi>YPD!ggxeW?cc%V`W>I?F^FTK$raiT}yYLzy6eh4+3fcLw9)ay;*UQl2-Y50E9QwuwmWAMG9W1jz(9u^ve z>^PWc&mlyqYD+-(o#4Gf_wV5U5}J2r>3ZN&3_bHai0-N_+vN7(Gz_+yhglCH96)(n zBT1+!T>+gY-ebn;3h+(9nSiO^UEor3oqrjkYgeq6eJ#_2g(YS$J@yWq!`XHAJJvpK zQspGSo5QA?j(X)Rw#k$l6pp%~@JKe`XtAU^MLijrS-?tQ|BvS<2^+4ivDFRA-mI;! zg#Lk@x<9P{)%-}iq`?OPwSeKbHTd3)yU)l2Wfu zk!lB_sXI@*3r$! zPll|WM6$$vg@m+Wg8Zg%Ut}Wy_=ydVBqV%DSmJWyF(7K=;)LuagU5%-D~uPsx|0LB zJx4Qrqvn^GDSdLPcJMC(=K+S_?}AI26yy)>-(TjGk!ku!qSG8N$FJX_DTUEwMB;Zi z9yYuxNgmyistB`-GBLu>6NL)%Gfk#kIes0Xn)v#3i4qeuX-Bu_&$>I?o(15QKowy4 zn*uH+*S@lLl^BJ{SV}jva*dCVfx#l@Jlw4bzM41uwe@k&tSl8L~Pma11@=IK0mH{n!9S0Wji~)uH#9pwHyv<8@;a*-iT@*h0$$BcLR?~Pvhs!C zMntUjsxKNW{#*e+rT1j{sRthqOacr)8^EO)eNg{(K`sp1J-6jHk@pUh5%yaZf}OBs%INCq;=Z?dXy>-O3e(3f?q z7knS^Dq#5gIQZVoKl3#6Q0xxQY2C6;@~m#~m)nLbde7P)@YBfrHRtJ*z?T500#X!^OI|PIJG&mGtmc&Ua*P)p2;SR$ z(0d;S{|WFcVCwm2a4F`TZq{j2&s8fnui4bzwtTiEM$E2zzDnS$612JbBFE~?t1k5; z!i7o1;*pS(sT0CGzRE4uzsR6nufA<#{KrR?2nBA_{m@8z89DS)@HN0`fZ^|4a4EU; z1Ms({eQiJH<}h@xvxT_}m34n!HAynj7lp}LZs&;yX^Ughxmu~)H6MGRW7_{!@ZSM{ z1PmX?->dnkpQ+E?JA$|@2enhS8!$V4h&`9B_bP4|&%4&Ec`Pw%2mx1#&*KsFBJ5TZ z)w(G!!^o>mSBAo&YEIrLFjAxP2ByN%+9;`wQk78@L`2Z9bW2l+dbuE< za4TxM!q^BLqQ&Rnh7g%GUL|kacXWMr!mp{%?cnzVy8u(4QTOTkXsBy>=Tg*3Oyor3C9N*~PDsyE% zkz`T*E)Ik(jE9c9bUiz%hgtW&3Vs7{6JYB3Ah?uV`G$O`(c|Es1!eFuC(D+hP6>lN9sxJ8g=N(rsZSRjcL(+VzOJ9p9|ArRm<$;D zKM%e)`4%_yi*tK${ZC%MW!=KowiPn`y6rb~xZ6um;=;_1uywDW6S+`wIJ3}52(<(z zhLz|FX9pW$snuL+^`^vL zfLC<~@9jM3y*Gm21@r)>-3$Lu(>3jWZohc6hxGfw4c~E5h_m>`Vl2@7U2YD9+)Qxr z7V|P>Rz&qmI5B?50lt8HgyW8jj&%{<kco9I7Q}IRYpW_lt8r= z@xrOh=E>Ma67|$gcoOa77;(K`L4vfmi6$uM3YAT0isepqZGhObS%lqtG?$`9+3EnUC z{|@f%vaKj!=pPF%#q6K`&oga4{joBn8-FS$4_}l+J15Z#2xFOWQi&wl)wth8ikn9)%&S7w!d-&At>{gVF2z)u#!I6^!?uBR4TJrtAjdkF+IG1bOp3uHQMAIml%DTv zzPsVetdIACKL$Jn7``ugK=ZvNh{t(#5I@$m8}i#@R;*grr03$-Twmt?fu4)siCFKz zJyvfvHebFZSF*DXryj{r9L;wT2F)3}AQ7AB9T^R$$EZozn;ZeoTrHKkTCHkQZgG;F znB|E!wS^hE)jQKcL6p4E_P)wni@#=j*YcdGVprPUrFP-hY;`GVxH;M-gE<*@N98fw zqsMxa+zM6cN|vV?-W+CV1!r~wobxy35nD5Xj}1F9Dk?W{gCFn z;lb>9oCba@a6Dl6J_}q*u6u#pQ-p0tJ5*0+M^M&##f-a>w5SfSWpWdwNITwbLia`d zRFN6PP8ueWnv#fGM&hGiXMaT#fllwkny)B zJ>h2~__;tQVEB1H_g=d}zS1&o%$0gPA zDy%<`@Xfv=oXZHO49E#B7A{4JJ&@+BL^CuX7R3Y)Lp;8LZ^=nUN=tFYONv6wmLo}W z6rDbf*U{;>aLUJWxJ{qcdUxyk)IY4-PwF!fd>SwVF!fmxe4nd*S8r^U@SFhx2Dxk{uz`*VJ5!t)_5iaSTAe@EeDpxaoQod=e-`)|VE8C_MDv-; zzEezo{En6}*l<0zd<_$5P?AfR;{7c4ClC2?5wqus>NM714BEmsIMM<%~1&?&oxfu9O*OG_#MSAd!p>J*N3dfVT$7mkySY2VV5i+5G!C)#8V7k zmBh7N@}tK{i^7k{>`r%nXWLWF0P1`~^Y>0bU-O8oYiZ zVl%mD6kE;3*7kCOadM6e-aChPnEqG--Ugfjn0h}3F2&qG>-*h5{o{q6AbUm7)h!<< z0Fuk3`JW-{+H#KYDshxsJxauIHc9OZli~Pe?`W2Fx{Exx`I!iMAo-c-)r(+^5knv$ zHH{5c-|Dw;nvim9BPNnQ=X8aBZKMptnF!gx= zTuQEc**cwnt3%eVhS|(AKSAduGT%l9u#D%?B68tcdZ4@-p$q(CgH(bhwSwD0jFUZE zsYf1Q*-A+nR)DFys!wATKQI=R`+$l~^~T}Wk1vE*=RXVl?YGLsRz5XQP2(FJuibPe z?nc2S@W602M4f6MscyDy0$~6H>_$~%BTtl#uIi^j{U6o!lW{T>d>n8%VCp|3_}+{Y z^EBf{LN-X{(+x*a&8VpAS6Q!D3~=4$ z-weM0y!qp=asDowY5a$rRoBTZx`=>I6*7w|xeupeaooXu!+}_t%o{9jxgC>9lN3WC zSNyz|vx7Wp+f~XBvr+YoZkL9~vg2YF_yS-tVEEexF2%$h?;j7#ALj=%*eMK75C->g z>#gL-f>Co6nW;$J62zz>SF;=ek_>BEX-;-VskvD>g7vKCYfnH|+U=L%zX9F_3}5NT zHD9^fZSAUqRvuw#j7GrZLPtnm%@M1?)(5?+ z=QLj}&^7DA8Q@<6&Ib%%kAX|c6?dw2Tk9%9k;pV^{G0IgCE@E@)`J1kmlF1rD7|@J zA{-uy9}pIH98L1VMZ~mZoaG_@!1Iu0fg^pQgv_4UtS8-4#}BtT+qoUxxKkd&9X}9< zSiAQIc>F;t0r-VX}&jY?HhnIOoG|#AFESbH7Z#E22_TrYu?iQOl3(5 z`^iKs6ONX7mC>qFTBQ6pwtC+#Q2A$j=U_z_DjHIMhPOq$5Q<~&`L;(sGTs-R?af6D z{g~}OY3E&H#~!p@?9F%D`Ijqog-VWdFABw8RAu30m?K}(ONA7EO;6k2-TdpsJ+^nR zyrmHP7v@bdvnek;7;hLgfT3C&y-%r!lsmR?o_hjk?X})E_c(6>|8AkTn15C7W}>X) zP`}Q0uebBAQ^_5~45}DWL0WlP@dhW^;~utSx7dZHDDBg-t`W2_TpucT)YQ^&x>apV zs&)j`BQa4=M-R87=iBZDcJj#liC(9H zI#sO1O;;5R%1^9xPs)#GTGU!ZcPB;i-9b#ZrOuJWLl2+mePTxzcGq3;>l>5K)eJHr_=mZeYQG3 zut92hS@ZKzKu^|-92{H|fU}owVhAa}x?rPRC zf>wK6#GE*(Ac%N`NffSHH0cI1Tk+7P>J`n;4(OTv_6G3p0N(`+KYs$3V)UAe`rQZD zZ#)g%|5}rVr{iPM#13nxZBXm&fgM&bOm<2CO&}ibcsQXFWDSQxH$Upc8Ci?GwBRA^ zV_3!t$!rtLEAmBf z&hCEkWqm8It^OL3>9|gq{<70fBR(FsJ{GPWZeP0Lk`LAB(2bKQy}yd*PevN%@bypbXlGIOg6NkSR^ zX`$g{JT6s4ZO%^)QlmLJ4B-fcAlEcs;{jf0(ZO6+x{bC|3e@!g$5QnWsC zjn%kcw@1@Yv-kQn;B7z$VA|sxa492m*mH@snZ5%o7jKC)7XXe9)2*9p<*@4~ydB~c zW$ie+0=j#6uNgo4z<&e03mCd1p4N18#i#dLclIxtgR@(s{+twj=Aen}bXKhu{(%)#i(=qejTo!mk^6G8{g9Wq@Kz0Qwu&C7z-GFri1?%{P<0ot{RDi z$iu6ndA@Z)o$L?XZE>si9ofe^7;74HO{*!O-^Ke)d)x}%1KbA~`j3HsK7BlNC3Es; zIq3R44!TYKpVjY|`CJV?5*Py*`qP5%&3b5_W?dxi5C*U!Crww4HnnfEy6XmTD&b5o zwa@45dzdQm>wX}hyMy?Fk8^Vp%en5v7JMd00 z{;8KaA6@}|6>v3R>U}4;lw9%*iNj8%XIRZMtQ~`+T#L0MAeX(cExV4yYNfp!-_`UE z@IFH?vKO0AAOjeB>%pb$3GBA_1#!Vm|1!A5G@tNaft{Jt^08vQpsSjnajXM_k<%j8 zK_GZp ztkY*1HPn9zAH4zHhF<+%nIFf4F9A*k4BgGa_hw$0r)j@~=`N=gvBmM{%2ejc09h%v zS|1IOQ$0>sB0`Shf=E&WqWFuU#;ojm@t$sn-2pw}=QZ$mfj4&i6* zs8CG(?*J|X41dpqOW7afTinuos2ucQ{``Ccw3gFrzY^LjF$XXf?Ie@f zPzD{kEJ=7L11z2NBj=Z*LPXbv(}3eRCu8R-QmtVO#ng0nPGUA74nJjFsB69L2js^ELm&*u5>`rGG!c_10_d%b~PuajPH zx3<@_KSX5da4{739e?UMXVC3_=?VDhfu3p4C%|6-_5p^U(LdMxMuIrY{rxXwbv|hF zHhovIR=zI6rc5|(#Hr!s_GPxcP~GcWV_R0$`?`HQ;n&pX zI`HoT-vdm2-T;?k^a)k{;+7p$pEa10$mr;}*5(*_5|9Q)wllBqRo3H}Cq%=AiE-pw z647RSNV3*d#fZg=h*cRyoSz)SCAq*)^g@^x+Zkj}N1po^&1d}!nhzNV^S~DaO98{@ zrr>)s&w4(e&*j+tXp45=g`w#J>47m;vuJ>a(*ua&i{-jkk|v+>AY$+^4(_y_xK;Im z=4Ti5OuM}V{x!{?dc7Xp_6hR>(KrR)mi zq1X5G(>{n#y}A2i^(kN5^;F3E80KVim-C&dgYi8`Me`8TkPg?^97QD{6Bj}GEb!M- zjNjdG6Uv+7B%IE6&cY6!%{-hJYEWnQ36^^P8qEI}HGk6YNG z_h#KO&tQ)CIVT>F{A%Z%R-9Rb}^R3cJ@?g;P+z>$EV+Z24CtKKWt za7yT__F}4?6r=l2+uASHM$Lm8s4ohQuzfJP+o(8?0|EV=!TW{&ec(R?9tI5kCxY)y zea*9fy{8Kw{j1$MvVXO$s*iMgr;tLL^U*-?VZbQB(47q~#hj0J2J5U@@7q>vSj!@m z={Sz*k9SHc?2_3`7cfjuj zegGIgo&%S%E?8%re(^Za?_{Hub=l{!2wsB~*~m2NwIjsnMXqQ(lduCD86-)5M3An( z>vkypW!5igIQV2>8er(Z1ukVu5Pzz1^`ZNAKwmBb<(=xU+Lz@%=Tjsf&CkWGXGYdB zZwnaxoOI%Gr2Wj^cwwX@lIIkpk~KsqWs5lis9;MkR3jSQY0j5i;ta==WQ&#EMzTHS zq2efrAf9uo0@L4eG5yUic9LVF@mNKie^vlw0C&ug#PC8E1+t%)sS={JjaccP;w}Xy zrpV!@ldY&v%babbd<1E7^KZ13wNp0WkIa z9=MdN1N-}J{p3_@*AQ9LpCE6Am?0}O46;pSACkS&n=SOp=}YNCVP znnVSzY;ocXVXffi70~@SH#wM}%kO2V3hWSpEC%tfB2~$XK@93b6)94+q93Hg52L3R ztG8|SYug#_XHuv-?v4_&}frF!gB$my+||Nx$jb^_j-!L_U9!gh6Tk5Tk}M zvTw>%kE16w{gjq|;>vSyKjA(Z^b;m75#L^9B)K2xh!r?o!8(PsTK=;q;78WQJ>bs+ zF9L?&_k-^{0(sl^e)2XgTRLIkqIF_ zmk|R4F1}}D$V4)FpO3Dv=BM#B-9Ez4so*PtR>1Jn7JP5kXY(}cC4NhqrS{E)*wHNY z`Ac0f_A~xcy#d`_!Fz@7Pr!SDp96;OOTqVso_QL&%NL%#d5aEL=?6$|Zm^yi%L$_| zG_t4bSM_?feiOlu0;U6o&N0FF=Kbc`M+Xy*)=hXR&1lyVM-8>-4xwf>1oXOs_es5O z0KWye9WeC%H~8MrG0#4FehNb!^qD&K9!iDtY(VED-cwIc3Z3X1$iIPsfT8nGa4B1Y zJmlm1nYsR~Pp zselZ~4HdhU8C60cxB<>(c2z`7Gb5t5nT~L-R1G5uTQc9PM@StHoo}mi5XXcOw5oz@ zZ1-BbRQ`k-8}(%>idk5A7+#L3|HC*}jEII~L%lI*cILZ7L-}}qS9-+na$|TZ4)#WC(?d5KhvXg-6zDB;$XBs`NqA{!L; z1WgIe&pXgF=Wy#y+sX$D0K?B=;8M(ep?`eNgZc6OG|7o@tF|0D+-hd9yeCYB$Av1L zNQ53En+XSSx+&&~=}4s)wXCn$&LW=(9}P*(S0{AMIj0N!M&R3k;p;(gDLLg|XkivM z$%fJ(K~={4mlp=%txTQ6#iD@DhmE8}S#gqizOl-1bw-~8W`Dp(Fr9b8jjT{fYbaXAG071_RP9ZZx5 zCb@b{Po0 zDs(5li2gM5A@&xz z4}em@^!G?`DY^6x!R@_+-cDB?YXse=TMtbd;3N==6*=N3$62(PnK%UdS3;)9`wj&3 zxAA^M|101-f$IT7|Ht4`{u6yUU}s1~!Q$|t@8fY@$l5jzEMGO?hXE4-!&eKq6cgw4@xbobtXqK}yR-|o z|M%(O9`9;<<3~tqafIC0M`P7lgFZlpmJF<99(oxDmdYczFj`V!Z?Emt5PNDUK}d#1 zvl&5qD>a|H;KQ`vUhtQJ*8s!kU%;j0lK-yXxJo1*+7hLIC*FI6NMKRj24=hx+@Id7 zKPV7S;{eS^bKJyC1V5!I1_h|%k?_zK5U9LJci=p`gh-C>8hR5sp|K3j9y^1xA(Q>IBB4d5TWqHBc-o2c^BC8C`T}UpG35jUHU62dDQ=CRjJxW!Q z*qy)Tk8lxCI&0jMxl)Yb*$Rvi7ZidJ))kYD(cR>!v8fTVs`1Y1%k5Cu`5!@{=zi5M zzRK2ASGgOY%XLsbFScu)=$CD`hCfCl`7|K|$In9iCHcQI(bL_T1eHK)&R#SUeQ3Ur z#04uqHjo%t1w~0=#f=x``A^O{%5jIrZnoXqWzCwU&gXJKV1{4;YZ(%Zf7;XRn|r`} zffoSN-ePNGLsO%Z7-(U4 zhMLI)It;g)a(AfzSrT=^)4iDz0yQ=@ly;YtOyhlNx4B|aXtKMkb`VCjyg|voA<`7K z%PSLWX%3e2Z`$@O^=I22<+n(~Fx?(|sIOTMUIqUR@GfB5BZ(U0^VWkvYpNqeIH|?t zja=+IgFZ4<5>|1J;kcC_iWhRK%tty~K;|cTdPu{?F8xkhv}~;J0Y6KiXZYCwej#uP zVECENZA*%Yce1@-yc6Fp!cTHb9}VhNJ&C=_?p4$M&wqyZifz<&CDu2Nl0d<6v~4MM zStvi2VqJjIXed>o7KLMC3dIlC;ZPC5ycJF-SbccTW$vJ=At?;}IH37ohe<^m#lHDb zmB~NZ?Qq+HGH+n?8k?!df#vJA#~*dkd`&H>!(l@1m&L zrSTU%T=#1??PS{VZt(8|y8zRUd%&gS+9%tzSS6i0Hi;d@YU`P46^P<|$1{aFtYw|x zuw>xhAJ9v^m$ly*3_cb(95D3$A7y6(SVvVg{<(K%-pqS>FL}w!o~GHlBEcLUovYutepBZv*2426DM$OCWMv*JJ_erA z)(fqyemJFZu*$&4Te_GymU!AnupL-xU|9qJ~7iYSdHH(*u@Qe;!zd*62htzvm(uD$dSdWd|594Gbgb{p8bfRfaa@o@S7oq@#Y$t9dBm+^ z>*KIPI3>`$FSm>0UWsSZQ{5_wm42s=tyLEUo5?95zo)~Gv2WT4z5}=zF#LW2TvC62 z@eUtDD;Ywk0vQ=bl=-IFbusoiv7xjj8eA~z_-W2YY`F#3<$m!{m}=9XF{>u^81Z!o zy0y@iden!|e*oBW^zpR>T++TNVg2Qv%LBf)tXw54XZw{hxIZNyg~Hl*wRK>29orRx zX$T`z{aE}&oF%cSqBU&C{L+*3vi#G~)pZI>llh}ZCnl9~04tgevlvrcB(q=Zw6Oke zfsb1F5I*k%e;jxU5bmVoz78&FO=Qn*_LuP2y>atex%W9A0axH1r!3^L2|kO2Po{)@ zbI^B3`9t$R4!7E)e0M~7NI84KZv<{SEMHUq=6O`Ur*xo%NzMbTVg4C_EdXAgOrdGJZ_?*lIbLS5+m23%6EoaBi5!Y9DV zVQo1r4b1gt1=12kzc(WKotsbG>4HFFhm^ub%)6fE>Y5R@f8$@W<(vjS2bd2S`b(ns zrkv(^1pPIghJ0;J4P*ydcg&OB3;hiPmVp1=5xrZ;&y@F3@aKT<0fyf1!6og8{CMW> zZyTGphy}{#C0o|4-O@BNP}ilV2n~6IdP-sOvx^6F-V?0K^Xgc5#CLjy9z$pf*Y*<$ z_fk79YwZFwhxI}%J;5a%Yz^z9<=rfQ)4*GS*?=TzkKA@J<8u9K5xUn{%WJHw=W`9i zB@F^f{$OU9Z!dY6dGkx)j{@HSOu3%~m-J@jN6nNw_uey#{zrKq49h!TirapRwl)D= zJ9gl4d%h`^W!26K>8JmirC$d=8W;~4`jf$rMgK5Am{FX|W02l)H0jpaA>AJGHRJTN z;I{yuk7!AK=8n_8`s@rg$*Wcdp1e0$t2S7R&`&^UCYnh&6Ub+^cX0+_`}jSub$-A- z<2Ryfy_apreDDgO8ZhM@2`=g3sJ_kl)zFU$n`vofEQw#aRXr?p`0(XyfI6~`s;rp$ z%ykASuIP|^&I!xABg$9ija}e30k;B%?!(c0GmgyD&|TkYs<}tK&Gl}N8h>fRTJj6J|HASKA0^-oz)-;OaYFRo&^OO4 zAJWrSZ0p##Lxxw6xtib(s79{i7+`whp?M)+ zw?uS>uLr;%2c7~9UnTE{d>i}OIZKb+?{wpmZe}ozPZ%eRb=@x4jn`>*W2?UJS}!OW z^LgxM3K0zyx}IOiA-50<3@=%Rm0@0)SDB906T3adkp@eV*eLN)Mg(It#^FD(vI{H? z1B{!7AmqYAryP+=xqeK0AB08Pe|%V;4H3Umo(sTt0oMYiJd^(xmZz&9J^4URBn8>8 z9(RKY?9aB0=v6Ppt=lwe?HnoO_S)|*MH+iK(Xy%(Um}YL4;d94HBtedaN>_B_ZzA) zMn3M-DqnFo8Ov}5FLDo@aPXJhIO7E(#%C#?oN)7fyro_o_s&m{)~+Ffqet zfU$9qNa9D}INaqo1G_CSY#*v_msZ~4U>UQ5QUu$@-o;`4?25`S^|KrNtH2|Gsh@@q z!usin>SxaBN47Wm>stwYwQAe??O-y+_Ufzc>$U3Df8aqy?e?ta-BA*z+nL}razsYd zf$%Jmo~Yx6)vcqExQpc!Hs=^k%Aq;EWJV&9$PBZGH&8Wk%mx#Py9=Gc3@C&l;KlLb zILZ;s^_sOe*e&<+Mmjd)X-{-JPSdSOFOSE>$;aLBaZW=#JK?r04a?m_xy(9u8~7gJ ze!!G_;NQb?_v3eFR8ZuRC$H^Zwgq3#(KJ}regb>FN1YWE`-`r%KUU`yh#~#JJk2hY z<9dSQhprxt*0LV#=)tz;wyi;KY{Wf)0N-kC?*tMmRy0NQo@VUGj} zP35WTSR$E_qW@YspS4xsF+H4c4=#(w0p+RXD{1Eo!7m0bjmjwV{Ac>vcgv=hu#GhA zPHWXp>uNE^;<~Ve4qNE@=o=Fy8SVZ+dL|UxPYLNAB=44p-e17&e<%xEroQ_91h}L% z?O}gm#mZP-c0M*8NRh@vGsvRU|(6%MmiNDK?zgs znIYZN$=A^B0>1#*2?#Z5=Z}L+`Zsi!QT;h|ufUw+Xu4ey-2>!n=)ML14)ABd(ER}X zKcR~Seh%Fmj!AcaM0df5*>SuAyc5_87`hLFOEUJ~eR89yo>#6}vou6QvUs5H#Q8?A z`h%8ejjR4i2y=WM;#Q1M3?m5Eh&W9b;Z+6^Dx&^LsIPkIW)yZ%%`Kd%as7->nLq)E zXgl{?ir}yEj7QSRW7Jj6xVxSC=B<*y6KjX2ndA&qa=;~&3 zy?UjLjse!10faAzBF`U;@^2@vTJn+nw}XEixB?IgLH^*9`inD8JFM+k6NcL6FUq=J z65&cI%lMirwe=`Q<4Nuc3uAM2K}Mq^g(8q6Geay@N;EUiE)XTHQ#CbsAMQtG;2YHMem9?hZ|<2+HB zz~YuAg;P%6`8v3+{E~9gSf*YZ-o3T02>ICsy;|x)>ghJ{dw@NF;pZFRlKv5$cXIck zAu~kVktx#Ys;81pv({Z={TQPwd{D;S*kraYDX|A>(ep!Dwd8joqVFr+H&51r50{?- zL;p;0NpD4RPveiu>;tp(jVV^^*F+uae6*p~J*(MfiwQvzi^viVd^Jqh9@SGp^M&KZu1nZHvWUKFriW5^^E5`F4pEcS(g$n{{vM~lw# zF&lgda57-{xC~rUvj27p^__&1))%FU#Qp2KpJ?l#t}9=FQA`GIhS{ln@nc3PPP()w zen$w&!p)sufJX$ZSj2wV&peu(xG)R*yxl6$@g`_=kD2c~u53@#OySg+x`h5;p2gDQ7qsWU0a#%fs; z*2630YwF=o;2!}tz2DHC8xQHe-x;p=trr}*pEPu%-duk$etYWmxH=d=aNO%0rPkfL zfKVA@5@%}MyefTL%>A3YKv!eYok0(NC=-x>uD`_nlX5@7tr5XFD>CV&x_X-3njag? zS#+_Jzc78G{Rid#k8%^4Lg!Tf4&~mi{8REvQxvXJ7oBCVLM|L@kG1H6rXgvj>n28 zrgY^3|9E}5GmXngGy&KNE;_X$Fey)Do>%#){26-be-n(0UygYd;jg=Uokhq9Z6`i5 zHLP+tuB7D$36)ut&E?|MHLA>EAC{Mz`n>Y_jajMRINpLdzMRCNT+!#XzC)MP`Zf6s z{t~Xws+^*0lzXjmVom%8k>Z?MXCRx@gx=XyTm zzleAq&86wSpNbm-{9fe`=3Vg#O}W4A9`V~l5Btl*as0jN?W5e5{M6x;+?LWrAEnBM z0N<K?H#Z6yP4Sk1y1kbDZA6p-?{qJf0BE5n?MA?4` z&5pMvlrO|GFWyj`;I580ZhcW5iUVwr z%2A#w^P1hyJMPnTZLWZa%zs#=9wI;&ZT=VAeG79{Ki@B-jD?&`V&HfR@$)ca^}#bh z$}OoZVmOq!SE-`y{*79OB*FprJa=YQ;i6le)LpJe7bY5%*fMh+gqoA$YA9T`8gPq& zGasY~DtWc?m*lHtF-!#Dp^;{9^sI#oULxw zsn->9Pf^>)gUu}p!#;a)>^YUS7`n%U|0i^#@}7tfn;nN28WHIcg>Jbjtmj_xHS&-zgMSTp1Tb`; z1((#1JOn{MQE9{v>M{fd0l|svU&;{7ZrEsDM})t8lv)z5oY6V6PQ?blOwO>@?udRm znWaAndu zs*0KBk)>eBplm(duR~X|nB~`Lc4t-$EOwH0UVX-?%0FYQH|{jtrI$_ghTvYBaam9= zYK957((wxOlZ?Cyx7wS4gF=xW@Y|!KCz6KX=K(ycfqKp&cmf(0FA|>^ZaF?bSRD}S z3`UiVt%uvdZNK#V`T8}58_2&ZeKNx968ApjL*6FTE_ufx;<~WCT2tA6vJ89!fFF*& z`uYf5lJQS^d5*r|*0r0nT@&%~j|1`XL8N<4lZ2}t(0PZZK}*sMfqUEMRl&Y z55xOO^xc>~tbADbTjQgrEXte<3a9}ll{59p?9_(nZz}gUI#wZmGr4E}bXYHVuk7o` z>%q?jHUpC6vp>BB@zQ?yEHT2`Fv9wfb3bZXF?>yNy^XVc%c{L0q_dwq&HV5y@V9|K z0j9tH16)$>{mBvYQb%X^#&s7i+PJlQwuGmE!!n5%+j5QgVBhdPZcSap<+zRO3XiZ8 z^fg9ce<Ncs`L^5Y z&PV1YWAGsr!_cc-U2Cf~XqBm%dNi?d%3@2gvbtNTzlU;{gI^5m*(wU_QR-uCM;inb{&#G1%ZIm zqb>_B62Bfy!SzxwT|T%6mWv`^AI<9cHWRgosW>B8jDNBHpu+(I#+@=KK_7M zfCk3(jJiMzkeeYdIkLvBEtUYPO7h^WlHjWQM&-N|GDSIRzZBNbF8DO%_yYKYz(as3 z$E)Cya_2EqPr(KM>aK0*YOLEB_4*#QO_q_fxftz0UEnpA5mcw;_QuJGOL?wA;;0Q{ z-oTXywh~?-!dQ=;g&B;pttIUJ zI?k}(#~&LGRq?=uu+p*y;fqsx4f==?-QDDC=BiAy|@y-}M0f9=qoI9SuoCO)hLLy`& zQm4YL6Co)Gcr)pJDTNDod*KMa30LKAU~!2lcVU!k|{D zm;1u@*cX*s+T#WA9|Nxdrd}FL!+Pn8?hEhF(Yu%SFcWyM`i?6?_Kx4X)^11UKg^IR zMjh9Ir?TR?j+e)!FMS(@Go-055t3HfRVlo9B9UVrcip-;=aeIU+pEA0Ak)!Uf(5RX z(@l+CuUCOC;G~qWx*iD2(F32R-`@;=2XGf)%JB%er2hK-nvHAc5#QzHzDQ`I)MItD zTOa2_PDHKv&1Uxy%*vKEP|u3$@jyf$%kRE@N;!BVFdQ)Smw`*FjpV7herva^+_;r% z$2HVv7>cc|{YRn@7Y8PxY}T=lXu|9sQpvbthM*&r7B&0HL^3^_i94avO__4Hj7_D~ z)l9ueFVQnqp;^6==k5*bX-~w5wD)7+PXgZp44>bN-kWh}o@V^5-m-G*28KWe%_BzM zan=p7>PkjkRWRzpxmwEE7SSs&&$i1b@Cm?ifT1@BTvC7S($N_<$;sWJW=dJhrR=3T zc600R)#)>duS0q3^foio9E#}nlCS9xUj}~w_!?m7J^}u(=+X|0JG+;398LGOW76&Y zYFNM6?Dh47D)2$TP{7cg2rj8VJ($D0fYTypt_rK;6zc(e^Ktw~8sAI@UAtsOEzVGZ6@ zgFTB?`*2vk@~SXDX_sd3(ZD#s(3={)H{;Aa&3J=cpSz~kaYAge^&Z49f)p3bedTM9 z=~r~t zrjr<#WBwl$!>WBGtmmF6U#aI?!M_CD3mCdDMDI=iY0X*34x`&Q7Xq z+RT!)SH$1Gh`!X@0q|FW*8o#*Z%6MMF#+5wUfyH} z6#T>Nl_k<0i8u2I*Ea>o5U64sViwbfR~Vp4`>@&Mg{{M++Kc*omCMHpy` zyllI38dr0ZxzBEYJmhBw^je`O{r4L1F92Tx3_s`Ah5Wo5$;;N{=)0}o(s_a52M0U9 zwLg+z(Laj?kK;cQuI|gTzN7{f6&EKl=_natk8^by)>(4>B|)+0XW3R*IRN-L2cTrt0U^(pvuIsl9RnNPhPHd*D9+UXH$# z8Z`aTJWYEBBS7YC+H;N7y#`$XU)LzHf~ZxAm^4F>dLlZt_1XSE7JLFQ8IUBO{q}nq zX`4FNOC0DLtGk9Ad%zz7z7Cjv@mFw3#{bk&{*;AY zS7+y@AV83G)~?-})!?%d2(0^O!~kFk9>SoCb5@H7;l#y*d?GM973WYsDjM7tvGvI~ zUO|;8ak^Cl{iZ;zYy%EEFiyHMdqD2_cGwOJ8nX4X0{lFn6EJ+=4lb!bd(@ykgl`GV zDQvgCBDxV9(T(W-jkdmF*Wu%h;OF?CV~?iOwM9){GydI)Ohxn}&ueOyyA#442Yf!I zoO(4y7vsf<4kYQ&Ga;Xc;KST6U`TD10+oQ_a~`;){_Yn7K3A_q9hY$18-sY_Wo<9Z z!sfBCb)&g?g;Q6AN&pTp#H3v`aPyp6j9W#m&sXBweMq1g?$yECaE`hNBofx4XG8va zp>O!R5Bzc9DZude4)}k{Ul37V>atgT0xdG;D^I4Y?)%whJ9Yjj*g)wwRQOCu@Sq}u zI-v?^$Y_}`S|(~Z)&~7h$Y?;_vTC0T`E4DXU60NLUk98E7=EtvmPHY4ukq! zu^N822)pgyk`tu20#>n@eFavDV5+@TYx}NoRDS$q0Mj{R|Ohg>E}bf zUV*Ne@BaX957Cwf7`|=>m-MEYUvuTBGLFm`s@ba_wI9@Kul}ABJWhI$RkHh^zO~C8 z#ikbhhIENj$Lx_`o5AE&LPe2mf1sNwL42BK;>8HJ*qw#hupZ*HotIz4hK#=~b?jO0 ziNxz##3pe*!nC+Y_>&A4cG6v(ojMd%h*P)|_?}V`)C)_FBtS4q2jL9_@X7@PWM6qQQ@+EXms2Ljv?s*bl zI;xuKiP?$7AVg1?$+zf<5}S}1YOa?asTuNdFP&eBgK>VF6&~3xm5IZ5uX-}l8E+cZ zQAY8ln|?dE^sQ1I&H~npI`>jD{(D~v%YBG))lx25FZ@RC0Dx-1l>1C@NtZ7P;pNrMK=^U)6y^{uMkZ_N$I{1AE&A6vg46Y_$CnT^jetG3Taq zO@5-rCOS_E8Z@b?iMT&nmlpGvx~kBt4koYv(N2XPt%f?Ah+#mPf^_KRkpI2#XWH#q z@YjHYfZ_l2rjY-O*N1#R6Ftp%3;AD%NKj_kn*I8H{ghVw^^3{iQT7z~F5OqAtv|#k zB9x5#zMnzG-RA7;O5{H0W98}iaE!GEHDMeejwed$krWQWAzxjs&LG$soG2;yfYRjs zijT<++!X1m#r{zDv|>C8WKa*UC)d(Cx4v$nGc#2tznc0bAEU}M*smOZ|2X}z+VU6i0VXY zroa7pSTAzHL$$27x>s9I=C$B|b%<6aQny`E{w>Yf{O5r$29^S*{?~y^`qy;UtX&uN zp4Mm83~C%t8L#ElIfJ-k86y9<7z*_0TlMYXTHF4MuzY*S-<0o3@NWUnL^S_>`L=Fb zL$GB^xXJ3?WbI0p3M~{L@gEW8kNb%QSd^5o%z26%4uiW`OtjDe0=dB9n zawokLPYRyZeFbjKvHlsPM=9d8$PLM*a;&o2Ukl6CL%y~AEaUP9@XrFbM6`rre|pFg zXJ+eq?)EKxp4EMxwKs`|BZdK3!w?x1$1*6g+329yD&+e>MDP8>=oJmuRt?Yqm~w6e zm$d(cu$+E0ADD3@_oq==O`Vo?Jt60A4&OBBZ?OeV)}bdQ%91IC?=dfx&Lj&*>!ofg zIZC&%#|ppACrSy17hVBg92^2k>qL2CBA46+iNe6{e~aD}o2DvIPLa8w^;cni?Snrv z4}1^&HQ*p%_+K_65z22Rk+U*@scQT81e=2T0ni_*6#vl?? zYqkcH@4BQXz&MB`u_3Q2}$X8XjFT@;b3F408w1E+NkSA zEG+538&UtKT&Dl;1AiQNGAgT-xW9e)md_so!RO>#0rzlFGnk{7D<1)W|6KMn?lGXI?VW1Lc;|YphH<0Q&$A;ORKo;8mb$xN~s0R zlURD3c(U-4N)zv(tg3Ky4C|m$_ab4kfNQGkpPD~E`cIun_!>enaX4CYC0A+OUhzd< zurmK#$L>(E9$Vd|oEBB3hM-8QeyP-xHmX^FP_ZX%eJUY`N2gEH&B4DBO&FwNbu)OSWIt zfHwmp0n_etz$KY^FV{aFaY(vXZt0ew2gksB&WyA?iEM6q>#mW%TB#M#I z)djjRi0tTNqLJRLpVNACSfT@e4%@3e;#b;h2ly`FTELX&mFT^(;~bP@$0=LPlch8# zb6pqgxAv-+^@B?7RVO?s+pQ;IpCHC*w!-4|2{Udxh17)*iLrEzuIF->&Q9oCO+e-W z8O2>4yT<~>_FDWTHpzu%2{(}*HjI(y)t42%=w^EoL$%gSKUVL%VR>4{g!M1wnFD?T zuoy7qIW>B3`k#54ez+L{e9$`56+=JV-HldnCZ8=oRajvp z&>J~6g)!Gg->KDZy*T(BBeB-Df8Dj3C;DlT zyOrC;cFZ2eG-M~s0sc731qA`HF>BWf^vqF zDr_vk7_JhD&tNwhgqnO;`IqRkFu~m#b@-nD3+uB7{wLA@r9N*4zXP}nFy*@+T+;jf z+@l;`KAGM#T_<(=*7i+SM>PwqDeeKX;#VINh-U-DN_z)7l==ofgs^V(7NNAJXk2-_s+ySAt&$d>SxxZv&U~ZglSY zS9Ha&In#BT(A^@M8dBaMV#F+`$s}4pw(HzhR;UzWk}qM)iY@ZN4O2n zn23{u5g$9CW9sEb@VkI}0K>;q;F2~(_ntd){5VHUboSMcFw>*H7-;YeyA*zK5OWju zP1U-_wH+@xTsNW!S?(|$O6?HSZ-T1ts~+pX-^2RB8oH0KVc=7NR>1Ie9k`@))IZ;f z{F$5i?Fhd3GLYr%R_}!E^*J7}cCT$cpzGL3;`WzSQ4Txh=!iRbqw$K0tDS+a8os;{F>sNI7#6=325zxRL|4Gm4G=aC=~IVIsVFn`jv7V*8d1*`B*rIdcnNO3i>NOs@N|?ZzM**Jg%|| zFifi9IwQpfb5WJX?!~T6A!#c{ePn#RBvJ0*92AWg&lx@n_6eIfP2H`Wc{se|M^e{E zA^*GKua=)>o_YxU+rV>x;s14TNxP$a!Q6g=oFY4JdhvP^$N|TQ9B}(!#>v@woB}=@m=72}P6L;;@869Z>8EYCiUr>G zCve+oZ={dXuug#!=+*Xc%`Uw%twOrH$+wn#rTmYAe;arXFm!(jE@@n3_m^9K#;eR8 z=BlKu>xXhiyGo?t+y9AqoV^$=UM~D`pFmu=SYh63={^rBXFeTrb#{F8>X4t7Dl4B5MtjM-;w>uP5)yZ+??PpFN0m9b>rYCAX{{ZwHp zQK&8vuG*cDpZ(A?=fEF=zXALXF#LP~E~!6zKiRitr`1n|!?Zq_R)2`+8ML7oWwD`5 ztOK#{7$EzhW~|*CbVIl`YIQ?C7EIy396HiYr-82r&I1e|p9Yt7aXer)^USm_Ucpkk(R!arb*`-MbDV)@o!uYNTR?ub zlvC>ARPZx_DU(BuPm~*FS2&U5=tk_SQGF_B4?-ZPMQ4u{)pc5F1V!r z^t;VC=;##52rc2Xow!6<+m~AVIF{oRRu@Z@lqo?beALFna<)zn^Og2K9ef3_3NUmx zM(@ozz&y=*DSA^uBm#3}3xgl*m|^WWBKARhL~k$onR@*J_)maW07LH$a7jniYvgBO z^V-d;H*HzmxnS)|wk~~A>`cqBQNFcfp0%6p9Mg_8XiL@_34ciu{gxTo^XWYB6M;6s z&_5GgQh$0#;wY$Nr5GGU<~c1w_XKMnV+xIPp^K=&XvvUKBCO}#Y-{Ii>q9QB-B^|QDrk%H_gk~=SPecB7z3DcT^_wR z=hWhybL!@hLUg0djr>=2a25X-F6I-~&hN&oz0M$HXoXy34zUaC$8dbs_1ui8!gL8Y z0Y$o!3r(@pb9g4ur^e?wHqKt%2}lglo5XD>dmrN6BwRp!Os3ya`Wo$@rBD>Xp+KX3 zg1S1;n34M5or=bP#JBX%52QRZwdDY&Tt(oL%s$un6EpoYEZ3Tq-Nc#Pf{_SSm}!|! zo9$d~?O_%`Ldb~Z0@kv|ID@nEfR!K8Zzq4B{DuBS;MW4ZfT3SIE2O_K@~6M(yzu7`YAuwQzf z-n5-LyBw!0b;-1cO3f;Z_=uYUc`=?yYglljDOfE>cAD${Z9HGrKjqd1+U4)i9Jeh zh;{0vYMJ+_O0LXXswAm4a6TwSb}52rj9=^`Ws@C^n502Qfmj zb^HuSwpl-b{&d%uqrXU3g7F6nQ*uCjKs(5stDV+3%V_oQ^vz(;P(Ju0SsS5 z=7xMFSBB%@{q`frL)YrrSEs;)l}d)0m^rVhlejRlX1!RIw9cnp0h2D=~SS?_vd zP@pQ*Q^EG%d3tPbT+L!8lOhU|&x^^l+G4>y8;1^6$((EBd9q-P?( zE4gvQgdYB>*2=tyT;!+W2L9|jC42yib`<{#+uBF*aS9%rLPWJZr`ay^hobA`6*Nl+ z9f5Q9Df)c9A~<=b>%)2|pP$_~H-nD`#sP+}so()${p_0!Uot0jE$XBm)>}WN9%jp& zFy0x~R}T@rUF26whB7X02mdeNtAL^RG`OU6ByVVo&Y@GjK%8CjZ5b4`|AK6}2ZOf&;{e0QJa9?f z{oH?ctq#`8XpCmM8aT+D%t2=7XO;CQ%8v#M>$OJFYLf8K?UaRQ%mWeqUh+5loG*ZX z6?gmcO)rvh!r`FG+p`$Osg1q;zrky|Gelxn>xXxriZ zT@>wZRJu)0zmoP34(p@#c=mVvEbTH9d^#`-F#N0mmoy-17qgEr?Sc>DF5#tDeLoaE zOuk+^! zLM}Qqq~EeI+fV0#p9Gu&82T&0CH3deD%j?4UfC73QKscYrYZ5czLOjBw-eRq{)`S! z``ZxJq375b(%lo~EA8+&__M%w0Ymq+6GFOOk-gKNoVeYx-`*mQjHNLSsmEjQ(9##b z7PB5@FEfzH&Ul`W4Zv#^JJ1-$I_!z+kj#wNW!wO0f@?`cz4&ZzUfdsgqSqFmg7j)+ zs=;k!>!*sU-9|ilqI}DywagueVN@LBR^{alWNYgVPtf>B&j-@(U&ZP~+7jh-b#l@e%U9dmJ^>j1{thn5#A!Yd z$*=mx&Bk@zYdSCJ5H|*aQe3Zk&<`Cuf@veH-J4Xi+AdA9e`HwR1t(_9dk**}pbIeNy#-uSzwIIJE0;1j z!_o#elBdulC($IA;M@AoXp$wFx^T`ary^+<8|g!lR&Jp##%(KlmBr#xWR>2mE5f!A zdizI({JjNz(;gpzCl+ffA29qigG=h~UN!JC+{XBs7wM;B&m~rzaQ7J351u#@li+LE z2I{7OKMa+rIXGJ4EYI@O(-QKt1A2|nlkt2l`0c=5fZ?ZRNyyKekzMDTIesPre&%i` zJUTrXU#C9}eVzVYUylOUCI5(7Z{nGHB@#7$y`QGvRC7E{<2j}* z!+l3Nt`=}0I@&MGV?T+vCy^hI(x*C=MEho!b%xiTIKiE7&vcHrOZsYJTv!i1l+)~g zZUX-@a35gm;dO9H<{qTaZ(_9X3+f@bAU>W9Wu5tSxXwJnBVk?g7J)eNn;1vyf*4c8 z7Zhc-B4DIwSR(k=1Nqi#W%hG%*f*|{9kJYHe_F*F)V*f)L9R7ECZm~e;s%OFns(OTvC5>n4sR4;=yp`*0p_nWNMcZ$*hQg^p{+U-4GHP zuE-KZ|HL%fvd%}=$|FpBBR*PB%I@2jfv*JC0)~&fz$Nu}t_%2>w`p5ooLScXlxY5b zMgo~#@>dkws0mLuNq^LhPLhjdZc<9Ta+_TY8nzhh;SIBFAkl8UT3iqp5Dm+wcX|n_ zt~V6ZaR_t2V90KSdZwc(=O24vqmsg3na&Stv(>Oa5+Kx8@;Kk2O2f;Ba0dg?6MnyR&DnmD~&@6X{f5aiO@NvaCHS ztmCdJAzuffYxdLbGVFeU0>JQ91}>?;^V~7`Ld7enZg>lic$X}L8;8TF1{|NYhK!2uquWTA=6w=FDzbMubOWD_7ax)POQlh_8$c~<|5W~qc z*Ca*aAWF$W~m2ub$elu_@VCdc*y*K9@^ECUT zU=+%FOjB%;H89h)TF72vT?g5=knDy&veu!9?jiCu^QLzya{*8c7`n~ilFUBfnDci? zw=>v0_TYOAKSh@id+nzDy4WBDgrd?ng63!uXF+n+?zHvI-v_5h<&Wq{`L6^2EbuwN z@NrM{-jv%sk0}5A+1b*s?}Uj@;ygU4b?gkJz0VS3rl34sGeWwDqI`v}dm7^bC;$xI z3UEn=o_XfbozofI>}T3rxe~kNEbCFIjtDCqPrS7Cfrwsvl%LSs34R%HIbi5r7ri%h z%rl4H$r8H6w6r1mWG+$oZfOn6`AU?p(EVTV_kq6yhOT@1e^gGPn_JfJ9D}UY8_{ix z@)f%0fo}n}0fz3S(R)))^UN*p1#8!K9aZ2T98LL9MECh9U!nU3_yZh?P#G+C={W?0XyXJpsY)4*>hu}O0bP29u@)IeK@jV;G6HlM+xN_$Bjnbi4ZOf{i6Y_O>L|6FQ z1ils64j8_AqW7j9%=5_h=$soYfqld5>VlkMX7xn$o{#bqdcOkyE$|j#=)D)cH+0N1 zhu+B;wylxbwEZj@*xRiepeRRw2Dj`1+xuqJxl#L{71poNJso@nunI7AyQ24oo_Xfb zZR1o$w6?=3-*HUJJrUh~9%mw>MTRs)9qh2WC@O}{7XQ^Y~9`c!yu zSrwdHKCP{Nuu;tYe^Srke#6seI9isIo0M~Y-*RHL%@6r`KB6b>a1i|Wz}tY~=iTVN zsekj#X@`?9+&Y_0M$it?)c%8``ka(&Z$!8Coa}mfI`}GJ9boA00GIS{_7BjVyCZZs z-K$=tBA5Y)^!8J#puD`8p;x5O6@_EV`Ux`tjj?+{SnmDgZ`Siy!QTLW2N?SQ0GISH z*Yo+E(4S@egCDk{|D)jFt?0dS>?AE%9@3HeZwFrwoC_E}x}*1|-p%uf`j<=jV5cYb zZ?;i4q>r(ULJl64Kgw6={sjCD;CFzb`(E_k&@;~?=q|>~{(QMHM1$~5ahWyuQbxkJ zxHn1TxyL!qPuR0VjrG-fSvV37M)W7G$d-Ev_!+?R=sS61=-r)TKNE~U30D%`nAh)h z?)4sY@~j^9Gmf8Q5|gBp)RbUiX5PTluhXm~1>{ySgQFyVgWMV`?n$N(7 zqdd{%4jC~6B;~n7N1fB*A|Cg-^`G0N?idl-Y^gt>yyG1`Aki7)g5f4RLnfnzn7pD~-XXO#OHw`n->K+5v$A@0zkykUEl z`$_Gta#tReN6MY--yQf=KLu|vkJ$bf?1od_yN)Jyw%Y?aH-`K0cWn12yV~<8AbTC{ z<|PyEsPxaY|8qV5THC$e7An8ixH69zJ=^__^529?@aI=4_qRIsf_7JMJSFJ3OCaJB zZp! zOXWVx{a|drrvD%V|E1y?`<#=P`-OY8<6q?*^?UMl+W(wmAMyKnpL5(R9J){j_`Q=t zo%tMH)il;AC?Cc(cw9}zU;;04$Rekg;%}Sauhr5A3yOEi5OY_Q;epC27Nd)lK$DlM zstc~xyJNT8`W7$tQ5+w9(?5-a0hREe>~@!H_D+q+b3qD#j+SKY7U z=OpgY?kCVj@h5s4V&}TQx1F8#hqgLFFXI=!hLLTwwb*@LI4{+%&B}GgfzJVs2h6p!mM)%Xt=iJK@;&$C#t?3~~Z<6Ybl$TakG+j<-6ERpeuk)&ITC*nUd zu3Ho1hx_>h(p(8j>@nh|#8C!!+=dyvbCG$l4gItVjHEZK#*pEj%^|-B;K#_5{|Nq1 zK(EX4y8&F%!;wDyg4}yDGl|Y#-#HuIPgX`4ukT4b=zJ7cJ&BXH7 zL&$;)$zt1f2!DV=MFyiHU+Izlu+$*O_lF^(!ZN8aBLUw%A{pp(Ni136S0ai}CL0*n zF~2b0Y}X`;7BZU>bGy><%iUy?KOCd~@f3BNzCk;Cl!{Cl(p_OW_fZbB?>PW|5cn-% z+9kCG-K|2S|3VEF9?msH!&z53ycTc&*hhm#()+PZ}c)A6C$;lxl|aeqYb74oYkKcV*y z_KXTB%a*9Gn z{eI@Jr(Ct)-N!@v-94`LaAJ&eLT!~(z%-ZiJ0(INt9Y7w9Ub3FqYSPSPpydm5QP(Y zpn;Ykgee~OOVmEmL<-ZvZ6Uwb#w@>u;8j2^VECO1E~zEr*UIq&AqJ0;Df>Z=&abm^ z?@`1U`$u93ld$++i|ZD~NCn0YquDH#6~Mt5iC8iq7`O+whkWdUjv2SNg5L`~2pB&0 zflEsFqi?eQFh=&PtHU$ACr9`m^$-_yh`Yl(6yr`t~kfOZtI553ye1fE}!NG)7y&R^VdvrQX5}!0%v68VFywzf{F!;+ zRq(ffKLUpT8Rv!kThTn1Yag+`6U*ps6o@wT-Mtb}H1GiYpym|NL!d_MO=_<+=Hc;S zNV2gg;g%};o7d44A0CV45qztGqq20rg^n9%UdS6uBt?6)GX~%C@|zWQQ63xMylM}% zOoC5@wxV|^=X85K8j%+`7pSl^P_EvK!*bmM-=>`I$%V zhx^7+XE&~T0>jb$ME!kA@$pqB>=!r2tOu~smk>gn^RcHcOQ!X3?!-%#H;8$>t^_0T zBJ8PMo)fuTD#Qu_54VXje^8Zt>lSk}iceeZ@@*MfJy`xE<@bOxz)gui+@=Knsc~l# zh>Gg;BIoQ_Gg}KZGEcw(?kS;-``$~#a`#d$Q||k~p8&oEm~#IST+%JkeNcPOcns!s z)~;n{9h0g3koq%F6mgC%W{u; zG3bQPh+RyN`kG_Cm98T=qV_X{Jt*?$&=5tjg)+x9*tKp=W_VG-r<6}E=QTR6oU`WZ zad?XPhqwa2EPD^w^NEn}_uNUx91J5U4xOr9Qrj0v; zYurrhOfF^WXLvAtiFJ2jHO5{ZgF8`()-A!3ke?mzjEpqjE)V(Wfle)SWSzPh{2t(5 z!0>SZT+-#y_`NvC|KsYuZA#nhpqKZkD*}U}$p}$<)Ej6vVcebe;e=EC02ItIbEa$J zI0&1sYK7;vOmJO#gW|&fxNvfT-l2%U+Rp5`dNTMNU;$wGI|W=)|MzDrB!p(u$gG)B z>o#hsaz>s-ggEQ$Iz)>o!#TyG4mX<3d$75+_I@&~pIgX3P5x3p4}m`hJRZ>$%KgPr zXl#z?q7O$bvre(ezh7CcKu1xmaEv?Jo~}nG8jvd!_$VK4yY108Rk<>LGe> zY`eFB&j(Hb4Bd}|OWG05KdW-MUls>w{R1+ngE9&Rc>ddtQ=E!(SppdJ)|2hWF(uiC*+MGs2#eHgQDLRpRKWAv6QV)Nza zSB{QV;T|Ncs(3+#%jR4x9IjQUPW07hK~tc+#;{+eKT;^egcaEo%>V~K71m?z)@*r> z1D^@Z0Ze%oflK!uc^ncfqxr#4ls1n-T%7(^^Jcy!9^ie zcT>hYMKSsodJ&cPZp``}m6xr$_{ehP1}H!1Vi%uXE%|J}_R!x-@`^C&jk)vtsmh_u z6hBuEZbwZuhQUUum%X13%hL|OW**xHz5}=@Dua}yzj;i$-^lKj>ldw+8En1Py52e< zUf-PLNNOO%};wV2@sg6kw=rb1eabm+Fmrf*fr2 zekN-7h`!9<7l2<0Tmu;X#$FKh<4AA!mF}Ed(=$fKt2$hW?R zg-1Gu3Awlou41d2LcUlW%Xqe5feKkFQHW{BF#JE;Wx7)0C?ylE*qF_$D!~~nQq8)m z`s7d#!*#dCtMO__ptLbaXK>v!fD6y~OmEiEDS9eGDK$Jfe7rYdQ~}2lRXU!4ajrYB zv;ZwZw1ZMMpgy4rN;$x6E37XFvo1=zQ`0AV@wC**!wRhw#>s8U`JU1T#oYZ;QJt;E zNA{OgJmbt()77bVpb>xI^I`q%rhZKOJ`8@|4*ZG&rv9$KFs#4#&kgIXWy{g^w{`CM z+g8e*R{ehGUiFlt_B(I6!J{nroECge2tIcPpD!Q&I{c;Zb8zr_e(>25e7+iHcvA4g z%;2*s`20nGc^sYJpx_Vcg3qVJ{Q7>0HvVU|wbvhm6D{f*DRQ}L;;1o@fIF4Ng|Rd~ z2gbxsqeBkI86Khe624cW5=40SlI_6Bc^p{uARH;DIfmmfAyMw)KoPwlFDW5f+~B8j zyL_M@J4^D8H4WCo^VvLC#A@(;Ux>K>lGr6E0*=%*)dUSCj)!mO4Q%z*y7ydWX35tk74e z*i9-nO+JPmnLV+|f`1ZG&@I0aVYus+m)K|omSeR&QIDnnl~oBu9p`*p z$DY#8d0eLEjpB>DRC+oU)u<<_fexRTfJ{J?e7j1{&s&iEt;*|8UZL^*GD$55KCk$A zUzJ?y&e5~HvqV^O;NGwwHtx*INv49I0-On$et0vuq-Xk(PpnzHx)a^z&>@DCz6!g8 zbP2E-=#?LaV2JQ>^@43}AfUBh&WXjGmi0y387h42zCYyqAbd6Qv&=v5g2yjH?-?+BF94U+AKz=)J|D*SSU8;p zoC0hDJa~Qc6!28|m?8p!%hj6+>!)l+ajWLUahlDY64j0KK)PIDdr!0= ze)jF+0$fXl|8yQ|-dq<|v;X2Ys=%(d>wJDrqe-oGx?J`bxGfi7z`k4JR`OXVzt5J9 z%06ZF8}Z zPv{*luL!l+qNHncoF80-s&gO33c`Kjq%`^&XA1n3&rd0i(t;DU36*G^5tieN1&@9i z&Wo1y3A<>Rd!Iw0(}c(vW)HK+s}?m(^=Z1dKNPlS`^U2L_eJ2>0KI@|&;8(%?(auF z5VWUgg08^+c(@Rz&ELAE(`)gmcoP=b2DiN_4{N|$wZ7% zY?^O~7^R>`F`yvOV*QG8Zpf;4TYDc4`AuJv?SI3;rvbA7!|yHNk`_hx9lLVuHUfUp z>DaoKz9+JQ;82d_MF#?yXLtz5m%G*tGNAo=IP}03I8e^D55b$gl5($NM00`_nYj}C zjpkHJx#>iaTgRRwzd13g48J($=h}hv1dn@0oJxjj&yQ#v`+TUPu;o_kV_~`8f^Rdf zJ^)W#iryb!%GCre$@u5q7y0)w<7(xW)f-lB+ab~Au{O9zU9VNIE)Zjb%MtooFR)8v z1K^JkGxdZBds9xjFfC_#Ji44BGjy10_l5lIfSy^`uLl1t@HxQnb2qr8{>~K_Y}weo zcJ3A#)S0$PY}dRco^^#f(<-lKS-})ZF}F-}O8e{#Bf5v8d}Tg#dhiDXvAR+7dN_^`rX;)>=ii)?N(3GFliX^+t4BFAM8S%C`o56VL^i@?99cH*yK{H2q5C zR}ypbG-=OSE4OUfxOPh)*|N4TDt6(;&nWBEk(j6kqM@<+F!%FT`!~XRemH+0PNaC%$TuHJq$y*=LH z^bSV!$}i83qv_x?fjNLA`Rq@xt+AP4gy@M&Fhcb9*Q{CG*)hMfk7~@Sj9J&=wBS%g zXIGS`l_FflMrwVuGOdj>e5+-)bsJah zD2B^CF~Zbq>l0!B@jsbu$6D~AKr>+IkBi>-H&1P5(&${hesz{=+e}7H%h}eOiIMc4 zfa+v3IkG>E==MbUO1bX@zZZA_Fm#`Y-uFkhOLheq8RMl%7|4=uU%EoIm#j!wEhxp` zmOn-}vnmj)6{>k9<2)JudePb zD+m%Be3hL;%UVuFyg}@ngf-@7CS)d)dQ5DHLK)A)eN&a1@7o@_K3<`4wn9G;Tw1g} z8S=L$qA&II9QaGXj{w8pFQfPU)l&|Cef3nu*dezvCdGnHmIQ5r$YLT zS7z&{4g56VOu*1z9=$j9VxIr5e)<>*XSp#mtQYJVhs|*95&b<;{!;$$fd35m1z_mU z+!gX?%71O7M_}lS_;F3(bxr&`^-)E-dP68reFCSl)Wac{aD{XAFosGU7G~mzuquY3 zZ#;&NxO{A!3;leK*uhqEU}8i*XL7d32tU|T%l95mdII-_RosdWJjP$)kG49933Na? zH#vP9qqe8RdhU(NA?17s{2RbG0aMQBqW7kL&C`@~)wWINMaw8U)xoOTSJ+HT(MuATNCIhA(W=HQ$`OVYR!}`!LD_iwQJACW77VGT-35XX&0I0%vj}{2h z?uc$L`I>#}{ooG)j{=77esD?s-OH|DeIg3=V!;xU9vSS@Yny0yEERi-s!^y9JASAy zbSR?hUz;s&J$Mr^958ezMDI;G%`;oxBk9V%Ex6!2Zo2huVRf2ownEBk!a`du&xY;Y z6Xh%Y{4Vf4zZH&k31w8^7m$tHl&XvZ*@iVtw8z`?%(Rb zM*yP%Lw`l|zQ6Gv)^{#_>GWkSD_HM(WW76%&G-IHGlM?A6p4Y8SDUCVL{#WvEGufE z7#NS`Cve0Kh_RRnPIS&u4Z68+e(d>9SYLbL$DA8~0RAfQOTh5^S8z$=`jNw}Up;HR zv{cSuC~G^5GvvZ0dDd~y<7}X`E^%B@yu2V2L!9pTBf0!27y(yzDyJr7sqMLtpVsTL z{bo7%xj+YC__;26-xbOCU(1mf9D|>r^4dNtcMwZhnvY{;f30k6x*U7mIA-}M8>7RV zD6B#eS?84}^6OFKKe zSwecwnfvF4O;s4ofW^h9(PT%WCncJNI=7hvk)?&!U#htnhZiRs6iX_GBb>myUv zwShVFo8qW-&U4tZ*>#CjyeQ}}x*T8b12t1KK0a<>_*taIjA zH+ihAp*y^AWvzW7q`QH9O~1Vi{AS?ufT8<1xFi#=<4}%X>Q)R9w~8P9Yz6fy#4r-o zD?j)=SyXE0e1$8p$y=!Y5QKtpa1D> z`_+Rt0mA{q--PIWzwj<_R^A=bi5bPm3cMNgxmnY@i9ntNH@|E_u z1NAkhF!a|)?@hn$%IUX#^n*YJ#3<-v0d2tFYS92(^e0v56_o_PRuzp1>G2nn#-Ns4dS7QZp)3?`dSEn60i&~beBi(4L$QT zbOXJ-9IAnQW$~%jy?ISkNYGY&@|Ct9gyr26xq0##M}uu9w1c?~d}9a_<9w9(WNj^vgdR^0zBmUpD0E-{Y(xuxRQl zHp+l6JAo|Pdxr_*%nuwiNXBy2aXdj_2I2yI06xgw;HbmxjlUe+CbH*P+{dsqbMWyJ z1$I7q#sMyixWZ`=-gnR^lVVJFzNGbe+!k-JOUeJx%V9Y-M0`p)dcdy*dI3|8d!zUL z)#DN62v*4UJ>o0mW1R5MWPNzTZq{d^=n|gsC&Cr35L8_D*0(B-`<;UQKlZ)^JgOpV z`_}DyyE>iZrpeCU%^J4QA>GX`VHFTG)8NV|2_Y;RNK8O+^wWrnxW|pbmAH(O!|Oi9-h z{i^E=#xKOwOtfe#s}e>8%SK@GUT;isJf_lU#2TNp_>XAPX>mt1vTch0D5anHYayQm zoC0Y6v()FBSHEihrL}@NR%~;yW4XsTX1;ND+Axeli$-Fs9>jtl{@v2=Hl>$%--rAe z@Fk#m_o~k|pMKT6tFYL2oHRHRXRzZAHh#jY$UP-#i6pI4d}W*C*DDJlF9wzXny(Hr zrS7g*VtnE{(btFWsb+EGxPy$F>FE+|m1fJ;cY?HY1Ll<|-t9^+`S}9m-N37W=6z3n zuKm-m+E2{;#)R+qKuAtmG2(mN9Ag`reih%+g!me-$oK}YlKv3yT*y)22te~zs?Rl_ ze$~8Hl?}_$k6E)eUZx7lZ=oTmA2-Fg7+W}Z9bfnDk$x9l9rt@0`FStohk?fc&G(%8T=VEx&4=bm>`-|MI*v6p zu@YTS@j5N8bR3@0*gRw~t|`dstsSIwWu zzJ%tT#!bK@1@vUWac`K$YeUP-ACwKhGS7@Zo?^7TChcfeJQRmVA@2g72ecips?RmQ zeobwMIDsVC@$t}N6Wf)k5t&3gd~c}yzcwC^>5%6F^8szg;p%hEuU}(!;OTZuM(C6o za>x?}@7|()3SPP5ZB}~8|3@G{4Lk#A-gngJb?W^8ewTe>s^h%NDjO0mugW)2ALO{L zxY`{y3H?zFhq>`MCgYw=%S($|Ov3cq+<3?HO&N#ab@4bH1Gy4d3TS)k)aTlN{hA~W zWY1!>LUJ**#5+Las9r2E9v&XBaCuYT2j zH(<%Rsx`}N=d7xWw@Nv6^J_iEvK7V-j%Bo@^HJ%1v*O*V^pf9CKz;^z9?-lms?Rl_ ze(jc5wEUWPR~jaNDn@a-Hhk^UUw?Dl-${_C1G50lJ6Cy$kaFzz#t3KA}F>eEL=M#`l?vWwvZ?)=V)j%h{*7FWYa`pl3=1&MVPc_Qp%wGslpUMFqsNQxh5R_M6VP@%3z<@P^JBW$p$$NV|BYVY zVT1xH7QFilLvcbF8sAs> z5B=Kzdmy(0PXe0%&yXo~?|&kH%>B95WDze?G{4 zfPj2Yd{LLP`ZdAD%jwzn3oxqVb7!%vvq=1E!noXu96VDj+_QowL;tD9R&ghn z0)=sZ{L%9cHnPM82FZ%6F=QtFVS*k+qe%ZOA7tRy*T`*+(!Na!Zmfw=pCW5PVsJ49F!kVKz2()CP1DHOqK76Z|XS3>{*PRrR47N92RlocGP?u?XA*Rm!NM0b>fr9`_6r-|BI**g7=N^^X*Rj7H!@ou}E7+kOmmUA!pDz7| z;s0FvwOw(OJ&!`(2|TObi<_RJ%yK@FJBf z{r+3y{stkB1ttRIE9svCnNr2YQorWW`A>Xm|Fp`(JfJ(x*x)%0HzUl^bU9Dc?5zu_+ zK&BK-;n$dO1bhRUEbw84u=BA_jd7s||BU4^zE;K827P|$BffVae+F~_n(uFrDYc~F z3zyKv!GIC_sSJE&#D{zAS9tKx_%EG-ZHli6`uxyG{@n=q4&ZJ;^KFMr z$*0Q$#}}ZaZQa3gpIfbCm1&+GB$rB{liAIF}@tg{eeM%<{Ji?Qb(%%iOAb$*e z0chTDAX6$!;pdphn39mnNU9o*qHch?R@RkRWx2Tv zb@^V&8~jt8cP8Woz)^taJr*)0e+qxc1jmmp39Ag2RVG$vZt247|GVVf3cY^lC4V1+ z{0z_rXx^70Q)*7Z8!8zeDh;X(mQ^QKceZxn?NGe_yW+fI$kTz@faaYKnUX(MdsI4Z zTqLM6SXQA}9lEs(Z|jfJ-_6kLhhFmc4#+!zM*+?I6l9T7_*)VgJ9g}t5}m=KD#hy3 z?VX96{vmmNcgJ~$Kn?-p0nK|5WJ--GcuPye;ZR8QdeB5QimDW=OLuhUt@uguZiHSx z^pd~VL%tpO6QFtTg)CBvI7h~o1QBVS!J;a~>QYN*-rzqaudyx8TL5_|FcQ$bC6Fn# zr>aM#p)nxW+Q_Y%lkfSUo$`v=IB%2UL7Ok`ZBG#nDW zBMP*tO0l}MErGX9@peG3A9{(G--EeNKp#N!1|U;vOTmk?!ML%(@uHU`c*R+$F;Pj?;+4inq;dE`i}qjYXe4|0Kz`f_uZ>p_eQsYlEZ;0GuG_}82U+p!HDU82*t z3tf6sz)3POK!EweCZcX*~K)BSB(}0^^F7&o)|3 z>CaZ!uE%Tcg?vBokn)Fo(&ewAdd+fJoCQ;}j2AQT@V?B;Hl?RS{zjCKA0ht}VE4z0 zkwL#-yu6CM_Ckl(_#U~1=(elh2i12)Ie>gHa7e=MV|LISMm(ofMXMC|gr=UxdOYq- zzRF4_tC?ZAq<gR`7GT<<2o%$?{?@Ygt4Tz4e~3%>q;+q(bi3Q z#y;RHDjQZT#vVpBVrdzx{2(zLGTrz*6MJEapv4D8v^$1j$$arY7_UbqkVC*YKqnoy z%IXHpA=UU(U-T<|b@;9J<7~+10vB|z537kmWj<8q8=Ik0#s*5ul)hH= zTZ+rekY5Gf>R#WH+NHDz>a$d~@$U`?i%p3TV9^OQE;I@+D>jY5yU#}!#Q)@Iu>P;y zlTKpTv(ul5Yr;3swpkuM$gf^S;i2#7_x1PHG43E>c;Br*J-}BK{LX(^12FCajk+fO zb^0odmL$rReVpiG0u1c**Y&vT?@jg7L2PJqFf7<$eUbPGC3}h4{N4HO8 zORHRLbpsX#VVhoimdI89r5TFx*Rv9$@1=dI9@&nLLLGP z2XyLE-bLrP6oskO*pVaSM=PPGAu>{Ro6@@?LGP)MPY2d_uUB+#L(m&C+Js&@y(H@O zd8NHOp@W#H{J#eIP2e4+m)>vba$Xiq^3(!72D(t94{3xTE-dgBe( zK&T&R+!#|YGFq!Qnw0)F=n5$P??V0n_#}z`>JwuN6-v9Gh$)sOQ`z0B^cJ;B-zm-$ zAx{BjsP`x)o#LTdnH^XXj^W??d9qER)4W@p?y0b`r-Q%6PRafU2k z{zv2M%9KKm022V6wBJ>$>S6)y2eB)lDExB>v2_-!)wi zndUarb(3k&C0+7{u`9!cmJY=sgR+hOL@!huL>Xv_Y*e>%jS5HRDLAex|W$ti29 zlWW_Qpbg^-O5aBOwn*vQ0{KSZmIQs;K0N7Iy>7t@n7BZ64FV_}0i(G$R&IwbpXobUH-L6PCs`inQ0bY5qKUFyhzu??cJwC-BBN4+ezek8_>^h*aZKfA1mt31 z44{)PkNaxe)k$NA(zinXR+PgtAfE+nOwiY<9FnoB^}C7AA^7(pw2GDjd4fCcR2nVY zkDwqh^u8!XG}nV#bo{ZIxI2%8Z{WXq5?x%7r!pI4yCXv?w2I*3*Jxbi?}d(&5opn| z(ybE(p2{Kgqhm_Hq(t8p?;$w;9GM?SJ&pc?ieEM46+jK3lgtmjVBat}In3A{APdPV zVJU1?Ct>`kTxwmG5=}HoGqw+)AX4Lu)S~o# zoS^R~$Ug(FKgaV!`xn!P%v1UvOVrn@^o_%BwSDs-9|kN)rH@W0(!OUC^|dK|8x!g&vJA%742sPs{2TD$g(>(;JZy11tHWN7VeT*!JG zXppIR(|`I?@icN}`7YZPAFo&l`AA?9K#9KE-bMd93|uTZNfG!!;4=nM?bND$N^g_W zLFMO0$hQEusrN{?&Zni=QyNPi(2O+P5xJP*U$$-uv|i{|4F5YMic5K(jNiIvWUR=~ z^C4dhT&~{h>L;z_0YA^=@Du;`U=cNHrlfQK|Mma9IG`Z47s_(f`dqvoz6JSR;3GgM zU0-mWT2)hjXf18MS6+)fapYzZ=h#LQ!@oY_%!6|&ofhKIl75f+Jqj46R%a>onmDdP zvK&Qm54MZ3VGx~#)%WE4bP|$(bS@ReSrlqIvrE0|dsyi);hV?kPc^sxOuw>H{f*c= zz3Ck~Vz>~&|8(jjGxQ2sIyGI~2{L24#lC*m7B8TMhO%Ml#_ z`6>rT;{W&exyqb_?Mu**i2e)c5fS{Swo=exF0FVqUD$*UCLws+X_*LdQee&WGjzn< zWIHa=X|x}GRr)C;F)5M;#ONE;i9$n6S8mc;BGD3c(1@DO+44P|amXrk`(+d5jQo>1g1!;;tVuWYqPH#l622+>s7Fo(n!Y3b zh+D_p!kUC{N}tqk@Qb9s`YcxJ6TdDqN&eRX>+W+_rN5z#>3S?{hICWa2hWIzd>_s@iUHn1^?-m03~hU#T>ceXE7_caccCU#Y8v@5+kp`(w| z`wHaOfVYz973-rx>riMNYAm7RlvJ~CplbjA8rNG4xdaFUI_WsjQ?^h$5NZb+zaf>f z+;la#OzB-Gb%=7a5%ML#j zfp3!N#r@8eYgVoj`}*X=)_mi8jL^weM%0KwvK$ocj+cY+kS76UfKJ+PJPlEWN3LOI zZ)odnY*4y%IQ>fBI{90X|LY-N1YDY+k8CPlEiOl_-~`-!4vO5bGd5$HcWUD)$y1Rm z!(KF@G&Vx-Qo}+85M`lB@qL`Y_akKc6|4~s=%npmUAelJxZ!{moDSZI;61}=!+JN8 zR~Bsq3CGlIc45}M3@!vej|F4X&>-f!G0o;J~$E=qlc((B(7 zFYgl|PX%Vm_XNL=8{L$ij(wsMbX&pkB6bHE57W~o;*TOm`9%LkO>I^@8==#$?B5J| z3vg2s9z=UcB#~x&8Q~E!axH6i6%!up|g%ar#Ppmpm#PBJ=wwsax=^f_x%yQW8E)5<$!~ zB_0~wL{ARhDxW41PdnkUV7Nuan*Phyj>4$lk+OK-k$nX$=ZJnBeU-W$)QdCGu~eUF zhlff#jo0G&n*%u?=q2A1-%N;$9Qr}%(_v&f))u77rX%Q6`pOgZRYG10tVpKsl!p0O zVj9}ULEAVyw<1F-f{dU_PpP*d$H2;!{+0y&PeOhcXiK7Bl}E*41?P#P_$%W(TNXuX zB#28ENZpWljTXgI_7g4eJL=MA-a;{7wt-KU4q^- zA)gIwOs2PT=}GboQi%8z8n+6?vdD>=UnKLdH9_ACkY5CLC($R?=RvfKpsmPgg*F`l ziUO4-*`5TI-oiKH{ttyb94MCWb@Ctml-1SHyB2!a8n1~iKB~8Z6* zAuk11B+*~npl9ECpxk4uN5trSTc-4EPSA5Vb!lIUr`4eh0i(R-;}hE*_EuAzY< zdFH)P=0T_2HH-?Se{X{R^tUiS49Es_(s962XEik^SBjz9ez3Hku^YLj8{BxgX;gYw zK!+X|y%O@Zz!rc?7iqrPTp^n*;P>vOfVer|CwP30-p+yOV~r-I ze`kXJ_aJ`?dR3jg-9Gp;yQACCIM< zZvvXP9Wtc@@mEhIO`d~7jnSxhgYU$7=RjTv90_RNV<1!7zrS%-+Hz|+wr}vBW>|PM zuG;cZ$x&&P^mi-tYJZ=A{0#6spn3lSnbHCH+fY|swNmT{m4i8ND6&Tz*3l@k78TeE z#aH-loNo-|@xUZN^G$(FX}^9ZvP~woqYUdPVk;C*wkp1j(5LM{3GNl9YODu4o(kmz$E&bX9y_)xH$Ugx;1De--U-IrZ|KwuUf)&q;mJgwF zT4Pw)PV8taBVJDH6mL27YTn}^p9ri0H1Elf576Hg*l~r%bdpxf4#n3BeVT6%$>GtM?0ZU(U+m-kXMKL8r@Y1mC%p3<9wGQQ(Ji1S7v9}WB((7cNwQ#ycr zZCJasmgXiW_0w0P>Ob^pKU*O`1H1rezLy|V+HZM{vn_+49`f@-_zA$zIr`~UqgnC# zKaBHEfjkSC18ClPkSQI2pYaVLx^otK{9~lQo1s_xdk^GR;Bi3nJ_VW5e)F{p>nL4@ zR~r@z*CJhpn-s6_qd4za$WwsnfaX0IGNl9XcOm)(SS+`?o|dJKt-v7{WAS3;4U1Oa z2$>7TNwut0`rQQmF~1={20R65{#}qM?bq+*>=nPIMI-N|HPE~tV+0H^9>b3C>=c#r zEg@+~AwJP|6hjUJ;{a{PM97r7?x!iw>!P2uC~~Zv4I;Ap*VOi(Y*@IFJOf+x=@VQq zEcrGeGIGT~vn;@b;-n$P*fH1dE# zK=bv6OevLr;}5{Uiiq@Y1?h)A>i?Yv`CQ-vK=WM!nNs)uC9tLN&o@@`?SVec_YLH~ z13v+p?`O!A4xk(_R!@5*ZJ(MH-|SE0d=-#S0BQlv*8rK)e#>o~ZGvuxHzE%KBbd+* z`^QN?TcKC``5NSRfcF8-`w?VH2jJ%l?7&2`>XZ7}toVYT#rbAKUH}{kXud^|DRrBV z`syLhma-iVj+cIJgzee*H{j8)kTi8P+iRZM)Lnn4o_PPP;}I_OXCC?&%MyAg@ES01Tv*{Nw0t9d1TD7y3%wZ zKbFoZ>kMlhc1Bj`lorLi2YNN{UdXPmFs1`&-gL;6y3OB3-Lg`Bb*OM%jw}X@IqKX( z`pPFuzmI}`&A%4%X}}qP=3ft)(gEc2swyldTCXnHl8rHto;Jn16M8l8dyqc_K2co6 z*sZ@h#0hNmhPU3Z&?F+2A0+(>cEt5JLOvHbAJBeX1esC_ztAaITeZf2s=q7cK5tBn zy;E1Y)W0YaI(98)sEqUfmniVZQ0}iathH3V)o_c^rtI7UJ9Hd|e2x2)Kp4<=j)zRC z+w%U)SXoehI!em~>Se!%(gGMQ%<}6|6dX;Faoq@ew7qXYeh>H%(Dr@;nNq5H5*bS! zl3ygY`}Ed=Wh(!_iQBmz^2NYqfVOiJWJ=wZvqis{l?4^MsWa;=MpZl)eObV`pP4g6 zKd)@6w6`7h=(vWz#TW)K1<>|RgG}i_%IhpY6+i557B81o{^9XbT!}H)_(u)cda0_W zvY|ozN*CJXt+Zh@D|?$@kGA(c$e#jV0NUOT$dvY9Zhr}DleF&BWL(F67q|09$bSHC z2eh4cLZx|xAi^=TS9lxC|CNM67>HO@;2Z;K>PIoWJ(9%7w&tA zmAA#oqTBPP;`RIx_iG^JVqgrQc_WZ1bz2^^f1OynA4;m5A>-Kyy*eLnfqVyW7od6X zg-q!H{M}~*G&o*RzMGc0_U^^W2f!HqW+uiP>SjuQV{e>)5ab{b0yO_P$dvY*ugTeO zV>tcg(&_IVSOCC+t7)nAido8k=-2-D`a7Oc1O@?`e<);1Dg2L}^OCf9DQe=1gr=LS zK)i)nU01ohdf&D_-k{?wP&y|5{hG>pd_Q%&)2jTfgFo6|&yVPX1KEJ~HxDwUZp+#K zK5vt@Q~rZx{#L*r?eCu1{ zBdP@zez|p$?A$~`6aBNW=q7J;;t~(*$1>B=-A&a_gZ(`;D-?L_d z;hkVu6O3lXzc+z@@;^;u25>N-<1!aArFAK;OCu%m{`S9TO-}i-`(C;VKK~pUpC<6@ z_`C#pH}I;mDP?>X{pVI4V|b4-tYd^7jmi%Hzv6aGhCCCP1L!!-hfFC&`O(#Ie)Xya z*!hI+%N3O0EKW;L;iLfIq_9lgS}va}{of3|+W)&DKLR`sXx^tGQ|h+fC1t&cPDjOb zI(ie#0GLlV3voFXJVf&Pevb1V1Gy4d3TWQtkSV3`H&#NEoR2D(F0GfH*TfSDW>D>~ zL26R=wSZs8WiRBP0gP_M?6VNYO_ee04oI33Eqa`0>WY9KcNCjmNsr$DBZB7QpO zFokF3>SgpKSJDw#p~k42C-ZG5^lILBA%6jM0Gjt($dtNmSCX+FjnZP#4Np17G~OH+ zyKm8E_pHQTD6@x3=dQ$S(pf13GSdAXEAeitwW-=Q*YeplSi6CtkyP6f1`r$eUnAJw;i)5>HOuTI&y6L#o$z6beJ;0r+8 z*#VhSig@Z8uyo1tBP!*MkfcLwLQjX{EwkdhM?+o;tN=7`4P;9Dt#@(OirI@<#V8s> z*8{8#CT*oBQqy5FU$#T9_V-1|uL5rXn)hwUln%gOY)T}iSN;zmonIy5qd1kPiZ;0h)IfWJ=xoyC@m!N;Ifq=v;69F;5Sjw<_Ky=+*w-4*722 zK0xz62$|9W)MmRT6Q@0UKut8 z1-Ti$4Zt`Zvz}x@_AQXSjnJ$8y$mg0W9ak%80ofhXi4stcH0?>RXK&F(+ztRKnuTk-B zhd%A!vyfi_UI#Sa+mI=B?_UC23jcyfNdJnwalV5f&je-zn(q+Elv4Q@IspG#6yIj( z)BfEK`99!5K=VBUnNs)uC9tLNui{AQpC>)e*AMbwpa{@>BOp^s!45j zcOm580@nbVZwq8f-TRlomcqZLqojWyL!aieGh9XnkOgSIY{--jq@AH9Eak%uNhXjA zEm%)o@m4^u<~Yu1 zJ=dygT(OF!I+Jz|pr=jo&d!YURzt1>)&QD!9b`(~=BGY?bYVRfXG{-Wf;8e30$`F} z8C`^wA0z#3g|o;et#`_$7RKNkAPeWR0EoKC1gtb&F?O(6*G0`w+R^z7(K0FMEh_esc<)}zjQV=&@8Q`m11G0?oJ~{utLVO33_#Tza8>@z=MG1eFQS4{kEr_S-ZUv*`|0s zxpCe~$SZ&o0L{A^GNly$?vs;Zn1ycCCysUEvB(#>`8 zIyB;`(UVtHucpz_#M-I0?oR$Axvh8nXQKKRly4Nly%oU);G*hL2y>0{YU$rP*suNj z9`fITpOjB2%iaHsSF;W8Y{Qyu7|qK5vYv7KpM?A@@B*Oo=S9erQq_0t??zXSohR;z ztVkYj%D#BC<4x$lpGi683FCmX%;MPX4a2`o=1*a-xPR9`z8<&%pp-Iy7X8n8wbJme zG^~}v#wO**#|eI<^>!IPAP3O-ln0` z2ILLEd4T4<5Hh9xwjcYj?t2YPddio}eA@%Pns-nimoWk;1~hL8WJ)Rg-KR*_V{kEc zzSiS@@!}^to@4euN0)fpl%0*RL)*Cv^2@-hfVT5Z$dtN`&wt;_g7T=o&b$SU6=0kl zzs_7C<5|=H2nubOZy*EQ#y#3QCdC6zervkCH6{BuEffRm}0)~C%7KMx~EGB>hJL~A2-8q9hW2gF5_6B0?=`(f=uba>&5>iQAysc87(RN^P&BOcx3^gqjO?bjs&v>&BhCX7?C!V0{e<02~4f1@T9MHTAAXDl#Ka#Lk zlwt5=;9?B!$wecUCp`GyqIjF3SNq!v`DtJmpn0EzOes~n6A8y}04DgH^pYT0BmFHL z5a*3Ro(9YUH1AxaQ)u6>mR{&z^FA>OV`_KrQaK&-w*xteC!pFw*WT-n*TP) zl-eiDby7N}$k*!n`r7)2;zO%xf$E&Hqo=U4Uby4Bnc>0x+`i`V#8PA~h&{hwS10*8 zpijp+b1?dYKrTRu`n6r-t9Xir3t_>U`jxAf4=av6)eXV|qo@Gu$|?OvL6=_drUvpU z!0CYY=Of6Jf?dWf8%|kWRa`WD{@OLw>xLE2s}(mN3M#Inlj&m&kGfpV*5m3tVD)Qn;)fW5@s9=B_#Yh>mKo4JG7wP3vMGV|?pbCx&IbD%xa4%q#~+V?}V z3weP!9$*JDvCL9hf$g)?Z0yEnV(rWV(`IIGZ#rU!>Ei7)U)x_V;}#qe_iGm9!+~P} z?bmN0Q}U>Ms))#Z>g?Cyt1$#b%h(l^{Texz4-7)CUCr)iSQ9bepve+QH?CzrGGlhY?1k_QF*7_qyBLf6nYPd6<375dKgAkr zg|Rkjh~q$}_68ZR3h?T3Ru6eSa4w+jx(_m??|v=qIa|G|c$MQ}mSM%^Yw4zbK^t5B z0%L9LUGoL3vvxiE7FC1=Oeeq4%<%TYvX5S$H?sf>3OHUnJs&ywoAd!a%>f>s@3jYF z1xzw^oE0`lm`mKf*$_6D9m?`;X>$8oX|Jy+ZtnodB|rqw_MQfr(!!{;ciUl|;wbGs zSZpwln%^jD{`c$*FU;MHTwwuEq1nR>pvZdrV7WYZu8pn6u!x>Hw7|^6yE$f>+lz%f zy&3qlM`5wFdB9_fS`CRU+(LaI*Ac5A4)& z{}S@Q0N1d%A7RLpzFR2mU;3*geqi~m1#;>8f@XG(iADdK+43zYde^gyUB>NZ0NdAi z02`+FO>=pRV18fI&Tw*iXIevYGy9re!>=bFw)|PDE)|{GQ=){(g`nz(hdvH$bMe@NmihU9x-!zm8WsyMevUSUYQxFK3!> zi!%GYg(pr%p~We{Bb$yzOBmW_sg>p_FpJGX(=jKzc-lm_Z99(b!k>MlV`q-&;iGVk zvZk_$mJh97xo5n~XC7%^!>|{m2&Dfs8OJtdC$$6bLjD%m3ur&eM@T>FRJ*irWo?f^93gODk8b6$xasm_>Db;``~7h#9Wtp41% zkwuNUeZ6@;Z+d2i*%SOTEFSCM`x<3@J)`3M0mvhP5}rxDWMqU_lWJ{^xcAm0x>1ZaC+fP5hK#KJK@ z7LJo)P~Qxnm1iL)nb^B?peO`WO^QnJOc{^D;y8a0@&{`?Vgia00u zGea)8nG+m7+5-n>8ar8Ew6da#kG8T@i4UGFdG|uE=Jf?##sFX_pm`TSrZj1qY#(o* zn$S)b4Nu@DkpkJsPN6HDDE-UA3IAsHPtlp9AmW^e^)W3^wl&x_B+KU-Y8GXhnT|Jo zPET)NE95HmP=mMDnq`ht{gL1~(#~dO2em`DLB1Dw0MK?mtUlN6kbaG|L(~fSdS@|T zaTbN8+GsYb4NQL@CEL7a#p5Y)8ROtD@$`V)8}I{~rwB5o9c3~O`uw}Hws^YShNYl| zoyqRRN$wVQ6T`Z-0dpNWRb@r!Ok2J|`cnrz<%;JF$eVy`0L}9mWJ)tCB+s*l%2)8v zb}v}$LvDJFa{HMnO6*?wa_A$1`enEAjUAZHr;eS*$A{cKJVm|DK{lU3-Ku=MZ=r`5 zW@HRVADv+zY|hRfdI-+G9?SN4y|!Zy^f*qwZy+{c<2BGW);gr5B6Gy#gm&{hrDb~aZhokc&2!#>~c>rC!WVAerfjj!p!^9G_SSt&g14r zj^_0lcit|y{gOM+Yxl_W*m-%5os;Lb+h_&mapqfg?6hjMT`280N^wt3d|Z0EE`umqnhOC+SMpo*q!=nhT`^XAP9^GdICcMKM;|} z#;xp9%h-ku?6TY*bbHc#+33LMnHjyU0bXPZy7O+Y+ri@EZfyMFF?(4hoV$kEz0hw6 zq;VHsd73%2M=!(pqiMZQ=8DvDvGi*X?Dpdw%9p=G4uo9B5J3BNJY-7xdRmv~Zv2|F zT3+)0oBmzl`lbEzT`K+C4*UJEpZt3h^4Gxkfc9@l_<;SJhb_@4?-G1eOG{+q0&pY{ zz;*Yn>^0MP!a|oH=cpVr16z>Tz0Cn>n62dT+9S*{5nO-wwsLq@CeJBwaa^pR(A~|< zL(Rj`0MuP3?XH7ey1bnS`Fh|cK->K$WJ)Q^+f1ybpHSXPQKY5;hXXYLhp|s$X=FPC zyCn87vl;C@l5S>UQRQr#Fmb??hFfStRLhWj|*Jkhi5`kFM9Lh zm=^(FEW8+s*KWKp$~H+qT41N{|2zu$S)dKje!LEu(%D_cm6RXFa~fvgu{z3toU#!Z zb{R6oW8BVG8QFbNLJF**9ML;8Vcp~w#alEk&N~6}OkfV6c@Kx2ns**n&X((|m4y}Y z9qeS|Ui4DZaV0I7kBTt|e=GfMhF@1TRLLvZH8xyxvA29|kN0v>h8DQ|hMP z7O!k5iHK4kMX4VQ|jx#9azVkWgrwiuoilnJ0s1L?bxGihiCci0JeGPN0-cL zW&zFzb`MXXlQoKZbpK^NLKdLhUM1tz20L{7@)qPDfS&+u=g0~Bvr}x{ZTaTIwt%wp zc)ZfNi|o7!>j(-veXx_ey~566wo{lEvl5+7H?DAnl|^Lb8tYDJCB`qVmUga#9lAbV z2Kg4?HbC3?BxK>2>UVZIKOvqo*HzW5U5a7Yd6jF#xJN<7CK@Fj1q=tA#aOkUZNa0{ z7;f^Jqs$|%4D{i%TqDxB2NxOC4d2A9Gvqi(#Wm6{-$Y#Jf|$-LeMknvfVOKfWJ)u- z^aFMMT0=vKR@p5K<*XR+0fkc-EIAt+H)6kwtPCd;Wi5lUbA*{Y0D&6i2|1%_15!_Z zKdVQ7o|$bJpE0W^@zh-_?b-@n9j|SW9|Rr&v|Ud_rqni3_7`tXGeG#TLIKF^Au2vKI5_TbX!$Y1p0U9N)!$|1vW+oP5j&Cxy+SxU?N- z4s~(MVIFg+ITRPRj>}^~;@sod9yg>k?sd4w11X(nIJkC)l!=WH(mffFvbfL5^f-`u z@N5TeL(1W~P7hBuq&%MQOIqmfH^n%ov_j7uC`atT> z{Z3y`KS%*S!0GStLmJ2jIROuP1Vab&A0mzF zndzA|)a*5f?+6u}frmo;;ZWENJQCuqAqQ6gL(RaWA^up%aoGrX;PDWDBIIDa5b~2D z{#3}}Hi8~_I>dK|oHQF@5BxdAcZD2`FG7AM#Geg0nKnWncrL`B4>?&jf**Jx#M?qn z4;$eR{3XO+3^_SAG9d6$i2pU@ zMn(i)5AiobPG1{Y5qLAi-wHYXZDdB^?GSGdIRP8l5qKxW-winfZDdH`y%2vt7*<&Mn0$+#tHzB9gMg|4G4e{?nPS{2k1^yP|--n#BHZm#jLx}GUIpb|)Q{e9* z{$t3QXd|Nn{|ND)Le69xSrzzai2p0(OtFz!fuBRXG3-pWkzIi^!+d?%nQkM)0%wK! z*cSBITN_OBsd6Xw^3on!6eAYT{e*N2_Ob_L`uVcr~eD(xkZZwT`n!%mgG6!J}B zeskEVwwFQvU6|hzc9z>KApbthw}zdS_VJMa5azdrofGUD$hU?0?O|t?y&Cc#!~Bl0 zQ)|~jzB9~Q!p@0yJ>)-y`CVbB!CnLT?l9jLcGlV_LB1!*?sxFn=uUoW<<3 z>FDt=eL_C`8-I?Q*59c-q4J{|oz%y)&I3z&T&9X%7~&xW0g zn0+xFJs0NBhn-89-9$$(gn3)oxs=(L(a~SR{Kc?yIkT^zqnE<`uVLp(W@9TnREsd* z9d>@p?9FuaN|^5nJ6AFLYC3u~%wG#T*D(89I(j|K-v~R`G5dNtdNa)53Oiev-AqSs zhk1M0xq;a?($PC%{%+X0iP<;P(R*S3e%SdPvu~lJ55oMzu=9InZ>6J;!u;c~^9N?% zN=KiB`KMv$HfG;WN1uiH=V9lM%)Wz;z6kR#!_J+|ZlR;E!n`Bw{E69j(b3mo{!Q4q zo7vmw=-V*=F6`XH?0f0xZ(;s@*tw6{+v(_sFy9+??q~J`boBQy|1s=5$m|_-^p7zA zDeOGN?1$;-pJD#5u=5DBTj}WMFmH@Fk23o)Iyy7L*GHVknf(MEofY9{N1P{_{S+OY z6X6>o&eP1^Nk`{K_{NCyXJ+rBqw^yC{D|`mv!A7-3nKi&i1Qq?pQodXBK+cr^8&Nm z=;)FNZ;Cj7VfKr3bZLZN7I9u;_Fw7f@(8~o;=Ii4-E?$igl~#CuP}QL9sM@KH%FXT znf)3aT@~S1N1WH0{RSOf6XDlJoHv>M79Cv|;nzo;x0&5eM_VGiIpVy-?04zth6ukg z;=IS~_vz@S2){Yve8B7v>F9S6eoMsph}j?0(eERCYsC44*`LzUA0qtLi1QhJR@ z>FAyazc=Fi!0f$rbYFyTk2rs4_K$RQe}q2}asI*VpXlhp2;UKL{>kir(a}Q@{&2+k znc0nW(s?ApTO-byroEny9*ywFBFYMI2W1r#dP#sgg+l~E-~#U9QAqu-bQf(yfeyM zqBsHmDa!APsuSSdQNAszPJs7B`Mptf0=zHEw@1|p@ct-&AgWG)4@UWps5${Y6y*;` z)d}#CC~u9b6X2s!{#aC<03VO?C!*>E_+*qn6;&s|r=xslRGk3-9Ob*B>IC>qls_9) zC&1^T{Q0Ol0lpCBZBcas{7aO-7*d--@ae;M-B&9#tp6ccT2=s5$|@7v=9q)d}!}DE~03PJkap`NvUp z0{kS(KaHvr;Ac_(c~qSMzlicLqv{0sRg`x`)d}$HDE}rZPk_C?jqs8)dP|q){S9x<$J-@hK<;^Aays2L0&87AHvU-&_m)G+v>Q&xc zS3JFEb5^h4*4vxvb4=T{A6(uamfGJ$_w%*=srjWof2TJJ zwf%hLe~CH2lw1E_&;Co|zZ;{!mG+ur&;DOlP~JTW7oPLXbD4QoKQ`C>%?f+2_v~J2 zbDb~UnJ4+)W?6+9_qo#xJ#Y8qh1QGMN>W@Gx24Szue0aH$0sTvp8(VW`ug-#$dtN{ zuP!-dO?3k%yvZ9|!-`|K84Bu7!9>x)wduw-_9!z}1Wd1Im8(C|uD0gLK^y36_DcR% z=-1;1FGJn~yrDR0D0_C7@zAck^Tc+|`5?3*OgI#;dMVI;Z-Y$fY&E}Ck9#KNk5`s1R@~T)6{vqcX~$mhXgjjYUB)n=7|?c{2AR?xHD7YJ zx)0sejwtr`o>gB1_eS>RKMjvxN^HFI#40BNjnhERqw<`XlpkK%LM93EbmjRl;6*8rT zD!xT?leZh9oQc6(-0`m$H~jCH^Hl=kpq!?wY-6o1<3<;iyj&Mz%(BhV1Jjwynvaoq zpJjV7{emW8qy^Ikq|I@0YG00UpN@GrR)0hpM@D0wjGHeSkJ|{y5nv*q?LGuDrLOn+ zx|R!J_cS!_)W(!8!ALNlLWZ8pjMp#}oQV<8o@O6OKGvLqxkqFL%4fc`V>5VkJ-q|+ z!@%Q!w&NYhl-`&x*h%BQHN_fR#R2Mj-qPAM;#Mw2C~s&9svcPD|m1W|d>vp!l7(f}D?(w?PEi)Zs z{C&;Qa+VG5V<_G_rI&cmg?t&X3DCSZs?Rl_ewDnjdRa_+Qk96ZMRyr60E;|bWt@+q zRp|C&4m{Y0$dz)08%De0?@;=Q|0l@lhvPmlp!tVFPVKiSO*CcYc%T67{sXMsp6JfE z^V}Imi&_3AoA?&Xf0O0C#WHBtNuwCZZ|N=LUI+d9KF$Wnmjasr&3_AIN?o5nSh98* zrpy!#Ur<%KdUbWZc=UiQsW=F?x_*WE2|L(bOq@x3y8GCp-Q3lOYShVQiEJ9{`bho` z=-2%uegvNJ0Hy$%fA*1*|EFcLUhS<>?NV2MG6V(;XtI9vTw<{%Yn1qZGZQbjTH$WobP0Gw3V9rEq;BohG`#m)EgTPvS-3j-0duM<)b~#%jC`M*c+JVMwWjAE7;6D7#nP2JujjE$6mrbO)UQsR&YM<=;WK3 zt}N!s85>tM#D$T|L$g><)3aEt1^5ax&o#Ywv$RG#yD0N0w$i+VnakK6Ec>v`5gD~P zgFHprUibIS#2@zY6&q;0HkGYtB(JU$?6B zO{`xb@|7}k-pbY0Vr}M%yXiLSne?v`mRHOBIMgh%yDp8b?H3YG*5R= z&zo*}sg*q1tT+E;%7)xGT-sHkc*(9B$o~a20oty1^|`L+`c;z2xnD|>gWv6?}N8)JWiiuBIJ)X4kp0dn8+IcI?m6#>w z0zP!-edMcYp|K8O2KZxa8s=d4HHxR@Waak7Q;V341ppS{qJ0(7jAGP(N6Mu|9HRBTL&Gw z{o4rn65w(``>_c!rLOH?;=Yn&gZr%Kw3BsN(5YGR?SVec_a)@7fxjt^)aw^?Vi}J< zr&!RbUFjXSC_c~PSCA`!YC!vOHe^agUHX>|YwD|NSD#c|O+A4*;@RTqa`{=ycLIt= zCV;6S#x91%ZwFCS)FaBE=W>xfZY$uIpI<%Z zLiiwuK&fnJ@kqi2sL+|Ch=Su8}VzwqWY%F7_AO zn1`p4(2k?2&UE#2V_y4k78&Zo&2U#nUdG65Z0mH2{ zOlCCuyR1BFJx(zz%wMw#a}3bTWP4IkD*bDL{eIX_{_TYP3GgML{o8n~^lx*Q{+ITz zX!ug>evLJVh84>TV9WO=s)CNYuMBcn9p8hx3cp%yV?E2jgR9c@bBs z+k-)2#}i6(r;T^b>xFzu^W>S<3H+q~=P~m#R)`r7nJ!Fg$HZ~R^YwCYf^_jb z8)qgwBZGw&O{)zB*&k8)5C8T2pZ6eJ$GMC&K*#4n$dtOyQ_}INr|UUdEDe>}@_kC7 zDFQ|SM*?$zLBQQIG>^EA9eDOkge50$q>brI-U+U;m@R)jbDhUL;}Dw3uJTxD)^gnJ zyPV;i-bcm8CP&Xs15#zp)24AblK2A2#* ztkO-_C_C34;5Iq_@L%@%C?rdxXW~{M0dIXLALAyCu2CCX>?h?mr*c` zit(zwTO2P}Lm-EN34o5VV>bdSvrp!8?1mgFFV(r z+21_E9++X_`2r6*3R#%aI51<7ot1&Ueb6i7nE23txSeVDci~AT ztI&m6soNQzUSKB8VI9$fWm?|Z_EhgcH%3}`4qBO>X+y1h5qa-5EG?6yd#D?UMT)lC znA`}lW0H(pSw+0O9S-?K;3PoDZ7XC-OS{ZV(&epkP3^KssCr#xl`L_O(fM&Qa2U`F z$N@s49^UUVKDIN=0q!2SfW-_dx8rp%H+m4B4|J?tm*W|m$uTVHH78iP19LNba*U_p zGR`!&!I+kVq`e)m#}9j`{je)BFB%vEXnT)>Oi4e_q|c*?_Lh!`+xsxtI|ZmtnU26X9u*R%yF7fiYJbF{Ugno9Y4gWUX_|iSbEb(NG9EB$pZI6ZNIJp>4L!&j- znmw#9@72gGH)iH!;-O8iYg$k4Yh>eH6Vfo{CoMA}s@YYOX+Q=zl>=|380|j7U&I3nOhSHPR?$^Bfbj!(4%Sg+xF!SC!(KQ@TZX7y1-8qCGx5*snjOWMMC77mSKFsWc(W~>}sbnnzwmc70;qzTN_D}~~k31xP zdO7n_PhlWG$jm{1VXiq0J%>!dw~?LXTgwk7&b2uw@!v7$7Uq#ZI?{ERcusAn>HQOP z_eG66g}=|(G1d`gi5&hiI-)YZ!DaFIPJ_G}XaIEnegm1(&MFz-H`HsV_|6gG?bT@R zHGgKT(QK73_c3vFi#+;4zAXG%g#5fr;{kJ!JJaMvp8h>BYqG#)4zM%frJwg7gv%Ef z9&8_mi}egPh~+Un)6|FKaq&T{)H~SBbo+#>2yS|r~tyXP&L zbI#nkvz$50c$F{K(c4*0deR{+yqzXg{vdT!KSsaVf$+N<4qbzvBE zLi*)i^^El#PNNm*&%C>R0)gTH3xVkN0Z5Tj?|OSbe^Ix6(cIEc-;%G!x?f z(0pPf-{|$(`E(BWJYWGJMfO(@bTaR+5if-0Tz2Lo<^@XG?N3?@>(__Al>u;ql zbKdn$@JE5~1E&362A9(Dyvwv7Z6;?EPI@VGbP7TntQO4IYgjg=Jgsw_M2^kUlFjca zj_iOdPm1I!+mO|h4FjJ9OalzvGr*-B=8qrm@7mqB$=iuEB)YQFh6AF6&O?LoqH4h; zm~*dgVv4Rg(8@4`WEd>abUA)dkVco)Luc$D5T~4E!p{%A#Q&(A@^H|tJ2~QWFMJq% z-Yekm0DlAwpUX}=I-lD%oVvbg;rb2h!U3=HPdKSojs=1WVR9c1wyG+{oq@CNI#rhF z;&dfiNH@FEuFzfm;zTlsuWUP~px8+dvWKT|f)bzpV)Xg8PUNJD@SEj5B5=Oxdp0({ zzPu}B1;F@;_j@^BJH6O947bbO0rb1Gofl#qQrN(&A~|;>hnd%&0)H9!C1B+IBe;}Q zC-Yk4wzcav?3}%Q?%M6!7p)IfmywS{KK(*A+%MvbasivXZg@wf{UDv^rg>c0V4V_f zvYTT*>NaNEdn)*Gz!Jdl@ie%U&iciswd=CY-K-w5WpmKL-rz-buVdZ9kwiaz9LmrX z%@wZCd7sR&Q_?dWR7LqYD0V%&z#isy4@&u_Z}g4yk??cucQf>z9AZrHSr?qWw9mgu zqx<>b3C2C2vo)DP*`+>0*a7KKdsav7oZgg`uRr(*U@TzdI|ck`^0n*tZM~{)8;0<6 z28)buDeGf==rU+Ca-^%U3&{!ca6{)&YK`2qwXBKw+XH>m-=7D6 z9e5Kk{CxucIr&?FCt75+Uk-oA0<%LNUscvK80#~stBgmGiXfTK{uFf;Md3UjqNX@HK7gnKEP)R+jTH4n$@5BCgACx)My&cT1L!O7Q;+AB!8q(Nk1Yr2tP0oZP6yVUGww0S~up z2PHOlkN$>MBB>KNrY0=wQbKb;sCiw~KI@@t__`eYM&MS!w9ik$|1W&4UBe<`?Wv*1 zhr`+i-f%k?=C0CKE00f!XarIj9Q7S>(c~n+$EDWw^4$Kc1GEIhQAMbo@U{7^at4LO zd1*N{;M}z9U>=z zGw`wYF+58+9O^znH9fSy{xn=8TMZi`c@DtuQuvj1aiWn}*+2mxMds*hwHQ%#YlN6rgwBB`t5<(=?QH=%1&zLTqMc6|lfvF#KiRw|ufL+AvhDR>_k zAeZZgl-bXn7V*~%FQ$Lo4t^J~yB&WW?RU)l-k!gCTeqRuBexq|J%kIs;^kU9g*P2@ zD!Nm~)J|UE$n#l3dbVAyznp`9lK*w(}u=Pl2zh7 zxH^v$aB=KLVdZtxg_!*$X)5Vhlsz%s8=+Chd%0iV2Y&^49WecG`nHINTRNHV+S8Bj z+q6jU2@@!#&X8&6E8*mmC+H0lqG_M{rE6W~)C8X6k8}s;aVXX@=TrRlIV># zFURkt$D?jybkO>T8VBXoI#m23Z_Adb-ETxbvyXfP{BhtZz{vk5xRj3eWJl^3M3&## zIE2>Zxb%+_Lv5eBTw8a#RYik!H?Jp-#EvV`#?V5SRXY7f!C0$uR)s@+>(+>$n(f(s zFadlH&;S^I)__YXisOnIdj!Kz%)_y(wn#VN4m=Zv#`42v|3F!9Gvkyq^P{HJgR$ZW z?IHR*EA=>CDN{~MW5mZE=u|>S`o+(|KL9=i3?JWZiuf2F$7xy<$3ZcCwC@))Htbxx zCfhA4TJ$^a)tZ%Qb@uiG@)?Ix*p%d#+m${mX%{`c zpYR6Q<1?n=zO(+a7kg$Nmeyc~(@cT`GdS3|b;bS1PBcTjeo0qZ6k? z;gG(Ny|Lr3^4ApGeky^Hh%6`VLcn&rI=u&Tv|GfnUyv%}$V?`ivLQZ8p5hJuX@eH~ z92Ot%`@RGX8|anV!~C8)&z(9uN0!sRE|Y!DQvFNETWPP?1JsG$5_6JzuqkTa^p5Ov zR|`G|XaG$6UI8v;O>B1(m^gCrx_{N0({^lcl8^$SpLN*8a>H9N^+R3Lq9%o}_@RJb z%SZCq?X#`7{VLtZEArA_KI4=`g2=I1`iG-^PLQAD2gQ!I{ZdAb9KT0?zx*iPj5}L; z>AT7~OV8F7bdFYTxVyRm>(O+jwBA9EQcdMBK&x`a=QJSV-`UgB3q9WO|D zJM3M`y->+3GisWhs^=8t*p-;Wq}hfS$oQp5S~T3P99q19%A?4a3YwK zm(O;k(Ya1&A3QhW?*R18Jo5j*-JRsh01STx;8GepS;x$fIW=0yNH^Z2ULnQ}LETah z(sO^VF3{HUD*dZa4|%MNRx#0$yLUE-^u zd+J)OY&NW((X@3Ha`)WlU1-1LseRu5=<I;dE5zr7lK~M2yC~0JV#aLptX+&e_3c&U=IWpr=PH&%PX<@lQ_g zpg1{IFG_gBPY6~lwa?ETs4Mjh?aU7vih{Jm2_x&4KoKRt)5GkM`aYQ5tYN$ zWpm`CVVpc>?pNiPDF2Kcw31ug2bHJ0vX^(=1rqG)x7wSoYwf@3;CEW>aWN>jZ_!?b z#BHP;xFqTqJ86Hj9{m#d&A{z|xj%i*iSEzc%cJ}Aa2$uq+@Di6oNDgPf&6QnxAN72 z{9Ej|@}=qbV~vJ=(MU#(Zis~2xodl+tg*cAY*MO&{skq0ogBfZU5I3W#=8wBA4^d{_dc#jd~UgkTy#9 z4Mx$%y=Wv9D4b;9tn|BzFtmS-bsBpwkL5?cowSEM7gvFQ8+Z&b@+Z!X_j(Lc7HCh9d47jBn{b$%HqN23gt1F0%W$^|z~W0Rd#`IQ~$4zL&|cc)RjG zafqg&$A}_+@70lfOX0sVmTxQgjlivdk#E^~k$ijO``S@HVzg~pVk(0#J2 z+S|42u-AuF_|ecOyT(F3Zx3}ceT($W^hkPUh4g`<91c)>Ft~DVMGUg;97%P@#X7;+ zb#S`gmS%3r#l_iS9h;dQ%ym-d~FSPFx?F4t4STrn$OZ1q+X=%)#+8{R( z{>lwFtiD?57UlNxdZz;SE8@xTo*Yc{y1E%2^lok$2i}X*H6F%nJZ;(?k)B0B8rvOF zNNu#>AC>;K(tkypuW8V|Uyj;yH|=Hm%Xh$^1zrG5dv5(g)SlB$j-Ho>SfAY1Up6;Q zkNU~$cGxH0PKaXt=juSNb)#F$8n|DYfUCN@)146kEuT)7`+W(G!hD)x>bALpr~0we z&mE!1Cmef{I}1_#F07o3^7`b?5Iq%{DdmXQ6&`)IQH4e`DO=UIqUH@MplZ&x-S-_HmX)?bAK>S7_HhRHRD}sPE{vByQ>R z?ptB|+!=#qM&>#A$eD5w{HR7@IfEK-zf}r`)ECirbzYBbfbeQ$ZnEodatOg6Pd)XB zeBTHEG4MQK===g)$}1iGRt%kJ9TmyP&A*7dE&|@Gtcg{6x$Y?fo|;`oS#@_s@>O1t zr8^va0x$(IbmxG7HeGX|x>ubS(Y;-Xt=NKy?#b=w?u+T(NWEr#@BsMJz)t`}ciV*# z-KXR6?t$2U!pIxVkFga_MYH{y{Xeam?LVmSvX^&B#J?|Lojq8WBzxy13nbcjGS?r8 z9w22`C41TlUzan{+qoW!--3mV>3pU0IbppS>|&)CsAb+9Jx%!pKCyA_U*sqJydIu2 z-(TQ5DbYL1Lmt>U#JJ{N@n(Ie!Zg2%pDp$|B*umZ8|5@MJEb8VHy!>A54<~7(1l+q z&T%V)6Wr1Ta(nKuz2jA_I#qvYJF?XaOY`pNK0QZ!nEl=x;O_$O1E#(H4lboLyRXxC zkSFE%4NdE1aA;M(Qn%ATURD26R`)9XVz|m~Ks_-}7?INa^|=46gpFHv)}- zq5Cs%DT_K8k5+~2`{RWA8bf}c`o16TCoc~@h+b9i1=heSq9s+96_m0dc5(??*PXNN zg?eCSKv||VzhD%RWkhvSrY1Aoma7p&pJ71u8F~qZ;wER825Izd8JFXypscIUS}vWd zd#dT>Gvt{@5A~el@t%Nf$4EkhKCGQ%?4I(?!EZ!z)?Ad`=gj~=9#{bwInM!?va*Ap zq3Mt9<&-dTM%GsKbDA0>%UkvB(0f&)LM}oTpv%1_EIBIFL^-Yr*2vuHR;ZBMR;B+C zX?M|o?TPO{^v!+v9eCnm+sXqBf4we=_`5sSS9IL(NBm9SzIs*T+BL#pG#P%)4kyE1 zMd9VA(bV_=$2iQ8U*RGg|E9ZmXR?d8vB%P>0wxY8;j)k#=oBIPZ`dylcgu?CAxQIPQ|fm279X_ zdk(OxpGbSe*3a-vN*^Z?_!+$F5E}WMXQ`z|sLeD)xzkG6kvpe)N|aUZylzhGr{Kmc%`?tWM7$ zNKU>Uu8u3NMSajy%~aFmq(Rog7i)ck#)|c3o0p$!`qmH-vLFp$7i(VbYr|M7#$Wu> z2D>S|#f?uy_jfnH&)K8kPXJE==KekpE~PWO-tY^?VsiFH)GWlt(#V<~eK|rJg-8-Ak!=H19?3 z-QatGM*u_jad0W0lWtb__T*nZjJ#F!+_A_K{fdEWw5wNvjwd}hgXUX21j&$abSLH0 zUytMZFX3B0*d@sK-_*Smjstx zX?BcgA9K7k?oIbAy-(Fv<>_Jh0Ao6@LxEiOJ4yRz@~xZU{q-u*Baw%$$V)6k^S#d1 z-H-Q{+L-p*DYjB+T%DGnDt#&Zhhu}e;9(3NcMkuY?ih4-&p2*R~*z@P1JS4W# zWciS*laLQ^XPPb_@avnE%_ew+yyJR zgwHxJX|+$^WQUg%!`G*A1?98j!`JEUUayRPHM8AEb3>e0d7PiiSWmcvodPePUNFW< zROWe=$-1&&oIkN%r;7>-6Zo|yf*ceABwTs0DYoWhrM(*hDCruchPjVASj01^!i!Y;B;JR*RR_+XUMn$Dp=ZxTqVO1dE zad9(16~}IElr0KtPD_#}IkQS<5HflOKDIMtHu{NT9jE`PoDfe!KhYA?kNdF`=h-pq$l2Q)NIfOSTB!VH{76v~nnc4Awel?PJCGr?~&jQ~C zd1sFc+z@-@b2Xk%XqkXXYugcU=8_s8Q z5@#eciDJxNN|Q+}q~}~8jPu5|1evRY;+8;P9~67KC4i~X>@eV}^0kPcozN?Tp73)$ z_$|O4fZ^vJa48+<+jf3%hBad_O`j;N-#jVDdQDwUnl-?xLl+$-N7@t9JxINVZqBu| z0niOFbSuE6behNT2vkc~HgQMJJvj;GYsqL0Shp)8BZRw^usUns>v8|5enbBX@Gk>j z0Sx_{!KHi-x!1HAG(_5y*U+9g%Peb*lTF`f)$Nb(KlK{AI2l+8AQv!n)8JA*Q||Uu zC0FHZYN_Qc6{=;jif)PNEu}s~ZwL6fKr>+IT?j7abI557iRAt^ObkgLF6hCS?mp@@ zbpHhYci74|=7T5q7dYizdd=5FqG;-?twV~@- zVS{Akd`<1JoE@}nHYMl2nC@fLYvg9r>uk=lt+I?-}YwCaBo$rap?t-l|5 z9WWd)a*YE2Ou0sVe!=#}bazs(k?SkqHv_lDv_3F_tsNIuO^pr(M0z zfxiU&0x)vC3jSGg3>gy15iVj18Hg8 zit&#!d6(8o$`69w4?YEN@sYzN;c1u!gparp*puBK+LO&bKWXh(H)zoz<_8?&aXdxv zEY84P{2jz7Pmb{dFTYD@I5du9@@CaO&Y1OfeBW= ze+76QFnmn-YQ)ED9qgDo@=?>@aDrc1m_7wAob&;k75q5>4$iQ1rHcV^ikywzbP)ly z6V4cvl>{Zj=%y#hT`(UlOmrm|33eUWJYXAHmFC!hg=dkMklZ8XWGCdrnNQM~+!JVt z&)D7KP?HZPf3}~CarC>kvs)x!UVJxd?@N)x>~kLme;W7+VC4K2xRl*-d^K}^`Pp(V z+PbjKacGaaScm32eZ_odzj{$y-xPHiR)+KK@O0~Ry$nVBd|5_^W##W9{%UT?-iKqr zHv`)M!`}zsQa+v$^#>CN?r{FXPb7j(TL`s%>Nzje_g{*>A7ipX;p^n^b-9?7?N?7E ztQTOkIGO9@=Ib=xq2i3Wu2_y* zgA(7ZRs_6~!&>yf=pq_iO?(!triq&6`va;~ncF|SYj)D@ZRZrDuXP9YmHGcp?Txhm ztDF@!E_$O>KF(2Uj6T5}hgg+=irT5+*6j1W4g3P&62P?6x51^D=ezU!*w#){H*MV> z>eO1)kgLUP@cA%w-hM?@d(cAVCc7mPoTc^l5gb^BIaom0JYVI+pA<%Mwpf!lsX5LF zxw(7)9Pw-2mgTn}_z++uVECN~E~Vr7WykwEb?dfmI~tp2Z^1S^bl+^tjf?`a3H|4O ziFooM@tHQt-fXa57H!d1{w41J&{+x{dCngIe;@b&Fns*+_K1(A@j0J4zv#$E`{$gc zI%$%4&arI$i*vPDw%)74%QeyE$Jn;=;hOMuRrvai=$qQ`P2Sa<67E+&$;C5hupA)q z+;eu}<91qhx$+)Xc6C`#_g011XQ9n0Kq4>Cu`!+CH$nID?2}KluTw7Oe3z-6%1C(E}_0;Rf-zX^6xwB8P?)r_#}-=2scx>{g0jt>!&DQOopK z9qH_KA4d0UbZgcQVFma)U?X7e*A8$g<70ou&vU<~nft{7bxU|ayB!Rb zxG81X5$>P&A3;&DFQ%WqD@%VE_*h^fVCYWH)=+e}zxsL!{@d)01|TAJO6 z&xU)m{b(ilPT)Mi@Oclol%*ZwmYVxBb8S=1X5*upjx!P%1mpvK*;^h^|BnL`tX#Td zI!+FCXA(D~cQHB9!_$^(cNF`LYCrA67F3+GiH1B=^*}KnwP>>+@%b@)nDHjDoA_=( z55Vxb2wckCn9oXMPa3!9^ety>*tS(%ROv$(MT@Iq@f13se(aEcaUl#!iud8V5dZch zo6xS9R*bOy@R+KMsJ*f+9nZDEc9XTam>P?&ZI!x5dDGMhYGB;+_a)-{4?m6YBlrJl z@ZSQz2MoW3Ov+LYZi)6Ety`n3X;uvRR4{PU8oGwycSuiv?K^G#8n}g30HeFaC;U3}^7557U_SfFWw*OCi zR>}?5VNsmu-?MKjol2LbQ++e(+;s79ULVz&w{@l@xZl>h?R;k6f_rWK9Ns)7IIj#5 zueymrZLqO$cn&@>i6r=_oFuiBNGR(uSTGZ=N%szduRFngPMy;~hrMKGgm$~~iF+Te z^=>cT^_O>7I036mw};?w+Jo@4aW@J6l-=9LBo#L+I=a^n>ojLpu#D5^E0lbFmHhPP z5WT@3=p;@FmgP>EtKFx=k3J-UUh-lUyllHKf)3Fv7O3c%4e!5F#`uzggjW#h82dVNmd%w*4R3MW+UvM(d2%FQ+@v z>RbY`4XnuR=k}1!?GC2dGkcw)zk0CRtaH@Ol&!<&W^{Il&f36l|#MB5{D7sShZ9 zOxyHh?d=-zRrf%4ex41!5oiPqU-y7ZXuf9dA;v()tFq|*OB+GTB zSA%iIpd6sMQU;V2&JJ#1A1oyFDE)?_1G47{`D^GA$zy#Zd){3JUJDEZj64g$r92$_ z**a}`(4+N6D9^&RO~kj~(J10nwBY)3wXIt0QQ_;7t8EeCKF7L^ne8+^Ok*jI)@W#Q zJQHc1H#&c)=MuyQw#Ml@w4SIgmUF`9%80*K=vP8t#=XbE_XBSMhClVqh`*pdYG<>L zFymgx-{K8xW^P#1uFWf2_2S#LYSk;k*H=iB$(vtr5neAs3kI*nd5Mym%miJDZ{Df8 zKI!_EUF4eUhuji+>20N_tMFLUO81KRZGfNpnBUFd7Xp_8hTq4)r8o;Cew)nscHD2n zsOt?)+a#uZv;&hy#ozE*OkU6pof^Ildx<7`N9`gYt*UY+<1M)%w6(z4QFFaubKLc-R8C6F9ELrhTbK6 zB6CchE*&#wTM5^cFm>ES`IvV41Zke@y^*iySFoyeW`I(3l>F2Pt+9@tG7s<|+%^ z(ll0=l@6XF+U+@d#NZk3#&YdejxHaV;aXcWU|{h;pTCSh)Ez_o704cs?*jy?qs9^(8LFzs9lE@gd3`&iR2n^tXW zYS^}QHSuGlL$<0fg(lMPpm?_qV9~Y!pEvk9*_jd!n)_n9E2-D4v$lYr12hAM?&aW8 zI_lTV^SdGP4?w}cUHtU>qDlKbar>>b1SnbQR7(dI9X`)PSXyc$d0(SmL-!Bh{{%h( z4Bhf?9i8qDLwJw+UF7kZCo1FLt1oM-M->4oc$_qm*8OB)`@ISDfF~7Z7bug2BLdFH zamV)zj`&#*J+rU72>g2BX29_CAh?tlVt+8BKQ`?!g;WCJ*pM9<vBbz{eC?^HqODsiGr`Ha-r1;TwoPd1ArW8Jx3lwXH^G5HfZ=N#xRlQ3 zS>fxD;Yzq_Rx9OZ_2Oo|N16&tQoIag%{7P+NANN{Qh9{+?v44l6gsATZUDa>xEnBh z+z&3LvwiP;++-nL*rHConwEH9tWDR&#-?)!R~B~9GS{g`+LmFFoCm1a z(ESkn6QT1+mTmwp<+)DgPm!~2yNoLP#Pb6L-D&+jr(7?R!F(E)yj;@5BYF+gXVz`2 z!8Zb10VC&`;8Hs4Piw-h`RpxWy5?rJJS4Zn`Zwf`6LNE%ou;qlBj=;w&jT+3M$X@YOX*Bb zL#OQsv{~Jpl{6Vjx?fp)I9x1ilQb!k5;IXG9TUk}^WE$?G7@|uFa(a$<8$;y(n`3%6QlA;O?gf7k_%>kZJq|9VGkWH5wH?8Cba^l? zuS@Zv1jk151>eig2W8;>fLg%Nn-4B!MXU#E>Y!iS%KQ^rZn3qvONZNu>%#5CLG`w6 z%^2*AX9?Lzs4FxcjF|m6axDs>D1V@=7-l&aD(34(`<&=WKR7Pps};Itef%)^kAdd_ z!`I)yrIf9S*2UL#(07VHSmr6i+x-!5tub#O+1C1yw;+=|^@!ZD&NLjNGlxS?eOOl> zoDlI>|NZQJnh$<5um&*vT>viSy4c_NidcVa=Cw29d5u`Jd!rz;>pq~{9aPV0>oq#% z8JKRAFy{Be;VEh`1}IcdG}(p9*{bKt_(-Xr6!EhUdggg~3;eIZKLEo|<_8f!ojot@ z4x3L451UWAI%Ma4MgxKq)-ooQ5WG5j|M(yoo)b>js5T;I;HR!W;%6oF0^Z9wwFUeP z;B3I~vkP2GXZxw?J2!~YFWq=NQ{h2%Jdx+hB_^WGf|IlRsg{`DKI$`e6mNn575E2W z=w%*{=rwk-e_OYDOVcI@vcUhs?c$fWTHNvustdJsGa-7$hPR`8huaY*o|~z^)lUA_ z$+7&bvO6bac@tz>}6VMefe2oT|a+tq#Jb%sEuqkY&7PYZ` zH~AC!(UMg}uN=!vVw3Qt+ek6Y5(!Vd&}f=V$2P^oXBU=$Zcf5cm&)X8^;`JK$0t zh{qRWPh!TGaQq9GcI=fdkM>IIWG8n}c5?q_8#(Rp&SOTHmd3sJ*JrhR6&tB-6b>K_jZvpQBh9B>T z5kIdqMDxRkvEIqF&)n@z;ncwRdmtKr&;5YC%t8Fbtt*PF!f9&;iaMFLy0#nk@^ZV% zv^CaQ&AQ=4z1kdDHP4RtS_)lr-`0We0L}&sUpInF>1-TYxOT1Vt&T7Z9W4Gl!%)jH z5g!MjW7_Ah;GY8aQ&~RxfJ^DDeHM1!JnxnM-i{9c?|;txB)yeA+x63yADI)o^UYPw=DcyjcR? z2j~wNerAD7DT?Rsj?YdkP2se0QZz(=sI1puXLRS|;e6+KJuRNZslQ=f#Ltb; ztK_|m&-a3V2lzf<_<0>%N^7i-J`z9S{-RawXwT69!~YhB#&ph5!yybc%#Zk~c{-ve z{EP&j0W1d$KWD_>oBL$0<~cK&yf~0oD{mEhfLhD}{;nD_Lz9z(j9(n+3|=&N%3Pb% z@J4dz3%Qd&(3yj}_yeuqNEW}4t3Tjq8V&06(al@g5b?Dax@Nue8u;&k_W;A!pTVVc zw3{$|VJ{{-p(EL-d?;oEPCFYFsi*R|i0+m@)! zDkqdUb%?~x3nF>To(b!1miylayapH;eHPMgj`M+;cHI%0EGp|Gc69|X*AmyWlK(OD z{psLMz|MB{)U_O{-(DEC7tOQQ`j`;Ngd~doYzYeqj+Ou*=0Nz))r!+S&cXp{63bc` z@&6h$8h9)GzYqQw;BW2dHXNDmNCp8z0Y3n|(~fR^r*uW+6%bxQnmr?HbUjq! zLkZU{irTs1xorPj2fi6N9T4_JAJ7CY+fgfRJf9~}O!)teO4)J%Yn`r_*<$75NWQwCWa-TU zpAReq480}bQjR9ykYU5bQN~EP5((c_=UC1;mNi4yik6Q!4l%t}>NE0v2mC4ES-{Zy zDY%r*`b*t#T=v+VgS-NE1^fw6$0I{{qE(c~O9 zw7r;eBi}siMphml(YuuTjGVWE?*_gB7GP|i=$ z9|ErehF;;%B6@q`eC}p`ZQ8JTZS5AE;}$lpnYw;Qr~qe?_AR{U*(^>8UuU;_{Z_PN zdo;Sd99>?BE^!vUIpNRaH&G48g&$1|U-w5p-V@iTX!R>t;f+7V5rNky5O{EASS3E4^`FS0(>eV~?GRWk3w>6tBo$ z!tv@95BF}O7=ceAZ!-20VvUReQc(Om<-SJ<1VVvl?4p^8C{(ZSmi$6F!#zEClsk5V z@<${mk`GJIcc#03YKAvm2z2-KbPp5JrsU~K%xUwy{<%SVkUxb~c_C4s5HYqxboX46 zeRd<53?qIB)!rcANtX-=YNz^xTxwEIH+!I)PdH*y!2~;}??|5Q>8kTET$!)@b9lJD zHX$edRJkvz&k*qhL|o>cwAPy+HiSPA-idy2nN;^Bd4R5TaAUA{I^)!N`s0Lsp7Zxa z{O%cSoWkx)Joc!+@1%d3b@?vvYk=zk)Bhd>m(nqRWZ3_R{J45O`2TYt98jJ}@F7IBaC@i5c3bc4)-74->&bC3ZJEW#H;7FdPtsA0NmB`T8z(@Wb-9-iWi6YkSr*4(g(<#Yw66Gv&25@-Jvd5_^O(@W9?-R0=mm4|Iu|r2BbZGElX;KOqp2 zZ@e_AJIc2iM96O=Tj-zQW<#rfSLwV+fIX*2{O^W8^Spcy{3+lW!0`VfxRezg&hf%_ zT_l5cn>|0e#1-fgKVdF<%`4XnWx_qy#6YUs7SStvIXge}2OkSe0t~%n;8JSh{g<)3 z$@%pqa{_{d zKC6=7#4{ydXPordU~t(Sw=%%2q{1CMk`-Dr0Wx+LvUUzeW|%*GBL zIpl{|DJ-LlgBA7(?)Z$JdtxlwVSJUH;7;`aqWr(A>hL!os`PK7im2fiLQ)!FoqM9a zJ^5>ubB(sI#WOFIKFIx}O8!~dYM!2U=8@~Kap#VDOE|nh2Y-sHt#fx!=`J1Y2%20E zM>>1dyYh=GB!$c0+W!Uy&US;mmsM^tF>Xr(oS4q~qFR1rO1l)2oaN(PG}q~+mo7TW zueST+{PBzSsp;n&`A0SGl`6M8oF((8*;9!CON6ERDM$WoNOqNftUqt?LU&Q_gz&CM zA}$KX(j&1&shfM`|E+Pi)-`nY)dnJ*%(AB@?JnfEygr{7;aQG54)Wij{5w^3M(WzF z($^gNOX4EUTqpm2gYxfD{?}A>vHb7>mFBg5l|3*b)AP?b3Z*Xo^~%3NRl8EbEh>G{ zp%vsoX`B4}Wy-%v`8TWTg#55orN4CO4-4GH2)o5}3xPx*T)anBHzaxF!tIp}{ zs{wVX&c3=5=R|u!Fg_fKOWn1HyxY+ya4T}J)n)IhaO56?iFVC3dXeKM__X|TJwY(9 z&$YTxT;8lD;x+cH<9sWJMcp+4$AEP<=CrlWTK6tn_x0AhL@{@C-{3TVj(R7>kDgV$ ze4TL35%x15^SEU!f)8FF&1XAb%kKBC1-}c}4Vd}t_ux`?#qpYV$M%omd{)yxbYtm| zCbZ{X?^gFoPwn-7q@MI-HF}kAeUuogi%FO1=ad0NcqdCq8PH#M56B$?fO%vP0m@ZR zTrL7V!#e}xwwYpHNGR`(dJ}(G5I6Y^$-%OamC}4uB**C2v+LLC;In~wfE3YpEb17S zLzW_^u5H?~L(&r7sNs^A-DE8uqSBs+^_4!*Xey1983NB5GTI=YV$yssM8zW`j$4 zufut1SpW8o8^T>c!@cZ*!a#plh@TltRXij)222(dWy0)0!~!evlNq;1-^9TDJg=wj zNx)qj&Uc9_!!_9P$$%teW$>i0_WBPx;pKnB!pog*c=>Vk;X`)#?nND5u8uyuC;IS%=<-%{c~CvcA=4-7 zi?j74g>AU2?)Ongh1h;<3v-4Zlb($;@vrTicWwLkHi``Y1>1hz_V?TNpKSZjcAq=! z^quzd$L-mKTdcutq8c-dymX&eaLK7-OH}%X9x^XDmfvJN_g)(>&`EdL?wxkPYoY&y z{Xg}%&E+|{JZA6LkILm~HMuKEBL<8P?y{@r1#haLE||qY;QmQ{o>!Dig`a;(B#vme zu$=O*IrP2udX*EauQFNW38%Mazr9=c>c{8Axb?rD{dAA69^qDWc|A+*pk%&+Gyh-N zUp3p+dgK>vDDT5fE_WtvlXyVe_v_pXY~S-Pk#8cNF11U3XzP7;oks?XTaWY~w@HM8 z>+RfuxdZ$fUG4Ut@o!C=_cJxr&iLq%_jR}*P4dT*pJC$U-^({`w5Cjc`;hlTNp7K8 zkotG&fx>CpJdoQOu_D*0_HLG%cwocFm`C<9<)v6p`PZsGPPJX=_30H5?bxQKOSm^UqTQ$Q!eabFF3&18wVU0&*Ol7k*8fQPPpd>gT<)G3-RK?1Ax)tUD*Q_K zSw}xd&LWn{6@JY)@*93beNj)kK-X3$YaF1Op<-mD;V6g7;G0D!#1rzil#kIAhf9zVo8;A65ac ztCJ7<`X`DwdH9E^-=>_ODt%i1iPQGzev@iv@Nvay`Zr2X(GM%{R;|;-|L#V8Q`Fi0 zZd83YroR<`cU$(m3HJ68AE;@ssD8Uu?G9D$d`l0WTHDL(r3&VRN)?$W(=SHz+`->w z*AdR!=v06~fSKpc1DDbQn4PElVDlmY{QMZnbfebppc3q0&t zzsJlZKUg00$mkxp=y-*G0uLxpmq`E%G4jp9{R~xb89h?d$-REgKw{1omMNdGy8K6u zpDENui83#l8#-`*sGaXb8m@+YkzCKgw>dxf75M)E=XY7TYQd#+JQvN%HS^d-vSet% zpdi$}^$uSP4tw<@ZQLW;dLpz}k?eJO9wVGD`PxW|h{tP+0Gg%wg+70Fm}&P?rEiHN z8i#CHEiXrWH^WywAIZAzE8q_T4+G|Y{2E+J$GFB>zC|s!oyZwcHqO$OzmUWAK|p^% z;@SBew11**BBl!bRs@T^L>}hVl~F>}0U2@R=;;qYou8)%N8Ijoz7nS^vg&>j@mcdu zRv$J7d=Ah67(TawOX=vJ5c0VRBP~w5B1Nr}zDc36o&t;mL=kt7wr(kq$jKUQF)6_D z%q*0gRE0s0S?>76_*{0emUWwQFb$8(%2y)3_CnX3p7~M*rZC0zrZo3kHlV**-$qKPJA+xqq zB|6pV&hc$(cdP!ji0;SK8&I$GJMZ`SLID}T(CrE?rK4SDNO!eFBw8nScZKy;lLCm2 zw>FitNDHkp`|36?H}**}z4g>*?$ZwNuK>3IhTadsr8q~@^OL-L)tXS!7WD|eUTDUL zhOa%s*OKrxd@h?cXWUJg*)c~9@T$e@CN(gh&^-xPH#((3MJWj+g3w-dw!T|o&AT!> znQ7P`wM+UB*>R*7_%L8JVECL3E~TUWY}hWx5(IgDR?&>t;yaOX(vX)p9r;u}hQTH# z^@Uy~KB*`S2FQKc%HA@&|7m$6;^Ri>R6NjG6#>{PKK%X3OeSireRs=Lq3?D^#|Gfp=}aX}h?9r025UiQ8X z1)l=U1PmXW!KDoER1dys>*_XE?u%F%8L`5F#y3d@4l8753t3^lwUY%bj0$qg9pA~T z(0z5EkgXP_!-)CKzlr#I47!!jmG*fK{AJ*mfZ^*ca4DU)&oTl@OAl^QQ?6D4Epwvv z9+BSq6V$=CtO;=t*#j}Xnm=Zr(-GhkfvJF@w;5c@5ua0%E}5}!2SeTfh}}aX^nf8R zkmT+RdAY=E%D2-!S#$7bb7mrGv~_+OrJH4)?FX2N&uM(iKN%_s5lQMf7Uk&)PGN1fK!S0SvwG zf=lUW&lu9<{!fdjIq8ROTHsh-bCv zNoFh(#IkEeDS3>SoG1pHxuMb+kRo z9c@p>PTlWgSI^cqh-@9~|q?c~yE8QL?>}9ATWqW@oILXit;##3`JDH!Cus zY$c7K>cc-A{9VLfEA;E2FZcNe;6Dd`1sMMR3@+sdv0Y-#%y#EKHT{Ldezl9Sxjlr* zy-L!4;c+l7d`&(XviK?{ulZHZxFio-S2pgcL{Bmz!QMIK6x9>LfwJM_)JK!Gz{{jp@tm;F4K3_W-ruM4Gqju^VwGio$evn_~-5j@%SO6a*ZIg*6 z5h$eJi}+azJ#${S8oUWO3o!iD{x#y~;rP6@CH8v_pO^SyA@JC*6Jg-7-)d3A(uq>m zW9h*&EfC|%A$>nhfqxtv5NaZoA9O{Q#Jmz&J%mE)ufi;}(Ut_1{@^T{bn zfT8FiBQ8GyWX9R!ivS54SUKNqD8Sj8R8;(;*eM{0M*^h_seC-!8>Wlc?hq%0d==fC zq~C-8PY%L4uc~UaJ;FYYK#IyAMtX`=8mkIdnb$JETOtfJ`u#w^sP!Y+P@~O%joPW1 zc1Y81(!Xy2zXSLhVA|<1a48-0zlZHq(|<0LOVfs}Tl$GkRYvo=+QF)B^xz!p0&>Gz z*OB8U>7__S-reyNB{JPEBjys9^al}r>x1lk-vzu9=nWY91Hq*nao^CMe)f2|Zq(oa z@(Zj7pdOlY^>zBloFb($rn{4R>v=D7UjzO%;C{f+%{ds+J>t5*J>9G=M%_Ic*;^DZ zvw%fmBXBDJCQFVoCsR;UP}z@JW=e|Dr-;Zgc13;>`P^A3GXFT$IX>$Wx0~M&-J5(y zep5Rr9FiPbG&osD=I)G)!;V+&C9C{ocbljubhms_lJ|G^kXudZHlqXNI{3G!eODrf zxxW{H-vE3SFmnD7TuS|s>>&=9bH;{k+ndbpv+i+`H7|zBP+ojuKGaoCx8x|KC{~Gd zP(j99_R)#F!bE;PD^s**h4Q%eXB)1o%*r_ZkBHykZ&`k8zy|<>0Vx{z%zn7eaJYE; zT3I0vrz;G%zGF4J1^ZY zrypUkNcc$FnbEdiXx_O5TP1yI_>IfSu?}i!Oxm)}Av5PGJXtszO_W0ntL~%t{=>hy z|J%VY04@QHe68S8=En2ZA$E2({aK`}>Q_s$-{DAATE7j=LLG4aq@=Y=Kdr5KReBbR z1WCU$gnT)!%47SLCl5IJ+?LbP!*oK_-~7*rpM%gd`z`ek@_zss!0=NEF6D^pxKktu zfic`HZQOt*zplcal{+VIj|)@5p_Uf~f6*Bg_Xhnig%l=tm9L=Vp!6O7N3l*gnuK4-Qs^Cf{PTfj$nS`EqhoX|*s(_7hhHJUkSe}!z8{8AR z^qu;k!nH25G1wN>&`l5YTsE5(?D8tg6Dg9s4=5s8_T+$deBNJ_KB!8t`67%nRpvWG za=Vs{#t6=3h78a#koqq#90Vd<`#B|fe5L`?ElwtyRDL-Lc^o%qEIN^~qEo8JBMZ@)V zrsW*RDeyASC7YcunTm;}ffx@dXTQ-7K{yrhISWr(!{>7FuL7-r;q#~ejQAWL+b4C8 zQP<}Q6@PwRdA z6q-7rZ`MwqlHL*zgvd(^$p}~v%plPt2NHe|bRm`cG$+R`W=-CWJjBTa*_tx?n6kl{ zy5wwqOs-cmUpEB0<~YvMbKdKelG#vnOs0R)lH6)F z!XD@ib1!kaE-b9(%%ep150rFy)K3~ej{1SDdz!&-0&W9LKlx?+z40G1*RY?66OpX= zLeJA?0!oY4>jZiEV~9@1o&RF}eaBi?mFn+!dHK3LuNS7M-8oqr&NYW1j`=iWFTz9- z)`-1D{4M=nm%``>{fRA;2jg}{#Bb%lvh&3-@MD1afZ_Kta48SR`o(Fny+T{RHY-%d zZA?^u7Db%?O%!E%x&%zTSbx>EZdQYxVq2#qo=(zF>&ad|ClMY-skYaLxYM4`5e8Qc zr*#Z(K8e|XuIzylDwMF&WDB3Gdt<6F+Sn%?tcv(Q5c4PP{U>k^C9F!o@V^0Eim_ij z#Lm|^ZMCW%w~KlEK_|R?8!e7B^y0)Hv^NPe>|H91i&=~goY2+oJTf6YrWWsYCcSA- z+8a#TG$LJ@@2AJ;;>+_VebJsYVMSwRYjL9J1 zduyurP20USN}TkhCR+Gq(T!QzCz9(i_%4HQk?Te9*MTsM`GUmJFfv!fG~ zD9_C&ah{tx)PiyDqSlyREA<&U9|nICcp5PDo&%TCsb55UYNaa|aUL)vJP#oAvjbR6 z&n4W=hU!SZ^e0(*1Hgv@BLPEi47ilfBj2KJtHOkEQPky64vD(FC#Kg-eMY{Uz*~X4 z0YmRza4DU}9d45^OHHCIe{x8aW%#X$_$|1U!{iXvu+a;(>;9`_*TYL?E$aZpj$O|JwzXf>ZZ)4~*RNB+7XZfthTaL_ zQaZ-F32%>~*Fja*!mJpo?x)L<+NJtEWz7Phe6cZKw_5r~^mkLgSwBAo{&V10fT8~e z_~)f>v^z(je@sXE%>!cj|Chaw)4=Bf#{q`^VsI&kwReZ-K5MuZZfNdN;Th?(v^hXr z?#4*{ZZ!;y=(bX?=|A5Ce-?NFFm(5UOF8=UaVXW5-;*Q4wEh+(h}VB5GMTu*-A@f4=&`k$jfQ((3|V3G@aGy=rhNN0V>JiEV>WI3$RO z;$6_*WpQszuaWwUe7KNUUj}Xj482>xrF1Ueq0~wnZ&9&B-zVy4bR)nzNv}2cv867O zlQ_9;blERkxj+UmbaC1U>3&W*vxDuCgr%nRkcjS5>NWBg=pM)4>~n#eku=3|z`l z?q54<*$(j3j(8ABuh2j7t-gb?y28k@yPwH*r|ChQsuhr$xLDt%bZHty@)GCec_)*d zcspC%f@D2*-+4}|B2Uhx&UEIA-AXTlct4|@di5U_Z|AJ~F_9egURI7};AaBo0!EG( zz@^;1B0iUjuZPQF+7WlD51i0lYC-t=XyiL}Ioc8t>cNDyVz5(|B%UlABDU~qkWSYW zR41G+-FF~tPA|98?-Drki**S>Y&|!xx+140?Hy|`bdnW+QMo~v;m%^w5<0m)ARFKt zlygwww)q|HpxvlYeG=a_6XC%Lk(@QY)225Z20j&-1sFN60+;geagm&B;y7f;Ielm2 zsx52io)ri6#r_9c9n`!gu_1fZx4IA3W0RcsI&Pku$>?g*YHwC)6hu2keMPkSAYG7g z@lN#f=CF_Vv1l8k$nRw1XG`J%KmDNUf&>fo&y;h8#=K+z(bc9q1Bk^sQnWRDCP)0g z2Y;3DC(qeO;QtlggDn36xRj1|Uv2yo@Lwjkm2*xG;C!7mr5vwup8%ne=UnBKh)x6b z)WmdFfu9R}5isra1h|xr`c>#~g0pb_+D)5c9k!FcRqTXD1AT$(<<0THbjUyASX)v~ zg{~z0cUcgnKIrY%Cn{A*kuL02RM|!M&f|zUB`qV}3vp1&GNIhme zKNtK$;1a;lxf)zbNBa`F4{a$I3hPHqlDp7Aw9N7-CPI9%($gb(UZWmE=L7J60iObf z4kzg$osR2O=!kbk)A|n173dBhMO~O53oZ3AU#|63Q4!lh~#~adJWxQfxij74H&wA1eelr zos7J*x6j+!M4Y)WyL4gwaGJJ7&$pV&aj*?UN1598Ga4o()R?jN>>lSIz;m&z-IS|vU zOl9c}1|JEG0}Q)%>i^R~A2^|kf?U1#ro z@5v>B#NYPwa}9jdu@GeYNs$EBeG?X{YW)-U;s29Fo74Dd%Zac~x<_2Uo0Lx?!4{SjmDb%bJvF z0*W?h{hy%AtVex~{0#_XCZAvG`d)keOO*0ll;>L0bFrsM>z#oP@j&c89r;{v9x(Z| z7Fp8vl=CX+C&X4tXmMgWNM7B^ZUfeCH%MQ8p^m3qbE3+pz34OL;5Fp8!MnileTXcn z!+NG4i*%jXn&}-~QBBHrnv_>elQPhpi55MLnzu45$vX{sCYTEh?`g=A4$rHj2PR41 zOeJm8e2wUfqfhd65Ax5zv%v7Zge<9pcA0j}lnaR-EpM-y$qdc5J7*Bbywn*hwR@ln z-)z;)RQVdqPQJeeA`b^6f#EwESI|+H$mG3U;8fc^B2}CYD5raRqs?uEn{9V$=2TWH3WG!4%(4vj zfA@`X+#n~!tbLH{ghn&T91eIfzV8TRjB}o{Lvg#W-7|E0`Yik8;LWV&CzgAy)*9t! zD}I>#{Q~*_z&F778Ok|w{tm8KsiIxx)z0Q=-sCK|&M$SQN!Cs>SzB|G;;TWQ;aiFP z9dIQue1AfgWa7w~{bc^~W1gp(oMzqN$7g_X~0(z5dX(oTy z5yLgp&Mb0bL3?gtu(Vge+nf3m+r2;FEVNq^^Kq^7m7n8tll5{I^7&vbFn->LENR9f zRc^NEPrsjoD+2{8KSYO*fW%sAI{5R?R@}pNuWH^cTl)^L{YeS zOp%ix=2DaLKrDT|_;`wYj2pLmxNP1?o9i6yE)B@{N@u9|nc?kCt2|Tr*@hpce1`K~ zD+}ZT<7aPVNr!8126M|^;=NI`faYe0vtIhVZiYL^>6J#km`TT*58jWOw-&vI_X6Y% zV3X#O_j>C5g_o~te6Pm?J&8`#(>klCXr+Iw^)~zTzJvS$_!t;}K1Y^h{28y~R(twq z5g0n9vsu>S{M~+yVs{JI3t3N4$^PgK1y7K1@CeCmmDcJ9!xk=7nPzgA!`mEY)c(e1Y&ECub-p~K?yC~M&9?t}_p&!|Cf+$a z;Yh4jm;b_~A0^16z&K$1xCB|!c0GQdc6Q=@VCG>=$Z>`WS3B>^27|5Ys_$(ok0++~RDs{>D8M-t7y=>D~hI z7&T8-5p!gkXEyQ@umTvKE0HC+=cxSpNS6c3pUhk7D>R5cdyDhAZMX5Ty^qsBC&zAc z-g2#hywo_&F`K8(W@smpu_m}pF1BIM@N{Pdml^H1L#5nmoh`q!toSnRKfH0ii~k=X zw}F2GV^?~yvg;VVuk6cYz2ItjDVS0u>pqnRY#Mu zJLx9S9{)(fA@%i|8ZpDFKTp|F3y-PyYmqMjmjh$R4akxXrkrCSf0jy2)y2z~F7_@N ziOpf`A7L~69nJ+TdG{oQY0ymz68upbn)xobf_aLTYyZ(Zo?nRne?tBj_&;EHqdgSw ze0?4$KUpv3`I`)AvVZD4BKOPOMd)P71-9EfZ1*YL}1)Acls7PBbc6-5ex?d1x&N`kqkLGV^G?ek%}O1 z;1au1N=e-+l|S{^VV=_ukbeyB0LIP-kR=UEImh7Hsq#nWK{1oCPUkc4dxx{tmb(=q z)7dW3L#Dt^bjKu`JIh+Fc)vui;f?lWz6X>6!+Sikq!xXy#q3M;@g_ojH`~%k(_(X& zS2E^4$NH2#sJR>;&5j1`ap_#u8O?Lb3%G%vt2iA_#1a-w_M4pNE@SI7f>pUj+0_7V zobOU@Z%4itJP3?k2aqLoFy1+rk(^ATk{51lCADRY)yNqqYY5YzZm+^X0f*A)`b604 zSsLYtgiIz%gbTMo^lAQBuOxpDnk3`MT9bHW+t(E**87t0K?wLOh)P?~eVrbnBV8IGkzgQbDO zU>~yRH0BN>vt*NTuTV+)Y-gwR=86NAXeCvxQ~B4T?UVfb9rDNEQ()}>xBmZTUy=Fb zxyo*rijh*1s*b0k6-^FXyI82~Um6|7-k}2NCtH?|7iKkUzN*sXd_^_#e6Ro*zVnbJ zrJkdM&s=Q~A6RC`Gs=W*wskJGIx1Hxus==shDwMq{yw%|`PYO#Q?CyozXjd}hHqqV z#kc>^`a-QkqL;J!V!S_b=ZAkbz%F~ccxp zws_S$bc>IYRf}QXtkX|aLp>}sL9Jv|UZm`ZlqK!RMeYa6fw5x(awm2qLdbVy$QfNU zBzCc~qX8cCe1D95FL)3bJDxz6)WQ6)xv{N2c~#s4^bRbJNJX90tKwQTpA}E?MUhKD z88Cd)kUQZ^ToKo3|ACz60T7imooR=kIMQp8xNpQ<%nERiZ6G~Nn0$7VW_g#yaXhO` zio$Pfr$$v@-lE!n_>BL%kRJ#8fU&24pHA(OvORn45?`c0dZJebyq@SiUKjKs0uNZ5 z?LKaQ_B4BoE^MdcSef0A#TM5N$ThnGi3rJoh#cAJ9^}f8Fn2%~I7E$1CzMh+6w4YM z95OXM?54A>5Dv##hLMA3!BC(q$T^cZf6Gvg&Mp46InJ;3LQ>6T%0IeLiTTG%kuL|E zwNEk*+H#EQC;Hl@gkRO`xrvMtpTj*#IZO@a@bBxi-ez=|e0vM|Ab8KGx5M!jErQn? z46e{)tRgfQaeH5p)u8nj_f6Vcfjkl%1tf{R9nO~~^%|24P+Y+6@A9hgQj^xd$*2E% z-y)dxJ2G}+1A5gR5tx`t+&Oe_fN>5fX}+FSIQB3GtrxAjmf0GX}#tBlJCbV zJGE|pYW6Qk1q^M~9ThV2n<88=yg1deCkMJDT9AGKB zORe#x=#E{k%H1dEi1S_Ei_!kB)dvg&re0McOB$p5fqRnuVc$IJxvSPLUU|xz4J%g3 zjOwCuy-`A0z589~n}A*K{?_(BMtsASw@tDScgP4XV+}fIx@jC3n?&qV_N-P$DhE(E z8f|x+b0*``GJ7p`rKVojf9!~3huGPOd>?oa7(4eMOG>?8gnT}4)!K6_Dwb_rv)Fry zbE#Uydem9V3p^tno7R)J=tyUr_cG=0n>C*`Ki=*0<>vlh-Cy9L z7uEG_b4a{_9>thSsssC z^B0bjy|dnbGbRr{W7uS8qBF6yuy;YJ(~I6lfbF!y3x)-U_8(F(I9OURBUsIE~-lFpHAa`6FCTxM$z5p1jo zu%`R&v240p@z$W%tgkFXz5rYZ4DTh#l2XrmdG*A!bc0!wQ%zk_-Ej%p-Q0-)teef9 z2%@L<8pV46y~f}7kpBoi0fzT8WJ#(1ZbG1yf7g+H#uj-`95?z0l<+7!|k~wz0`|_F8_$B}f*rd&J%G=Aoje{#xa4Y;cly5b`K64jA5v$dV4{ub;K3b^{Oh zJD#)K9LojPowC((y6X5eeoygkMX&MqF68^c!@%%9iY)2y{w5|gr4UzLE1OHdk_(Dm zz~<8VNr!8`uXs7Uncyu#?hgh7!#f;V(&7AV$69-{Y%YC7HkW>7e}cz=+pqEXV)3~7 zI>oyQy~f`gk#7RG0Ksw#0nZ!KwSMBzg%iqVZSA3tK&+z>R*&WKb4H&+3 zWJ!nf)6XV*%)d(6V=jMRulW|B&+u(Pz7$*m4BuvCNnP^KTM&{W?Cm!H%06VbIf`yj zejY%t;r$T#PvFm*OZq2=Ymc;lhHU~4>Rsow*IIw&u%!MO$Ti>;VEj5AS<>PCG94l* zrZu-p%*d}eX>YlJV!A9@Oqrihe(grD@#`7nSHNq)@csr_(&3(;pS5<26w_s1DZP$T z3YhJ8N83GAy^J*|-uQ6#c%WDM2S+2H2<8IAdlj;z4GUGjeV6`Rw{+R6rHeOItX{No z>FlK&makoM>Y`N}<>kWuwm${Doo&BnXIs>I!ufrW&in``KO+|D$&p-sR)mMAamGI@ z)GK4MJvVELdwkAFBF(bvD?QJS_Ux5&vJ9VAut}`MX|_XW5+kfSG{Gs$=C>-fZBzEQ zVxP&k|3MyC!F&!d_TPalsaUV?PFt`1F!s;8NP_IksH1P2`)=TKmqS2*x4n-?)W@6Z z<8k%zLc4Egc>l1s_w&-vi88*|xhLD|HOiUd^k51h&5g!RJ2iX?A$bT-5Mq#(Ijqp# zV&@j;6y`>ArVbzAe4kz!Ke7nwn8%z@elVxpxxsej2Xkv2STB|T?R_8297K9q+NCm| zHq)(fs+jEMrY=C?NP2mO3l#C5d{{cU>%d>|j@~!a}m2a^T z$$rcL_!NRoP#I_@#~B@=KJ8y1~6%Zto(p0&?8&w7+&Tv0b;Pw((!yUUgp3^JHlCDdc*Gc8Yx}wSj9Em?+L^|ZpbN^WQ80KhMKzDP# z*E`G{i}#bzGyE^vogLY4gaGwP5oqvmo*`#_9M(41zEiA>6{$kRuL)L zS2(MkC3*^}>UNcH&Dc?e9a2AENB$7}f56x|ZKSgE1wC){f}Xcb*tzr~J@zHq#-{-< z+Qu$E#Kyg0>!t|xGE@*vi^!xvx)&26Xpbl6D&aGniACvz!5mBWW;+vmq{p2|X|P~& zn4^^u*{f-X^U~w&-%>JRIwEPoq8ZE~3=dxIEvOTKij$uFJe`x5kJv=r85b(kJ8bV# z{xxF1DHo3;KM!64#=qYnOG=#&GXBk6v1W!Cr}F;#P~K+EyA{30 z-<`47b;=UcFYL zvpsH;yZmU4=7#cy5X5n;QxWYKO^@~oMWe?=PYZEhP;?>zbbE%*brweZM`?Cjv>jXF zH2&X({1fmfF#b0qOES;Uxi1(9By}l2^o&#%q*>O7=~>=i((l#!>wNmZi+nS<4H!Qk zMV3@KL-`lc>#~QG>nSVLrNGVhBya7hg|U=0T1}4iF`i~goS#r(U>>L3hljlwJZHE| z*fv`xHJx$RJ^J~>XP$p-tZU_gA|R^U}Ra{{nOw{Tq=t zf$wxj|MV40S1oBzQlF7+#kBstKK-vDzX9Ivj(%w%F+UgcbFD2IvZqs0rPg0OE@}Tr z;x=pb+(7!ckEW@pzVDe{XPclb6!ugZpj$ID{Q_UcGD!_K%|h} z1w-6?dXwpalFG=4T$}4#LZgbDl7difa3n9`bZ1g9KNKQ>$C*K=By(nX8oM__vFh-N z)ic9$(%hqhg`rG>{D!Aba0!Glo#=u?S;fj>PfFSZSpuHmEMfD?B6ovxg>0pnLs1;( z%(N%i^FkX5ArpU4m6rzmHRa_YXX9#>734%-%{Z30dVySq z8v7(N)E5Ml%jKn>=SsA1?3?Qjlg6M)+fjV9Yt_Od&t)WXHCPCY9m6LmJBoFjmao@! z(jFy@=-V26#C|_$w+0(By^lXS??b%Lxj&n&6d4-ZY=lMD_cG@bgp2EDLPOm=r-b;3 zB~Gn7&^^~V)!{|y#tQ<4v8>|Ee1}WRvI3dJLm}oU7x&~xa*DHvo$8EZw7^YQ^4-aF zv)So46byC>S!|tC8t5J4!R9;t_*Oy@2n0n#0dX*hH^{mkf6Ye00(X-X6ZUL|gM-}| zn*)0V3SBPW_#hbmP?kO34~AP={|Ns!7=D-Ug|TAKf}qXj$hU&ww}Zj#lchg%iF+0+ zAvC|QIHA?t?&NNF+_UUC?kU+5atAs;w%MMS>ztTVV-Lum?v$1B7xjBod1xe`>-2MY z7Wwz!Ltvgm?}_R;EYbUGb}T#WbC`0m?t=7f2sQ?84B8FB2W{_TzW0*@$w4V0Eg|dI znF|@DNX;mxgBRlgoE6OBCZoK(NZ(Q6k;Jl@*fY{=w9Nt#+fu_hk*rbS89cC2QkuTw zT<8$Kd4oe3Y`)T;dQ$mQhrQ-K_dVoWz@5PO^HXF=<~^6%uTGTjnq=R)_Q&#~>*+y^ z{|DEuX41C~(T@(T4D<>Ut;@2;5hHthVjpMAUS$vGcM|p#A@>D?fU)N|WWPO~_Oo=p z7FAus+WBB6p7wEM%-WtMucABxG*P}nfp9Qmd|EiovuCt>ZNeIs1D?|LA3jt6A3%N_ z>;uN07m+2I`rm0kVCwQkYt$TaUR?!ak7{q&@gv)MG)roJUeJ3du5!JFNc8Pf{IO$` z{KJvQgJXf=uSV_?fA#uP7p+@C+~dVGKt*+95+<;#|9NsHH_}6yaG_^HtLAS&zbPO0 zAwLgZ0){_*Qv2u8ssG2XS}He;6ydmCHv(+ZpK{4?$jglXI@TLlQb-u5{t{nA23>5a z3WxGD8EO|+=Y`xf+K2o+-VFSkw488meh;_AVKAGI>xgJ~%j2}NjmgMU7rvCc#koTJR{+G8|Ti`wW^MKtJnDsfud7twJcc)~X zO%}Z8&tG44C}q(P{9R@qYrpRwl#95D8r zfGnxM-uHZ@{1JPmGbWHHR_}hI76ecJ#(QEPIo3nj^28P-ZQ_aTF*XTL<@3s}9q`8a zE_VF{c`tYl7`xsuS(0hDJFS;9mtO1{G#P_xJcE8} zTd#V?^!N7tcxG(n7^)O#t4;IoM!#tnpFw^Z{2CbkcabF>v0YRXQz>oYd)XbeiK4IJ z1?~ToB>z<8Iba?z{0osK9g&}YnW@q#Mts(h5tYAC{JYU_{BK77C1?SL|2^cc@_R)h zh5YM|$Whp$`OBv!`Hw@M1?B_8zYJMYxsG4nX?eu|xf{KGOLb>c1Wxygz<0bNc^%gz z#0`s(fgICk~I)ix-jK0KWsqj=v*II%2&rM%*nse9!l+ zXpx$+z`6}H3L{*cNY(gZB)pvtj%N#tIMWhUqxB_aPt~+!y;y*}7Hj~ePz*h^O zFxfR}+fhCdUgxu-o=NdOyNukbTZpra5v>cXEihSK!nJ*d=HeW)z1< z5@B>A@%cxymCC!><8Ir1&vvdz%_%FM+Z9Eo4ctlsJgSZl;Ac zF5WPI(Rmdd*QNnxxA43xWHxY(^{*Vx0;)68)$tM*rlH-18LpYR0alfbFK@HQb! z+N9$*oAX?U^3L*In*0sN7l^oimF;~Dlki83%U$cb+&&RT+;WXJyXVp}op`Ay7qTsF zSfpe?xS|K4GXt)4q#Xhvl)2H_8RzuR9ymKXCpg=w8N_u5!CkvYQ4%?udg@DpCXd1rGpeSiVc=fd8A_?HdP~{6347|XN9?^5xd}WDOulE%RQA4L z<`?Qx`!^lf>+5{=Z4TX4@T^>h_^2b7A?|aoEVjPRTbWd1+Kfq`CW7crwiU5&(I1HuD`I{7C! zb>6>O5h-`&?^e+EMb0GxaHP*5H{9E~UhdzN->09SwjxmO3=GWV!sqEFY%UHD92Ut5 z6^{;&88kXP_NYh>7h>7Y!>p`SI~N@%TGLhp&mVJCWOU^G;^UktlaGpwEnX2hKhvIN zhq)iBDi|9V9zP-!JT_c8*bSz~xJGKkAZ1OkygE{OtsVKEoyYOVoQqNXo#js234s~K zmuZ87W2X`jG-%HWXJ2hcuCYfI5h*s*vq!{^m3vD1Wey)ukoYz`*dsg;^Lw$lI3X~D zMH>l?&IZ!k?Bdtu3BT^OTF(=!({Z;r9MxXPg}QEU=hVQ4v;nbE*(ZgL2~3OCI^3DL z)9yL4a8$w7wtIG9apAn4x*XShpvpx9&)t;c$B7^BPa*UP(DE@<=m zHif-sij=vJMukq*2M2P`nYYq~)rV0_PMqQ3ts_lW)ao zTwX9BGH?_ZHU+uzW@I`!#QzA!&Mb-)kIoGDiVPswwhRex2}GW;1M|r#-I6zcr2Jcs z{c&CHHz8jNuFyWodoDG8f@w$PWjt3_ar$8@F^daX8{~XNkU#NKi`L)b)Bis5r{Hs7 z^6&qUCGF7b2dVQJH5=B=Un}niwno`iy(UY}uv=&+E6G`G^PMYCyUIN-(T>*sN%=Kn zcJlpQi@XI~3k>f!$db;|&+VXIZ#VuW=5^|{0c8z=ouL~8c0=G3+xw{Ye*RK@8GNJn zR{dwxdZ3UHKT+o9mhrrG>3CtZt$qIIRBmAP?BF@itKBF%aV)(Y-=9ZnYEU}NUCj|!+owO)xX5N)t*OK3tBQC9nYW%>zFZFx<;+4G}sq=uV%Rm%&Q!Z^=OeyWt9da86kr4%nB5E z3%Op;c(OBr`#chBE0|-|eWv|}-`IBr^7lalF!t?6mQ;15al>)zy~D+9x%J9tkvDqS zVtXC;s~qb^&pJY{6Ah;im*Wk$dj&k(<`d=iq~fzUBxw=cL3$U*mVqY zm+YFlcFl!L*KJslG)&GpFZJwV)$MKUipssV*frAFRKrS?H>zR(=HHY(_3)Yg@9oHq zV3)Sx@cm!C&O3GOYOZ0`Tax=wT>4m_6!ozhwEj=fW#-ksMjm<+{YhZ_-GwY^*14)Z z-KyhMn{v3qUp&eh12+Wk4A_l<-rmnYy57eC->-^1nV<6NZA$0-<;hHZWX5}xxdS;N zVE16!EsX=kIqoAiSI={$Jzc&&v}kO83ex?H7Kg*JVrEX$BK=NqPn18&q`y(({8|1v z8)vxvJ?j0zS>_K2{LG)^ahLJrV%3@c$aY_K2(@yO(=Ysh9sQGoG|-tVn?9<(Q2B11 zoXnSA$U{LTF!?eKSyJl0Dw8h+AY+@;s*97wliFHTa~f+c13%AN+{hfnJBgUHW=mw>V7kI0ffnya4E_LJMc|CTSh zaB1}ts__cKM9WJ<%xSd8cq6w4bxcJDaPnAQ3|QCnDCc6zZ1R0V=u{`y9?1QJC&;Y1 zQ!BJYd;=SuH4cdJ+%GrccQ1ig><)bA#EU+zEj?+1AQ<9hW! zMtEP8;vcGC-J0?zl2xA`7 z#%(nG#|4H|fb<&(3lhqu5*24%da-lKt@gs=^kQx?<*EL!O46D{-bHsYM=LlyAm&H00LL)Or z<&G@nYLie#o-@)tE0{^(j^L==vI4I4&dkW`6^!O`aagf)QfOvc+MrBUtb#*gG$^^m zKPzWWr+Q?GlUbQNGB_k$kQ)xB1qnSB9$QXN#~R^$Y&(Co-Tz3ezgq9U_S&%Wul&?x zyqNLGi@|bW{L5UR{A!r*Id;Pb*E$$t8ueo-M`-6b@@eAAg*y#P7=Kb6m ze9fCvuP?KIWv4#(C&45^xRNr z%u;80gu}a;gyeH`(6%zXO0=CF%;&f0qSu*8$BMIJPGoJk4o%)~JUy$!YtX}Cmkcf| z%W#5ML^s=xlM#tIM|l@0m2wI9Fx68d@?yAffD%)*o`VC!TF;dYIUO1?UnX4S*sGS!}zb_|!H^|AXq z)v*)%(N+)Pg0dmiLwi?*M|#!FYAsadu!(YJ-s8_9zX9F{rX0R>x+;ec>3(+Xy!Pc# zjt5c6cq_0x@qG3-a%}1M0kuBy4wq!vr+{qhv-k+!l)aq^0dAsWn?xpY*z#$Bsx$hB zCpu?2m%6#x1+lbnBpl1&Htt9btq$>9WKc;pi-tDa+0-i*&t~#Zg0W!wQ7->9669jP z2Rt{I? zv7SFYP~}E?jFUT%IZhkBdtTpTcbX#Nr&!$}qRImf_QoF)EmI40y1+ospa;I}7;|uoal+vinT+T;9|Ds)mh+K9^aGE?(f>_~p3C^9i}OprHPft$rc zIVlk68HmTCk+gjB)g{z~{L4Z+GAfepR=8`Ccjv3+?z z|0fiSa;LPLA1DvSGuCif%uV*7j0tz!;d_}gI6KhyZacWm&dQCY2ZOzHBRK^(+TrW$ z2`-Jv4@Jsi#_N1HSd_JqS6C!FGaPoK7pGqy931{ndHBEO!J_b=%EKR*2g8fGxB4hM zZDe44a2&@?rv*oISl+44VMmWsn|?Zlu~IGiZE&i&+voI1O?bbP^`zrm5V($)r*pae zsO>UaG1tAq&I=AD3c-7J_Ug!D=h*x@XGPg+=j3?V03LA7aNYi&m8^HiBF_QyfO)?A zktH?GR?l@>%KRFkYNc;ucCEG84+mbei7Rz5BDejq2`0mOcVr*tk22%Y(kz!9^{@*oZ4*Xr0h^EyKk@$S5R!B7t%YIppAL`vWA6*azR-| z+E8a$78eQ)3DBQl_#U3<9Yue|jtmT(;xI@Z7?{oNM0}j=e5$_Xc)yz&xX%vdP}=H8 zYyZzq_V*?u&jIs*@qaP0Br~s&y8h?w{;#N8>&@0npR{f&!=yYQ8x!`+M(u|P@53f4 zVk6|MOY?qg76H*)Ge)<6@Raji`o}*<{tY+?j2+xNC1zMnv($5_OzRG@ILJIBVBc1#@ z;Bc0J0lBlvrE+1r>#xBX%&ftsh<1+GN= zsvEEUM}GwUQeOUpoLNh}FJSolBTH)4^>z20ly*7EPaI=!hoO|5HhY*iy?;A>WwGTi zj@5`QIUz1(4RGg?y1-!?2UN=Je(sb&K`28Nl-8q_U7O%FcHNA8A9x5DyIw?=G=HA5 z=S}_DLB6ybdJ;-*+KrCg;Oq(9$W;A)XD53H0))zA+9nc;1r~d=HaFX0W#JOf!cA^j zpkHW8uppA5di9jgW0aloMal8#805)d8ZdU&AWPb!;}>;Y?~hxuM7kVBoJlqno>PzS zkz<*mNot;EoU_o;dyzz6i{@`cf1K~~{PrOK3_J@A|I5gdI-56D?aq|7Yvsn}Ej8q=0{EeNP^ml;B;3#1DrXou^yuVYpD9?+DUUzZA;g4+V zYaA|eDkFn~)zbGEO{gB@b9|EGZxBxOi@*0EH-X22;r}`Ek@?qcT+?ELu66DVFjsUB<2fmj2h*&B zkr8eWhR<|WB0cz-RP%jv`0dO+wzrfze?dGsKi z@bbaoA;SaVK+itmzLj!x=@Mp*s^vYl(jMoY%%;w3Z0@~!l9YfZcJvOS$u4{d10WAWG}zM)@z~7Q5@xCI|XTgSOT^lhgO!L@VT^ zx*5uz1@M{o^jhRgK|L_`Y(th*qxUVPt{ZE6nABY5?Kdl`naOn8?Q&Fdzw>>^`VxDx z#2Tl+yDmITY*~XXKld z&5|j@!RI23_1;6=*me^q4#=HeYz!noXOLj(T-hDSrTd(n&JDP^>y9dRGBO6!@y>92 zb2GOSBs7==z>7_<@;rZn{0#UxFn0eHS<+{^pVO4m-&A%d z)}x#3?HsToj@$q7AqDlP0jm|Gdq#SO*qa)4nTU-PGoWV#S5h>_VaH=O8=ePMhu6uR z5gp|r1gp^RFyXD5t?aBiFInzRL0$xw0b}PTWJ!lFchkA4(c2SLQ^ixhK|SUFVHwO&?QucMI{4%>6xsCfO zuHmMC{520c*eSuaP1ei`-JT<7vkl$Ug1AU`L`SU zCoB7AtVr6o1bHpk0E~V0$Vaws>Y_E6sJ0(TLsT_{ zMaT>2ZjORjdxoPzyLx(K^OPMe@R)Yz&&X}y3t;T{8d*|)C+nZ4 z93+j%tDCb{It?qVhuJxOyd0aGoY*E~)ob1v=O^2lTI9>XW?*=CB1_t$&ozCa% z=0Z6g-Ol%B`)-ajCE}ot_2ha-PC0qKx+i37xgCvUWn@HpMM|S1!UJRD%8m;K)2q|H z9J66U2e>dkV6o!~3l^ zkrvgh=Oy3;I+j;L5s>SU_dB}+)P%C{RoE{FzLBf22YEk_ z_I_r5;}xUd6KpEh-zmwzlIe8zJS?Pdl0z3&!Y(uJbtbswMHBKOvETqqJlgq%?F_Kb zWZe6(KGk7a@iUd(Ggc?d|3c(Cun`!$e}gP(nqCk3NPiw;H~WLV!&@!R7T4Qy^o}EY zj`llOhpmqZkXYjKrlS7!;^j{`Y~oACovJj4z-pYQ&&bWHakKiQ^(Iu=fV_dz!^1Lz z*}>k-1Ev?^&VsZ+cA$5<8w`)^!K7qXW~S34t323`)kWEzIE}!6v)sX)lW()5v2btZ zY=_7sN$+sqU=RJuX*x&wJAO^Fe4d0{3zh=o??z-vhc8F|&5A|bydgU-OoR84ZM~Z# z4PKUaNXx6zHSXoQ(Q90&>}ZB34v*B6gUIiLKLTUNUy&spethKLlw3L98zarLcI1{a z7gHSc#z>{o?n$cE{;y58v!@_00V{yvy#iU%;rn-U86zxPwf3Uq`+qU*M=@CEH6aa5 z$mGfkDdbFN_L5T=bW7G{^Q?#=Lw_XM4~Q*NcD2B3+W)^G{|o#dFm`3ub;mCAzFeKK z=t^RndKN`l-WcZOD{HudR$CK4SJ|-u9%IJ_iQ5S|3jphNK z;r_*TrY9a?^Acrm1NNBy`rXKnfxW=kdk|UDem!oe8{2-qMzw$QygjZ2?tNPIddI3x z?~feoU-{%2ef7N1nY4BJZZyD@bGS6Z5w}QCj_M5|SpH;ZxG}7Csj{nlT{0ghBTok> z0%O+#WJ!mwXV{gPikRkAvxU|U;+U~4PAcVSi1`(LztBa4W`qV$Izr&`U*qXy~war?^2=K zpQr4pT%WXO2J(DxIxzOEMLx1U+*5OMVv3@@JCkjRb3cP61I8vWU;)F7a`yZ?T?ebPUX-784~G&QolmkQv;u| zXBqN3a1k)}+>I>hi1wJKXBO7HuB>^MBUS`6$ zYOy}%Z9*L4oQ{R3c@{RGuk34s-`E%0$Q_uV5E%Q)ktH2|9-sU&T_Cy9K~3RvXY>=E zc}3JN#=pU8nM@qwoM+~^L~s2{WydCXOh4y`$oGSXfwAK~WJ!B;JfSgqU8Q}00XuwM z9Y$?`Q>!Xxcw@IrHCX$SQ2=(8(5uODFDHaaBpxiviR3t!%V<4vsuRtQWH|*Va9klW zFgOC6$2#o6e@gcC9UbWF_VW79Yn0uU7bf%X1mt;O0Wfxd4_VR?pKqc`mk0c@dcbcw z)&sJSO+Db^XaNtD0K+V~JDD-3=ejJudyhHOJm!904zEc(W~+9svhyHznD@{BAb%}3 zUX-*m4_VRz9p5{39U{?gBz9!vd0}-5$R8$P*w9p@nyt8MH6)J)5>+THomo_+E6!24*i@ANu{*GH@` zi$-MRM=1P}497i&UAe_vDL7zgbYw)@)}S*WE7vY0OnX*V23O06nM(}!D`3m#@Zqzl z-Rbf-1A;kGcU)+eGoCrPaIl~(93MW&>ux-0huG)2#+eno-nKW}(XncbF5P&YHmH2B z*_6!pWys$FR|4bjc4SG1AAcq?ovm9l?zHVj`!=<8i+kwhWqYq` z)4hgzle^1X2tj}4MrBVce5M?Hft+(O^&J>{W*|%IulJMf()TyEuV-c>S(E);^+J70 zeXR55lrB(j*O%C}SRywhWMrkuLLO~EVUKW0QLs9L)3l*tr-*smB0C%?V1{>izkcBh zq-DBDCTs)869Q;<;0$69>m04WNZH?reR1rQ^0NoI1-u1}{r`t7>G1U}QQ1zWvUw99 zGU;I^KMK6bkH0zAhs6H&CO_P0P}z)PLGD`5SNZBWx$ z#M$OZEjy1ZAVxYD%3Ipx8uQkdD0>dVXXe8`M*cVW8W?+yyHwfpg5HOfug|xd=RS39 zot)DoSljPau(rGT5HlVKTVHT#XFg$}LZLJU^D%xBrQJEUENx&Ynpc`ODm$Cc&~`h$ zGNY_VWl`Fw*m2?9iJYDuk)FoEoy@dN^57RaD?%^Z?u_t^&|JGBaE_A~=*!MDZ(}6m zhRgNy$4=wNW5_Rnmx1x)e~~3E(eH^@Q_cg-CjQ(!-FmQ!+U&e9tEg}BA28yyi z&friE|D{C;lG|$zdv)Y)k6yt7EFK;#U@rwflbfB7c2+WKcP6q>Jd#xh`Og=3E_S7| zd%<^-^=<|7Mc_NY*u4!|(hfa;dt1u7qu9->O(wzW?YnL1Xs^CPOn#Jw-*_KqU?`Ur z61m`vB@@@1fFH}goJo`kZz;BBv$CTV9#jAS2l+q1xh!c%KC+}2^u3K{9oUou?>*pc zTq~-%T4oG4c$I~_fm*R5D>lqMJy7Bn=2S?DeA#BZ6Q88Is}z4N`VIdYB0$#I0D23o)y<;>W4?`QRm-t%jAtZVvUMo6NO1=CpL-O@}iLnagH zZU&K7Btx3ED0|xAGxq!kIsJ0hgMhJTAoAht;c^)DOn%^dCXJ4@(=&q}e5BN!#cH^I zCUZD}Gs`>^(c5yhvSSlGHGG$LtpWKy@DMO|e1I%zn0_Db(dRYWJ(r3_-llkOLp(M0 zGp-1xgukjP>`AJ=?g?85`cPk^Gh;*LGK26m>gpgCo9NC4M!A{Ug&Dz&Yn(m|(YUD~ z#$OHZ5ZGuTU7?tF(WfcM#%Iy|J+aINyA>Wbw1{WRp|U^Os)Y(|#U zU$=X1O1r1}8F~{vIm>iaz2i+$JvFih5Nlkj+fw|wr{coaG!DGGOOplK9 z{?(Y^$ikASlUo=p7*d!`Y_d=wl$)ImPZ_@*5*$2aNcJG_w*#~L@!QkL-m7hAl)E^v z#byKW??bv;Ta`ah`8)o~WV>9Ad@Ey3i|oi`-B^~VHk;E`^dGk=yISBi?~6Yoe-6F? z#;%ObN46_56s+1TmgRbuJ;6{=TNc5xEVf<~u+w#<3n;cMQv<;kZN~z5s_IY&;sb@)xZC%%2<&juY>RD2dw4`2grSXR2=}ql=&ZdPX6BLOY}pf{QlXtc45Q7jbN$Ka(Bc3HovF z1qphq;YZqk^c((vApZw2vz*}1MLrULVydDYfAit_Z_@swzX}5JzYh6ga5*skUxO@Z zRwv`I#TRbS)ui6OM$NPlAN^gpFOw=ciMz-u<<(ntv*K$(Ulsa7JML zZ+9p^_oBB7#p36$k>3L!0K@w!a#whh&fem^(2KoJ7F)}{g#CWaKFyh-hqYGyj}`y; zYm)r4kxvC@0>i%q`3U^DoM>t4>D+kJs02gVJfM$rjb=XD_+532;%!226^h007m?ot zzXgW(L*ygyipxIY?VjH~J-=V4X@UJ-%|6MQY5b1gs`x9vo8+H@JQLIa!@mIe2>d?o zt;*>KSlfm63RR*<8J|T@i{{;p-YUL}-}{kY1iu7^_f2F;hbh;-=Cr}SnGE;d!?x83 z^$iJ+M=OsTZd3loweF^ypyz-noA>MNcapfI~H+F53w;XvC7zYe*74i{yz2@3a{EYUv z)wZ62_;Ky=QsuFy&Whcs_#4n)#jnKg-N=uECxPK_MwWD#=d7rGFOBE)OXH8WbpZao z3I4IBbfd6Q`~STpe>w6fFb)|0D&!;Zd#{U5{C}e}|64VG1Ny5V@cc)96g&wGe>3tC z_!YJ9rRDSgz0Uk^xl8;1{Um=s|1$ySE28{UfK!Okg03Vg5)~ zgUZq~Wd8RUr-E_)T#i2K8L8S`%C5@ml6F-gp9D??#;z5}lD6vk>a8j3Q}RAnb~W%m z_r|hU>+10^A`#MoI3C5}3@lM~s(IIbI&}w}^<@=ZLn)#7FKj3Z$Pzj7(V~{0v zeoke5YTP3g11s60)DESF^k}l_(_e-r;o=a#OYa*a0FudcCC7JqU zKFxEH%TncW)b_?nj#t~YqrLasjf80%bjHgiC%#e=ez~OZm6Dv7OA1~oab7Oz^-2kq zdpxa;RPyGBwEys!=Wr|Xz2HG$?05uOQs>V>N04iGSJ^xkW#z82XB-w~rvSoSE%zGL z`k(0Mk6yzY`ysxAI552Zkq^%+d+a(Vo#7`%QPsnWce&DAFZq5Y@>X!2=5qLVwb!e4 zkvjcp@>`uN@Ma6AvIU>4&#XLVgl#oDCt9P1v)!6KT>NL6Ppd)mwW8bjX>aGu4afk- z&urw5{FL>Wii+in)-SIxCQ#D6NdI~a^-nGc9!eh0h<4DScXUE*!G^{%cR`@KH)#-A#G%Wq2ZPDP#r<^jXI0J*EYiCy{aX&>;> zT6K>q-bVDAa`Y7P3*cp7cz=y7sq^;1t26B?>e573GX{On<_B4=ng^@uF~wVabCP#7 z@A&ri^2>QCs$oQDCKK$5geo!#qHKEx0Vt}qQDe^J6Kri9DON<0Pp zsMS0*=rn$_ZS$rj}W_25ZWp2pvr%%_u)PXVU`NnOn+{pwL}T%#B&wf-GG z{dE_rFS%6E~P_vg$NXEjnvaD*c}C zAYTEl^7H8Pv#I?|e|<S^!bY1eA~Gtg!9FGpSp)^<~WyQ>olc?yNr zEx=3lnx_e!rhR<{`B&g|A5T}FgFe-$^655}Pfc2X?9OCd+@Z)7U=)xf`P9D)<<<0a zj>d(ftvdkw0=51+bZzCk)Q4@zKLS7Y>HkEpiyp4Ldis-5Y86eRM`Kk!rOMMmAJ6|H ze=Qu1Nk6*5ql?vXcypY!6G*DpJXPqd=ezi`6nQyV1tdv+t?Fuisp>bKcPxLXxOVZ` zqIq_sGmbvtX-57zc*)0;djGoV9{Af4FaEoF>i4Rrj>3H^zan=f%T*ub{-7L45h~n zNFGWw=T@EOsoa_LVU2%++a+G#AZ6JsNV}Do5ky5Un^P~DXw`%=0=ra22kk^BYeEJ*pezU{X?{*PRi)oPwE(P`cvMfcF>0eyjuLsHKN zAWQ1Pc*h%HdI4+r)4ZB9ys^hd%iYK>WL8+zmFlgUw+_9A_j=?V;C5hm??RSToH9N* zWW3X!wRQ$Wyy4ym?}rR7fwkU|3)SoQt8&tcUX!nZdtEC8qCk@P+j+jSimDDI%b2c% z!Osg`y=~MyGtg=LTYiX59d798^{CN%e4e+*)r_27d8w4Fl zG<0p6r}(}k&p6}>U=rwdzO@?+y^`RGJ*}Qky^p66`EGFEx8Z3&UU}6JRcfA3d_0-E z@eSmIZu`^0;ON(o)o7j?(T!4RU)Lh90~dZ9o_2$y7UPapr+N1Jcz%og9%%hGJSl^u zH#Jj(=84~*EZ0+zj|bJj2m!^9SppuGA{OvD%T6pX?QL}t_NGb4NnJyf2#T4d^uE zgC~*qfoFU?o%h>2;z=DOd}QdXR?TNUl;j(TJQxfI#;@-3wHqvaOb1@4%4b!%s6%%> zzmxXi7UbK(T|U0f#|s_%Cw%P&4WB5^dd=60?zrarkMR72IB-Ccy#G4y@1^kh1`nT7 zI-0cpDs-9hcMkF*u+*o&%jM5Mc=#+){H#{Zvm2eJKD~(iGWeB`r_1%$KZy8SqFH5O zPCcL4!%3de$Ya3-VDhWWJckS>+B~wj=Go-q*@1j3xbs``_y!YyHy%}Ko>m`^{Rqz< zM8LQ4$3Lj}LKD?$o*C$jqg2ZEGUOFtwU4LE<;*|0_*b$VG-#eCAJ1FJ2f=$jp3eK@ zspZ)p*j{y(zoK1j(mcgYNq;6IPXW_`$+s@^bU4WP+H}jU7R|TS$Jd1X7gz?(yqJgL<@m5(OUyMsRVr^>@(8-lm>-tLEA3<9QSL9q_wu^R(+^Z}%9USLL>NPtuRE$VY=? zLHF`0rE|SQ`5-#tny22!a~JY1u)Etlhpt52rm3nl&nM`tg;$gge3NJRnF?sW$MeF$UDKk zKK-4y!~XnA9gN(YC}@?M=Mx`K^husQ$N|QWuJLp*7}-r@PpZ*8HRv?YWfk&Tu-?bh zwft%~7;pQs`b~Q%RKMzBi{hF`Sf?~IruxVP3l>{pvqH=Pk$ToKfu4ct^bhD>!YSX z#Wm0Pr;>i0g1i8n1x!A5&5!mo;d>yd()xG!^gn_86nOgE==XP8pDLI z06Ts9JAYp!^v^SQ2dNdQSH1dIr}ej@%ao)4MgCfJKhrJy+s%~!S~npLT7MO~jQ-P+ z&jPjG)8DSM-lFw4Y5k2p{rixg2G4a*fBVk*8;YPs>$jdw+Fyp;7Yqd5c)lHU*5A}# zFz>2)miu_FMBW0nc8{lBXZ>x>5PM0L(*r*Je?gY5h6R zG4=z+K$6tw&im&n`cpdRA4=z()U0_Hh+e*X;{fD~z@u%y*~Y~ zBfkj_c29r1PWi`Pt3kVWK$WNB=abKS4DvWI5lHG{yO-K2|3sd4mDaz>r~hW;TfiON z)89d7{8ROE!^T?8(~3^>9R3&iYvK5L(vL1YhjyLu&vZUDX#G{_+613G=QEJc28(?9 zJ6{(_l&AJ90)Gq0b|I@p>u*GtSr2#)`2}#mr@!<0`S$u#R|47;jTL)Y_XA!?@{}VF z1tWkYdEQ;;(Zxz_;rV;uI8TLDt9k0sSc=(x<=RMSKChfU&;|`VSc-eGN&C z*1rH<#{PB48^Oih*6*9y|F80(PV3+6)BhXfx52yJ*6$x2)w?pK+Mx9pzmzOLmB^#P zIAHRp3+2Z@DBA4Oc1vp3`ZxLX-;8_eosX{5zGO$&bO10B^_p5WQGFf0KxPXo0cw-v#{+4LCL*B zqOV!=H=^IXx1K|O6}%1%|69nCIvodf%3f4+9^uR?=E|v%CmHkrPN$ybz zE6IF526-}=3M5In={%p?yW7FWp@)JpAFp}p(P{kLiF^;Z-^bH=JDSRqG7Ne+=+(Fu z&GQL5O}UBulK5vJ8+6~FcEh12@kLUb=BYua;i*Gj4=(yvJne=>j~brXuhjF|>*M(? z@_V55Tk*6X9_`UYm6|91YSN$S$kkvrkkq|$(7`b23F8&>r<$+9$Jd1X7m9fX-Ts zm-hElJQ!jcAM2+T&yq4rCM;;1B0OMEJdD;!D4yabh zvg$QY9Xd^U_#yI5;1(ZG*W1<9;ngc%!E4k!2Yo#MMdsdRD+r7~UFYdwnDuJVbTh1G z%{K$x<~c1#UJ2Iv_`05d?S@;wHu=}4d799<2`8kSzmEJSIOyZ)e7u!f{@M?_T7urN z%c^`$zyDrOj)$s{r-BoJ$-mCWLml#@4!_>ebXJ|_+v?+c1o=_$#QzIlyJ6Uy!Q(v3 z>0fBRFVS7k?<61ly}_Ip7y=|oJ??xQ)`@?I49DK~IAbj;KbNCBj$Yxr2KicWy^pW+ z{&XszZ&-HFln%?P(mXBbH0AJftHg!`y&qm zLxH4jv}5Bt80UTE)yUuI_8*0-MKPs%v&YgHvHHBSpVP5Eg<{s;KC zkEe^}M|k{u)c&iRF{?)NjQ?$tX94n=U?J#!zO@_Y)ra(WvQG0f`gop0egPc#Ry^&; zd7Cv+gXW36oAjpwc_cUrbl;y2#(7(eSG;dD-zFd54&+`xG!-L2V zgGYUQU2h*!$9daBG7;3IdD?tDvERE^9w-9Fudeg78|U5Rk)Whi^DIE8DG!$-Uk*0= zc)H#WrH=DkkpNF zUedoq#(BFu&N|IkgYG!Gg>Mb=1z@9(uZ#U|_wiKk|?B9x$&dt4;H4_3=D}{0MmLTk#w+&U;A6 zV(+N((B|XG`H=k&pcr)DpZ4RthqXtQnr8tzP5XBV@@3%4Z_DE!=QSy!8qL#;&N#+P zd3zuEL-4VWr|ad-KhAqJQ4Z=gPx&8{Jadpw0;d3zZ(SVcNx43BocBbsoo&>7JA8c2 z$Ug@!eJj2W$9a1VW3%Rqe3bNWB=Q(A9(3Qoj>mcXG-0de+k|dYKJGxi3*6)5>&E-B zgH!*;JFGvb%RRbHdy)Sq;y!{hV8&T}ktKC^oHueT?Z9CMdi9#W4*iCI8}jX7Couf? zB1`JtIL~80>_D&Tx61!d&~NfP^J8R?4y}8Wu&OYzVJ98@$r%LB~$eVy) zMDcX7U*t3$#S>bg}-pJkf^UYqB3}lsw`8i|~wvJPw!y z^dR5b8G1(~PqXCN9>wzjR2v-fyC?_lt~?;3m!lE?lmV(*ne z9t@NLDqUUN*NgCUF!)-e!Pg@BY7w{UC-y+z3)~aM*NuLnqrvwP?7u>I z>tB0=?{i^+wMw2=#Hsu#Q~m*;Hy{kC^mNhQYvbu?@O>c-zT$Uf|A)90-*(7X1K0h3 z@wGGfTFtSp>RO%TYew94_=xA@50HNX^e-am>*Bs%RQgUb_`c$t&62Miafc<}0?3Pi zrBQrcoPTq^D1+~~tR0B>J&}(G5U1)d4nzI}@Ol(aH`;Nu!S}5qDwaHyM2(WC5pjm0Jg?u)kpBq$If|zn^)1@qtF!nbAwrAf zN&aVqXAI;DU;@AcuLoVU_uP7Yvcb32YFk))U)1mIQGAa<#g?Nd79sulTQkd<}2|p!jcw%tQC=J(vBo_FlsW zqCOo({3^fy!?})Q?gQ}9jecyIyp7!?Mor0)R^0Y+pSl{CAKOg|~AU&Pfdkr#Gxc@-%RU&RxPHQ1= z0BU>2*UsL%TQb#4okX6i;{!rBO6Ns}$@?@XD-8Vo!zyq)6 zU9|TiJRR)4M=Y_yS1$RMA#T-A?1X$BaAOo-H~NW=_Fg0JC~726a}>`%As+`$^o*yS zz4y4BAT&sxvhO1GVjkoLz+ynU0=k$g>vyAB`meEb~pm%!Iid|kBnqSAMgz1PG!i~lOht@ww?ym&g~vw?E}9(cde z#rZeqi?a7#l(hrv9Fk`@;#B>`A;`}F&qwieqaH@vdoL-XddZ{xC(@3?kb41r0F|C@ zwBu-d?`74qH%gvmQ9Rc`t_ODYjOQeK?=Z-kB~Nn{&sUJY0lw=oPn09)t0G0MlBev) zNWPs9`2t`O(1UzKdZO*U*Ic5|$D+P9AkHu%<@LJ>^6!A(NAYx{zD3)6M^rs1mpt}Q z5uPH*1A(D{N>3NfJ{A0j5x>gse?V>p zj!VvN*eyc`cVh2-j20P|JjFDU&Y6(U0nP(>;5=RImpM-dd+$@XNmfdp-H21A=eLlb z1)8FGx>$c)o@jgTnCQl|8p)&S5uR+wxj;Uk($fu|cJ|(9lBZtsEQ{jV0r?u>`kwK$ zxA#65M2(WCIg00BkiQ3h>={od_TCpVRapO(eC0+Y{}w`C0xSc1kbmv$y;jN8DtQh> z@%#bu5#WuU@pQ2Fj=M~u{}b&f#3Jb#3V9eX3g|(4PPX?>v}K=GEcxmXcNHS%(-g(?A>@yNV?E<(XYbY7AmQPds2BNGq+U#cJRO(` z@X*cvwWGavg$;WzEP3jqc%Fj%H1J%{csjB7w%Tglxm@yTcBGuLA?E`5fJ#?4%Bh{b zw@v0>jpSK|IBO9puje};Ujtkp#nVN5kJrEU_TF~ewf7n&Pc!0F_Sbiif8ZRRNP4+qiE0NV<1-m6968%VefIiD0{D7wJxnm@@z+(s=qh@`9a{( zD4uTA!)SZ&21V2=d0G*tnpcFpOp61O0F|C@jQ7#@-Y(vTc?f+b%4rVbR6M_gTnB9J z8P7@f-pwE@mOM>SJRd>+1o&Hzd7|vS-6BPmk|*C6NzYl3rvYaJJan`F>tOHQ<`UIN zo_fR?Mx4BUH$r{_cq)pgi}oI`Z_)PN9#sz-B+rQ`o-9Apa)3O52cDiT+Iw!jKH1)D zXzOR2B;PW`9Y(x7UDre21?=t_U#Iro-IB3I@*R!hqXDKdzyt8m&GdC{@9mR>e;4(A z65>|%eGTMwz@{j^ZnUdT?7jVM`5BgcO^93d7oR}>9B2iIOyAd#dFZaaS2C~+8FXrg z&IZX}9*poWhP)bB4=DbNA@k5Zdrz>R&fu&1T;%s5#IN%EeaIgIpGeMbv_}wjV(>k# zdNWO{lYIH1NP4G0o({|ec;I|p?4Mn}4u;=B-ZmR0Pd(yP>3SUUZ-C!M@pQ2s37%-f z?@5uSX329RiYGOOX&FE^pwiPFo_2=cA;Hrsd8!bnO3#&$w*fnP$kX2Nd)g%m{X^7; z!%;k~kiQ20)kB_648LbpjVP9UWwDWTod!lAeHy#RCd@`kiP-Gi{j~`-525MX!so! zhF_)RD@%&-Erh%TSO%#4>j7Uo!|xqw_%%qr1Bkm$=Hs6r9|hix;_IT_7oEP748M25 z*(&*xlOyxhGRPx67w6$FUzFkZzNj5o?`Rd}R);uMJ-iF@KHxwUPj~8JwBgqx zi7F+}F~q6HVNVLvd_V|L>FG{8jyC*0l0AEkv z2po#y=}x_iHUK|U74M&--kpfz38yiw7tjY#>FJ{VC+hdf2H+Q}zYR;iWr$m)>jua- z0k`&$uTulCRWO!IzN1lmdOFigzyW%azRnH6uUx_^$u|jct9oApc|CA(6km7RS0@JG zah0ESlJ8Iy-=87B1H9iQzV$1YFRnht&HO*KHLwQB6V8bAPop501LFXdkEiaRqIfzO zJU^l?Hp}?y5SPlg+accx+#MDFsq-y5{%Av|&cm0YT4nq#QStv9@{a(`jOgE`_}dvc zSGe(qz7p-I9C0cA=RsZoEbean?G2l)oS<07-w+l53y@y|4tF>HP7IoDZYpr^q~x)) zBI)P_IS(iVR5^DkpV}ER+g*kl8UM1V_SZ=*jgqH09I;!bLaqd60d4toO1mYhzIHHJZtxUqEi(Rk#8rdH`1tt*e3g9SoIS9&V_Fzn1+!;#BjF#BBIN02zQvN0-`lM+4<%kK8muy^=gth*R-w zhI|=tMR$4H87RA5k~$fG6XH_s?|sN00-r?1-=%un(J;A9mAa-iNS^$h2+w55Q-Df9 zr#8nHWdHwSBVp?r?xvzPR~gO$9}=Z;|hHv@~<9o zhw+}5&;5`e0vePZQS@-aZr?V_*+p=%lbs(p9^^&Pz9*`Iko)|RgXHk3gnRN56dM_Lln>NAioT} z+FhPb4Th&(rYgx}=SR}h4{{MO2o)*NZ+IeOH(|Q9106~IyJMRaXhtup2t>3V2%`K9C0h0|BMi5Xd}q9Dg_9C(Z^8ShjHevH|B0ES(SS@KbNd;<(Cr z({0dQtQi+;+Bn*efD9pgLgYgo;#2u>6XXWqUO@5P51EJL4!^G^_^Q{oXG^NtvWCy~e*u3WfeiAZ5mBe{<}N=PGl1P`zF5{Zso1{f{jadhc0ulKwRdm!M!$>+q`&KM_(#|3=-%zwvOO{R@`%B*~>2bSt5L z5=SYSVUD9d-%di)3_s%^SaDW-Km0Mt3ecUz$GmZX<+lQ7#6bC5NbF>*zd6IdofzYc zFtKPJ8%q}Z#_GkiuNPn7A^f8(f9R{q|7OUK08aoaJ*|*=__*qH>1i{pBdL0~eX0&x z+B+RnRoa78jXQ0saPE_w>FPVDf25w(K;8^&0aUuKgUmzuXpyd}p(m9SD%%3y(Nr&7 z%^Onrm@%Zh_ZSOBv_<<7X`!^2?dZJ>>P3?pXAI`eSgWFf|0v>D^}Lny4nRHwivMHC zJe;PUbN-F1moHwkq#FE5E#wFK0U<5q9^(VIqTFUsi@Zbd;s;WItBF=mv#HmYWg66p z3xtFHSnnLBr<>Hk=Q=ek-KTp^pFvZpZlFQXAk|IX%kYU8@4SWwuf^0)9j~QZXe9VA zC8nJ9WfTtL`6e6FOvHfq4-)z!p*+J9ZM+WQS*=?s7P1nbg=kPp4)a(6U1voW{zWs<{m4q& zG);my5Rdn_JRW8tlYb-s{(^k=K{w{N`WxvqThDb6YXUV~y-@n`lLwiW?l{z<&H}y4 zqRIR(^YwYuw9p;;lk{ZM@IiZ|O{AsJ?rn|Wy2Wx$4HWelT7jI1X9>xa4%4Txslcd$ zL{`KKofJO{gi%?F=^)07>mwa%yi92g`6byxX5pi9uPDD0D4%>;e*O}S0YEOG%5MT> z9`;QT=;%eL}B#@T&gsZpilo4+BcC-$LeL``A$GcG2JMF$;V^U&!;Kso4fa@cXtw3|qYOVaj1Vo>7t!;{xwM45L1SZZ*0b0}!8JeWq(qn%U?FVr&!jXa^YQW-}Vpw1VOel(nigUyYB>5T+#pX@JtN2r>^pGd?cn`qf-T zFzd9|@Me!0=UZkrDmF7>X)ZKyh{Y?(0;7Z`LWO3@UyJw^|J9Ih1?~hC|3Sz+{LK7d zt*byCxf0zQ?|!%nUlHvKse%{X`dP@Gv(O7ei7Mz*fE+;=>_(24=0uSn_RvWE%!FJ4 zOazoZk3i-j{(MnSmYgS^X!L4c%-jFcm1`DmK%Qi^&=2Vcl(f(~-F-YM-c`D9MtnfI zqOW_jomLU=)6IDpol<-iPCSa!Fyb&v4$+XuLsJaucar^PA6kZS1S407Bw_+OSD$6r z7>bx4zyvzS!PnzFCW{|LLxV6T*%-Y19urSLCMSH#c^#p9bn`}H%*M?0Z2bm8?jmj` zG^EM&mqyAX8*(Wy5>V-{fy_ha^V6%06+n+9iZTwTqpMKd`-UniuQRJyO1 zzK-GNFuetLy1+OHI?3qc{76HoVNmoskf`Bdx;cWDpwhV0Y+}XaLcWx1dOe{R(V29S zKA#V4T2qG5y9s*Pc+dOoX2^d5S^%Z@3CKLmlkK}zuFLasTU~u|CCs!9V*XLN89xVC zf}evsOpg$42j**8wq-GlUKTB+L6X4IIdeZ+L$itHDuHqrY6=D{U03a9TU7&rkvbVa#(kJxO|?Bx#EhAg4SVeqJa=WWRE0xgoevvs`)|GCSTY*@z24ZKO(0{{#k(EyPT=}3#XDi;!V3}QO$7SlTwO^TYx=)(&Hh>JRDyj`1ehT=rN&&*WRT<`)2NZul$UM}YA$YfrkMPfo@Hdc`FkR>T zpAt;hIsXV+j@MklKaNhL1-#Za^%A_bh*#zRR>-@6TLHy;H)I}um?rp+$|tX{#|+5Iii9&(f0KRUaIwq=gajUp5GT%Z%{iuSnRn% z<&4L&Uyh^l?Lztam%Ks1DeO$n&{DI4)UA8+kn!$Y>d$RW7%Ki z%4ejXU$k(^Io0bHLFcRn`iilak_LLYcQ0lnhw1Sk?#C*Hg}aSlRiU2|LtiGC#q|p1 zqw@;sTVgIJ(B4n5D&b6m8Eu<>=Q3ETafY88(W#@YS9l_aU;?7P8Dqsx@^8`kzna3+ zcMBH9$Qombak2g}MJjg@eH@AP<$0eb^jCyDNPKy8y1xz&Zys{6e6UFO0i;W%`x(eD z1Fr%q-S0!@q4W77FE8Xk1y+-g?zrM%MWi^b$U=(OXm_#@V@do3|lZw{g|bWbHoEEzfg>}1J(1?Htns<5@A!T!fuVCx ziDmxS02{`rpIIg~hYe&yl83SqD+EI|ZG4!GLV~6lPqDUcK&vbh>8gd^VVSO-kaq)j z04iOtL*}8SQ@c!-=L9+1PO6%RDbp3yoio+x+71{;eg{)a9}3m4o0OJ@C^uQLl){pj z=`n0fIXyayrNI&LECpIt8`o2=W%DqhUvfpn9vA?53@{E*`fY~H!%8_G)<%tsqJKaM z@co&U)wR5PXeMuo$?zR`@XWsnYrST+8KORvd@e0R9qf-y32LJv#$hdSvS$Wfbr|2d zSP3%YV-1!RgB}e!-bLs&#F(c0Xdd}5v^TDI%}AklGxQ2WFJ50hf&5S4TR`buc!tn> zce&`#+S|J_U)z?Gld47{V_y*&d!Meo!810ICFrTtM0K(9ZR#E6qX`}_ssPQ-WGUIH zECy$+yrV)aEkb3N3TX`_dt zSf5X};tgA8MxucwgrF7bquY4zx0xQa!~H^iFZ0hr7hTA(7a%MzEch9t^+d*c0-fEdie(O>UOA6iZc47b5NlW=e- zZbdvh3z_sB@qIA*f#ZP6&-LR)e#Xxf<-S#pYwh}p$~A4)P%F8Hd`US z&g)uy+G|#}5k#}^@ADNhSVw4F1$rSh6AUaj7DCRWSlP_>VbY1r&ZTb?K8^(NVu!J; zwb_cZ{jjJkbF_g0!yCs;+i%7xefKn=sbO8HL&n?;Y=?qlIkZX-V7(RSOpv~ak;WVA2IiA6nf zN6u@pD?oc=91UYYVb&(g9W=4DKH41!tu!lrv_CZ%=J_M`n5J+my_k-pzajQG>jHZo zgV7vo=CKLDFf)N&XiTB~^*la@=Amh(NM{q$p~i=|A!kfvS`MJnc^PCLmdqFFT)9j< zBk5eWaP^Xv)xs6cZA|s_kK{T^>gh+~k>I}hNA#N;sQa1t%k9yB!AE>#`@2UwYM0U^ z+dkWxF*p>T9HJg4DYJLRV066`kjz9qG1xBD z$cHfUf!Bv0Am>kFT7N+0Q{rTiPcO-S=1sYO7|Ev^ZfuQR$8Ap3hHu5*;Xd)W!*FZG zPOtkI?!MlPKk+{3*?8?~PcAK`XBeJTAFKp_1}e1S$pOkc!S*+$Go zY}I9z%-1`XWu*JUo(Y(i^uhp!3FAyF7znXRC3);tV)a|Sh|MUx0RN;obu?SGb`hH! zUdmRn{G{MQl{+nQWC6pK~5twR90HNEwQE>1k)PRl)M40c_Pdi&#cd zp&Om2Us45IwQLcaoOBLbRgiJeFH5NmMg40bu?HZaziKJ=KSY$Z!33q%{`^|5u4D3?0qd$BB+ zn<2jf9063h9GN2ftrfE0+R(B7y5(}t!j&7VQ8GC#)(z$d7HP4*VeaFfKKF5ZqWic{ zyn8Ckeb@T~)RM#W@cG&?XP}YeE2P7X{!bDIdo7O9pBAI-#{2UBhge6*@J|RmMq=ni z#IS8E#l~iEDB%VY&yt2GW9K?E_a;hr)5%!9>t}4XeC|MS9$xz!ej`6G)cXqJ{}o9) zPH3#1dnKjY+^^n4j4O%db-$d*XVCv7)>otm?-TexD`TbjXFHIYwx8YJHUND>tWU`} zIRsfB66+%}tH_`xrs44ht8uU^%JgId1?w#Kg>EOts0DPui;)W&1 z)9?|({s-oq5q_1hS0H%tf1=~}SktY_J}fzu?8z{)O`DzTfy{=O{sfGBjOo@H*0?^2 zc0$NV*8To>2`#hp13GpbwnV8p%o^UN6A>O``>?G`JlIXr#_Y!MA8OM+> zHcPEZ+#+9Q71+Zl>mZD62n0X*`R|i0>U!g+Zr) zV&zjmk0y}*IlukV zh#>nlv38JIw%_ZcOytF8>(U~mHNglYC(ettV+u`wD1Q$@QsLxqZl;ZHE1C4g5S=4L zrY9P9Ce60iST(Z_p*FGa$Qf5qC?8M#aeAVOv_4MRV>HoyJsVTN8_5Hd-A@zUS8f@O zGyMB0yMvb9N!jhFjLt5~uBW4KrtDTa`ZgYylWWp(H&AvB9d|8dS5uQ#?x5^fv~n9| z&(OhsJJudfg{akNSm!Tg-w<5Rg2lqXHkB=1sm%UV;t=zp|nk$Gqcau$#asQ%|7$UJnm9)a;- z!n!r9#F&s&hnl^G)RC77b|GL&Q|(!Qwh>3u23v!$RZCc5sK^+g`_jBL8>`wr2iqaA zK^%&?GmA^6b~?AJX+g4w71AQh^f6<&GYqOePK-lhu^xJq-yrlp1ijRJ?={H(2Ye1F zy?xW=cy_9F6le{%#6@E5+uhhg3!Hl$!E2WL+6U86q~m_7Z4Y4HhrLtFcBqH=W3&DJ zVYOr%VN98``GjN_F|L*x*4!xcn*;ty(3g+5s~}$vYy*^jcSGjkxSV&j-%sW9`-Ra8 zRt<$6avNV54+EBK=-p1Wg8}R$&`bj704)9trZJ|E_GZ~$cX|GLVq8KkIbo{bCG=_q zuUbc7mDu+J(g3B`aL7D#zR$t+!upBGI}A5i`#nIP=WD+&VLgx+`?a{17D{c0r9suY z4!0Rb@IjnR=2h=vV>FqG=}dpU+{n{=@sBjE;bx&x2fr5>@g?_~|BIETq$g_d-0HxopGo^kPig9|Ed`9L`OV(7XW$Ua) zeP`fNoiyqnq&(^xY&Yd=p9Y58L7hHA?R$}jSk1$pP#WAi922`kJ~K8E6AcG_z7r4U ziWL8u6V3iPL;F~T6zfrxTH6Wx<&dG+L&86uNc*RjQ8U0Mv5BzK%GsD0XE;_WF-rII z-b3wul!0SE?dy(>ddM911f>UIhkLN2V8oc8^2M*dG2E`pOb)|Q5QDKADITQOLv$K5 zOr~E$JPfTFcBEt7N38>NET0!)LS)@Vt-GnRDKTsE#KI{jQ4cxzF0pQ>)*k$oA$r?L zC_3*u!oDZP*!+jhfN8S95!4e0P|r;;LK#Mcpp}4Cm^lAW#C`Ad@&8*&LoDkSGTIrH z2v~0u>mAZ(G#iy+jkEDh%$^O0^`40}1~*#2{S2X>6TO^GWJ$M>DmGp(V4=iRdjefx zJw>cTq^OE5NQi;+P;aa6Y=induxAWvB-sP>hY5X%V(!=b7P60EmSKA^E4Yo&dx*8( z+E9eg?jZ>tE62aeKzSGz%gMszgl}sCem!;|bg*CMGY%^Tds&J85pdoKvRLlIV!~@11+l~L!y0D&WhL>iy^N9)&Z)0 z9DvNjF6rm6Q?9q4)IQL=WYyExbYV|@t8352lo}4|xPzHq4(uWa?qt;L@5L>43`<%x z-=O*|jO)xUWM2G@g+hGKdp|KI({*r76Lat8M}(dyphp;b@c!998+Id*11LQ!AoI{5 z_W`P+_Fu&MmTbpjTcU-0Ay&U@#IkoCeu*w78@nJLnrEb0iN*{)7W?o8hGXO$!ibOO`&P);05<@N??K2s92z0U50&rh*R10izrK3i25cqI#5-OBb>xo(E9tM% zZ-`cg4SOsQYfsMgyu%_B^PorFa%I~Ooz-ve24X8 zw|rJrFIm2D_4K8)mPucR%1clqenU_tUZc%ayNzI()Gi4*{(PeZONIG1OUOswK#z%h zWv_q4ucG;o(5Hdx06v~Ck3fDNcnMJYTzH<)XRGwWOjEW2t!-!&p{e`(|V9GRdems2zim zI*xjLEW=4ppw@*b}ylqo3Pl)Rjxy) z*6_T@mqSRms=tRJe*k<8sC>yi|1{;acH{EJD^!JPB+a}sHo|;yABB8l_ceMyelr4o z1P*2%9DMyQ2MLbHT&zzV|0IywCk5UXs8CM2X$EL9@xY!5Iyr{p$=7KCl;2F>Cv*}S zPlpggw!r2Wg#NYAPxbRxLf!#f2Ppk-hs?u?&gz*|J+5XAPCC4X%@FNLJ%eV_(ZVyP zh>nNjFZdCvUKD&Sh)?l-3HdAFTgk!wS2~U-qCPLI9amlBdc}mn6V?uM4`WQrbb=Ar zjlWLDKWSd1ADspH0$?$q(z6~i4>i&c`rstdzqvd!`B8k{nKY6=p%8eQ{zbG_oe!Wn zSg=95_`c6zyzNIP!AIHA>V7BE)r5G%h?lpIw;_KBdh+esn zdFV8MRKMD$R|D2`dFOhB-bJ-(=v=AnTn)w?IB+LLI#)jTszpz%>ix??pBnI~cKd6{ zHvzW+DxaQ!%)`(3uWd?|FUG-$ZDfoCwcs#zQ8q0!^RV-oLG!T9nPJjk2KFGJ&Pb?3 zvqT@;@_V6=wjk2K#zD>n3IL_gA0YE^y8cyZf=>1irrXIrJ;E$1c^0l-i>3o8a6>nn0k^~4x5b_GTQaA zg{*f%p55DB{6Zgl3!_)VRZ;a)m|q4gKlS=*e5}Dw#g>8)OtsCwpf77M(Mhp?I?7%g>9WJ z^eS!^={P3!V$Ug#fVI&*R&Gai_faz zS0i~U5swb;f&^<7>en53?%}ROTrj^vQFZmW^>6gf) zX8JdH>13n9#hB%criNlzY$zrH-X;q$ueE5V$4F!`W&oc%>2}D^U{|BFb}U$(iH1Q? z1F&=r^HTSdfDe0&MvfjZV&JyofnARL8%`SteTKplqlzYyWZqy9>i#J5FT5zyzn4HB z43q&p@bROg--kE=xZXVxi0yQI={zLiJZ+v20|<7YaS{&Nm<$GzuH)E_#eD97(jxhG zBW~4C+z0tLz|(-r$D@#W$nUVer+Cj;vvIYYBH!zFr9;q_Hq-wQm|fXe5ivr{X4V88 z&GXP$4>RI*%PQh&z66_dL*?L!_*>o->Cayr(Pud1vA}ph=`$7b>GfH?VIjsFWJFxm zG@Q$5rpvV^919uG>(4kNQyM0fe-eDV5nmV)y7NBBzX5&=D83gU^U%>hB$9r?C!LYw zDl1?KHPiXpo8TPAIm=wmM#*O{iSVUCE(1mZimw{->G&qEUQ%7FJfG{xrY)q71o+Dh zZtll&ahh8Mdvxs)ES?4pFAf3aVj>mm#Ic~Bj@pVA?u5*9^f;0gEanTB4-&ePZsw&? z`Dc+YjnHEf6yf>uBILJ$_W`BndDTMCUDEICu=E#I`Ep_P>X|hwUHcWgn9rK-R^{s$ z*08r-{1b+@X8Mt>y{YG-nPH{HXJV-;Xp|+Gsc23<795GwY3G^DW5D$XXW4?xNH+aw zSayg7Z5qIU6CfUeHoGJ*$Aswe$h=>R7LxIV3Fph%8kU(0Q4+~=c zbK!@Cq;94S6w9Mi3Hs$-1Z{DcUS?b**KwQvBJ$x7(pfI^;V|U?1>OQwKKunT42Wx=^=(`CZ}j+KB@`!?)BZox|CZjsJGR|TZI0S4rSX7 zp1Q^lMY?LBx9ZonLB1Zi8Bpok2bqWB3NbF!$n_VMu377rubNW5bi)KWS*==+<(HfV zJROIKw#&}O4B0ft;Hoc>o?%R)y+p;S`AG1$B7VhhEyKDGkOV0H639QtfA;bVm$fNS zvmOq0=fIz?nf@K8f}lVNcI|Z|?8%2Om(OeYuu#V>T&_%Sl1bxSg{uB4^r-`%(&q-q zw*q$pN}v6Zc}SP*aGm9c%!|0H6>dKKnrJWD8FUc_P4}>yn**(quNCnrK7Bdvd;yXH z#Wxx<52qSemh*m2Wq!@o1c{FWCb}809lqywFLZ4|iV+PzA(CkZVuFb{EzK}Zi$Tjr zpJ4G(W-)Ks?$YTeA|JMcSLwAE@}s~(KIaz2kiC(DA1T{&0k}ryk2Yn$A1cm}ipV5$cIMw*W>*>sz zg^R1*0q-n#z+0+4;$+YYKKP6@dWiwA_*0pF86WT0cSF7hxDQZ#Ps+cmd6{~ucEP7; z14=kqxNjB-`?D5&9dNf5;D9$%xNZ4;AERYDh+K+)4D|tAGjZb`WF))dIHZEO2drxJfEPOW;f1&<>VZ{Vu?W_RK z>guSlu9lded?V6TUK2^z638onHGoRj#gKV8+F>5rKL7Fy+m(AYKj6e$an#htu+}U${xMWnS;9axuf2j}5LJ z*y7cW8aT{?^WQj83-g)s<~z$6-R5SYReme-We#}Nc)ktt&A{z|((47tJRFzj>Gw$g z`P1r!J7?T>i~E%}RM)!ZZTU+Ct6vj=zE}X;LEol0kDg7_X<@+frx=OYz)ypbVZqtS zXQ%js0T#q5X+B5&gkL={TlF}N{}OtK)%U4$OaxbrH%hZR7*2uEW z1e`XvXsY1^X>u@V;q*iZzW>O|bFfMsB<{Ht?R%l$9Po#cPkbD^6!I?MRzT_Z31l9Q z$@7(!(oQ{XKB5cX=<3!=o}yp!rJ)zZ<8Jt>^9=njQ#*~VEA1qPJ3m40zG#p{DhG)e)7_?1V7IG2_5~-)mp)fevxk%XM#JHH^NK=|# zYNWH7=40-7#q}=#k4R_vhDbSF1o>j%Qb48iPRKlTs~p^P&e*tSLp8stD5>&(f^D=% z$aFp;eNVL}6BQgvLv1=Ru`DewodySn7`%9`WRDS_2E_-#&lnCKj@I;}(DNAdsDd86 zJc1kH`wR>Ol%CH+=Hd7SVthI%?`=74dB7N0j?=wvLu?^Wun+k8HynJ!>lb2>`V5ER zc)?ub(^}1JJH;33XZH>Ev-&2&2PQAxiOY$%{DtNj@g-inZ%kglL@S}t^!bn$G~Ya8 z`hMD^9Q)JR&`rum57s6^Ez4oZ<%^BJaKF`A#3q^?go1+Sf6L z?b(I{f01n~C`+Le8X3CQf0od6b{A>eAz0`J^Y%CWB|{umG&*+pFnb)cN^JWKTKEfiM*TN|qxuxXU+lk< zU|TPRh5Gll@@jw}E*J(fA7s_MJqKicB&1vww9<$d&8ay|7-N!NJ zKK6@uZ;N-AQ};uZ6948w@yOVV#p50H$S`f6N0m}+O1zVYgF9sjMJOlR!L<&tC<8y8 ziYw5(ILdFHkFtqB??%G&iEmhVvED)_lXRFIFmmMGJPs$((4z#?<%D6O;R!el zmvlHEsetFlHGE9?yO7{zlWVS1>vTUYP~+ zecMQK3X6joXtO^3;p<)lv{mok{b_+2h%KoS88eY3EV+QKHL={e3MaNIO0BXQpzZ5@ zGE(7jWn!%(W-Tt^I9-!CL_)tKbT!>a=vCC51<$hOzv~<{~Kkc}I_2=q!3;9u8*j@iC3@-Tj^LF$-(H`+- z8v&YRhG@LU4y=N^m^)t^N$G=(Z}FPdo8V~FW@f+!%SjXPaJ;DYVo9IMtay6C+y=$RYIrQTF**%b72i^pf-qW{8z1N9;toavR z=+9)n&fKtOT{RzOn*BTU*Zri~|Au(98t%KVP4{ujDEE=^I*NM--B+o7;Tveg81GOT zGQ4yU7VKx>hAEty$i`uVfM=vN%(6cuSouA}&&sV)7Dj2$-SA>1mcbJClME~KVS-(P z8I%SFslniUXOc-DA!DtIhlzvn+oZAaQ#@zsspb~%c9MhhZBdTl3*Tg!GsGMmuaWML?G0xT0xeX^L_LCc_wTnJX&Sq0b z{gqfBla=mk5SOb}#0`tbW;WYNi`?h6xOJ(|1?>Duzor(ZHDn&k;)P#v6SZ!J8;$!2 zrn9sWWGM1r2(D#w|NJXzZNs142QCHdEB~CwVgjXR5=$L}6{WOsY}8O%@eQ%QB`e+6 z;7B&2!dx2}6;3$X1(spql-gNHK!YZyO)(vE(`x^9M7fT-`?q?5^!h|fw3i9Y?&xPLA$tbxCtz{3B9|;bn z=w^Rx$vfW?_BC01oZw`RXA6rTp(+WVu)F->ty9S%vucNkWB?Jhd=zNp>3V=_*PxF39R1uiobx50ioXOLMb+O9qH<=MPbT zEuMfAL78+ty_oh+!5oNA9<$y^!?ilYN1jpIyR73U!$yxA)xUgbU-i%X=1$1UFT0#X z{lgI>$CnOBM64sT^4pXs&iRa(RlRDXJ{Utw%?oJ%I2F~#bgtVny3kEyZ+b!Sf~<-0 zrEwOYt)hROEBcMbx`@5;9^~V|cYx|QVlEf`My>QOdQCo0+uynN2EQa=-BPh)jc)lK z(Jk*0kG^6#>{?y>EC}Nxgj-s1tbPg0qm%6cMnA6OAo$If(Q!DxmaorH-LzJ7zR-Ia z^a{)V?k33lfd>Jl_n#p1P%rg8&=tMi`E)zITgiUiH4L{&i|~k{Z4Y5jCOH@*r_9DW z6AtO7>5mT;1ZiSPLIzfBD-+|3kcQDn!HdLrjgWG+-#B0BpMOQff9xE{7Xm8*rT=q~ zdDth{Ne9pELVqphpV0}xp6mg`-HiP^_GEd#e8|+ALb-GZl;$(Z7|bMXc;$`4Oj1X+ zGo7I6I7K6@k>f?OY<3o#P++Dfz#{M$*g-$8^~5Cz1<6hjdoO&>!<*ZgSQq)07-h7A ztv3dcUzmL@_u^emTPV_-d}XAbO@zDxr~y=ZABW7tn{z}uKkiC;<@gkx;H*Y^7k!kH zM$ClW$7kYEaLR> z9yfqe^IUkE2NMh|;WLKyGMrOFny1qLCeCcnmBj8(irAUPOfuCD$YoHia*0THXltaN z_J%wPr~p*D=RoG6~n>v!mcm8j2odEn?6 zsk{S=?%EZx*_dDE(F|VOM;ldb%@&^9f5cZ((7n|(9c~LBmeMsDQbKKW2#2fhT@@%^!PP;a?h>kVSM2_)8 zK$&p5)4dKaV`AD9X;vRSKTKHzN!m;B8oQUEo>=;AB=#yeukzbiJtn+WF`8oivVi4T zmVw(rs6LWn>c+37=AW0a0ann&K~4AFFgDamGBV}6v23)Z{{3V&p-rB_rr`$Hnfjbj zxD+RV^F&jjc2jN57}EgX`*mdwqUA2_wvHH2M?jVWuSj>(lia%ntP*x(RE zb^HNmjePu8n7O9<{%yoc8o963lCyDd6OL}*LC8{E z8#YLPhLG992Zh(OhBcyIlwB367tcS%J*$IQjL>zULKZ))IBfU1h~n>9j@Ch(|r(0@Sw2KXLOdeH4ckDptA zo4tDd#+n)&E2v)5$xc=r_vqnz?IPN1dInvEu2~ywoD*p;RcnPlmEcqQTn2d?ume!~ z+yI$}Zs>z8kBuF-)}T<;78?p}*4~Fc=kl$+8EQ|N$KN9LX#tqP$4fX~J! z-0ry+@~yy~fYRr2$UJnsud#i-!Oe~1`9`GJDC5JF7M{C6i5elQDH4pMYpcGL0jEBrarM&-dyYxqCuTOrV`(Ewa zMeW*Ey-2Wq5`<&MTl6^5o;Jq9ryA?!x_dZlE^dMtO-s@5H*664)Pqlz*Fnh70M7$T zpWj2~;mx11x7+E{wx3koAD3ReMJHnO%r+a&n7-J$=B3vu@ zTM)mhPydD-dky@Z0L8xpG7lT%e)PVJI-9rh(`6BQOi~|X?j&_5bsrggs`?hKv$aDk z7dO||qUm{P41@av4VkIfbxpQx$9JJMpSVXs!k3EtXhnL%NG~ssz_m=91I!0he!K#ihtrn_`X6_cXe*JV z%I7JnazYfwM9EVi_m%G}Hqyl8#5R2+%^X~;XZqmQ z1`imgFtHCV!NKhxrU93jLQH9_eo1&AbW%+lw;m6m$ijZ!eips~?@JSRxIqr}E2%_N zI?GD*R(fz=$vVr6*PvTrrqQn`{hX5X=sdE3&XhH{sZQiq__|1YIs@{Vz%)SR*Br<^ zywt((u|t0#yf4H^)|P2;HDzn~7&cS;9G7Y1Tqy5}Mv2R`!Ji{Fs=LyPu>m9##9>i)H2-1n@R?rabR;Fivqe5~_B`!nINScL1Kaa-yNHw6Q%QeP}Tpvyz$Hlct1^%4E2 zK%NgQ0+jw&LFQqD)PGi|`tx1;PV`S|C7+4g#=gXUF4zADLwnBRrO+P^{2B1cXC|%^ zXV5-gFZK6B-sg+FpMz6Bz9G0@X@%Jbx!<3S_651_&D(|EEznElyL|)h`2{iorT19K zJPelp(jUwH&-V3)=liVAb;qXue+#>Xn=f4V$MLH)R*}g2DD6Y6$<^MQPjO8mhwSK9}<8@XBp?<5NRe{Y@~Wx{Z64@ z`Hd0%&Vzgrum({2)kEfCpS(YH!>rEg_43slqSR}~sb05bj(y!7SDvI=J^X5MK*zxW zp$reM@PV3f@Mw%Pg80n?oECDusA-LnKr*?$DF16@`Ga5O-@hSycVQg|Q2LcX=Hc}E zZTwjU_jgml&~-w;I`Av|{vOB&f!_j3zto$Aeuk`{TRW|v?zQtW2M4%Sw;I!~tR{Md zJx}2`R4h5+>Q947mH_bzf4-%036Fo@R%c>g*&=Ga7Rs zoD>za9h`gJE$ct{R6d)x!1e>u0HsepWFA!gA1u#hwby532kW?P%U06=Sr9r9J zxo!15qP+vvZ~>x&?wIR^ab=Q`LF7H$<+sZ62d}F4dm-NsJOU`azJ<)gIC;KdtGxfM zyj8(GOk|%(EQJ2=MsvBsnx>r{E|Q zPO$LV748?rlH&XzW}K-OZZ!$w(xY^fg@QpApGZT!k(%-J6I^bEJ1DVTpR6yz{<5qA z<$GlL?~cs3Yam|^Yy(uf9*4}sJbAz1B`C zZ_y`B?Pg~n9ceyHjCE*n#Bb^>*<8ct(hT!LmWW@0!I>M}6e2otEN+)zWyQo2;~bj6 z;*o+rBt_KWy1hdG(5;bj84P(GFd0z#-vOD2S<6H}-nzE4{ye{M)xw%i3Z)&TTQpDkv?q~-GCSF|d5t{LIno9by*=RrY_X+(DfM2!a z-$OnMyay=#5^fjz#j9~b`Wd&^&wW?TmtobBb4(o{*WIb(i*o9Co2l*e;zDA$OgSVI zXH8?UGdGGBg>V~R0#*y`4Bt|8J^WtNL^LCu<|P>^m`n0}KND4KC|pS3$(`t%%4&^R zPqIDBh*h&1?0-KX(o+k4Rr|ja^8LUgfJ)DEka8vIo<6o|3tJG zy{fmI5a})5+bHWFl;yuCQvQ7)mjR;yrO#Z*Jd9I*1oHP^+UGBCw^0i58qh%ABYU}H z`FD8mI`AE?QN~8aaNjgh1H9#Q0A^Wbybkc*WDp%;q{=#wY0aRc2)_rt{$ZhKBlJ-D z_7>z%fxiPvPwS4Z<(s>8)=9oKkejKiZVvayc#FP6wXcwQ2~Y@EK$yR<(tTJ*_rzgl z=-$a&LcbumA0VE0^*ppbBJ`XCJ=D6x#gMNAwgXDfn<4Y?v+Zdt_nDK5^8BoMieMZZ z>`q>m-*R`ng=vLXQi5La={TJ`ICB4wwumeda>u;pf^VTxgbzh1Jwa6{}i^#j9~} zD1QrU#oBXF%}>YTh*AY6n<&CnMkPwJMe5T4K9xT&LOufg@&B>+=J8P!`Tu`+PtTdm zx!hIzf5D)<&oB|3&!CNFDBoGNCCPC0uiHM3P(cN{`)g`X3a(JMtuDXixMpxIY zx`=nYSan^E$EqBX-?O@_W+ow*`1yVR+REeguJ@$7>;0~ytE%gG7f||q1TS2RT!;Nk zhx1Rom#i6&R!AgL;UC1P%klGsCf6F;t7tOIekb+bqCAsjrl^TCRi{b_dcaPnu?-Qu zPJk~3X914T2Z$b~#Q`CHDoi)vK($ zv|>r*;C1$%JZbMe$+3s}FJa-jALB5IDG3bLCS+L45)%S(euD*xBfN>6Bza_PU$H9S zI^8u|A7)&xi{=5h{UKY=HRv&x-$Kt{!`}k_2vqv*fER9>wEzEchwG8WxMW1l>^k#F zqm_+DyNrKxaFRbCE1U5#@gT#EeG3yOvo`}wbn<LpXtsR%F&cqlw#(<{@<(^$zh6fG6pcYPqeYe z(R0Ys|E1H<8|5ftP5uNIrwE8vrQol2JX?r|>PMv9=F|p&p+LoR54><+NV{|$k0-R7 z@323^LTb>Wt1V#}4%J1ZMX7a#*L~j-@eSz|t6H z`dP@$%xRx~ta%(^dS^Q?XPJYCeH)$$e0ugyGLrflX;2O*HQCFUWTXvd*(=9L^1m!j zobbA*jW!a3fn=79%SV?vkrqd5+K)Z!fn@b>ho_dkc{%olz?jIt=Q2LZ$|epZOJc{f z`$|y-Og6STNYVRr4sOOaiFS zx%`ZDRkP-dl6`_Pes(>$zp@hdnpmxl)i{~mB<{R$;tr&bJ?hZJO*K+UT&PUkR3lR+ zF8`B>JH6w?JsG2lM|709;zCD>JC`jvxiWF58Lv5vYz*cyDoZLHIdSyo_GZQN$?y{>ADMExGc4gq{H#Avhs?G8KO?J+Qt`!eWP9MkI?RqpT}#) z9$A*~_7yeMa$~i~c1>$|-j<(!M`XU>2>3Bz91yPieQ}G=wf4v69akzg;|rl2-xwdm zv)g6(b%dqf$D85r0`~zGzlY$3n<>l9s1CnaCz|Vf&8u&TY9``wDXglK} z+JlBGi`9P0DlYrjUa;foxieCJ`@@d`e+Ik&lwK!p zvGp1&_g_@4>8M^7?Sz&8LaV+_S^I{(k|lEE&Y{}p@e5pYS-?BOHP+QX$(`;rR%!x;C~*j@ zUDGe{T$p~r5v-NZI4}Kzm8ZtRAu=d*W-D3Wna!Go)^=X#`Fq(rr+<4V@Bc# zA8XHt2Q7=~M_6=>5xh-z-_H7Sp1E-RHr;U-uNUkFeO6zeZ-tZfoGI}fI^)bA9C8lp zKioOmt@9Z--8j!Via0q94=3k|*gJRVq29f2(>=HAo<5=8o<6?#_w4x4y&!J2p5S{;kNuCq@P;`9!|dhrwR|uNsPc3^yl~IR@4NN#d%A7^Xi4RY@|DGy|CV(MhKye|EJMcgEjrJl zGcB5UFO9`6W5220l(f*(n-&ez#6}9|fKOvZU!38M@xgOS85FxlLp(!A`dqH$qdenA zI^srq#*9phBjraXSl6-ALv+3|SR-gRL5&~S@!E;r>OJ`sz7?3;BJo-RFWhE1E^tPN z`;|(HOP1LSV8U+;ovK@1tq#4;yiT_~cdHejPu$v`q2f<~3~&!N8AD(^Io@j=$*!fiVa)UD&KPEMdK+0z zH%Cfk59S~)jNynWb%tK`Bh528_;Wd9oAX@rjMMZ%dcT+{b}dak`iUL?M&cJFej;CY z!@mPQka6z5o-V7bSRxHaU`%kguqZeiLrs0Lrr@Dq+h!d{x+}~sPeTRUbvv_Uv<3Rru6Jp#T7G9$}%-Voy9ooefBtO z!bUOLdY%0v+xlVuE63tf)qi4$#(y2!`8kGrcHArhn9#6J>rkfSU^>&ZG z;8Q!^Gw+VXyA1wZa3N6fZh#lAu*-E9#Wf}6<twrkhDe~3#hW{SE{Xq^;`i+L~UcZ`h zaiG_6rL_#tw^j30)Dzp#*@2FV7qJwI5#l&hOx0tsghcBml&Y|F5_0N3v(v2(xk|6! z!QTV^43u8e?zQz=BF7t*y|lLVQ3(f)6ud#%0&R0_Y+3evCHn9=7M(77@^2Y0dbI{!^yI_Y zBdjD+?{NJ46zBX*ma(yBJy!6EiN+L1va^)&@mQZLXNpr;$RFX2^~ZWVe7NvA#a7Rt zbH1}EWsbPtIW5IVJ;LH9q!{ytS=?;Qz#q?y$P}k5v^_F!X)oT8?r28OEtWBZK@!c z{BtBdR>EHdE(J=@8{mcOdfjV{uzND4bZPlYD|hErTgwQ=YipT!7=T5BL=c=L^7bk0 zd^mF018rhsexNsrSsv7zVO9&x>h{@sH6vGzAGX3D_W%l57Ih5PIa1I3unJI05+|3oFr70)4+ zy|7}6rT7%4&lR8LQJgtGCwvD3a4zbFJnlb_CwzX-(C{^muX3qp;==zO;F0&&>EZ#> zOw284oRF~DL8EYEWurDW)E znXv<{jQx*p**;DuWBsfh%+cMhfqtp#5_7Fp@QSqKEV+%ySNYov|1J0tDE;CeIvo8( z1{a-7Epj|a1Ou(wWIgi@tWnKEF_}r`_!z0!T2AdHDXVl_uTzk#^jZbK72FGyUip9N zv0l?xE{W82qG}UZ3g&=GU@^EA z0_R97tE_S2h?kmCoRDSzK9Yt%`nQj1$t2DuF+|BEKkV!3?nADcqmFjFSsCJr0oLr_ z8RiiEOsuo$BaN?g$ldDu#c8M42GT>N*KP3kfct?;uSWPDmNU|8L8TZ5Nh%sa8VtdN z&O62`YpHIEC&@90g^E3pgm_lKZ<(w}7BQW0YvCi0WI3tFWRp45n^u81RXQnH9pJ=7+G!!ne()2}LdliNKN?k`h9|GgWY*K}} zz^X6mytY0q$W!_xKFWC)pf6DRjD=Aaih{gd%72*fReJm#{$21PQ1Xq( zdn}*NEBaRj$e#(OSUP;EYfWuZBU}^k?i;Rwc8Z*Dy;@d08v=H^6e3sYwG6%ntN}`| zE8u&WF4L@&JJOgcR(XVl*DuIxrbP58inI0DjU1)N*FxqFr{)Aok8Jp!>tQF6 zojjroDzd3j*XmfJ?2lA{cGARHz2qu$hNV<6-qvRs@{~Ro!e0)q0ZO0S;d`jh^l*OJ zdG#kS_;SnN{`|2J=J4=`BE{h(JqJX5s9KI zVzYe?)hF2Lu?9IxkB#s*fjLGF`sbC0&cfceMIdhiwj9b_}O)}X+!J;HH zeCiP)Cff3UBzz@5(8#)Q&<7~_A^0B3Utpzys7>segn@E(60nu1n7XXks-d^* zZ`*@D1FWH;KH{J!MzQF3dUH&_%ftF}W|Om>* zRqzH-`g{v7T!CCK`-PlmX`3%ms`FS*`HtAY{S+xB&PPpQB!F2W zF;al#RJVJUNUjT+=d5XN-t zg{jMt`A~R-6>gAX4J7SXy^DL$UEgI7}5Iyb1a7Y5v?klhas}<;u<(ZJhz)i^*lpf803d zF@c%Rd2W9u`+fV0J-_0myvtzS0E?$RBOTL?TMT!;Ink4hMRn_aEgWd4&rag6>dnvK z_kmWR(r4IUSGY=$!G~tUqBT$GxU@je$ja%wzOo$!f2_ ziAIJvKnF91Q`nM|$JAPq$L-~`UaWDTae^xa}eFO22wGB*lic?A~TVw=p%7AEtoH)bDW zi5aYAoWg>E6muGNjo;-rig|q|m`53Xn0y@S47fPzmeYTO-u!fDLY(erQwtL_z5J`Zl`ZE@lfR={w2;f19?Ejb1}Sd z%Kk;iB_?D(yHR>(ixT2k?NvoGG71|J1Yjy_xo_br>9?=;!?p`tJb~)>(#iFWD4DB%{WCkUoWlS(uXgZPRh7EA;BTdYmd14)5 zjc2ovsIM`bH3>vPD;#C(tu;l;MULP>E>LqObd2rFx!PRdq%ma902 zQUcg|Bt++N9(Syzg9x`->ahVis-C(Z{&DaWPr=&(BBJTZX06jNVK8Ni%w; zMWzo0Y;{0x-nHB;NtKgBVbPR(mmqb7E*4DSl7NrpC%Lz9%<{_ zDD@HV$LsK)h~KY9^qmSXoLU#salcp|aF|xrhtBY=PRMqhE^#x5ew=uob>^#W|q`DCK)3h^dvmwNqNv?Jm5*&=t!w| zIIpD(?QC|XeBg5a!IAQe!@13q@~P>3!b2R!G8bgb)wes?W76Ns1=dN7v*UFGdaLsA zF#OYCCs6tD61;F-&$|vDYTK|K5;>Y9t!f(4n@;RL#CE6V0-VdtWEcwJs>a*$(_f2x zZ;XMT3}yf&e>S{u>U%?_Z~J;jt_U6?mq4dgO$bY8oO>c*i%3{H`8q+ypYT=u{{p`g zybP55f4~c;+HJFw{z+KAS{hyFxRp~~^g74y^;SMhKQ#6@SiI-Zw7135=nUgH`_+t} zXzLMtJ<`rjf}aiM0j0-$c;UKhXTy5PrO|0sE5ixF2E{2rTWKzoxxn|0l;1%3s@>WR z|33H#DEa?_7p@z7M$rZWhU5)yn@iTO(jmEJE9d|uRTWuAS$?I}dw(U)j)}AELsd<( z(lu&jk3X;25CvITpSr`W&*~v1dx{YNHf_s;1cKbOUl#{r5NcSHUiz z^m-Fsxc2qGXnFIjQ)lzom4#`9;ID!#M-U9Z*^f3pXf5rQzk(NtSH9qQ=1s0JDm1f# z5ikzViACzJ|iZ+W+oj>bVn*3yFCeU8fNt6p@w?S)} zZtK&8Je4kAz<&#V07{>I@WQnpkBcfdr;l71wm%a5l~q6r&zR@YJ~mcs=4w7Q*bB!9 zob9S+*m7sS9g({jeg&uoO71!E!llc8qZ&63mybiGrd6$_i43q;>tnIz+XPyfQDDb7 zc#JFugsa9y--3S^d?00s@spYDvQB#{{0uM~ z2q)xx*X4M4J2@vX_Qqqw5j0#&9WKJCl5#c>rut647yf?mP?Vh5pA#P;XGV3UXx436 zS(YpzuR+TDk+4;H>HRM41LzNg6Y*+aPP$CL@Vcjd#H^pzzaQT#Qce+JjwL+NPhSsz z8Mrb^&d*A}ldCyEA{?pVR-|UyeXpRfU1+f1H11FrBi-n}bWz-H2#9;GVh?NX0M3lZGhx@BVv+VRQM4r;;T=+V$9w>b-ga29S z5-}I25~Rb{s!7UkB77zP2Y90y`=3C`kAWAihv{*M^sZYc=C@|s>2L~ilpgEhuLK)` z(&IXK;d)#?4%t{vsZ8p)Y*^tQYwOXB9Hocv1J-+hOrZ4W120?;)1xCTx-1)wQjcZG zQF>eh|66b)PDCg@T=_fQx`O64j$-e^rI`BK7t47Z)++oj&k=%xBc*`Lrhg3&yR5XLs@8 zHHo;#*zeGm<#2|>wYrN5LSqQlZ6~pv(&xXBSq08Mh&R1Xv0`^Q9c`CiXUb2Q^4fla zo&KBAvk*N+|KTh6>^<~TfQm;Ayl@NT{O48DUiaa~V`lNnB^9MpD_5+55%Fo#Z!=yI z=3-B@Xr)DWME}daP^Z5_7VI&;r_pB4G?A0Z%)k&IJF-u5SGi40C))7)UA~jtBja7f zez+^eF(vLK&q<7gaV&KhiF$%C-s)o0sYsa@bPpE(zcnzIaF?MEv2r?evYkFViNEUi zxc`Ms50DR3`mBT(?sd7JIbH7mJ>2wBXG~=`IqoxFap+Bsdu%V;`mxrc%U+>>u*bO0 zt=*$@YQuVt{ox#KSE4b_Z3K=rg8C7jOyg`%uNPnp*Qui-DHW$*_N{k6ZESSw_3qbPmUomzvn@K+qNN*|nc8DK&({pwALh)B zot5dpUO-e*T*{26he=V7XNY6y@v#BJbEISJ5wktB*i#=^mg5=vm2M2y-TedooX#L~ zpwk@gxq&&D_=_ad^*X1Wl1xkWGhCQpBt*^^oME192Uy%&8xXYLmq z0aW~^zzdfw_ha{$=hz%>{EjQH5e0&6xC>f!z0SB;7Y3R47(eOErS|8jUneKh@*<$( z1oKMF%E%(TeTl7aJ^BREN0i@P@Xg>8p!98l7cN%X1Nn6FFDt)=j0x4AL@mywrd`cF zKm{f=-o-8~W&kh8>V@d#FEnQwgCg%+eW|VQ*ndabm+Rqg1h)X;#P{R+cHgUqo30#T zFg4ur)XXWbsbMV3YHX@cJmI+Tk@KnAr$(w)k*aN%`t6R=Z}b;@gMta*|A~Gl)|6JS zEM8ICPQ5xkRcn&^)k$4Me(!*P0lW-UemBYMYP>}GhntRarYkAF7n{|m#Cf#OjdQhF z4y7GoOctX$g=KcWrvE3>-&qD<32K4TYYn_`UG&oqSH-A&rVJ$&tYEqQ9;`oWyf0#S za;)mx3i-`a-<{~A`jx3)GQST70;TUzc;Pzj-~Qidn^sgyuk3t!Wi)#X)B$ai=nKzK zUEyVR`mRAArSF^YAA`?;()T~`!nIG|!&Q?Js4m|i7VxMAlvOk3%+wdgy(Bu&SeGCt z2)9f9$9@&j{|5Nmz-FNIzYG5Vf&S_Z>r{PLTlKY~ay$KhM86;kTK$9;*8YQjK^ii^=kgJi?rLhHI23 zffG1K8Zo*b(=YwTJEj;MWi#8H&6+9C2xsVM!#K)4c6GkT^yE1EI710KXDJ@(9$o~vY$jHcboR)6PcJ<>;&!i7&9P6IDT8}SwE_M!c=B2uib~%rA z&sgn}{~4HYy5lrfEatj-j&o&C!^)b|9W#D_bKr%T8bESt!XRU&^Qbe$W}v+e&uIMz z7sqvSj09wXAiE4sJ~Ph5T8Yu1>l<|AXfxkl2COx&lJ5cOtn%Sn_}_pVWZH}N3~tV^D6UyX9;A@!DcDj-;VIlXcKFSNrRJOVig3SSjVMt091Aa8`|~T>%9&rq z(RH$EPb!+V$b+mU+80<3D-e}t$jr4SNeQP)$~}c}mD~#W8n7BDxohFOmpi+%TokW} z$eSEe@X8a~$w<{4Gi9M4q z`H<6gVJbf084@dO?_srzQ`0y%k=1%hnDOE$NT=KHcJ|SE|j%3oPTz&?0mj9DmFevPqrVKWZ5M&>`^ zEBW8S8{aV=2$cL@@ZHNl%gzTx&lRFC64sns#CqukIat?r@UlAfSYMWNon;Xod)(vI zz-axswjRr*9Fafg!(Rm&fYRd;d0n;d%5R%LYMn}9AB;9^)ggKFe3*ke%^2?-ZzhPN z8!+r`aBh6!X^G=o%<&gF6V^FXF2ZzAN{eY+B>Hb-jW?pkWwxJZ>*x7zj@Tpes8omw1FFS zqeAy&4ajh29c`33QpG8h+jVm}me7_lYT-64qC)v~sc1Kf8$+<`qM4Vild`O?|~mhSyE)F}{O25ZE;hyV^d?%Wl?< zd2!Q3w#>wGae?@Dd))dss9$UA)qq?Naz#2k0{;T|J5YN43tqT~r5)F2>y9 zEX3Nbzs^!DR?&?WI}pC-^i3^K?2quWer~zZ-{WKTvf;?|TC3HDa#+MXW46Khpq8A* zI$N)?KSbL9-Q>~l5+|Wetz9Fw78Ea$W{85?J|l>s zsGxXWxI!ss17WK1xwt_}ogeo~@JN&m=5W-;e;)iTD*X2Il^y9Ho~B$x6a*5?SR>U;b*B=Qi|zbQ-)E)!mr^Xi@=Mp0mQW6@{(V$Gxmo{*b#UVW z<6B*unZq6hQ7w+aoJ{n&jfI!k@(1sajH4U{KO4*gO8#1S;hvHE1s;(5Pn7(qkj60VT@C4ACPlpmnvUIZ`PD0vP^qx9R!t*KpN^*}l0>bK@5aboYC z_QAdR){oux>AWA|iFA40PbJFcjzrf`_mDUbO^RnGhu8IC1H+=kV~o+(?z>;>38{&R z3BC0IXVWF>i&C8_o?h;(k$NEAnc|0Y>KLKZM>~gmLn&@fsXLPPvXqfePNLw7PtSJ@ z7LCyo<08X+Q|FxcB7LzwUa!Uq*m47-qEG4Zqa9}%6U5M zoth7*^hkskuA6)yJ?QO-oTxg!QshE~_847qj283aM!o_xEqJZWf5HtCu8_ML{$j8J zD7n9Z7p{A`e7}ogSaq$==lNV##T+o!8QL?LjhbytH)o0@S%}Hmd3Mh;be%1~nef&4 zr{2n#2p9&G{2Snf3zgdax(eyHD+jB^iVHTo)Ra`0SJhTpy_^PPi(Mo(MHh*$+ZKtv ze(hC9K87THL3egqRFOEtDEG{hMdEs$E{D$@)B`>b%k#zIFH2*cgWOs9WV+wtocdx4 z#gVd5c!JLSnH?94Wk#!R{#*A9)Jya!dO8K8(kd8Rbl+3hq89~2*rgBMXs3^+xx)FA z13wrH2P%EW!3$SE$xa`&-o0J=lvGsKltz+A?0-%wI)U%R1I7wY#l?a!1vkm%6L0D< zX14lT)U*bv#|Gr6`uz{^FM?Nq(qp-9>rp7r=d73W7VY$yUt3&lPe?eo_%=HAdgtwi z==}e4`O&y#xF~DbGQXt^#P0q#TV(2;KW+sD^ zC_ORGnEW(%x+l%um!l^+bLmV+AciBV12^jK(c;ElW0Lt9C-~X^wY|i{V??puubW>Q zv9%@}c&{_ei*&~nSCaDtW3+3c6N}1$feDknBaAX*8uuUVeOeFRtQ$w>REgG%@A2E^ z`%n6*^u-9O76amdO5Zei;o6V4MbdZrn)2FqZK$Y@MHbK3?%@E-d{GGuk>BM_Qf?99 zD!HrR{{U_SO0Lgg%UvMn<&w+oau$(m)&D0Km&<8|ZKgG^P+-wqi*9C)fvJX77R_q4 z+SGlV^Xuwwq+`6(&7q*_oO&Keb-0)U%JTK{8pmfkdwCO`ain(^c6lAnIA@llm%%lI zj16Ei|4Q98$Q`TqO$%hQX_aj8d%Y%uR@jdAr?_4DPK|-r3RVu+7K$hW(8cSG>dRItHbWViSG~MjpmQBu zQBx%M*zqnhBl&+m{KeohpyGWkyl^kc`lU*)pN+)Zs#@l)EGZqra3i&hs9FjavnK3- zae=nk)0^?|98sSXngj9bq}<(vtG*k*gKq^)y@ur`zzgST_x;?VTuTKZw_q0CkN8P$ zWY=oJ9` z$``ReR@>phNZ|mhIxUp)ng~zHYk~g(8~{pQz-7xjUw$tSm-Bud#=EAttTdeFRjaKw z_qV$C4H3`a1KzDCL#+cRN0>(%{Y2KcNIgzL&RF6l+WlJi3&F)e>G4~5;Xao84BwIZ zbf||~@5mmihuK3V>g>0$KEz)A3`P^&)+t>hL`^x`9LaGEqS9>IZl`}Ua@2dbA3odd z()t6XM=88;)8x8|QPPj-Vbwppcl3MYi^nM+H}UD9H|x6%%e&L=&#$z8WZ9kiogVEj z6if`icw?*=Z=kW*INmtQdh3cA_31C(FMOYV27aE-);&GWIns|QVB#~^tmR#M&IkmZ^O3&(-Vo`boiddkN(xqjNg0zKgO@>5j%bjQh!m7 zw!{AwJONbxy(F)z?@#5c{1e}yc_YNT8{&-1P#?@H9AxOaPw&KZ(mcyBl6ZAbq72~) z*DU3xdn5g#5d0)C4Jf&%!dv%uQh$_{uUs;n56@M##fvLMot0K~HvQKAAc^;=&he72 z4bI_IF)R?%fpEJF=IxV3&Wys?cf$qPw zZ995gW##fhrfkrJZ<)<@$Mu}(kC= za92)D8WyY*#Dq_wIo6z^_aS?OjkZ2(kf-$71iu;F4U|5QzzerijvwAUrEPvnecFGQ zgjGx0uAeK0HxG!dt_RSGQ)&#M00XUk?W)=ezftPriH+#fAAT6f2TGr#;DuWt^%#6e zeJ$%r`ri>HicYsa0nX9(aJs=vJ9h?{;|;ccTcK%M!IO4+Y#@BqUf&M?0C)r_`LDqX zr^b0><@%*|`D69}E%_rwNpCUUcI^foLV;aof76Tb3ZAv)KTP=Q{rLp`3(x|T z{O{m}Yd>DB;w|Od{mQ}Wzu^v#+6-DS%Bo)GaRB!`x>`m*Rk74dJqqG%IU@bb;j2I` zPWu$Dix7y~SowlAoqKDEmB@rHE0pUcw)_y)g zB^2Z7k@0}=ghGF9ouj`N+n@SLhF?Tjs^4-R{6*jrpweLjym0H~_h0*Q=&+Q?4*sNq zV|gjpIm)y^nOH^GPqg{k3wC^V5}u0Bhwz_(&!mi=$LCxzfMrJ}naJQmGW<|dBtFN$ z&jlv{6`vE~h3i3lEFnpS3;C2?=UAhqt`YrxJ2H&hN_h>0r{c2%{#oz>Q1V`a7p{x) zuCmOkR78a*-f?Tq|AF?qs)*-{b~>gfN92xzp9H1>C3hygaNWM&(Nfba>+JokB6%l8 z67cdA8u5|(y;;hyCwvv}ZSePi`=!jT^D!)NNZwr59)>e=nw639f3xG)LRe$bU)0+% zDK0Gl5`l0c{Pz3tR3f&iuf-HDx95_7x!R0e@oa$%zmTvB`7Od<2EQCsMund&zZ=@O z2Vw1%^5Y16oK|fe3P*T#GW>@Lt4fC71pg*@52*b45MH>D?9aA;uOf0}Bv{*ViCEUL z&Oxr!ikw+$j)~+;=p{SdLaCAOq6zTx!6`t=9hYXyohHW>cFTEhv5q6MT&&*st6>?( znr_j90bv|#y<=;lR?h-~1W#Q25Npxck#kvmb;zPIpJ$bGSa_+JkCRM>Fka5&>QA@>!T1&+iw_7TfVvJ>}SUyX|Le^5T#ZgPe zLe^5T#ch^~VR)?FQn8_PopZ|7QnB8~MCbTnB0;g|_N=L|F^&hvg4+xZY~$Ajm_O8O zjH5&+T`T&ho!$+kr~1C%2LA}y0aSXw1}|Jk>xc5>@~Jktjy1;X2}X(@tKH=| z_G-uYYa9tzJ5sK3#EO3AId=OLd_%@xhA-s53I93x3Ml!R8Mc0P^4!ZtIY01o)`?aX z*VN>N2MYQ&n0t*)rrtmoWRod2U+*!sF(U)>v9IQKjbTpjJi{Bu(tC!{;~i(4POpn! zoVu0R+Z~@mGFF%uvP=F?x;a|UmaF|}58t%oQ-!`W$uAL~t?)mBpMZ+btV}yTr&QVB zdkA-rO`Ks-$vVI&LMN_)tMQZGg(-tq{#KJ)g z1N3LSP0)Oc_9AUc;F8U=F!%H*#~b>JEXKtZ<4(hM&VY&DiSATK7$SKvzLRQ9H5M`L zo?(oG_GdhuRX0c5-cSa)#UlJk{OcOWAn|SpSO0;Xo{glJYA5y!zL!hu4ODuLgBMPn zTdc`(^`D)dA~EwOFA?=Udww?P)&`&T4$C{kqFG|M4_ozFphP7W=kYt;o_uzBiOoJI zo8Rb0FzHK<`eqjYmDI?197HZhv< zvGFXX5oqQD#+Sk{n3q$g7jl$qL6UXiN51hlospgsj12wPh9gH5Jj?ytj?a(iTfjd= ze2(Zt{{&P46`$?!!rdju5o^yr%zDUrZ{#kqM&}dy6HdL+dAGyz7FqNO)AC+3EN`Ag zH`@1QKS8_nv2k@A*3m}tN+s}0EfyOmU8Uwjer{{*v^OORM|VoB#D}H1&FOSQO2V;+I=|_C^*;eQbOX zqut~X$x=WHj5Q}1$$H9g&oIMR&hHIkH=WP3jivDu5{I~lPG#MC5}3hnr}JOBd$@Oa zpU~*xUVEnDbjH3;G9J_^FsCtA$kStWpE*>&zm9J*I4EBi(o@|~Su2zc<*!mSp`9i*H!q+x8$^Wr&y?F z$x1I0FBBVWNnK5Q7Q8*xrELdSfMsAjNCuxyacNJ1--9*aSTF$S;LXXj?Vuhk2h%|& z_`blUHGw<9I&eA|4dTIPlU&;KU=uhGoDA}T7koI;r9BL;11rI7FaWe3jVy3CxD+e~ z6G1QV-wC7#xD%`ci@*`U0p1+XI0Co^oCT(X9B^P9*T93|YH$`950ZcZ-ag8u-3u-Q z3&BX>1iQyFR{?$vYQTID0)Fu6kuL2ea1Xc?ECv%m8u(@m>zlyc;1aMHOa|HD;Aofj z4)_bW7F2_IU^sAr_eW80fE&RoZ~_ z_-KSndk)+V)`KE20VILXL!=A12V4azK_M6p0^sv}@(yePmw?4!66ghf%Hvt^5V#SX z2TlSbfD8OLmwW=7!6l#=6oMf@2hGE&8^NvMVo(CcgB0-DFusGqufbVh5=a7{4rP8A z+yl-4hTw-VMgfiieL%}#?g76AE5US-4Gs))X|I91!Oh@&a5|U`z8gq7E~{Kon!l22 zKYwXueob{r{?Dyd@=I1M$rrESBG$pLT9daF+e#CPSJhT7E#+`h&i-67QPc8Q)l}zK zRF)K1C^6P1m=(pfCCjWQI=R96}-<1nMN{yzx0O1z(f{JeLpjg_2y z44v25x*YN{w!M*Qn$qGGJ-fBUI)b=I_p*8fBQrg^wXCvYNsn%{6z}YPA|4nNsL7Z9 zBJ8DCbP{U&TZ>mL88fP9_jYzyWp!=-d1WkeYg1?sN%|UbpCFxtQ?{a3nCa=_YLzhe z(8YCeoK6>)%POm>Lpr%Z+6K#CQd(M7YOPY~xK2{{71yj-WTzdYbUkPV)N_`hr*3qx zrV+aqU$eTn3iCzX1hk@fd8x=4>$V;!DVq#?+0&w`>dKO`&R!&LUCpxIMS_%fR)o1p z#HFUIx>eoNNmRH@k?rbYacwuji}QJ+s*^+8Eo6web}pofHM`x0&`leH5Ya$&qpNjG zH;uKpr*mDc=Dz!GK~H)FT?i2kNjFi6YHSXv3rGw$1$7?&lJYJ?Z(EDor$bnQ^`MN` zmeUP9k4=W^nHRpEuCRq0f(p4B;R$?S8Dc8y4NT*j? zkuPd4s{Qt6O`nPn##Y zNlSTecXxGKfhjG!duiL;XGNtOk-S}9m2DLsrA75rdhqImU%SOvS{O4b-}XAwq_&!` zg>!^C!^Pd)VjVQs%{}F{mBroMQr7(~Y-+X+6X+%+YLxO7EL82J6h>lJ-u*3Qo!mlK zWLbXk;?CMv>oU4h&4#-fhrXuKchz*(k+p7GwNfmP>q?iZ%GD!6o!qc^RTLw=I zSi#(hFm=f)+pSnljtX?53gCHxo1^v+1PwRI=PR$5M7eaud)uVV=XKTqoU8Y zw7POtRaZAvuU;XHjCOg;Dokm1+FV(pswyixeT{^%(@It}btR%J9jp!p9SPAF=_~`8 zNDnu?(M0>gl8P?hXLaWiN^Va=EU8*m zzNDgZbx-d7*8w@ii%8{8@=57@&XStSHp$j;2~@XtQM}bHwbjKXrHhM8mUkoB zy05!?Ixnb79K%Lb2Hk{HQ@g6uIy)SY^*P>cK;1{oI!C3uaLSjSy{dFoXKzthCyqNW zuIQ>y(C*Hf@}LMI=>59%;@yIO|r6rwJkm@GskL)IGdNZws(=+sOKMg#bVHNhT@>Y=-QUIm ze%*>KD__GmRi|SIDiU3d=*Vhz1)I(~?Q*JcXhG~MwtMZnyQ74Te|7f)ONvXDbyv5n zSX^Gq5mentq+nH-ciM{zN3kdANs2FDRMtiRM1@vSMp^B)0Vyw|q3K5bWfqi2QN2wl~phj zFZ(84_XbL6Yr2!Vw34FOZC;je8%3!5z!uSP6_<$fP42MVG)uv;2XloIDYh?7tNv*q|Hwg zelTs6!WBgpRuwdsy}HcL)-Om|q%H@E(1`MX=+w|wsL0^5mL2v;Pc)T)`v zxBshczow;^#THn!q2?5MLF^jQH0vQqy|7V=L#*YLoEZ6AUJhTcd!pfqx=r;@)NPbE zOw+X)GjvTor}a9vm#!7|Iv;AeWx6)@tjP7oUf*)%K(AJHJ+oJ)uJy^xhFUIpEor$u z{lDq_y&xREscZ8<_;*Ox@wa{*IZD661YJ7^sOJkjr+akmOwXB6 z>wd4UZ360g5wWcR>bHh&{i5`%^Km~=*9*CJUexs>uC0x_uEk<}6{!1*kh>PB-;Jd6 zk3jtnZJAF@7HwH1TiDzDjZ=+SUf+ej4O^&jW}z$OMXphMOl9Fsx{|ujLN?$Rn8H)BXq4{#G}x*t|95aN#tbG zPtdAuPi$*{{X@rBl#;sP-%{@P4sVsEKN3dWmY2!#rY&zm-`n!O%>Br9E$c{fY<$)% z=$x#1D)+)SG;jT$9BSP5A0)SI+k1$7Eq)WJ+Pvi;As203D|0jaxTay>U)SQ?v!Qd` z^X&RD>T*$91tnxrH3r+JAt!-h%&M$*b!j>bMeF&sE|JhDPY41`dn$tdmwxsP9d`7FR zLo5M_x|RThe5?X%6D4n5gKX#b=kk9o_iFlYYzhP%)|KaN?twRMD6jZte0Ex_ex$}uOq$wBGar9 z|AqGHm#k~g0}*}`{+p5yKTmqxBGY6OzCg784YUH^0P(+8e1YieSr|a2?Fq&Ob!})c z4_X#1hbs3M?JwMand36TEl)Z-N!Q-8a!FmkB>hrCOwUQDHOkA$gZ@5rb13q>=5iAL zyRLVkaqc+k#}7RpQU)R}PW!1f4jID5!^cbBzGH)VIXSi?^W9*!>%Cwzntd4j7+Q5l z^&R4wMcSlbb9O;+K`>c6;@~J+yEzBvK_|6NvRcZ&Y8k;ZvwH`}1$%3bJZGMv`SSdE z4y`xJnnFZIA4*#=V;D4)F&jLff?T;EL>C!7M_`4jvWE)Qmjr*lOOqSYnlx7qnv~Lp#(vR3BT@ zuCFh&?}r*K(BUUx>-xwpSE9w+=b))n&s z%}h6;uJiyjK0N~(OkWMHOWz9Z$`zc&R}2t$72%glekFdT%{n_}|3~K6})`8H;tuw4zyK@af zU+dZ|AmkU~mrK41|8mK9{xs?T`CRLA!MMV%ZtL_~-M@d?^V+}c=NtZF`<)8v?1Fq= zd-#_4ln&x{Og|mW%7%j|7FhyxBjx{o4@>J&li1ln9s}d zU-!?$d|sBHf?dDt`R1<=@AVuWdluV_J!5qx!zJU9|*N1S{F-+rx? zt-5x0>n+euT--5nw7_u{(6i%y2fZ=wG3buCm!N--dmZ{_+*{C&-7I|;z2+KM4gJ{F zajUuS+_-b0x24@q@Bge|Wl-0K^c&i*v*%qQH=5@}#a0{j;2iFr`_E0#y({+dZMg4E zXveM~FpUw|#=tYs2Q&V{H{PQek3t{Z`p{Ngdt~b)(7$ed4BD}q=a|Qr@S=pG1YLU| z?Ll-d4VI$wk`YTt%ZAnlQm&=-$IjDFtDB^0!O2+go}y{zP16dpW@v>^AEWiJomF>z z`mw>sb{sc&`O3L_jg$^6sG=6T+y>t|yz<*D-`m5j|CRi@V>?u@<3x-4Z?n|DZujBo z&tQP%_|&jmteo%(NIzcs41;y(#P?e*5SJ&DlVT1<%tieJKRmY7pAlQoVGw*HdE|GJ z4}Xm0$Kp?yd?9{?rKXE%zVCf>#{Z=WmxZF zy)nw&dkwTXx0Mm(f;%?x{^uRcS7ZNCN;Jej8_$SR{PWP4<6nk0#qWb2h;M~zxdV89 zQ0^dTF0P{#2oRb*k6_?uOTG@jRq`#&GqlD<<{F~J!y4MII}AH*?=-Ygf3f)j{N4}S zd=UTEzsq~tKCBfiCw{=nKm4hZ|8-^L`?1Y8O1tO9&uoCjZ0$6#2K){@2wn%@0$y!v zaAq$4igrnGt@C+OzRCGHw8i-ywDjj(`=>!??4JjXINk5? zGaurQg$Dfb&_w?@=+XXZ&>8-j(AoZZ&;|YyXqkU4G|ENQc7c6y)N={@5}--@lA+oA zvY|Qqa-jY8^@k4HHv}4S&*;zThW5Pv0`x`wCFs}sx6r!m%d#2U%Kja+A^T3~pR=E) zE&4Y5Tlk0zIlYa(c}HmV=0Y1`@Vd>FV9YmdS1+tHc*~E+NNo@;@>9AR?R<{j|M`fn2QYpQBUOH zua)&0KeYy@UH%&<9bWqvblJ}rl-Rxq^XIr+#yb}}cR01=DFIh{e9-4f2&M!@&Sf(G zJ1%cL`B#va6?#Vxg&IOt+K7WA$;DI1%NUuLT}wN3KG7L+QX1TC`d#Ds&(G_3DXDie zf;r!*TeAXL%nCfotiXq!*Er-dCis&(HW)`-?0JZy;1c*Ut4G*+aBu5AZC~qtSqfEX z9r${8&d|l5gJb-F$?SyNKI^$P zxP$Z=yZOLR&zx9(&}{v^*4+95>GMhJo-R`9$z7~U078%b_$hDL{Am1nlCQ+ST=HA+ zpO$>fm%8>fP-)O%92moP%5iKDzJR#jhd)~KN8*o_`~-XfanB@tfv&<|=f9Zt@Dl&^ z(3|}CLI3RkEA(;yNX{}uEb|98+%U95vqSZ8c3 zG!PpPO^h839U6NS^yt`W&>68}WyInWbhPlBEjdm6MTwgg%hTM1ngyB2z=>#Ox8 zeuMbawQc{ZZfV(X#T z#cqafjr}w9!PrNjkHtO%eJ*w<^u^ehq5q8C1${5}J!o_6N6RHW9C3lia8m2M$AI!qL>nBSz{NzmoDP4!@Gkw&VCao#!MvjPPS5YN6ZfRH)7s^ zJ{9{ErNS;V6a5pZEl>8J41LA_3iN%eE{zSw2Gx7?ht^Huw?Owfc;lQtA2iMv4^8q7 zh7R?Gpd)=pKu7z=K*#!yf==*FfKK#Hfga@?}>Q?x+CT(=yNeUp)ba~3~h>Og4(INCuSe~ zMEdRmLZ6fI1q8pHxkCZLKaMXT_M2~ZvwxA-Wb>fy)|$f^iP35LGKLQ3Edjl2E9A*2=uRk$D#H(*>i#C z;CBXIhBgJ>guWAaAKH;C*Umz}d_A8!a26J|b#0lk40?-k3-o^De(1N3Zy9Yl$vla^ z{3+%s(8awMGkS4-@9Uwr_r4vvx%XyhZlByf)WLoJ20c4?c91opIkR&3Y8-z4@Q&qc zj!MG5#JrSHk9D2MC}WkY3VOWv1j_yP%pIA;A?wvFU3)#N8Tw(?r_ldo{RjG8)_2e! zv-Uz8d;b^t`+K)S?e)z~!4~8X4dv2u+!(qEYOk&g9?Yd}R&J}dmH0o(AJUA6iEX3t zB(&N17;3MGKF=Xmz7Fqw7Gc}tHox!v1iT%?wZXN>sSn-^t;$(TY@7Oj)?dW=0^)r0 z9k(#HQ*~$6ooIUJUg#Oy7Hx~j*IXvCb-7}oepe>6kE;(f=$Ztb?3xWd$yEtG+w~6g zJy$EV(7l$m0}Y-B=zTrpc^vw>=L6_R9MK)xtIQA1hyE(~E9jNME1`*f6Z@*K&rH5# zcu(b*OaXjWD2vn%;n0z<8d`4oRdWh5qrX#CE_CiwEcrkXIMivK{9oPK@l)!m?RPHO zzS5cOwxM+Vt4H#6!{IPZr_<%a9=^xx_4#6AVq^XOKp-wIK0YBK5toEZ#--p=acQ`8 zTm~*vx?a*{N!MGtKJ8p~JJ(GD455cGO1nTCAGafLbllCUi`+AU7Y4^_*95)&er3ck z@}I4h4_YWCAM67xWC4>wuCDaSr z$Lc9h{3-q5TiO`<%Z4`d;AsaFwKEQ$3GZz^x^WPLn^BkGRFleeetc|3&| z>J~ztS^qUWe<$mI1%9i3O+1CQ;_BfkY!l~Y-HUb4jd%*HSi``pTa$0sJQ!TuxVQ#u zTHF@TUx(tpcozE?4}|Phl33D^^)DG*qDMP!XqjuRc?>D?K=oKSjbC&FA14`X!*NK z_vT|{M7kjUR>rzqcg*2AZEXS-gZJl#?0BQd^n z>;l;xV;>43$BgY6<5lXYx9@#>>hpAxoujYJi3H9cIH~=kILTv~8#X)9?Q&tBK62lD zKUNog`>og_%^NyzuO?o-ysmobeX8J*+iq-J$%)tB+@N_uF9f|2q_14Ra(v}RmHSm0 zP{kXw1hOJV*BbmpzmY>n_B^)o*t^HJ9@}iDzZ*e^Nc>Cksk2}8dbk=m% zcIpewg^`8z3L6$SD{N8Nv9MENm%^079)*1h`xOo-98{QE_-NtC!f}O@3a1oKE1X~W zc41Co{^bHp>M-3%zJZH(o7S@pxW^x|ZRlaz&UQe)=6wS-m$6Dq=d$k=)FCJNO-22@ zkN+Ul#?$;Kfky>4gb(#!m7haxl8++)Dm2afs$sl&vKf7|=6T>LmcbVMr!A?qzR(V- zwH!5ypK6tWKVA2wx_Ae~EQxG3HTN-*DZ;L95)TM28~sRw}zM1 z49@Egt!^iyzS6$<0hjvPUEctAP$%l-9zZ`K2Lg>kt_-Xvua2@rPs+91RvaqVp7QaLa_zOQ9V^d{m-0!qJ*Z<4`Zj~Qf~N%a0`C*l2fSakdG3tFKAa2(~)(hDKvWJkden^Qy$exfrh3o~{ zOUT}ky@l)p*+@QZ`E90-}udnm@7hY~UGAx$?9ZNmw= ziQv!Zrhre=O#`2WdK^5Dx;fzKy7}M>bqm2?(5(i4OLrRlvJUI?u{zbG@Z=AyJ_P)6 zrHz@Vv@V&cstLb>sXDmX)E>N}sVjJjsW*6EQ(y4@rvBgqO#{IPo2G!aYz=6NN9=r}az z=1U>F&TmSoQaTR10J5AH<2nb)bv_NvFK7;;V>(gq{1HSljn(K2B02Sm((&M~zS%?Q z0WJY4`F})y5Xt2wKE65C@GsPSFB@)v=X)OT#4q7J8m0Jo?@Qp1`;7LX9_mZrkNb}H zh3tC?oO=#<&+Oy=qy1r5JQgVdeNlJjJul|K`Y7pb#s_il78{p>^SNVu6#N6qtd)Y$ zFEOIY?lM~?CA@Dq{$1f8g4>k2kSP)Lt<4$rGjL=+3pU$38?rK!@^bbK$b3E>pB2eR zX_xnn|4!RQQEvU6$NYPbwN~lP*{if~cnNe-TZq=yc=YKQFfYYs_<@}>oX78e&GR?> z?l(Qdyv(eYS3NI18{_>zz;XTFfLq2U+Ao6JhCGSZ&!mVWn#mDU@LS0Kpykyg*$UAg zG|e0!dV+ZG&*<0&artN=#am-og3>}tw63%cWp7w-SqEWMA8#jJfBSp=jkj;VO|7MA z8RJBsQE;XSWmsBfdS-~|IXaB?Q!v_3-{y=GEhpZWlveUaNgP|{(yLo~4^3uE&B$7{ zYS*q)r*7T4_3G8D9~Bi%DMm>&Xedre4H`7CTH_P$q=t7=qehL9now$5nws57&6U(b zl@e7ciBikb)ap)3E;rfAORY;&n|maA3p5(IkKsH9QBR9RlBwTCtxG#?qh6VNZCB@) z`_aDCr*psi-|P75^U3qlxv58qT7c;4VCd$MogB;u9wR^Ik6!3NbaYf=LFnwLg6@uL zEEsFBhQikz&LUWKRs$m{%*?`SvPf1-=>n;XHSg-PC>G6PFfJtyZ3iohX9;MbH$ulq z6V?=+BhAs8NMuRyIJIKQ%*KYWq3lui7#oJ!(8JjXMm^3W*^_J(dy0)l=gAm0mW^ZM z*#!19n~3pUlTnxK&jz61X%J=$rn1(o4QtEVvG$l#-2rRvKFB(;C`%W3u^wXG& zJs&VSP~}eU?3kKC7wdWiP*HuGG4C#*7*1APKYXB-qoj#o;z7yQJs4 zO*n3P>51G(Mmh`5lb-IJk zXUxx;QDZhQ1P`&;EcIAxOFPt)I$IW7+OroeFGF5tSq|>7WLR|UJ{2FTw;o(BJ*_RiWq?0W5z+Nev_$*W{%F2Yi=wD|T56OL}pNDird;O6g-ZcaWs`KyI}7Um}} zJWlZi14m$ivvfl{pht;+nPHy2Dkn7p*^W^#A2Rlz%b}acjzm*3qXHF#h z1e@k<4gWIPF{9ZZKX>>#+4xg}v&ZmnlM4)=j+p(-spO0nCz!`hXL3NnD>dTtPA7l< zOmYX^mNUu2EsmQTa=%Yrpd9aPa-)^6*O@WvT=Hk>9bRBhoKJql^Pv-_&OaoNOWSeW zyWWN5gIZSYJXRdsXiT~NdBx7ri|G=j5J_({HY5busx>uR5cW zJ$^}k^0(yNrTc$L9{0r14SUlIlY1HtFL1WMB0 zy$L7=1f7poa-54q7_o0m1Yy1RS8t=SOphZGhRhifLKr-7{1NJ~Yg29gVnVte!k@cu zsX=&g_d^$H#MFoetG5&4GM5lO(5LWUgzb z121)461di?wW1}UL`@3F2+TmwYsOXZKa@C2Pb<-q4rLui?--A(vp@SlHd<3kJc`RX zzvgJz&$&P6YS_cY5943ftGG9~rUV}rP!a%cDlvf%DH-x7|FT|aGxP@0|F8qTb4L)# zJAgZd+#2nrwxZ3n2e?#3$QlozF&}y*{7#=zZ(^#``w%9ppR9_eJ03zAJqX`0D-q{VMs@ z_iOL>pkHslS$@y^z37+ix6yBp-vPf$3+Nd5df@iJgMoXE4+ixP>Wg0JbwPPSJA=Lms#Mut%|Ccl z@R(pz=-{wFBKny6nFg2!nKqgBn7%RnW?Ez}i98V9AZBn(o!HFS_hUbZ&5PX^dpP!s z*i*5~;%wGM@uq~5g!eNKWtU{v&25m|w5VlKa#5S2_C-C4hZj#M{-LDwZrLq-+^S>H zzc+rh^hp1INa|-zdylXEXYaOq?5b?0cjW(MqIdfJq|T^|_dxx7Bu>pJqQk2k_aa`2=(1KE>RG&mjG(xq{DC ze16rm*Dcj8(XH3LqT8f!9V|?C1?&HW^$5Mc!AJJWdmVq1&tQ>H_RR;D7x%%2a!HP6_(q38 zBx70(^8+a|=_0v~={$$;A!8?fh-=v@uBRc&RvEKu9AqLoPCk%`o!L%luR5Ds3pChvnfyq~8Z_;sZ|&m%PQIFr0?-%p8| z=oRRNesBN4AaGvWAEMOrM=ACEpR4_X=a<*^j|HE=^ZQlsSK!(Z54;1s+|>LBikd$? z-+x~7Zynbf^?!|0|1VbR|Nf%>PZ3t{uKDkCsrjE$VnDjq|5KFu|06E-f4>sHJFS4Q zl5ka9;IWd&?z9NFf8p*?0)Ost;A05x_B-%V1?QDf1#;d3jV<6l2tLB#ab<)-d7cOw zbKvTU;NuVY40YFtc4d7N6yvQTzKJyRc#O-LP-X-JpY=Y^0#9T)BN#lbK04Q#;TX{n zuerx)2JQjjGv@iohWqn|{MGqsVaHIOgXq8e5bzNp)7YQkLY@I!F67O?4~6^@a65?V zq%$$TR|$D5@Tiarfu1M$zBPe~Lhc0|E#&#Y zcZ9qP_?3{q0iG7}Ent-|_;IQM!-d=g_>hoOfIWqr222<7eBdG>=KyyJc{lKYkUs^| zJip$R7>fkD&iBKuDJPL1_`2c&zO49uoh5p2ObA4eHcH15z0X0&9*RZpi;gvnwZk)u zJk80jY}NZsfZgC34U67?B7Oo7C8yp$60+heF7Z(E8@z|pUP^vXCBKIc&CN0RyhL{2 zdEkmax!9oO_cUNI6EpaJ1n%WQeL9|AwZRoX^DR#$kC&3iQ_174&d z@w68|f=_)qjyKIlQ~c7Gy}ZLAdntK*c^?1Ol*fNL*_E7%*V^gjHyRdiCBH8}Z@^Ai z{B+dT@lx{pDrZ+b+xfm;)nWJaZ%TPQsBg(j$?vb^_YCMtc2Bwz#rtiC;F|P*aegSC z?@;lqHv)DQ@(AE`A+G?w0iyrOD&RXHy7mlUwvcmxYe4u>*?YiELM{OQC}chU4<6#b z;R*B+vOlnjkgEYBgxn0+T*!&QRzkJ`+X?vrU?&i@`#J+tg#Ah2Y#}><9}4*x@E0L_ z;eTZj|FI-sPa&rP=LtCrm@nirz?(vjz<;KZ`2X|*J|*PEz$_tu0%Z6VPHz9WiJ}l%%fJBt1H;{T$=>5~filzk**w3s}RdnX8%cyODdwq=pEth% zUSR$P{IvNr_&M`=@Sn|>z_k`F%56`JC%BKLGI&)>Rq#+tb?{o2THy68^}%B-vEU6X z@!$8mkxgW1smO@@(Sp~k@@+SD(mUqB0WEni$@-FyV%R2DQmJh(USq_31 zSdM@nwHyUMZuuJgTg$iLXD#Qzy&`=h5zi%Z6Zi*_AAlD`7J#3LJOl2iy&8qUd$l)% zZ>yaTzPI*1@K0)g3VyiuQSdXh&w!t;eHQ$O+84n+>KN+aF4eJtx2e+xJhjfF;G^n1 z1-_^5-nyt~VRX9&2d@DIS8pVLr2AMDYm7NhL|B1GXw@b*CnX zAFI5i!JP)t^FnPUY9CQKKyj6+eRKgYL24f*gUqnI&V8cz>(oXX13S&0{9Uw_Xg1!x z+Dadx-Ly@#e_h*6HneeNU-Wp$6F_ur)GvKN$kZqOHHiEf-vV9xrCW-2G4(@JAM~5p znfjr-f#^8Yh8hT>cl%!8&Z_A9fK2Tv*M8}?)p-6?po~+m?xU9RTPQ|mMcPx;XWa(p zqJHZ{m-ZC(SNHD@9}C(~GS=dtAMtJg(KY{R!fyvBvyx8({O@o1|JHBm*o7Y+N!O0N zXQjAS*cE3S>=Nzgdn@_&C>;L_fwoorILv5MEaux?_?EkLz8*$uaap`PxG&G2$}!!q zzoI(?+Iw(aB3r=EXHFOA#druxPrT1{>k^Lg`IYEc%k3>h$F;=to!nkiISOMEh5DZh zc!z0;aD_8~Ye8|4*8$gq=zD(v+#=){ysu_}dcnQ{xCumg@_@3hF9z?fIPo4!05%jd z_4_$N)bcnDJR|H{^!3Rx=rmU}S@Z$62HtBNIgK4BFDSJeXxw;Xyc0i%+yvMZMAv2m zwia@G;9Af~*w+Eq3;Tz_k3e)EwgGnt`%WOuM=gYXEpQ!(j!Ci4KN9i|pcU`gv9QMj z6U4hW5tt<8R=_o&r;z78;QPW({gCEh)RADf0PBFrC(!`!b$4Rrp$uk5zu+;bKb9&9FQD`HCS zp+pH`mf9B7twrsM*Q>h1(oM_>Spa#lr8p8tt5pZHDQvYmfv48uqesR?qmL{474X-i zKLp<%y&wFO=p*14qc4H8xOQ=Zvds+?Pa`r`2$Vt{@a6Ze7&*Ch?s70JN zepNjFEAiiho0Zun(-ICRVBC4bl7_H%E$NEmEA!FPmHBAatmawxKV`>dqwb~51M8pL zKNnAjGP}cA9E#eKRrIjYXqFMhBf(3GOTaZHX4Ib&F^dh)fD+S)&lTe{*qut`lnW(= z*m|SncDXezSO1Gm^Vj?@t?|T^7jMpWO!WUYAB~K!UXk(Lu6~^R9qTQ9Ks44{`hd#B z<-_wWWBj=r_wCM4Vv znv9w98RRd#bv`kOk3hb)nLayw5?P*4KI8*FpZaLoXFgirCQOGo4vEa>+rih9b@c7* zt7Bad)4><<2=aVUBQ6t_;4@edM!!u5lswBI7b_U2a?fd2{fN zU@w*zya(mMzTo}fk)d_alU!e{+z=1BVQ4dOn!${|kg(oiS~eu?QSisYMumB^r^3d< zt`Bb<9?ufPTZU^{tMJws`O`MM9r%p!)!`thHWpB;)U>{{~&(^XX+4NZ3qQyoXv zXILfV2a&xlFhR(6Ak}loPW2qB-;hjon?|DE(iBKUc3P)~h~!hi3qoe7lepGx+|_5g zARq1PIv0-WHF7Q-)oWxOrY&Tu$54K%%TOJKWU8mQuFXRA60&~-lBaAhI(j%1aQ*Uce9` zS0tukhab_`1)_Z`5*t4Qbsmf|#f(cWo1uT+!&mcyM}Wc30uA384znK(w+&TTvEg^m z>+Gg?n(xz^tG?Iq#<=M_&2KjA=0Dj#ifICM_(xX`tQv?RlYzmI!vammKpUpAhvvuDwu9-^}tz`ZQq;8iTu zELs+9sbTSCCQBqNwNZ!BVx^fD7C)9~>0}9HT`asNGvAWP7Fb@f_^?;q_7G9u(EDZj zgO1~9CoETCXOW($|M*3kz-va<1CNe;7JN$NGVqO&UxS~CRM(MKD6u)1(l@k4=^NTr z`w#T~Fr}9#tX*R}N4AZq}t zj5)6UtcjIsS*?^>*5ddV;}K8ArDnyWTty{xNI)NRLTZAM4M~^=d49rL@O%*iy0pf{ zSEj3{to+y{t0~@Q&9f%vw9-z>nT)s7?b~Nde$ZSf`32sS!jfB<({@|bm-zfmIa~8P zdM-6_8ZArEGy!j}=>XnIGYNdMW(xRp%?u4@w`t};o~xM$K3_xQSYFV)2>z1hW$;%u zuY<49tOQ?$s0-8!l!2U?nr!ejn)krp*Q^6yui1dDn=~Il-lEy2(JNz&@H}E{5o)X$ zRfG|cny<0-J53=tjV?mprsj9Ze`u~lzNtyjYFP_yB5M6DwXMKgYum!oPWu4lj@pMH zx7VfVqS;v8(>gt7=grZ1-kFj2f=0Sh1BIf1g>QGD7oz!`=uXKg5U(@{oKgbQ; zP1tYi8o=9;s<-R$t@ZifJM{;_3-oawTEb0CF=^GB}^v*Vi=Iq-7&aqhU$EE7tfH(>B=mBjPwpY-LX01=B^y*Olnwbu3X9 zJw_fS;GZ|s!eTIkBId6>V;OkO%(zTE51CJaPtKeIJ~eX=_=3#m!53#P0e>|!2Rv8I zz}=XM@;}p3GO~9~Wxg$5b#4=%IlKwu&7zo7%oZ-eQ>Z~iA}vNvH3e^>=?LCgGZFk5 z%~bGdh~|O1hh{e9bj?CMH%m0HXmo6;W*O{nXjVghOY;u4W@+Blc(ApajmWcE^C9fp zHF>bpI5yl(j9){%B8*%^EOgB`uz#z$1WqH^P^N2cV6P&L3C~cZwjp?uHd(7{yRIQ#3(GG+BIASSj*}t?;V(Vz_7|3I_6L5qn+L_>U zwF_Zif=Elg>U(QbG@>%IX066-7? zW{47*={H>wo>8lQFrLmK`ssKg7wGfAcj*s-A4cqH)T}(_phuan+sNZkPp&?tI_A{Y zcm>bp@*1ma7}#5weU1JDlP8`kqcZ!{Y^n>{YHA8@Q|6#{$Lv!rOEnFLB~6)ey4JJ~ z@(xphDTp00IZc7=wCS8lk9pd&EKS4;s6%3g#pv1NF;C(N8yE95p1kQX-$T9_QwV+) zlZoKF6tS#hV-2iz#wa{_(=(QXM`kv_v(+$jH25=_&w)?Fd~YpVnE7I+2YV^=wM;!* znwbsDCd~cTvL3ljhxb4CEofnpc-z%xb-|<1 zbE(Cgx)$gSOvGFYJ^H=|U?v_#;V>Z92CeLuhyJWQ?Oa_ykE5FY%BpJfJn}u7vX4FX zdg$0yCBnJ4!AI%Y@&^w`G%+1|ww^Fxq_1HVEXNS*2&2K2bx{8(GluIiZ-Zu-cbc~^ zyh_*n^}22W{Q`Vh{{VepHuF$Ma#abO9XN&+xU3q{$=D68ks@Pi)_HQ%EV)y!>m!Dh4Bn_0{} z#z-?WdWp=fz+0Q!f_E@?2k&9-Y1Xn{O4N}XF}Ls>6e}yzreW&hVpMYsaURSw&I>(Z zzHtGF#vB+|4RT0aD0p~W4OmQZQE|R3TA5Q~jcX2jQd}~4>$tXvBZNLQ>voM+iCfYV zF}Qay*Rf{fGNxwuvMb75lkqNdO|EC%MD6TWR$O)h=A8`Awz8ednz(#5T)rCWcV)() z8H;N_T&cJk`olttt;NA2BFclsU0`t?n>JYSLXIeYqFBq&hgR|`BGBqe&>yQrp!LC= z6)g)a2}9I_aLioMGc$aY5tzU77-smCMhq|ef|SoE+7TE-*Z^FPALRYA6hCw@dS)Xq z-*Pppg(o!^&nG72@b}FIeQALTrX0^6NTf~8sA`%zsAWDC5 zQw{nsKxntHX24`2PX^8t@P{bA-$;qrD8G z{8r#gLUsV(6Y@G>o{)C}4-5GS@HZhFe?{LuNI4F0q>yQSzcoTW57b`ad5pkBA=`i* zg`5KHE@XBU?K+V19k0P3_B)rIz>7k@4E$ZlXbQ4%Aj)qC9uqRVjyF4q>_%V*A*TTQ z3ON-xSICQj?+V#?1CcmEw67UhSIAaiLlBKeYXod1>^5L$A*TQb3E2*OQONl~BISEw ze@gD#Kh*MRrnGz>{L_}t^O_}S;k=?*inhu!4L#ds+dnxtPA*zO+A^)6t(xtqTkb$x z2%}@r{?V0b|6E4D7u=O>U7Szp5Yi<)=yb?VtRf!LjrnIJb3@yH9uWVWI@n@-ue>MwoF413y z5BlHm!PqQByoA46`w&_fDZ1X^19d~e$Ll75^SHXR6wmBT{amzO`+D@nFZ`m%YVfx_ zwu9$+*ag1ZV>ftb!^5b>_BQkZKV@)&^Y|@487@M$dUo>Eunf<&;6E!7T|&G< z@h<<~s~9}VI|)9TuHIe2yL&$ZKE`_t_%?5vFLluSAUKb3-BpQdz0GGE-v0-cX!S|H zNxs-uiEMsQi5A^eSy5n{-!?zwQR23D_3sKF3SZBlLqL}Rc#8ra0^c9-8F)xwC~6^% z0~>=k4QvYDJg_-9_qognoCSGK;9T&%fqTK58k-uC$JhdVuJL*BMaD(o%Z$sx4+I|# zM!&eS9({9VCF}`e)$3_txaVQp!5f7)LQT4z;xQQ+J`QqDcrJJo#7{&Sr^K--a1&9P z$G6#C{V@JjzbVm`Z!6K2x0|-(x&HImq?clT#WUL=t^sNuQA+IorOGPfw-gWZ=#0@B z7%`bK1$-JJ-pDA)mot8a94vgt>3Ax6#N^#syR-1$%K8;NTJa;nHi=Xdb_O0?yRxxeJ%eO^?fNW;v^I$L~Xo=x#AyZV&Xu~MmS z@&8kuV&{o}f4vb}tN7ookCYkjdig)QZt}mmKEi7yrMwnm{dgjVN-Mm_c`RcdMdeMF z0ZW!LB4-W!Q|QrGVuJD*$2_`9#UdU5t{Zd5vqfvd8twTiosC;;ZZ2RMsK+ z)hEq&8oR2*>7VA;&A)(6_D>Gj`!{&Jz7Dp94%2*hm&a?nDG$A$`F|Rh`R+I}a!ii~ z<$ihIvJlv7l;bV4p|-%I&vYu|Gg}P%ix%$v;(jl8UM}vx1CD&LvJUTXynBzK@ z=$7kPqGM&}c+uPxs=w3x6q=ht@|!>+l4-6A%~K(n=Bl{PQE{CIMsvX^56uVrSjaRF z?61sMq4{AInXf`~R_I(bZ$-{mq4{KT9+>N#6ZM=hIsZgGCrr*oQO^mJ^HS7v!sHwk z^_(!83r5%GI!5Qe^HBIb`A?XKLTe*A(YE^@ztLYE%c5Sth34O9;5ak~pT@a_p%J42 z()e9^257v?145n#bRF*^=jyA+ySUEVr!g-y7jHVyb?i$%bUME49DW)H<2v?*#=NXX z9va^(=kvRceW7{%G`1K1F=c$OyKyjb&cAwGFU0_$K7--F@?t{M_!v3=pT@*|45DjR zkBP~z%I)egF|OlaWLy9m2P5MGsK>#`7y<6a!MMf_a5pA~VhSt)(RHpwUzi*pLt}a6 z+F7n+c`FiMpv~uKuYl;741HBiM1NHx@JS(00L}u@*y82DRl>d+_`ZJz1BlKMse-TqLTO~#2a*Y&aZ3QTLu=?mI}w!%JTb!VfpZc=AMZv%Re41>Y>8d4{e z6_ZXI&cgD8;R5(ChF`!dc~(O2kkvE!PES!auV63u{JbK;YkSoNukRHDe$49>`1f8v zf?xL1p?9bS#slM9x{L(w>D?Qaq27;zPZy(tcS9~aDwtMMJfp0k$X8q|yMkI5l!$x< zwKShGkS8c>r}4EFca&K-@iS~aqpX<7SLSO~X4Sne=%M1P?hRGe+neD#1D3MuobeIG zv~C=xgrn!GRhcz1yTHQN$Q-JyjyYY7GmQtZlXp@<2YiKbCHUaVgHav_ z1y@E%nGoC%{Ndmp;A4Zwfp1pEEzb^_69OMiNH(}xj9#X3%fVscVKi=e5crU=@!%|6 zkG{3W;cda~;WNNjhi8MY34a&-hwxv)Ybm3VuPF0DeyDy8eQTSQ5s7>y`0*LfW}qBZ z)`O44_+%W%Wqk6UtUa*Q$&Si~FC+V5aC`Pl@QvAd;PrEwS~NgdIqCPX6bsNe|Emd^Z3`% zit4nUx&bj_Y8d=Ijp%pn>bcG{AFBs3uUIduSAQ>x3gf`)WXHS~dehpYFJZM&T5FV6 z8l`^+tujh08-9cTg|f0JRw1M{2rFZy!6d9ONb3vI>Vovo=!-Q4X+^>5SW9#p`eSMB zP+B>Z)(urw4aEwTv_55JtVKyHQPMh;v%>yDl}T8wa~t}3>Dm7dPyTsYjT5WE zx5WDIwE8=({XPRL-7dr0wzRS>^#dQq>WdVMMOnob&v!DS<4nhDe{-?QAFc8CGFI}- z!PV6ZjQ^Gw(AV#HYa6H7Et^IizA8hs9XGVGCAl*dJ82GOf@+ z>od^m3^dk|Mt89)E2=rFT}LSAD#2z%)3o7vPQ}w~M?W#ec%jv1ScrcJ#dtA?OboGy zK7Z7fo}TXhzd^ z%w(c@ObmXI8!>e$hIyp~I z+6mx$7`kTL|-sW6GF0FGxt6Z4jH%UXUGezU4^=WB! zT3VZy-57No)*53)wZ6n!0@!U5V$91-fgiZN|37 zIOYey9U{MLTde`wWbq(6FU?(`*lW}dqxKukS)iCD)PDOOMAKT&0$tm18oc9aUuwhI zK$M5tW97BOnxWm5EZSZao2{LYscp6aGz$A}1a1-bt-w4G&3ViRQtURmHfq1EM_cU@ zKP!q=9WN;`9{a2HXhA$pt+y#0@s45O}P#z=RQ!| zkJ^2Y!(Ibu0?~150&5GoE>N}$t?&c6&W~sbo$^!rklKblAio666!sk8S|P6oZV>V& z;ASDaYdgAYFAhIa+Ftx$*G5#a2ZH3R5kXuMMj8ruu7=x0bc`?g+W7 zcXw|+d$>&fb(?o0+o`Mse$e}jcUAVix5lRi)1o|X!CIHI>TjBliH$+ItY_1GX86F9 z>a)|wgY6P^RvJBX(C3T~j^m^8t${V7lQG+^wNhuLve}!-dTPFJD|Qg2ZbQ^ZZKz+~ zy=J?tk8bnBoI1a~exB?z#pf#PpsoFFtc_9!?dm_&zbbnarSEX|xmZ;`KA^v-Uv^MD zvg-mi2I$x(m-;1NFIW0#n`3Uwn82y1U)o*#vaa>cy@9dD;VjN*#al4J#Z%i-se|@$ zse{UT=WNWQn*%?tCtGP8SUF!iNYp;7;QyEq+z8yY_PH^56D%JDZwKESd>~lIJ`o;Y z-;g-whcX-^+C<&d96FI%LTjQ{S~s*FctU9NP*2uE@d^irg`jR49@Z-?k@Zn(tEpi_ zG0SdP*psl26F%d$VexF8;xlI9I@D7eg*U;ByQbkSASZ>l2{$nAKemTYhvm)icfhlh z+HI~5+vh>V1t9Dixs{{Y>8*C5C@Njlo z@gmpBjzx{RLw0v?d-e?Q4cVKsb?k%e4Prn~{`<6yX zv{L4{b}#d0mY7kpH`UfntYEp#!TeghFP*W zW|>y*LD*eexk;EYi=&lk>z1xCFW(_Me3MvSnc1_nruP?ktJG(ja@x9G%Wdm!^V{Kv z>rrOa?iI6Y4_2VXOCvveg{7?F0JzQlacG==>g!fNl zrNvwEHxeHyGREy2DcU#;vv%)p1DDR%mG2@xnuO2SrIzr(d%TN|;w|)Tu)8-;G~PMX zdMMi}PA&6pp_ROO3%QZYcof-ArWW#fv>~X4Ok-2z8-uU*eI>#Jb9c*M?VGRjUEW)w zfmN>jJvw77+STLTz9k~FLKw{lE^Tj9OPh~4k?)Egcr)XRI4>QMAC(W)LlKIYNaMpV4ZH1M#ll<5b`wL1Y*B?Laiv z+77x2Vxr$!_Bm63GmZVDF|9<@&rEFtJNlScfE=I#5czVb&zWKTRV2s?q8JA$AeyIa z2Yn3M529#d4DY3tAQ|&uE##x1lb|9HLoZxikQMYOh~iceG4!)FLCwSl>Iq5(4F@sQ zM?64Ypk|;XLCL^3Kr*(q6Y_5$if>IZttkdpa}dSBBC>-%0MWQDif#Ql$bh$oAE+Tn z`ks;@Q;cgFH!Bq~#kQt7`Q(S9_|_CRi{VYt7(}tNdV>0Z#)2k+UIfXQ!!p)2!yBO^ z$PQW$$_Jr0fXVpRspzqq3L-xj#V4lt*A!cU{93f`LjmXl=rZUAh}umQcPj<-G{_F3 zI9s%y-Zcgh4Y=(A6J5UO!FDMm6al7mw zYLn!H4uBZmBcUMao3cWt@zoC0W+?7MiJ*MEEw0lW1MdQg^Ce?Jq(NQ;qP7XOH<%f} zO(d`ut`}qnwXF@^igC$}fbCG1d;mBC&%_gW9zp*C$ymz;kbePDn}yc4U?Xup5UnRT z5i|v~2*gI?`+-tGG$&lf({@58VrdwgJQtXb?=c^^7VRhy+lJUUpfu2PAUh}>v>3D$ zL}SP){+RUn$noPec6=;|+CwxZoW_H<2eG5vk0X6J@$pVQcL8e=YfE96(9 zvE_1Hxg1k2$CJykK2jUgvLi5xR7$BWCc;&Pn093w8rhs&|ya$L9^6Hep7X$&~| zI*7>ELF2tsKs44{j`Nmdyct^TCop@FVT5g?546k%s=h_b%%IhWV80IiCQ$ek%c&U( z6UBz&ZE}k5T1UwBfGvca1Z*kfWFVCnxN~>P43cHJp~!guQ<*@rEEhpGudn)j0A=`me=1_ho@QRSH z0jcaEJM+eDLlDVkAeBKR%kqch9kAsIJM+ODMIzWM0V{(jPgP*BkVAn~Mv$g-TGeQmzHtWu5xnaV4Y?LaECNS5Uk$vPvADdzT>!1skL%OWLD zB|KvwlBp~jD`YB@W`byZ#Vp`@Vc!YdE#$9&-+<_Mq4KH{h>lYk7%gNfzvc*;uT9MJ zFMy3!DW?33fGdT(3YaBiD)YV*^53=AcT1FUR1Q*nV=4oOfan^i+-n3PxdX71kf|Je zU&yr$V3t0oCvQo*D&dWu}yST(u_R;Yv4)G9?e<+a3L)w?h#J?I_m|_akzSDv8K=d8|YHVRyHYxW?lusnf zGKyqbPAPdrS*6I>=9+TYR=n#z(&TGA@SJ{(7RSrl0*@r!5%>pD%6nV^Hye`ihHq`? z1pbs^H24_9QSjr2LPIFKWVmVYg*)UHEF}h`C)OkNY=D+RSI>9A*Li;88OlEO{0TDi zs*1O=&5L5LIlMN4Z-#df{rTSXR&ME?f+*;HyoW#@>rL)}Jl+u?((#J=(V7V;_Y)8LoAe+Bn|FA}wBcq8c@UJpFV#|oa{LvQZJK25-z z!B2_Wkk0_{K|W)Bs<3fB;~~%Xc^-U`&x_zM`DB6T_^btA@3R4X6FitWFZ`F4nbYSq zeZ z!Grwjfk(mjiF5h&@e5~t;r~Q!-fsxF-EX#^2b<%!5b_Iti@}%pWr64TZ2;c{?TP7XW%)-eS_~5vs?Vv zfp75t2%P+=I<^zOR6OYc)&Sg%fQI0B zlvWf9zI@pn1XhI=LhXV&X3{oMVmb6 z1o+7yBg&|t%2mP11B~CL@**m=s!)4tbhT;V)2l55cU1cc{8xB`as9!5Xk`TiR{}Q& z$AjB~yMw0&KMDR+a2mKhcmw!1!RC;5%o5TDrB6F}h+z+z1wJ<<3!J>g2DT0!V;nQI zMku}!yv3-O!(WV?@EGGA51%o%hE+p(We$4;+#|dpdUo2wSBzRjxC8vX@b|&DhMxmx z5s@gVx<+&Z?-wxZIo4SHObbJ-KqlyE*7I=(toRv1Kcyq2iz~KCb%tY9Qcf^4d7R@{s1q6k6FunvTJ9fjgkETcq+Wjc*3*S zgFCa&g8z_x3H)YuF*wVqmxJTvv;l9I(-}N9XEgYjoTtH`$(fpict<(!LtdA&3G(Kg z4|8;EYtD99^5L`AvafT#f$Yrr3H%ED*MUq6A2!zBgclq2H~6vf3+C1Vua_GKo}YUL zoc!6i=kRD#Te1k8yxMpM;MYdWzQ|OBc1}^fBHWXrCg9DAlE7OP*k2D`+|$pa=%g8yM425 z$E|e}OMX|`{Z5Q*ed)zsJ1X5Od;LkbrY(NgRPcO^%06>h&-i)+x*vT&W#4ole}RGU3uN^!*#}TfwpIZ|Z{JKx0ON~|b z7uGk9DjMEweTvGSn7sG%Q^)qt8mY2xJ$N*%Zo6;y%vRZ7Jy83jL#sx<$u8Z=hu(Fd+GX_tCv*vE%uU}tamqU@+mI+eHV0k?n#fq zL+933*?U-bHcBnob|6`0?^$Q-iwkEz^lCqqef!k)9&%;pJJ2UP^2C;ck_EWYxgD>zBRepHkU3$Hx!rS$pll8!G#nY0nny zJ(Ik&3jexy{&$AN=&0Ss0cYb>_M=P2{cCBhS~(A@>;a#!nO8Q=z5S@l{&QHRC69TX z+cs5Y|13RawD)J*7A{rUV}^yE=@b0Hkqs(4f9`B64wYj!zH{utg}dxS*X;Ru(z{fz zcTKarU%o!6dGhocu13fks(K!H_Rwqj%~bZZ0Y5!^C}HX%8eid>M%aJMeY@G`$7!62 zYieI}S#X`Y-BzW$8X?y$+I=kk%}0NEQ)SP3cmKj>!@gU)U1k4zSZ>%0Ui)UARN0qR zAJgVW^?|#usO)`y2+xT5SJx%}s#ohz&!>f<9rIOPmA%u%OUstNHR{baD*Nn_Q#L+3 z$@|Ixm3?B!x06?&ePrWAm3`Nq<^7k;=|5+Q%HDF|tNZu#XuN-o%D%zz+RXtQqh8sk zvVT9=v2^>Y2fjP4ve#bN{Od-$mcMgLWgoEW^|!_@+xvSpYGk>jLpy$aq(|O2AH=Kd zXIj_15`6VmdKZ=bok;_ZE~WR-R1eFuSNm0aeY(ot!fJZ$n@x^0%T@MQH+(;! z$B{3yHmmGO?K0o~^10)VE<0Vsp zS!J&u|KgA5-Zm~zRM}Vhtyo>O-1tLJmA(G8#GzlB>#a#s*=HZld}dJRcJ>7-d+fJs zbhfjWymwUgMJ4S9HCQqHg?yF0^_GPzRt7gb_La(>9sd2sC0~cW@tey2<-}84pUQjn z=Rg|l<&s7gUS6K4o%?>2%I=b-jL74|4PnoqrJchzp)YnT%SSY>o$LfGCq=}c^vTuO`j)a<&mX$!=q;U(czvjedh`PC z>oLT`iw*UlxED0ywzNfkcU$_L!N|^|MeX$$TGZE+2njS|*T6JN>pIM zVXZ6B(jN2QmiGVhmi7Z^75}|0?Y$V~T#bGEH@CMP#vr!ZxCiZR8Z~Wzhn3pixBjoR zy?LZp9$oYAYKMOj{7tY2qcPflM+-bN%p-gdGyH{i_!P9gd8E+0TjQ*HUUd|lHL9A> z2Z52@XeBDqL3tco9#e-$vrScEgxW;}9g1LEHi8aCvy~BazJ}~nV%o|GI=5gMW1eOX zV2d#>96g^FiUcWFBP%}!Bt_Xlzq-o`WDi+pS{k!ih>8nOixLmg8Z#&ct>u`r;6Eb< zDO$f6OO9{k5>towHH?n6$5vv~|E(T}25}zN6B>gx-Wtsktc}svkcd7A^n@yX5G$># zAg@;XAZ}rFI(kVe)Ca+PA8sqX4}R!naP57tWjqDTw2YPD4y6wwIMbAg_}G~gO=W?I z&-(%7KmMj(iNo2>>`Lsk(l>Gb9(@xP@0Ix0rB~t_WExrTzE{GkL@F8}A{E`chr%_E z(Ld2!VNs$U^9V_g-?O*k|84&+Lyd*T2T?UzjtwGNjt?SPju9eRjuTSs20liJpa&7B~d>49JPT zPcjj10uuco`jrUtp`QRzGAkVAKJYssOPdq=?;zLXU58$*veC(iCW9y`hzFtp2&1X) z5UR>Fyi-Zd#Wj+vjwnRvgbC1_D)~zHZ4SMo%GL=w?|&@KHwiW(N^`|ACqtjA*h=$F zgHCh|{ojsGV=^ESPKQoJ>2nTj2K3pAt@L#id=)k#N=G@c*Ps(oI>Ldy4t=R&D?RTr=tOUcJcKKt6H$`KTM3qWjVd3Lq|`es$W51V$b>D-~zX7@a9^XPIT8Eu!3*mRrFRAkV3Z00Oyyh#=iCoWn6*`gYd9OkL z4di;>-=PyxS|!f?2XrDz`-SZ~bc7N_Dt(5`(1|Eb75QpHZ>Y-G0y+_;=qQef(34d8 zT0$qHG*BF`6?7s>^~Ao(&~2b(sRLU>Z=>WZy}q{4i72%c$7=_jh*EnFtUYuhN*y?` z2cUOTY^BFbflg!+=Oye8ohU-s2p@({R72PZdq5{5KO&ui@Db=l3BpF$3wm!*Lt!KA z3!SKmuo3o$PSjY~2nRqX>h=!*5`?MHiCm921UgY?k&p0E=tS}2c!a~C6V(&>2+2Q0 z)K1t4M?fcPAoeBv7j&XnVIzD3I+5$XBcT)hQJ-Hk;gisbT8ncKj)qR;db}~viEfL1 z3CBVwiWcW3oB*9DO4taeKqvY^>`Q2ePE<$aBb*7H$kjF%I#HCkKEib9M6UVfK_~i1 z9FK55^aY^0!bZ3dI?;#1Mz{nzQEg!(TnU}1syHv<8_46!faH0VT>#&f`WJt+5ut&XszL!U2fwS{dVbRtSNg`<3jzDU@T zh3!S?tA))hY;Qrwv{WTY+ZyOZUy1udNY3r|L0=0S;X3F$K~7;K+y$NJw6GC=4E0f!e5~itra%HE6|B31_dR;tI&xSihP9Epc7HrE$rm8 zBytFy@DJ$Mm3*b|$s5p#DBTcwZ$d9p<+}|XOSvdXmLCj$PU!E}|tr@bZXoI&`9!gpF_pbfOi)MmQ7tEYKUmMmQTf(Mn+> zoCBTcZDAvv3!Ug|VIxe3PPA(t{|!N=QhGAuo0aP;5G#@faMis5KHO3Uk;sU zkGRi-Z$Kxa)cOqn&JO4$imh~CX2O30B<~%e7xX|7CHX%zLa(aI7XrPyDxVp8T~)q% z&>N`oS)n&o;dO|01we^Nhp4b1AFaxl27L^u6W?9IvCt=gdI=lh)6ge^9uqdg zNzf;Q?7~L)4D@F~X~IVM9P}xmslrBRhdvkNdVT587lA0r=U_4P*HrmlhrUXc&jCGC zl`jkW`>K3vp|4Zr+W?)&o1a?2Ezmy%QIglP75YcQwpl#;+n^Is`a{@uKqvb8`;ro} z6MhVx$n_lip??aZB+Hf0pc7G&$18w-1mt?JPD1}ubwIJN z9s2jGd_O}kRN1aT$C{x?rRQL=sM~`a;y*}O7dnxvEfzYFtId{ydjN7ho*nvfm91tb z${CPrz69u_Rkq2{pHtbUKqsPfYXbkBrb3^q%C`XeLY3`#=tPuG_T&35hW?T&->cBG zRkj@HM3lCPeRH7`QCcT#YoHTR+9Yi6LMNh>Cv5LQC!!>ew-!1Pr9zQ!9dsf}CxmT1 zbRtSW3)=?hM3fw&?z$2B2a2uq_wA93vKEwzapaVjFb#Sh$U1`C2rby!Ldk)?6v~Ly z8hSsFYu%Q?XI&RWsh+}t(7S<7ivKF1^l7{1lfG@&eA35C`E10Hq^~t!9FLHEczGa7 zW`!dkbn@$!xxODY%mSiRQ{<}&o%|)=iQ^G&Y0_QUY97&-qm82@o?~jD&;>dLnvG(+ zK!-r5KyxLrU7$mtQ=mDBZ+FIvd_s3fyFhbgv0b2}CD$E7cM3FD5yunT&8@_K!tRjU z1*VGa=Bgr}K!>n9gzgk*uEz736GVQA!tRhL>}Fq{&nfo{7W)Zw2y}}4PNADaL_UEI zflh(uP_bR0L!eWjIZSL9=n!ab$n8$KUFZ&J7iez8^O?iNaRfR9It7{|#CDNCRp<_Z zPJ!m?BA-BqK&L=+4RO9ikx%Fjflk$Svq|I==n&|X*h(BPS>zMw5ZCGS7TbLUnngZ| zNnCdb-6_y)5%~lG4uR(S!Y_$%?c%-R5a<+W7SGYj!zoI+ChP3^QGFDBzmcQi0^c62SP^#W2G?a< zpydZ#7hOlF5c2()fnS%@%_`lh(l2|I&2Lm~w+a2R`n)`j7uPfUEI)rWq5o3Ab)(SN zearPKLSJ=)>p?Je~Ci93p$GW#GMTt`S%VN z28nWe>H~Z`)zm0S{4f+1^_mL>K zr?%$%dkTX@x!uu@Z=M<_Z~n79U#iG=2Pbg*owkkGu7=BD zJfD0&N>t}_tFPz#zbi6GOnr~ry9&ER^>G|sdA{0WgT(wU+%DfI62)U&dYF1VpS{Y_#AiR$}r6#s8|-z2Kf<5o}L=aKIfiEi_&Hsss* z{<3_LsLFOnRo_4B{a$|rKfghoLE@bg-a|0Y=lhQm`6N2WaC~8=3``o{esDH`(AyIvPb1VKkRTUc~I-cbANMV<#-k(+H`Q-B<@veMs4DP=F zVmHsP`Y%IeFtOs_muS-iFdZ&LvVNg{S|!vtoQl*yE}h=9RFUjz9Lcmb=>WL zvVzy|ZvP7v+&{GwzfQBbFp28xbf??y^Y^Zbi=tKj{&HRb1*<-SCB z=TqC;-Dmmb?)S^D;QhD9^6QuVIug~_=}r$3&zXE~C8mh?iqs{lkK^w8(<->Xxh21T z*?%h0A$}KGUP!Fy`4?C4{O+!QZ3Xu?R^`_(>sJ!h*Xd4ocm8@6{Qt9N_xJqT-1NUR ztKj)Nx_N%weP6ZR-S=mS{CmmrRHAzS0`WV^dXGePK6kpi^Ixvu@9%DZV+g-~`M;5< zz7BH|&nNu_64m+K=}ysqE&I15y34O_Us~_;`Axac{wH_$kJaG!MgE^8s=t@J{ZqyN zLcTX7s`u~m552$pRPg`f?)t42e16>RKca%?&%e*|W70qL|4+Hk?{BN%^OJI)&%e9- zpLUyE}h+1%H2c`{&>1`4?C4`!f^&pUd}>#Mkfh`fcL4^1UHZ{r`9O{p}U3 zKc@Xd&(GQl-oFBoPnLTU)!);d?)Ljv@cun=pYP8B_qqRL_qo5j@1I}6@9%E^towX^ zx7_Fc`|orA%N2b7+tT)z=>)zNh?sC93ne z)9d{o>fQxBs`A#8AykaAP$g8;v@{!MkPQeFi|>$Nr0VXW|B;j z;gU&!>KQPcwh^IvCLyt&6rr}^qP9^%dV)ap1clmzEgoxBIBjE#ttUVbI^S>2>}_SY zL(-4$dH&BIWZu2sz4m)u_qE>bExteZ7T>@B7T=Gy|7Ewh{>zndsd%H7+I5W9|MzaO z|NHv6|1onSc%sIQ)pG4Ej(>kY$G`3t_pkC6>F;~DsK0Ez#qsaI#r~hZ#s14~(SCjY z7Wwl?wd~S2|G3X#HvHYi<#Le|C%OzbT6U zOFPbJ_wU>y{zhB>&-%Il(cT}ak;%>H)dR zI90nzEw$?u?Y<==B0to;54DU2ua$#Gqu}3r%DSlVYN>7a!>1zsuU8(Z<)(s2z3LBC zOVz$s+i8iC{}eMT^1d4PQ%mhQjw*aYZC5ST_O+#U{qIxy8KMBHrS?7bUW>=SyG8uj zev9}YqvRK>{zbKnpBGs_^%OmUeH3d*DWAY>QYCf=9YTIv#5r45jjBDLLxqsUCkETZEsjiD!-WLV`ly1K)UW`J&?N)RTKw6xC<13t;M6iki7Tt{YN;K^hsPuDE1y(| zQOo;|M(VdKFQ}z<|9|!$xnT$uuRb^yxmWk$_nQ0v(7+FWKLW4j9XfB47!V&u7&FaAT||BK51)r|k~W3$6k{ZQHW-)P2Xe{)QDDDNrHuWRO4_350j zDllt!G;j1^U|0d0Sqvl@Qeo)iC_W5g?{nS3c z(tczA8(+I|zu$a0a<9tQZJPV9Yv!M<8Bdbt{sZN_w~CLeG~>HlgOBGl<9S4LFEstn z(cDkh+%M4FPtx3L=aZ&+K38)eueo2PxwmWX^ECH~ntSd3Xy^C;_x;k&PkaCLyvX_8 zwMuzZDZi(b&nx9RrQENSo0RfrO1V`jTa>a)DfiEhwEw(P#w+!ADWy>AW0bOGZUp{m zrQENS&nsoTQr@MMBb8Dp<(qFs=;uql<+cc4eni6uK2hpl*6`QgDfMk{MA}j1-lt0a zLnkBk!<2>mOsW5G&36p`SE;}2-3YvTUiXSpKS)!5O{t&%pEr&_W@Kdi_iO6ol={~+ z^edG5i5-!4R5?COssA4he;BFM@6fEzXr=y|W*zQQ>L1p$KT)Yaq-iH!saNstP0e_H zn(=JY(C1Gz&$Be&ulTy={z1)sNb`QB=J`a0AFKTFZq2SS9WUfPu;jE=-mkkO@Txxf8%_U)k8fd&2;`@#Pcd9I$T z{<&s7mT2a8|L<>vcWd@{-igR_m7m$)jNGgKt>jaYd##^Qiw>$Ck#;BouimSrOQ~1w zF13D?24B_ZqodRh)!>r~U!~ELRQq8=l=}Zv=t8A?6~0NK2UR~;^~isZQlF^Nk5u@d z9Eq%h>c3O#@6yn}s^{GurGB0UA657>ht8oOCu3wH)Kl@q)ev;CT3O^zyqL=A3^~)(zullo9 zy~`J+{#5G`h=$J8 z`fqCXSFPWyXecqMqtrhbrQQ~${##M%*F>o=i&DQnO8u57_4QHepNdl76s7)$QR>^G)c-6> z{m-M+zZs?emr?59k5Yd=O8uXr)L)KLAM^7Y@kGUk!BOgOk5WG&O8t~5^~Nam_eQDD zj8cDpl={V*dX=AO%TG1mlPtU#Sr1iT*`u)!ay0M<{wo5n%BvjB`>~%yo~!y*hlbDH zp|KZxHSN7G7Keu%uM9j}(_YKFk@i*oH$-Faz5ik4xvCGor{Nba4g5=giomP$Kd$l1 zyrEf-Le2B*8oB#&DAJy)Z#|>22cL?K%um(3#%t_1ou>U?Y1Y3;W1s%9>&E#SH0^2a zVY6m^FI>NIymx56$2nWGKSMS4_n$TP>eHJ29izyb1T7*e_v`->>0i~0H){H8)yO6J z(+IrkFZhmTz3$T3yPGxe$FD}-SM_IyrvFWv_J(Wh{ZShDKWp?8uf|`N{z0Ta)ov-* z?4Nd7rvCSh@Q-WOvsQ!u|E8JmGn)CnpxNIJ4Zf_<%FUS^pUt_`#a_P1fA+)zB;bKC&LF z9UK4G$i2#sUewql-5R~}CC&P5)9n8V4L`o?_Q?EH`^>D^eeufr6lnOvIE}m*ql`zj zr%q_v8!$D}zENrKgOQPY)lO{E(93Nae6wrl?IF#2lV*K(X~wrx-`OdUPdYNpQORJF`q~JSNZ2dn)m-z)Bh^Xc&Bwl z-dFt{?`r0IL_-hCFup8eN5zu3W9X>Z+ha!#oB;2RG!qqkn+cZ%-4jDX8uGwMzKK(B z@PEJ_pw#1o*28f*7a;im_Y8>PLh#xSPQbMZUV|ZNcpeiobP9@$p+kpmS^}5Kuvm2R zz{sJuh3|%s#j^)S;(E&xygyHZ}|vz8?7{(B>s0!*HW+Q(wdX4w0{8V(z#D zFN9kSLyZ3N7XS0EuUwCfw1r`w-WnSt#q5DJkBz-HWC(u4hF@$b zt0=jkbWPtd;ZZuuJhHp8sG?7B=Nga0Vn6@U8`h^)*)p>(4eTaE{dl-pW23l~)%yqmzQV%%!Wnl?DCSVo+R(V|7(! zQQs@*0&ew#URc$Fy`v@6&3Z(X;i>fReh5tV11tcbiTHz zA3V<0FLvMpI#+u8Bo2U;0RQ@ga~D;XdHTUB6*xyxzo0$dej-g-fm`ky3Ck)VPWqe* zmap%o6t>W3V+veKe*shb1oRe_7CHN#g}2C6(05z%8qiuq(DY525S$E+0%EMNv>zNv zd85kR4|xLE@~WbnC?zT<_Lj>1;Me`**4|2>MBh@;TUoWLZ(8xLcU2aw>T}Uq3F;fD zqCY|j?Ackgsy||>s&e(*K0B>0^m-x$*H7KUS0PsxIiLwBO`8juxj<{{y{<}IZG@04eRn$7xfRgqH@*^%NRv* zR!8hzudunBw;oowyvdOw>RyJGeAi9&k1&YGeG?)ILzH09v`oHpH0mV30;AwuG|f8#Sy5C_c(X36 zR$~La&YKuF7&Jh_zfni!DyUqWT;}nm%(^*9mD^jeIywstH?z9b;{j=VT{mw^0lS%b z8*Z-PChQ+F#OZNYvt=D!)%yyN9Cb)4P+^f%hH=m*9E>YWpddP$stvBL^h8$%R3N!O zK;>1Q%IHh4Hie~#E(eR;AVo;sUA3T3kWk|1E1Y?mh&$`vqCqA!yI#x^Y| zEV_cDwpX;S$k~U&c>`#_8pWFQIYOn?{=)Thj7qCFh@xn8uFgw+r(aXsphAZ&yFNIH z+QSC6+-?+jkwN`aThEjoMXahFv3~K@fkgrLco~nPE`8W#wc1kwHgI#8o2qr;Rxq%e z<6#(TgU4MYyH`h-bvHmcm^I&gU}}S3?Ym!V{UxCmdp+)CFeOOPs9i;t@vD9Oz2*lP z(BjRSxVck_-)FB=-@Sm4Z`utL`pw;3+!sULln?;4S}wimqVV&+y9z_~)m0hfW1r(; zHK-5%fKlJn#>I1X4)onh7^<&P-;DpEr!Y6T*402OVkO6M)h+&AE1rofT3iN@WsAv<0*uZ;KT~y({nX4bz z2~~sT7^up%?=uBCGU2J)gs!d#!Q3k!W6PloUf|KL#yAX zadv@1O1Ty%{e)rrVY8=tE+I`a6zsAK$cAC+M@Z`n^T-|&?6h!_?<1Q=zO}{Knzl7o4bA1_pldd07eq~Eji6h$~ zcsywL>a)+%u+xHTO<$=-cX*JxSCrO1U}?8uwZur_^@zEXg(+T`cwN06_(NsxxB+y{ ze>EtK4OP2^QP7~hxDL^9F5(7ClWECS?16Mh7H?Uk*_Y%?QZ`jzjT`g|4QyUXafirV zNVi*OmOLS7=m{F=BLDkRJW0J&q${NXRw;psuF`m`s4XRrSOCK}ot5DpqrAEZZ*(Cy9SHfM6-GSf!4FbJCCquA4yRly)h=LE&>lmlCv z#7L?-LPM;ba__+JH^(E9TeB=MRzV5e5jTZ({OpwLW}lM zyqyl$>8Ng>pxbs*rJ2^5sb(K-%$26%bw;&XcQBo<#vB&%ArY|CfSuJMYkHK*a$t^!tb}^2GdVBo(zhID7IG)lvAwB zTP6M|V+%Yq;bO4qa!;i=i~c+`tUmaLNWPMoY0318$5;M1X&U+69uM7iu2D>-Y3FD~ zKBg}$;)I~u783OhHesZp^}=LZBP?@_7NTa_kWT{^(RxGTR6oU@Ab(*x4RD4BwsZ1< zDdcfWxtC;G=O%xyNH7X77LZ1yq(`p3ZW^3IwPx&mypNXUQ(Ap6U~@DWpG-(3$x42+ zrNNj)WSwoHnpBdo>t?#mN*mnV??Anu)*WHEIy1#tX}uX&sWe1SRr~alX)K89#K*rW zO)j36Z^>q`_4)F)%8V4F5un_0wSfldJ><_9Bh54rFXv~_csrH5i=WT;DsKb}9{lnR z``_NUMgx6-$JiH8$rccaK?G>BkG^F<71g=R;)c-G+A~6KItCcn&K?>Z z3Y<;Df(B{b7GPyo2G!^XifHhkAYUR?^s>Miz{yL}0k1RMSuz2f#ClR;09nvdbBltK%y(wi~9#Gtr67<717 zi5!vGEfR$ve;cHgA!+<&F;$EMR}5h&^K9Ls$t9Xl;#G4s)5AZ(hp6Wqlb6rG|0oQDQ(77HRbemBK!7J=6qXyEBQ z-o!^hASInb4HLy5V_mHcY^VpA=WeGV8&(O$q*}5nQ4U?n1Q{|5AG0; ziYesNl`s$e6|iHWIWImhe&z!?J29@J{4l1hR54{!EcpI$y0clxUqP1K4wBu1#-vd> zmLXIv9BuN-l^DxqD&B%k*bL5m_GwCVRjnpzXH^;9Q7?)cO5{?J*zl)f@?K@^g`8N= zf{W^MX~QmzyR5^K>24>w$WjN0fkzwN9Xwgw*Xd5i4W$n^To9!e>q|6LPqnFmhotmN z5SZ0&o_n1xClH|Oh5T%t?f}KPSa6QP_=P1$v}OjyxJ(=PNUfX5CoKNTkNi1Q36qb^ed?_A2P*q-RTGCrLtU_bEs)aqi_JPCnW@g(bQp* zAQZ0Bkd&U*K;YS=$CiMC-VhH1Etfn?qYq*9bx(G^B1_{#fxyZY%WSlvh2p~UwJ!Gu zGzc<6pj68wpDK2@uW2VdPrJ!Su7PD(o*maY4sJVE5!6@L|9WaU#Gae2f(hKB1^nW zadsg~v#vsVtEZ-*d4E8mgQLvuq}(zq{Zy<3_BPKKY_tCV^k2<5lD2P(~t8$~bG z<_mdGC`iEDal3E z+i`93lC$N(JQi{57ec3{b@}|eJ{8I}`EqHnkE-+WYoe-r8tS7;{xy*|A6hI`gnvh; zQGt00)h;B-2U(3@6V)&Ufg$nlq%=smrIz*8`PFoH8Z9#imgM*Yf~GlXky+ARi@Tkk zhFDub15TuiQMMmK8SyfHj=;7DyMPxGliZ3!d>v^ zN;ATe*+5iJ-!PL=&vJ5*6NuXsFq+!LxNgUTEgefb86B5_9NKpj=)Mm{_RlvSi=Z79;CW6ys$%@ZCmCPG@IHG%)@XmpvKCo zb7aW8IDgmlJv84ZdT7w$9S?Si#`9F1N@G%lV@JqlqVyE9rqW6s&9_pHnI@&s-BuR- z;OjnfPS6Si2){d6ERCmiS81Y^ocT;nVDw*wr(xD#1H+nM&1stn+7Xmz z5L;O}9pDs+nKaNT?5v=D(*SNI8A7yl7bTq#UDIfU%fiCLgL#}Y9~7+t8gQ83t1&k$ zwd}Aw%Hx4t%%H)|C~2dvVX2pBr-hYjmY0nG%@(TA^@y(G6&4!o!aJpAX`H*e+kiiJtozWkdA)~4@h?X=1414VY7QV_4BJur?{|uh65ZQ|NQN^eSFD2Bl&<${Bj2d5AG$D-&%@p5kUV$=~rZj_rTUKOJ2^twRJ)Jyu4_+VKlt!t@d_PZUTvsaV|`VWYU!`PXUrZO=X zkh57^?-8A6O*80cwFWv7Yi|c7pIB+ZB-t|AxR7dead%MX##D%(rv`-gtldO%VYt$a z%2UuUfNW4LVL-(@p@FRmV-#5zFus^uy_R&Cb_Fa884k9%wYq_hVqLQGKPRX}tIRS? zaNko-2*UQ@Ck~n&6e!4CS3VqD78U|Sth3DY05I?NbF|h>X6FjBndPT!mRU48g%;>g zLyml)`YD>GU%|~KSV6)0f;JfFw=suluoH~HOlA4>LCoRm+1nbReTZ?6%0J1UR>Avp z40^|LRAQ92{8@7?P#vtZFx=m6Fkm|l#aWH%)W}XBY3lWhV9njr*!2TlycVt| zXz!v`$R2{dViDdlJAM;|<(I6mT7qR1yZI37Xtj*wn|<2_6q2X5vaWZhKBwbR@PsZ9 zI!)12%>`&+sSvb+N(-s-Dnxs+qPCR!Y1mGd!VtG*P(`YAkS4Vk=xe8=HV5%!_*;9s z`fiUkDEivD8yf5^yT$Q=$$VwHUv2LHZhX&Rk;5&*d)5NW$nU)e%oc4G2B`K$R)c8c zNvLpP-)AX&pROG5YWN#id5m2I?o}v@gOjBMD!qyqwu8&OL%!|c-r^HM-a;A%F>{&9 z7D5T2G6U(X^m^S@u$RbA&>|hpvbVAt39T%J2By(-z^u1plyN|l1lIj+DE^Zf>R4*7 zLjR!(Ls*k^0-Fmy3#+b$aii(H|0MY4B$%JjuY6Z&gx-GuHd7&uX@(~Y(giAltfM>a zaw{|1tKHw}CiiwK&ZV)yD;?{nQ|#$esr)JpvloNGknaeyypejIhS$90g|I&g?1>Re zf;(oe7$DqqQ*1e4{!XBf?DiMyIu%W^LLlGg6=7-8fFg|V!_IjO=yF#B>jK-IlgKTh1 zdtxyzXez@tTa4L$BdjZ<#TPd=50Q>H3Ia6L*}9y0b44oPy(@UPZ`Z$UbONq%PA1!I zL*epWpU)2_!vC-xDia=>frxkw5Cb;b<_jv(Sy;1&KLc_To;7%j@rw~aF@yncAQL>p z^1KCdM^nQ}tRS<4S9zM#*@Ysv&2M*0vqON3LkK3g&F>e9KibT1PR9}i8@-W=JUk}jwRp0NB-gY@kcf zvvBTw5Ti#!fljPE5%0n=ndj9l5Cx8Znh z^xA4^-TO4$-r0_Quh}Ox^JbO8)GRhAufh)n+l5_4hIGENK(jDQ_k{OU%EyYa-xGAU z7vAoGxZDYKb{r51mVE4KHUdgT7Ar;;B z@?QHwT82sb!}AMYV(mug(Z*8J`6ONF`PV8N=1P;VE(ex1%I7|%mtr^5FX5mKH2tyq zyA4}~|GP73+@ZM*6ze=?GWoqCBu1GeQ;2d3$&_NW6?ECQlD?kiTIo0F_WhWY9BDRv z4zJ8X;O%%TeT&CJgPL2VahG;;{EE`5M2R%}ib#Kh&R|x10ry`~%5^$yheI-4f$LHn z2v2?BA$XPB@qQ%`r*v!0iJkz_OJ|JGzH`0dvhQXv@M&tn$-gNLnkW@&OLyqWs++&r-o zCbPZxgDmRB`u$6+Q_Phc`~ga-*Svcgt=+zeot8g=2LUsh9ySsV#KJ@XgMmxwC|2?y z_AVEg{9)`xQSz}3KED((1rjQ|Q*@nSUkA9uo#&wbe9k}R?Ed_6 zv|lY3mhO;;gS((IJB>UIjB1s>6B~LUMM5y}D%#17#2%>f2xX!XSxUHW5&OZ`&%pQ3 zE~Td64jQo&e!VBeRx!>cjO`FUh$gMHHHg(K#keP4d-j>UQ!EIjL+P1Rt=lGM?1z^Y z`p1BJ7<~sb*=t*6&SRer`C*!)Rp{JySj0T>xVz}udXButZEmj@^F1Xx$hV|W(ymfA zwRDGrBH$OHGVfGrVmO{CLg#~fHbDe+HZVtgwHQIn1~fY$|pz~Z0?gyp? z;UN%?x-x0vC3wPNhBk)-s!&|K%#w$|yNN}!$?}6DTX+FC`I7Em>nbxiSa>JG!U#os zM6FnLMT|xOtEqv+PNGA5q0tmyg~reOI+ht88&7xnz-v~S1sKOhvt)$Yn+enqG%Sr3 zk+h3KZhXW0M;equ>rR5Tc**-2R$lrBm0YFxox!GVkEo=$6PRr%ZXEr=e*wdFE$$48 z#6XoaA=D1DPEg7ufaKUH7Lr(&OCFxv`XC6}bE`!xVwo2}{Y8#G^f}6Ks_ci2N(+x2tWsiuiZ?!{_rpS23ut+bxU(e-%HEEVf85}UWPB_7cur=AW+-x zFeTU^rV;&2V~u6xUUIp49LNc%&?SJ;%U)KAAe;vHSm+P4>rAh*Yl7^IM@_FiwP$WZ zVo)|FA)vg4#0mGBV%qRxRtAi~RK$sEb#7@b*gHI`?GSkw!ZZ#DTy{7jzN>ce>JC%w zE5>Yt(OM}IAy0(iZF46ADbSA0=CY0~E?IoV!R%gVm};iU7hwyvub4Yy!Fa0Og=t%s z8pQ*1#p6i};K@>+SxJAWZSqvh#<_2j4x4vl7Rjt24Nsv8H-65N7b{T59h z!=R)zn{CIGd9EBSLSfb@a**=TL?Kg&qAD^w|p?Z!6mW>f_gWJXm*b2wpKrageXC{}iNoCRB4vN(5fE_nW8TANFg z;d(T)F$SHgHkYY<{yAEhuWC=zk%Dke$la0=eCzWk54_(Lr=im z*j#JK$uSy%;Xaem_T-ZsfJaJ)w1`R!Ig5hEc{6MqmH|tk;r=Don&WM-B+WI>=AGNP z3pc?T^Nh2Ts1>S^EtQf|EbpN)I2&ftdsv!QEX{Ch+gT&!q|#rNwL;Ta=TEV)=o?B1 z`nbnNkFJBMX+c~H@hxkE5h-4lTx@A)A^jC-@E8y&fqsUho_AwXOvawVc{5<=v6&p} z^U`i`D{lRFwFZmHhPm8km1!$>>T*m<*hTV)o2J?kJ#%!^f>bi6@r+HW3+WuR6X0zU z9Ml&25pd#NvUhgUFF-vvju!4zuHXSf^UG-miTx*r)rLNxtc^+`H;B*-UKM5(3xV%z zO!E9Ni&+F>G}8s3RU-(p32(erQ%Em?TXw~qLxA5v{}G`S_Dy~SG~WY72`zH%5llG8 zpybYg`dO_(Hu*78I0%fD?PoiD-pObx!v6Fs; zfk&OuFCkE-xhNMMSp#Pwe=TTih4Iu&;l@U$&>C)!E^XXLPsG{3i{_pRH|Gqm#~-kf zaDxB_F8-aEPMINYJUtJ#4f{DEPi}aoq?Kw~Si!Qun_Vxn&vpb%wZ>zj^0mNxAuo8U zwTJ3jSQKn9z>b4?H4e`k0*@i%slmaDkDQU`PKcWTrf~*Aj@Dzrs?Hauk#vG;b{P|B zgfB?07h$~8a0n(hYR39XLM1_AY8G9x*ddpkeZDeoqM!@XBsB7jKR0e7t}jNe#VOOg z*`~SG$RMbM?+vmATow`mW?wBEp%C3`PhJWIJ3Dt%;jTGsy^I58=Tk{;2TV6ZGkwF2 ziy)<*rd&5wK9V{d@B=_S^SgV*Jg5sBb?`J`0q+7Acon9%eQJsP zY*KG_f9B+p zrO3wUtbJd|uR)3-WJ5#kEzn{~=%EDBZRkl#y3AQAwP@^Bkvg+}Q){sUyd0N^+N4`kXwF+SC}z$4}%TtZ{c2ScG_aC?pmm8}x4kTfae-S+0O zDIJbqqbhL9L9P}W1HIrnJQRyy?UYoNu`ca1KwsWb?P2W;=mLdWhYZkNK($bt==KI_ z;7%y@97-HyPx9IP{yZ_RyjWPgz`b#ZIIhYion7{H#&3?kOb9ZAit?^MAD#{owh(%BI30LB8N@(QOu)`U|2p=OyGE&RK7!iA# zHso>?@heZ@sL4)8mJPynqd~*e}+I5(9>{-{!fe(Wq!D<%ik%DyCRcsU)*Gv<#z0JCzcsbrP#v{BBLd29uKYO+yrvs z*DQTM7D*=%s$-Gj368~;;kZ6zm1jE|c`Mw=i?z8K(syIOkp4aPs+5Pc5J3+hK<tMSA;iyI)Owt?h^(n?+adnee`D-7H28$unh*{ z_Y^1s)uhZbjeP$k# zMAaJ9909a%YGqDbi3u0M;6Gb{u9E|F1dI^PgVu;kpihQ1RE%^={wA1qX-WbBou zhP-S$C)&k0xgCbq=Cj%BkRJobF=z7F#gm8{frt46fdCBV7wy8m{77lx^4Cj>mK`l# zo%eH_^zbF9Tbsyf1_k1sFOV`N)9^#WCQS)t3NLbv*B8u#ml<9ev7l=Q)cB^r)~%O0 z)(-Z9^qcTra)F7U;NUwK?r?!15h#Sck`SYCLpvAJL?;O(v=ySd&TXgsBQ(|NUM?P4 z_WFUcyrcWeZD4d^Q&OaHOt;$n$81)ZVv#UwM%c3qTYo%e6085m_sF6NTWAW*gvn8x zzcL=qe`a%qu(Qg=gB+ydmYU>6bRM5dx<^x<*;(?GeS?6mrQF`mA)ixTYQ)WIh%kjYEm z#`0{db1##rz|C%7e)8onQZ&NX!`T~0>aQTzLMz`5+zB@UW1O3Q61y3adIFqL1A2vH zE79KNVK!r@wW&10&H{G8p=`37X&QFUjo++rEZd$V=>B|!*Q`|NmTflHYGV&A-xT(O z{TDdj%ShqsjIozwA*$C!uhr?6%Zwr)$Ly6RT=v_x1{*~y1V+2RGX#}f>cylCtggl# zDh~Tr!L247D()03_lozLdxRgmZagbSA?|Dx7Tc?EoX*`{i?JO(*e0IKlf};9D{9y>rpmKmoSYwhznNy8r@VZY|K{_wU>{!`fvH_0a&|ys z4?yCk8}bl})%I`G_`MxJT+6Bz1k@M636 zwztB&9;`bFuQCEw5M3weAW*9l+x1h#UND3+xI9?*BC7OWY3d~?2tbG**0r!Ua6HBu z$h1itLoCU29$N-1-$K8Ov3jA|Zh;%tDsG46DdpjL4P?w2sK9?gEbVJ25SVp;#3`)Q z3>Tp-bKbT#q){#W`U7H4A`M+6+TBk z+bMG7-(?*I$A0S-zZkPjyuM5v%@dGg3t2fCW0w&dh55>o6N{h^^lV@^7{Xzdxl$IV z0Z!j3t^^z4n=HND+-zw#{wh%{f&b_PNbVt;yP3YBLuM>J#EDWE<6u`uce9{7&K0wE z0S@oUwRJ#S=fJ30+RCo5u$-#`;?GK>SAaWpC-vPpDuj(4EjsyP45(@^{W~6Y#heEB zadqw3+As?qMKC}}MJTM`ykmMraa%x)T_%5@bwk+N*g+iaSi@P7aM*?Kc(;aPiYBVK zfF+PUHmW$OciWDcfk$H@69>DV_eS{VxN@3)ky*4jL|)`)>ObmU!%p($yJ#YU`fo#b zLkt=XLqAxPOJXm`RC)wtQ-PU)_x=J-h!XJ-T)aN78299(c`pO+@+`&T9Bo*L&CHq! z#v-05ZWnWAPQw`eEC<*P_c}6yIDxCs4NA&I6xNK$EHLsFB+?)zK;;G&Vji={4ZHae z`gjjR@cWoy!9xk-V&WA%!42EWP zuvreS$$Jc&5-6Gq`VQD^7LqT}UBIT*Ei}=NGeKo77tkas{4JCOs}2&X@dYu@)+9#N zB3+NFJ_E<1e8dl}i|8R7Kd}cEWWk29ZK1E>El}p8g_NjYhO;U_9NPjvnkX!U@1KnD z(;FyW&#zhA899!}oCk;RJRt7CHf$~xQ%#5w?(Lw&olxE7oZ`TfUKfo&ymAJDh(}ja z?o~>*BHb}u(jDieyOGvFcQ}DAC0l5;vlFzux%Ee{P!?jpP-?1ZxQm(dz!UuI%YBuG zAwHXrF>r#gYX#=X<{I`aHf5o77`Q$w{A zI+#zK9{Vjb&9OSaOV%xPcRgn^poLU@dJs;sEp#%be(Fm1e#qfm1|M(zm}v^Rs&J8T zRPf$GX@DDd%v?aAYK7}3uCFZEz^c9_0sL|$G>^@k$Slu9Faf`A+5bZ!mcfL=-> zmRv6o^6>HABP*uT?1Xt0i?e#y64F`u-Hnx43{^j@;zA8YIe5nmhfl zT9ng1x^QH%`#6eY+qee<&8sYy)eS;xBhd6KFitwr}bvNk6ab z)MQ$RbFEhTCe8=IN30V`Vtu)2nhuU;ky1la{$=s8cn=~HChuqLMy9kU=D~?^80+1} zlBC8hZ35MFAyuoy=$!QyvIr||e~>E0{yCtIPRg0DixSHlPajzJP5 zL{$dW)u&s<`3G-cZILs`#+@F>15u7UI5^;S+Qj*z7-YCfFmVFv~Rs31PLwI4!I z_g+Lsry^y@5(;fDgA%3V18Hmu?|?133u&yAK&j$W@!K|}Z>+;%U8v1Q6`c@10 zGIFlGJ)-VS>62JaJc7oyjVJDn{NZ%7{|CHXwqP_?>^m4=#^^5}BnOkFYa6Tc!cvUKxOw)F3H7ic+31FTO zR?ZDbt;|Q5M$ddhy!xB(|64DUl{Q&fQ(H+Yy_Oj0r7Q#GdgKM{PNSo zjWc&e>yQy}j8^B`_~t%tk{P8F{x>U*9Xk|6_9uG=c#VF31WwCm*hen+c@+ZP(^+>PtQq>ryWq9He1wHQ{EsCE{McBL^nqEoJ z%iIboAJR=?tzHCjW~7AeZ1~{|+)pCm2m->A2de{;%LJ=joc+icC`E`Er*XvIBw7L^ zvN?d1pfpP$=Of4WVe~)-j!Z*hV~KE@Ov#o!r~t0engWrr6#LCCQUplLAn@a+(AT#M zOS_ycdy1KC23-`z{?c}2qS3i-c$oIUQGu!Xb7h(31}FheW9)ymPKI?9b}=Nw!R2tt zK?jBgslH)XFgpm>ijLNwlneL`Bh>i_fM9@i3;>4#>%uBX0zeuXO1GNi(kESkm2zMu z0yT(9>yXiiqbXntJ9c<4)?qLhW1Sn63N=PoMh4I%GSFx6Dc#5g7)UXK68h{Ph##T{ zTjzqwB}~0It8ant)&qZ;azVHdi5B@i&gUKJ1Y1dTbsuNHIPhQ?T*z{jw~KQs;LRAz zN^GE&s*i9w82OMaTJME=VvgvWwFan_XTqxI9VuP38Y;N8i%Pd}E{pqQxZZD&&rlL_ z3meyT*-WBG?h;cGZ~(8$jhl*y^i^r^Sp7L<9F>R{#mW9gB^Sei9p!o>%_;AQs|jnO}^%wiC1Cb48Lq zNBYL~YGj`I+dOb8=Zep5Vh;b8DXqFLJ#t;jzmDupQPOSdG6k~(+h>WMa>OH{$znx{ z%Q)`19&QvI(b-_2p|CdG%&S0aqkZH$(imzB_Uu5W1r7@iNV7Z#JDSIb^_;X>lyof3 zk>al-QVIt!{BzKP5qf}%Qf=;loG)V$UTw%OgQg5bcgqhs$|1gsAz<8)w^J~=;DLkC z^F>3aaGZig74PzL#OOP9I;`NIW9)Fsey8q2C~$jbo* zAs2YDfs*Zs?fV-9jSgcmsQmWxI0h1GcgT)X<_;yfk+Zna4IowD!P%YCNH)?Xr1-c& zK~=?PkiN%>Jj0<|$_Ltn*J5(yh>6@UUK!OZTtL2K@^zQIY3 z!%pBBQORf;qqm5pRb8)^{2;uU0G$0)G)2(VP@6B)gZrvwHxeu z4&8hod?_*T`5xKS1&yG#WpPJ2J_g53uPD?aMzMkolR6#b0&8UIF zL--KqQQMg7O~-l**(HnPwElhAt>AOs(U8Z9V!TNf=Yu5$!Xb->9!IMqhy$piO_ruy z7VUD6zqJ9mc&)hY747A4&^-j|lrpqCc5;Jo2;cAaP)M{kIaI}-1nurLlYnjQ>!(kxhTm*++@jnd}m+ruM z%`oz=m{|0&lEXHi4g>T%R1J9_OW5jveOXO_{va_|cMa+aK6;H|APr+0FeBm@F<1a`X%OLm)-cs&mq5Z0`(u6n($qcFp$ii0tmKh9gTz-Bk8dJ*i*}~XuxfV zdML3_SK_8ocNL5PmEzsmR`Reu*#4e5EamFZoGXRt_Efkcy8vK5?GW|z#{PxNIJh=Q3 zM90|;d{zb|xR?DEnOUDNC3h}ja_}c0kTBgAoJ=V@1AERsQ~&*E7SjNrc2}^Wwe^Px z1g+#?5RL^Siv_7pBQeUh%sd&cuX9*LVO(Jm!8Y;jY|#<)p9B+iNngX4Mtu8n>9%Ho zcKQ|f$3z^I_vT$LL*^{YX_klq%X3xF3U9&^n1X1l7?TsS1 z^1j6{E)XRwZgi{zN%iJ!*&dM{FLIYxPUfV`3-C3_Z9#t%c-SQ@JQC5_I^4xx_D@}W z$Z{Wz1TxjSWzOlZGE4ban7&6dwgml%8mlVgF7``*3IhT`KS;jt?hcJKE^34Poen;P z8HWe!-3S7|hR@&3LS7;^3#r=U*jLwt0EZ5c~R zq%5BFwyyMgS9%bc*4cFaba)6a2L19pi|rvO4ZQByCSQv!2YzQJC`fEpgV46% za`TD(#SN9nZ;R_~7lHXmN={((9HMtvc4U1Xu^3e$#G?(8(0z;Tm z>~L!@&OSxR7=)mZLnX*r-Op)vv+*eq+$ARHr`p6jz)&Z8yb=__dmJm^e-6|ltXZ?~ z30AjCzo)a&t4 zA{cm;sYtj{4xr&93^<~8wrl~@#LDu3IO|!;Xg6rDFj`i_PR90jgvx{Q!6g(2muxnS zKbW!uHd|;GzJ}6!t))T& zVs<=R_C@K#o)m~Fsgh%XlffXMq$ielK~MDs<&K~iym0XOR$;^R2}}(@yk!ydwxVJ2cNj;8;ky zc%d;~@?S?-lRT+VChLnG&*8MABOS*1_AE-ch}4!D`~i#^IF10aECTf!@j)zn5Xvcc zhiGjf-DO2;c#w}s-et|iA!o>hyQ~>d87+Ux5YsZ0>=CcojWlbdEeJ;|`)~X>aOish z$RHY}g;(--BQqDc94Zs{=Sc~d9&Kd1iNDar>g{nbT;q-id#Tak>mZq6B{+31dXUj` zu9=;x;Ji{Z&T%Blf6kuAV!lD13q3Wlo2m<$)xaN*!<&@hYOr)P$aMcc=8BPer@5>H z&O-)SWiC6WTp|r7&X*=;_E2F9pWF7AT<%7Ldc<=mZwt+^ig{f>FPRnyU}I_xRUm`6 zcHrl2W@Ct%PlGb#?)br_Odvs>0Zznbe2<2^fR+Js8{vW?^XzQArVNc84v3xMA1l<6 zE5DQkhWwQZ*fYT(>me#A+z;1cLRsLGvgxUlPfbQ5SgbSH_D1J3*|K;=mj4LkO>hMz zb4U(WS}zg3iq(%2oyMogAWM)92Aww0Q zmScG|nZp}noJh)BBxl>QGG|>{;%%6NnE0X>;XMaIf7AUS;*`j0*9VRFa2EJrXO59M zBFszgLb%r*@|=g*48)=IJOfR)QZBnOF@$6mj_klW5rdBwi2Xg~V8Zt!n_og~D)eK} z2|{P}!cvWcSAOK*V}veoN$fu>9QUWBGMLG4@{8^l_***cXBiH~DpZWrV zpalvU)Xfucec+|G{gVC?7+E5|?6Y83wY2VfM@wEK7y~B<6@S7Fj_WKz;^6CI#?lUN zW=5{G=yH0KNAg`pe6aoF9sEZ=AdCU3_>6RV5HTwz$j3SbrMEL1tn-9}sTCSGh!iGa ztwFbx2BWgtydXVufjI;EejCJ7{IX&Y7<&3ncY;)Y)%K<(2(LqUb*5v5_%F>oywvg= z%pi%U!9O^h1SP8xxP!xfIG6^qhOCptv^KEiCaOa?8_H#kyG<-BN)~4jEh@CycTJPN zhO@JsnbK-LK&ykVq`A_9KOOj&)$tzxwt33}7`pI^f>{-O}_06RP1wz{P)v7sPV4CW&E7+k~QduDoLIFYVZ z6mUd32_Xl%tvA>zn(&p0Aub(qma_2fl3#{3a9xs0#{b3+=$|4k5;P8eG^#gAjAq;Q&uI zJj=-Ey2$TCQJ+LZdaH!x@o?DA#o^s#E6~$I546xMJ%7Y9)yLi+`4D}RgR$5a8;<3y z(m4f{Z{dnUUjh(_|EW#I>bQosf zc?Z(}p|5~TvPFe>!5TN%|C)zMEMn=17>9$iI|KB{7UcDt0^biG)GFjuVh#ZLvdi}M zlw^X*SQgW;X6P288qymFUYsbnMfmp2;Zv_Q=IPm%u&M(BelzBT94toect=of*q_r_ z+2Q4Z2qf09ccw5)e$sKE?f;PX?(tDo_x`upYtV)F3)XTA-~=Xu69`Htz$9@e8PqdC z0yz_y2%SJs9700U5Q4xYfZ73}dcq}Y2S~(51+@c0wLw5_pipg8tUajE+Gz3AqQa>S zkVu^8{oNCyz5Gs}*Ylizp4Y==X7*?Az4mSGwZ7NS7Y0%>unB^T(DMQ2!tM@Cyjyi* zHqIR8(NuN!euy1No~V353@*&tcq!Z)BlBhj%o*ccdm}D$6^BBaY&vS@e58k!{85C8 z%ltWJSro%=VkMC=w6-MAXIcCiLU2*y&to>y&PRf)qP+D(b&I)m4fkE$_YPgydryQ zkK@oMR0wO$UWUV0FY<%!=i8x&^Y#!rB{vf*AmNw+6_`VUzX*uE9eAN;*Gt+6FF8QB z216%zm|T10QF91=n-;EszAYZk%{_l#Xi`7W*F>XDgdi_?mJ}}Dzd^j4k(T$7n1b`0 z^xiWXcB#HtFK%SuUBukta4~LN`Nb`M4u`J~Ly`%wn5@^_$2aC{s5c z+bl|CXta;v2+IONiiEKz`*`A8m>@Z1XpV1UzHgYUx^F)&kq5ZaoSmwI6cA#q8zQYT zUIw+<7HZPY)tDUzpOYb{7XfaN-I6laCK~3oY_sX$&TY}x2rne)Fk-egsilqdj_6TL zFV=*Tj2ro=#F`WH-LFB$C{-nv&$;OSxlfA|V1R#^x2*|9{M`NVDd^s0Lbs9%TDeDf z84`mC=?oIn#lt|3!57T7OOnN>QHs)5B_cI6AH*+?idKf3==~B3R=Zsk-$lFS0bNBB z&=C|7`r+I;yxT!_H)^$q=+Z0frzD>m~x27lyPH{Zu(-3cTw&8*$iQ2yV6Bh zODIm4QTXBparo4hMV=s(A1l*f^pHamMaVmo=Y~R7VnmYIu@G&AFO*S? z9t0?0KgS)soxm)QI$N`tlsEjGjELP~{URvQ8yH8{7LXk!(YDpr6k!U2gFME!HqxQSo)V*tYOnN2>PI)T58b>Ho+6a%b$JD=} z-$O>=j&@&2dE!)bh^Rz(Aphf#<++lR(IBzGM1YOxPn&T@ky+mu(^Y^DsA`T!Xc~dttc@(l zBBHGH!Y}lYoZ9GuEV1TZ?6=-EYf_5!YY;^g^MWu^_U7#2Uv?CH zfic45jta#G1JI#tSb6dBF&{z=Z1KUt`r0CXarj;>F4+6r=`9#^xhok5GBa98Qi|I` z_gNNEIV|1!(7Yh(?evoGWZ_PUh?WzW7K?;qZF*V>R%YJfgyN&VrdDe|Csil!Cz>QC-J8iaQk< zR|sH+A{3BIa}}Y(Exy1}p9J`e>8PF|JP@f1?MO3jJ4@D4n|`@O6>qoFWSDk6o7#Cs zSd`uCaN%lmc}tmzkB=Aq^5V#*S8@=4cn!Y0FZwhlQDtoV_}~uJ>qMZ{$51LZ2vu09 z`-j?IAnWVex|W(^--1n;{+fBNq2!$^y&+P9@&Rq!3-Fpb6uW=V_VWHX`&Qw>Y+O?0wGo0X!x**8=24z%YglmM(Z8-93w3Sm0 z#ZUDOPF3Pdzd6vu2^p4?2OQ%GDut-I2ZRiy5Hhxj~n)R=MSSpwq4WG9A##RRkuJOW=Gkw$PDkke8K z51d~bn(hu}YRO}#(-N}?AqGFbUzno?dSv; z8L?FKCmRX;+(X?E*(|IRX|o}59=ZToED2k&NQ;_KB~Ms zRAwjEo0*xL;4@-ok3DUSJ*$3DFKP#o9-PG-A_9b===YLQW-4ccfEO2cXA5!k1$hB1 zlZ5?W>d}PR?N^fFHQJY-t?i@?4UL8H`9A#?QH4In>@w7b(fOO0??=-n&NngGkrbCu zJYFOXI6Q7r>ltRUHV5CUMQ~sY5=Z(xy_y^8XeGVkzOoeWJfV`2H+`7wflP{4v`K$% z>P59pO#$AO#(DDUB^p08tj*ZuYV3K@mRpgm(;?1S14j>&IJT`>*cYD{NgMlwH4(N4 z8MZB&m0LZ{oqLx zYn~91C)OS(lPXCze#mJjONXNuB7wezDWG&y2r1Mrbfm#yqBlw&`Y@I5F?0Ck4(6<9 z+=@mXn^w{uAw=uAC_JS|z))!V2Tv1u)!`xAbzL&>|}uL z{+(G#0-#&S^@-k-{Co`ORKe&so8~G5QL79`PbSI8KC*e>mf* zj1_%&+_Pb&&@gbLIEm{CZy?6Elw3i$QwKWW(2)dTk!m<*{Kv(fd6L6O z?1M`*t0h8(pyqrsTz=tv5Wb9i#DdJP#iC)xn#-rWUNk>M)Upjv7Kc+q>A6k8+-qqeHU@HYuWZi-T;! z#qdx|K4R?{xnINpA4|Y2YQ=B~3F$smNU|Z3Lgt7jAKX$uu1ONRl;iyk0atA}Vh{Kt zU&#Q1Rlbp_Br)%2ufr0f&9m*{C@%riY42k`GlYCqYI?oC1;ZF%9qQ^8de_8e{l+lq zIw5z+yN27jl4jW@EQSOjLPiowlw^vRqu$jK{m7)xMXtc==rWSJ#z&2GB2>;RtTFfH zP5lZ}3Xj8nLYFjW>qdtj==F|!9!KVAuh+#4UH%SyT!ch=?OrGaW{LgdMn~F^=mV40 zU7zq=B*n(?PZZZ9(dvCAE$N2p_JeBnel?QOr%AVtb+%`FS9_n}1+Q&9jM1?{d~DiD zud%*R^FvR{1iYE}FQf*D+fW)pfjUfn{mvI;6fZF5p1&JgL%3+rSldYTml+d`)dt36 z+bCm|p~^agP0NM)+rWHI&-0jfm1G3?>6CWN%9C~F+I}BBM$acDDr)3(y&ZLc^NX>3S5*tH`{3i?vZFshq)m}x_;}##+tEzZ86+HjRB-3y;OCPA2;2PMmvwG^xkz`sfz}0E z(YEr7tEovImadbBW_zWrnh2Z800U~EA7owf%=shHIGTb8!REyPa z=^W%$50>y%i)t%ZgnR{R#&#pQqndb5s6TWlGpHjKnR|5IRI>t)$2(l+F@Cvqi-dbz z!YG!fKa)E^t}ZE2E-FwxZ88^zMixmjYzX6knAsU_DiU4#VX@_i7Z2hUMjvaK!< z8p7WS3`(S*i-~NZ+ekYn)m9Kn7rMtKUiiBJ=I?Bg!w8Wd-0@tJ+2;HihYnOuoX047 zgK#s~8EG-&wwQiyeoFn01MZ_nO3cVRUyzcV_1KOXMOm+ABpHLw>#MV76lE;T$b1}Z z;lo84nZ}?lepZ+>*CU$Lc1C7C@>%B02gFliYSeXf&~LubNQ35%X)sFeAJd1^)X*GG{o5aYLWuu-{ts_((<#4sH zEv$W&6yYGCu2w{i#MYJA;DnWZC=8zY_M+SBH|(}WMlT$buz8Nk;=<5WMd@qpqY^! zSx&tp$w$n7Uah8&g+p!}OcJ?*iUob1Zn{N{Dkif;{e`J^Wv%;RrBfx{LLGrS)C$+{ z4^jD#Mj5U%aD=Ow!fB97tSe@mrH9q9@z~spA#8FhKP8|V>c~S^1^d;_so@f&X3EDL z$9hD{u_#EXl0|?(gAiVRn3VKXSutg;>R(FTjGr+;lM^hH(_r$`3frhMvyNz;6^iL& zPM#W^Y9*~%scTm|*0+=(p4VY##*^ndUjlod-c{>dx}s`l+g_^c{kT4wxeK*qP zxprzysCS4!!d7mSHV1a9Gd26wLr621oq)VOqJ3@6M9%DIoQGd~tZoie7U?2A$*eSH zs|B#-9;0_yG*=sFb~BfLS+30JS9`D#6hrZYfNSXvSUn~2=G3!m*A@#SCSCUizm6J1RcZ%$wrA$GquviBAO@S29<+}bZ?dDmxt{}2ErkrT!Wl#iZ!AR2tZOzNNKj;! z5khode1pr1rB{_9(37Z!TG0)o$?#9$UciT~w*Dtf#^WXAscbZ|toHH7|Fiai>;Fkx zr~d}~rY%$>$+G%?(UzRQar?h$=I_t6*T!{npKKi>nOFb)TJF;~FprZ3FcGGRpC&wI>(_pnUELf*=|w$YPJ)}R<3$sS&ozw z8o+Of1cU?hfN%>jg&q^rc%&$B*BGb%Kod&kI9fu6k#!oE4t!6N&M)`B$pxnxrllqO zjZ92T#HLw%D|qO+Lv-ZJw`~qCz&U~1oX|ku61zFcHJNW_SVar`M!z%Nzx34?exzmS zERpH3zTq8$`wr%3T0^l!$_lxI>*ReQc8pm~WT$vGha@E2LS$-SE@rKSj#DkT{Unm) z3cuO(2qri?A!L*s_^!Vxcx$PiB&Llki-!_%Uz*^6f>-!24|gDZOV`;tIaC#3@Ixi(A(Bj2+7U(fIS3&^)uvG&4Vstmgm!5ENZJH^M+%j0o*_gK0Ua+BEM zE^NXl_P@xWMMQJD=jZzTp(l>G!)f>hsJNMf)cc)TYJ=eZXiYNbX5 zPOO_!y{cfly2)>(br^d{LrTJ`P^fE~$6yPyM^M_b!(6Klg;$a7+Kj*effUny86pe= z1NomqTl*69DcBb}W)4PV!*Bi$daGw9y@il(!i_Ou6&S9wG79-IjaFmoBjy(#d3TwZ zr4s2Lb1GCYj{*P)o#kOxM52TUmP)8^3n@#FNgj2P8wr$NW&0jQ05AfT6RLrmo7@=K z4!~)oQjE^J!UxYlFq{PXSd?V?<=H^9tLtt3?wa`PFLB9nvBRU)=)nNfltKk zTJugG$vV;&x7H5@f`lD}15@EgJp%bps0?<8CNXdso;MRkWbEC6OJX6OI`~|L@WmK( z7E?(nHy0V>isC?6T@lmanE~N<#f=ecl2_bpSLg9m%+TIIxQoJa1muz3(F9Et>u z(Ps#{KT1zyd#YWz5ybSEBB6`a>~r^8)vwq`J3oRjg`q`9!Y6URO<>g$Vn1Or2~a;o-roo3#|2Ph>6S zb|5W~Wl4<1$pBJ{I)wS|=Lw$Mvxg&(FuZwM%chucR1qD0?E)P=psvadR-TMTqi@X& zI9ppWa$F9jbNiE7EjE|Bf9YD1|2{klH9~N#L?ib~UF#fz*{RpINdyIp+12o;FP?;f zK*kkZjy&Y=Iu^@_2b~|ultg}uO2{cyBtJRTmL|c0mUedT89W_}k5AXfrNX7{km#iB zH4LeWz~o-X!Y`}R<8Z2(U-BANVF>s>=I2~VwCUx^&XKT&Z4%^Ar#y`+9eeg0tz<6< z=NKePA`@0h0Z&+aAP0betME89p87+z=(I6NS{j0+{QU`-n5xjb$w`3(>{fJXv79o4 z)h5T0Bt6&xF`HU)Sn_wo!0wkCZ8xXhG%{Pb$!n6uAwZZzb#kGl`+s|@5tyUMryuD_ zmXk*Gt4XGFC*y2CVGQUbj_tlq+gS9PZ2_IX+N)<)ZOlmWI)_iDU+ai#9#O^X*GGMo zx9DweMrQdc=WoSphO6DO9AGn`nAU>Ad2D2J``K&^FxMaWdvGk^o-#}8HD%awvN=5bF1EgLg5PGRQind$b5{##VbNjC zb4daFU>OybxZ6%dzbp_3!~jooB~jjKYBE8^4ca+7@|oyQGnsvc95NXUNemX>apyU2_ z$!twJRG-wOpnbUb;%nT|W;q>(<=JJ`dNmot*Bw#!CT?1oF@+wXPeQM4`7kvqy}Ld7 zq_3-hh>5B^Jcx`Tcjs*pFDtesL?IajM#TaoOYQJ2+2m-v-p0~o8qHV9`$%aB&!5dpXQnXNW?E);+>@8Y)HS7T627~aXlkOE zWc0nVn240hPN6l?8`ZMof6Hq!mw0fa5@r2HYR42}awjPG$Qn(`f8{6iNlmhQ#vbwI z*?XXX_*0VE^fZ<}Qf*5o$h}W+jNl0}l-W+$D<2t$-DM+}rb>28fgw5<`N-EfD(AAo z;FdIQ6Kq*txZuHn6rd#H4G{^MaB11=Dn-nvA2*k*W@hWvF;ny~wP-PfRK$3bD7sPv zS9rL-*r)DZ$@EdF=B$JSpi+!f5CIG|-Mv7?=bwNfZ^G$yvMdfy4=6I6`2O__# z8Rt)lM7Tt1*-$`F{h$vMoF0ZL0s9_2+81pcV{aWXl&}^~WsiPY^^S2<2SE2$ec;5LCBHPIg?Ptfe$N z7Y4!8cqXu&b?uSB!w)}!(Wyj8GB0;DO@(_kAOVxT{coga7CiX|p4K2-Hjz3NI&MxU z4g`L|HJhWhajJFEenRE8J7r+#l{%70q1X4H@9Q1p3YeMB)~yG0P5MZ8 zRz)^jU(RNFdS^?M9a3%$GioH3LTdB0z>XV@)+lu#*JOet?!{-#AdUc-1W!q zZ-wV?9wG+{1)+m;5f2z^U?66wX~S$vLr7e;_0#mi!6KI7MIf?6Pe~E{sD3^}Up-Z} zzl2zAUJ^7Y9Tyc>x8!R=%c1*c>?qLJ5_Rd0WkQaI zy${i|7kZ|QB(rW>pT0F)=O2A!sBx<>aUcsyrPfq=w?gjssu1&QJ5T7V%h}UYfT!;r zHS~}!fi&R6+B&#ExdQqRA$|yOS2Y+@=-lSQr$i4x@cUj26E6YYO=TbBF*m$jqMd$^ z3Ms|}fn#NQs2DuG)I+e+jAPk!x=MZL6v`D{%NCChYcd9R4jXgmS5N8+Gtz<+E5h1ps-fL4AkKP4uiUTM9Se zP6%szGgF6tOkKW@J}h1Ja!1{32w!cG8MKf9MR189;hMr$#0C3F&dSS=JjlFBa1!}r znX~K7q}Bzk6~^6PDHlg*p8GjdMkxl?r6~q95FKHCr^LW0$3hhG-h?7;S4omhw?R$* zM5Q{6@5i_a`sx|n`_k>AqR6xb>$)7GZ_H&z0)bLh^obf&+@w|D6E#@AzyFCEQmke* zDtj>zJ}MC*s&I(xqC z;wq(l*(G#;i2;j5XTTX&mXl6_4EUd~KP0*k2HSfOmGDI-uE3fgXAl?%EzBV4@3+^h zwCc&m3ge6pTRTfl?i($_sv#a}#3*J?H+ZQQC-VTbcsViuUSItXMKut@h2i8HNG}V~ z#_53+qSV3WH}RkSMb!{yMR*Y}^L)fBX9+U`vv-Yt^&CAkUj(aHtc)KrpedS4SD5yq zv7VfITtJEr8h9<7M5epUh*XRT2Hsd539ru5g`_jxx=Q-#rJ@H6jNMu^DKO5ZD_eLt zHT#ozRgJ{2NC{uH)iF4r`?gO?Mp3{uNCjXM_B-AaTe|x5QnGD?J7}{W7pP>6=GgcTJ+{hl+`xgrTWHL8!8n3-)mBXi|;?(xfEl_!fv*D0LKp+94-aslu6tqi|$Rw{eH&TH?t5@896U?@eNRf{=GMy>pCC_AcODhQU}U#60% z=EYqver6)C=IqRtCUxCL%r0ro%aD3t!?Cz%B?{*TwJ(3oe6Ba%H&oC_smOY zdNNa5QuN6;#Oo&2+#TtO)EnNMO^^$(mF`HF=B{TxB!NjU#4Lcu*9%I45<2689prT3 zg!1X;NtJrXDkdx$*by%;@jC;7p<8!IpqE$l)64wn@=`tVTn<5~X(z(L$fuNqh&o+& zPZ6dla@`J4Z8&O-?5JZL3%t@bl-y{ZOmTRrtDBIN9k z6BWVftWcrd`G|Pdiv-me=Aaf*2E9~>D{6T#Ype7(grsP?>MJkXh?u0$;od8s5980O zxm*~&4}6$7vasW^zIg#xsN2dP`agaWvXp|mhu2#seMOHu8ftDch*u;}w9FSaZtfW5 zGt4t`?Y(I<-dM0jw;?xjqCLML&W0%@EKWW)KYZQi)9Fu(+H}| zVn>@>NQ{#?;7SNn|LJ*iUBPvR{aiUr2E639Os!sA+(+DLLt@6T?tg@|@)seBxHkDA zW)o`_pN_L^MqGosL3$<*g&;jl<9a8h1_00M_YpN?lqaSB9o$SQ&kjBG#k1Bkpm z=@UpQv%)+E9HG^n%}|<^u8}0YaGeBT!9spjD#CG~7?0oDo8c%L0=bg?=b>V)+(RSdrGWB&aTLl^>O+eO6^ zQGEi$*cW9mgN17!1*^$4JrBk>n?S0FFbRG^Gw-wY&YJzR*5D*wqyB*Y)<7WJrMXd4 z_(3+}uHMkB(kSdwObRZ-hrQG)Irg6yrRG+70?}|Ztg2T^Iginl=)fuX8|D|OrTi1a zlchFuyeH7Ar0f`qV2$xI%nqjU1e2Wzc*)3vYRNkk*@Y^EsfiNok0H~(CG#F8>WML3 zCmFPh(9NYFrEHCI2!}j^;eTG#Ax73eAWm~9P+6I}hVPOK=WYmF@{+a8q7x(4$wnEjl#i3vbqE|OX@IEach&R!Rn13NL&mu-fu2CLTxv!86K7I{>OH? zxma|5#NosT>7OuDZR1*h4FS6vwn9i6|8bX_iY0$1zL-5;FpNfZZ*qt(JpqA zSnFORIcD!Mwmp+j3^Dy{Jea+-E0;wXKFeQcT^4Pv;~3A&@w*#*h4VPVHjOm?@9ySs zL&keZ;9;$PM=<|SYWAO$q*~$a-NI=c=N`S!^Wgb5(C8}uCvB9pJFCp)!el57 zlh|yC3;mlAPh#A3@~Vr|M3f?>-&jh%C)d#6}MP^6!qMTCtctoTQ8Id+*C zNBF0E$Vx09$H00e1lhpGC7_+J8 z@eX!t!n*iLa`FeNcf$)V!etXBCITy4Foj8&!ys0%1u@h^cG20j^Fb&W-c30}a4bB= zGbNt^o%D*0y<$)X|HcD&_I-w(h z2y7D+4TO>zVfG9WD5o(+AvTtGokK{_;U`zqmyPO0LQ5bdm((+Y){Jah`6T}hX}PM8 zwLmhY!?;n@yWSpNajCN4Fp`jsg;&f!>{M~>EPQhGcX?wLSBNaf5jB)o;QjnP~; z7#eCH9_Yiv-U|K_*N+YzNZjhxOLp|*g@52pNM_^ zQl+m#frO}1Sw^v+YN^{b7-{?-@)=+PwHO^R3R7s6V8GuKb7#IFRzTFH9EmQJAHmg? zVf{EA9Bn0*S>T2CW1$pLju`X1$O%nB4EN@|Vua)R+n-cl$+Lb9wPy9gaMy$4XwTS?#Qn)ZHqg&d2i^Hs1b^h*LdAPW1oJaNPrlQ8Pa1R2%0KKJh<{ai!I?!fFyw#5@cR|*=1);Djgd5X z8qvUkd-~4KyExWREk4&lRJsQ4Kx)+l${;?eIo6sLQTO} zru(u(O_AXKyv?YG{ECpGwclo9xj>O$B|`^ko;*iJ*+uS9*oWbXxtf6WMQ&0bQb`Fz zKDYjg*AC%MqIldoD@+Z`36|`L1WD&|?{wMKB~VW$J08u>$`Px8_K2e@z5}wIm*Gqt zMoiPS_5ZL*h-5?@W~|3yw)7v@*Cy7zAZwYg?)!(edc#I%Kx|QIXPsr6r{qWU7)ET! zw-OFz$k13(cChDwjKrkNC3viJBu$Rs zsBhmi7I#=tdiP;=MW#k;fYeLwy@yF}+2~hctJJ}_iQ#<7Il>7=%{qw7PY_mzOY#Kn z{An)fzewl%ACZIEs<}UvoB*CowfOXiZ(*15wBbe3p6T*@LhhC2>V{MLOk{)pV?C>w zMAt$8j&NbiQYR^3ZtA*?B69J5>1RF^FSl8?`ZbCflAcR!E&D;?j zidh$v9BO{;V(&Bc6?-3DB=-=@4e8{Yo2aanoxX_tl}jD*4H3R-Cwyx|NLG;a-L}5W zlhwK|QcmH#`o+>=mWwu21ARdMwF20+K#Z3JTzRD-3O~A zJbN!%nDA}=5R;#IvK$2t<--$|@%TSQzZVTp^z~B6`w&;cJJe+>kVf{Jo^Ue@^Ab(7 znH?l%Myq!zxLazFm)AjX0G;Pf`#6TrQ-dULe$*jkEY%U)Ja3{Gqmec1j*?t6GF@W? z8{5#j7QUm^PBaWgzqN<&F7PaT$P7K$x#9EY6`)({6X_UF-jvq`j1ll{ zikH`Irl5~;L_z|t*2DC5oZCD}fm%xSx@O^r6}bZ=RvyIGZ!X!bBhBSDSXyBhL>vf- zeYim%7#wZk8NsL}(cOEj`hSmx`mo)f3}JJ9G$d@U{Du#Pyuz|F$Qut4{>x)fZzBCt zmK{UTKI_{yLj8%uv>3Bt*0~w#YSJtTcTer|L8wc~HlsfjH5I-bV?rm=ZnB>`!!2Yv z5tgxall48_%)}dufE6Or7~YZ=Mt7bheUG6sQ+qS#Dy#tgV|0}f;uOH1h5Ml?`88I-3zolbk7Q74jLL)Og`E`>7O%!W@`IaO zg$d|Yf?}wD$K_zGUVRVQz4sFYR7cV3BiKcQ@W`?GwUW3w0z)62{1YnP)fqoVVi=Cv z)xh9vd}u8g4ZL_bmB4RA>|uM10}S{rbyX)br>~O~i6JD?yjLe;&gN;BYBd5z{=J@dAI>*}WPFF5@ z7W|#=vwJ7G?55qG>*Y_9)9Lj3DjC-OzDj!m|EK$$6P>=HJ|{d*H;nfMr=_Iz&2kZ| zVVc>#zIL;3|E!Rj*2kAq=kt1}DKEh{A$I{qA9o?5nDSJ2FM zr36{wg3C2PhxBI$IX9PUY|!O&+I{w*t1sVu2{qjKLROHyCpw);KIc%M1A<<*N~5gl zNT+jH(B%ud0t48VL56*Uc5|qUk71_EObd=>ThlepNo!`f?*=Xin?iBwsExu@GJI6_vw2`PM<)wYm(ev{$vBdQ8<6J zoV80;^l>J+T*FK!^$0F@c%5*kP!iX{nzf`5dA(5Vc{iJ0YS9P1>c)*e-ZWDsjps?( z&^l4&{bid_{QDav5~X? zDD0@Nq(F*mC^|8so{{QIajIo~%#pAbn4<{Ox7tQib4rb1*F<@EUtDB8JTG_J<@(!C zXe%{Ib9SB7&?%jPWmr(S^DtaJDq?PeaI*rk5a^_ zFh0>WmYT&5xkCQSm2w|x5~=phnq-PvW3%OZBgU=2@I9Ck1dL?7CnK%T6q@wLkF}_e ziOQ77$Dc3C^|`Y7C(nOl1 z6dE^qrF`77$@CM3UZ*z=y~EE9H`mJtA?@7zEZ4*oR}xW{JU))YK&%XTdTLgmw6rv5 zQkwdn!zZ29dQ7w=-%ekD>!~``9esE%E_rrNW*ldKPJ_{e9;Fhydo;a!He;2YwO-dG zySl8QZ&sD*oOR(JL8l*<6|x&`xF)61zHNe9)JIN67XG(BcG5Lz@BhF5ZMUmWmTfo9 zQ9K6guY6cTw%6zN<#rD>rZr~s!7!>S2u$#d^CihTmhCc(I(hOu?38ZI;j}=)8ZI;- z%koFf>m!i$a}hs5mi2KF_0)$~v$l_uA9fg}Woa3|`q}PK+iO>v(9e3leTFipczu(6 zxx7fZzM+*v?Fa%+`v6XYg5gf8ndD-a8tA)lct%?5&)+Z0^%PB@gtD8?o$GWCbh^@9 zu9Uu93qG7=4yle_lxwFOsx=7%ohd1keCmc=SBhyCFeglOrg$f&c9vO`r9_ zR4hlan(JRcQMGT@*lFg%D)nZ_y3O%@xJdrU5x>2xruIAuS!F#Dc{m)I|GaC`3)B*x zg!L?V_m}cOxDg8(CGGZpT!_sSfjU>2$))y<(p}; z`xo*9y9=fu3}c$JyRvDHduG@DWdXSqaCP^WoSMB>&YRf%1|Pd}3N*Hmxsb8J$FI$x zw8f1KO&6jb25y(R&zRLU-{YhsZG}E92({BT7QVu^Erq4 zoDNI!q6vmcMq2swGG!7?>l^BE4z-)UzJy51BK6LyefDW`m5gj`#r4b=iHT*7DCf-8 znY=9aP?dG0Qfr-@)_g8^lBnozaqKSJmNUot;Olq=c@SX z#TOvieYOopq@3_!rcROs)zr*o8&-H8&-|UXBwY6Hd{S*Jc zX&}CyJ(H~sSo}HbrJ0^JtmI$vw-9LtD1KtH@EHH)`;H4IB>-Fe<5$lXto>#KT9Qq> zH&3=!#W(0aR2;e^e&)|`mt@m4YrEbl&aYVO($q)ag#zLS-=7UFu1@RU%z3IV5~3am=#&t%uh^yboyTIl&>m_DrFy!rVU=hOsVMJU%^sGL)aL{wxpR-L?H(^}Duo7FNhaj~= z9#GbfcV8lnPYxj?RHB%%Zd~ptJcav!*#AKtdVZ{#d}cKJob2Ch9xO~w?QLdjNkxQ2 z>l{fxA;zNGoj+YIS$R-wC5zlp-$Pb}dL2P4X~UM}PSw#?j4+6WOX@9W`IR_*@YYpw zC7m}cBO~3o%?ixG z7PR!RIR37~c8*UYhFK%2MdF6vBCrMb(5W`O3lcSp1wisBv_FEMZ9gSV7vQFO>S;{0 zPg$PVGCtk=pUPg4oiX*br!tt^$RgpHN6T%w>X$Wh(DuW13v5&}DCA1j33(Pc0g*bd zJb~@W)0Rc)Q%hCsSyRB{f#iIktlsgF?1P7g@JRf0*Aq%sgVlfzs;EN5yBDw9c5*Y^#?5fkLXKDE#?VH% zJb5ED$#r+cZThPG6Kuw2QBJkkr14G}q?b0RA8g0Y!&4=M7^mR4PQ%q{%f~%`oI~HD z-e-JFK8t(B=rEGc8OeOAM%6(ywJqPUt5=qFl3n!zhiJul{zAeD+f+rkHVwS8j0V&z z%F(8NkA=CB8~?#F_X#@eAEkd8Cot-L%yv&Ecx?Z!3d&YJ9f&AZ`kL7$^%E{1UkPD( zc2#8aq{@I!GWvE-)j!jNr_!0{Ox1()@N_OEa3Xo%|D)aBh8bkuW>+h>$YR95oa96z zp@page@Tl@IV`MFOY;6Qg^2&uUH`(npe{bNdV$nCzb84Xa$@obasQOnH+dyM@e+rZ zk|DSZsQ;~gAZ{hAR$QwN_i@@}s*gn@@edtX`X;GrG}MAoPsxtisV&1#$On5ciBDII76B?MPZd}3mMeu(;Zv^dA-}v%l z*^oHJ0|>Lwb&DnXZnqU_keJJ`e`^;u>tG;d69d>{I_|d?eu--}_zeD(my*o(Sh{4z z8>f!4;nKuU8A56#;VpP2So5nqkdADzV) zHe`SOZ23X(F%Gxd`eIq2Q}8yz9*WhPMaikdqzCtkwFomSZe@(H1n;p{s*e%v2)DJh zD5+7nlLQ!JL;^i+J>55ycu#^*lDNYQ!uqWmkGzi;zAN z3L&8a)?%eqPKwg3msyKHXv9OWD(i7m$-Whh)W5Pwv#iB(i!H4}5=~_-ac5)>m)A?c zG>c`8k|DaFUQvmTMGX0LG9oyyu@<4jyAFOQ0y?e55@Ob1bfOlkwKxyzeZMLps?u5v zHcDroSI+~LrtWPNa^YaT%-Jl?Z6sq!-CM72uomyZ|LRwB>*?;Y_U=a2kEqvr)z?~_ zL)`_4lIm4IYq7WypRJlxPp*e-Ji8HYBvnk2X={=A=tRG;7Z0=+i|FirHLG4cK5QIF zRFC%~$w#Xb)Rp>iKfiPY^+$e3`uQK1tO@lo3!D1+AIp-3k675;&;Mw)EVQw(rJuh( zM;89TLIY=6i+_s64_RzvQ96eO{2t&50O=kU@H>F50MbD$;5fjO0MbP);26M90Hl*x zzy|z@0_+5k z?qdP1051SY2eN=)1MC8jE@T030PF^kPGkYE1N;m?x{(F^3gATm=|~oE7~mxU=}H!G z2;k=c(wQvamjKNG(w!{eAiy2~=};DM0N`Z+=~5QZ0HaKfGEJ*0F&#bUmCFL20XPb9JIMzY@HD`C028G6 zt2Fu)!219Yu#B^SCV&qBa_Wh9lr4S&a10>39tvXto&-1!kW~*^ivU{zeg|OIs|*Wx z0^s)mx7AbhTDE8e_z>Wg+IsT+ET{qK4?z2Yh-;Lswg9yO?F0Hn9NG-@5ztKt z=wqOlfnYR|9V0-01lj|1Fb@3~=mbzR5WJYO)#E^)0R0?@+;)K;1NtwZmw*n(p+|xK z1oR>hOwh7bJKLa9VUZ9OYe+JqO^hO-o0CW;)7tpWc(0ZWHfL;JUPRR{D1&<>!t;?REpodSviL3SfsJpyzZ=%+wO;?ToD{|)p!&^vMHM?il85_W88 zX=KN>Kwknq3-oRrS_AY~pzT1vjYAIswF7MfqM)zrxEkmT&@(_sHum2`XCNH2-FGm6QE;p=mDUwfSv?`e@u3~ALu;LR-oU-p_M>g zKu-X{7cN_^0QwrJ5$MA>v>Ye~)ByB{I24;RM=fU_-2&7WhrR|{0kj$Dqd3$Bv=V3& z(8qD;Jkb3>5uiWDp|5}*0Qxb|i8#~=^dQjVK%c~+4xk?bJqGk&ap)XS80b-;KgFT5 zK&yc2frw<53pxX|8fYWXpW{$F&_h5QfKJAtzXGiRS`YMD9QqPyEzmlk&*RWvfPMs2 z2SjMDH2>c~4+H%N(5X0d8t4(AM}SVpp;JKr0rW7?f5)LOfa-vL1O!W#wDmdAI-s>c z1kDTd8PIy5H9&ujLnnbY06hfM9*6!6v=L}E(3v>&DNsGoDxkA*=ube80)>Ij#i9QK zdJO1?K-9*TBYpz(IM9PYopI;{(2s#00QxEp{ShbvbU)DfIP@{lCZLr-U2*6mpv^!l zfWD4HZ9rRqmIKA&&>w&rfMUoy%i{vihd_-$Ujwb^mVtnt0O|r-8Haucv=!()(EV}f z_?$$w?j}np`>cRl2XBW6WheQ);ihh(?9VK0ys29#`;>+Ho4SRvKe6!WP2ED-f3fh` zO+7-{CoDeBBFBm!>IA@#0eXb8KLSJmdW5o%0X6~j2xT7uYzF8N%Gv<70Q3lDe*kCz z=n=|31ZV{45z2lK@B~1QQ1&~3tpGhj*>Qj;0eXb8V*oz^=n=|30B8c}5z5{NcnY9L zD0>g!X@DM~>?pu906jw4e*$a+=n=|(3$PuaM<{z2;8}nkq3kyR&jIuZW$yqy56~l& z9Rc_$K#x%NHb4}hM<{y>Ub3H3WE^m=YWBHMXdGyd+c z+C$lMC0DTfrhi=f_gnw#WwoB_&`RE;t^NNu+WXf>{QuGxYBgN!qWKN_-?}&Ix$z!U z{q`J4AQu_F^O_)3SWHFJ53bW$NkvC1#G;l;r2a-@EVjFkHtVc;aN*q?Q&pdk=G<1K zU7t>g5c?iV%zuVVjL~PZ)8AE#S5^xDA7P)p8?s64Iv^Y?kV*-!D4EZ}x|mT)^-5wc zQ;+|uXk#-F4JFxcNvn>ONiQ-E=fl0O*U=ayEL8If}#90dCg;DRT2#98G)ys^QpyD zU5ml;JQiB)N_8;j>oHS=)<0MWcLkT)W)`stMHg4LRO)q@OAgx#367>=c#|Sz3SGGk z8(;)WiTo^`tP3R3b%1AEUG%|OQo}%Mt6qrdGF8O^X=nTlCqf`c?%wRKM8!Dq*}uH)Y#Mx`;E@KI>&YyV5MMGK)RJ zo6w{t6e1o|Ox8{CU+et&0d*e%3aMF!0|B`6sIY5eZ05)kr|y_V{^q5g9RX4nVBVOM zYR72AEe%Z`1Uu!j&PV0JR~7!K%kZ96^C5Zhe16w7429&Sdk71+nlSR>s~q2~5@r|t z7R%gt8M;XJ8FEs(PCGH-uJb3WROmROxgXmvCxk>^%=ae<{v9X)g_bgbR?$a(u*qIF zX)Ny07~8!t?4)dQbFy{a$&B0XZoIFMhj0 z{P_q1?8uueL#H`r`##sdBGifXxcgtS8Z8#(2GwDk$(?!|b8>uLk{a2;5Z6Ej(_UMFjhjPJZ{=W}8hH%p-=2a0v|am22^G+2#=4cv(mI>1J1D zN@Zo5STuFPB+BM_B z`@AJGJ1$*2ML%MlY)&DY%gO2=c`eqkWXT(xkw?!<#SqSEQzCgSo{Wv~(U;;?k+UUK zZL}JdIs(PiLM|b|d_4T^L^b4+C6$OPFS9^$izFrL1DI_}89Co)G?7|vKX9*VpMFv( zM6a-1Ay=&7tyv`oV+^mYg5&gC1~q6eM=8f8`&#OJX?1<63XG;+6N>03+!Tjrgxm$~ zcT#b}pGWy59SPl$Hc#FC&e6BjZG}?RA}wGg$gne(Rz_NKkreg4pncuWi66blkvS7u z8@DP;d}*B;R1KRUIYkpQxYuctMOBUk<03La+*~KAN%5s^co{#tXkS=Y?e^POH*6+F zWcsFew~&n$>YV0*0q2Z38}RV;VF>P@+P&QtwwpVB-Mbt9ZaeCK%69#V8R_6Omin)4 zx+_Px)qDGoKA)tDnL8Q($hy&fBS=Z93D~0_-c-&zgu4o2<$I;x=XX=%WvO@-WXWMT z@q@u~b0-r^t_o)rGVj2U_s~bDM zIiJ`!=kwD4{`t`4zdE13=hZF3h)xjyL@t}z<8JlfvXu<3pC@#wtJdh!X8$kM5-2(x zu&Y!LziHYYm0L)O#;h7~vXOU^P@3kG%&<7g2{u1fvtP`C!~HOJ$TWa>JRCt=Xllhw z;J|BFDY2#@z7oc#i@izE8PFBwc_qQD)}4Km`u99FBDEx?yIK0hJ$WUPGTCcCJGZN% zJZq;r;Q>8@sU{CojWktgq0@O+IaPh1d^|RmY5NHidJ)=g7Z`CMJiqRjly%{&|WQf=2}5Z zJLQ{qsWZSFN@`Ok8S$tr?yN7x|II75giIZ>NZrQi1d_9C_n?#FjE_dM?30WkXFuMt zYLj7-Z4EOE^U+$?u$ka~(xWo%GB6>Hkms^A*;m<06hd({puI27mMkRbHF2~aGl`YK&;dEjk=ObG_`c~Wc#J_}iSrL2_mw${kuJk5ccW=S;hnaqNOqH_3U zl$WT@%XE__>G=3c002 zBphs;x;r2uzkXJK9gYC)VbzFDWm~|+NfAvyCl_~DySRbYq?csc5w)j2DN?CD(+J_ zpg(ZlqfYU|KMB3KQ^&?KeY*W! zdIq%oWIgT+e%93Vpi_K}bi@R|H2i@E{~LgnK}ghhuW_1nHqXEJVfG5@%7<84dUt zj4{x`cB0q6zw@cE*|vmpu{Q;l^Q@+SG+07^9 z$VkQ)36gnyajJbw#?bj3X!uE@UBm>_~-7LZ847)r_V~C)jYY*RNvi|L1QH1PHnsU=s0CC&6(l6JD_~u~T}_#i^bWW0<;^3NLbc6`hi_T9GVOLc$5^ zp3b7QS#EZz?JPDJn4u}z26chDa^F#i$OzjZtIn>cqV>S%NDze|HB^m%*s>v}YS&SH zYgXwN%msUq-fu$*cH&)#Q@<&`7a$t^X$ z+-R_n$qecW%rxD`%(HbLrW=W8@0ykV?hJ@KXDDbmD+?J9%PO?r`Yfz_M8e1_lI@(KDNF<9g~r$}nl#}4;Z%4k1i5f3vkm9j z&$Tx=*O_JvJ;TuwyFv?v81W`9-57ZeZNU~)CztJKZn!!27sLjMx#0)-uy9~>i5g{* zAD1gbSZK$^bh)~gx#JXqEFnYH1VR#7_Z>f>+{^$B(+H@^K24|~@tI5yxh|Owc=*JM zi(+{AqH3>jU5@KAvd&5}^UYl%RUp{yLPQ-J*GB!YqBEo<`LiB$oqS}J(2g0NJ6&qh zaSRw_<0s2F%`}DXHOimGKFOiy(*C>qkV>|^Exu)SA)DpP9Eqq{0D~8yZs%?Dly5uN z@*)GIfD7+cq8(bCj(()7J$T%uJn0uDo=f zVo%{r5k3u%hbvx;UId}_(!88bn$(FiP$=tk1v(L9R0|LXICD-eo^YV zQ^VrDsjtnN_U-NNG-rAacW+XhNBE2}@XS<<5ytH?$(^+-r!J;JUX1+TLMbRr3Ik&K zyd(y(vmI*wX^Yaq&&Y#?CR6qAP;*YlpO!J~Jix#XHTyJom@Uqi&KKnwu|HE?-=XH6 zX7(1nahUAbw?o}?n!AE^2(2IpazlsE^P{L->}OU_=m3J%uk5sC%aQ{!`q?Crmjv4i zW8_(@Tr6zswJS;YWdJ1(CI;(+lwI>Q83Vd_dGG7gC&RLF7d<&YUAZ>WgNM_DdBnzD zU64e_zpp3c)tJzwdXow(-&bQ!g|<&eDI$2;2}G@D5VK+Ya6Cb%*Az7z{?C(oWJ&2F z*BScpAqMnS6)0;H@TWVx(R(cE5am9%9iMa|-cvH)D?f=C{kdm+ew7C~1FR(iggVEi z;&n}yjTrL;YG$y$lv2T^!D(vRoWUvu;X_RytsJ?|JFJ$;j`A>E5A%3&&L&!W&V)m! z*ozN2QGCdhagHC1=OD+kqCj%h^ux3vg`P*|u8glY@mye7ka8zhIUZ(Ec&#wCTtYqb zWZc_stMwQ7#&3^HKUo6v7#`KwkP1FyC#OJco&BV>YFarA|$}L&RLdCFTe-O*<{7^j3j#+aF>Xavk zzQg!8N?u`Jea@oB?XZivkBF;gG<{xVEK3CQT~eI!QHCnagIYYk&k)fcC#btSd8`Cb z_o4usrLF6xqtM1uEsK)k)L4?{Q@&ys%H+*5`krC9piS+_%4m)~oHAVMUDX9%cNn*y zVcW%Q+c}jXU<&&nGaWiPxA=CYj;z|6Wwyh#M`Yu&`XVd}s~!W0^Z-}v)2kx0Yv5C< zL3}t75}FgU@`N1~N$bWrd3sgU`;^nRQKS7FFtG)p6n0yoDaVTx6ud zaytx1;uFf&VY{2zv4aUQ>8x#@k)-YyNS$B0o6+-r+X;SmEKU5_T5#A()aj+$4RQlk z5%5p!f6qTc`a$^w>G@2yep{cm`Np;cWk*YWM%yd(#Ehh1=4zBrhdFZ=gf=3uUv-SJ zs_s>l^nWq;_Hj{`Y5%`-o}->xnfA1+31WbQ5-O&VGQbWvR*MSgqJk3WST>>v4Tw)j zT79vkS~P3B(R6LCBwH%&-Y=SNEtZx`t={cTt?c%tO|zRyclQg(0Qdaf$2DNqw!8g) zultYR=5k$gJ)YP3cszWL&#|Eb?r;&PZSJMCcbM?(`uLAPUr6iC^3-MZsU{K@5AejP zWz`?u4Pj7dk6_cE+p>%vG~z&z>do*l24?2nbPVTo-&i1NnVsi)9CN z1oo`i#)%zxK-5p#7XdXFZ_1!!{4IWPyk1g(<%`_36T3>(vi2%ge}8aEMvcud&zjlj zmSQ}>yNLn8;d*vqT#PxQ3)0QAo#u`7*|B1RWL?W|0)EUugO)aiWPjW6okUs7?8fm0 z(AH zu_iovDlUxpJvy@h4KbFH=ET0b7jTgn|H1E0kmb*W_-f5eVg+8qU|~G^W)C*v4DDL1 z6SGue7y7=h{?92gPVQJt>UcR+p6-*Z=1l5y7ehCSu)V}zA~u-*u`^GO4Mda06~m>- zeYk*~l5Bn?+T9#6sO!m|#QpldY!P)Z0uOa~0SBjR?_%T#*5_F=?_lehB9iQVsJgPd z*6&M7N5wJYgnw>o6o{(P8qw^>d=&!EFUv1jlrDb+ib8usx&y@48R{s0ZQdKgH9qT<>0YgiiW`t*fU~ z6R~11P#-DXk50=w)a{hA3v~r9iBz+1GO-?!@Dy(~sZ~b3op}S@?JV{Ur z!GY$7$-srVtKL+6v|U!K>KQVT4)e%CHj*9mMiOh_W^mJ=hcGY+Ex0C@YEm1t_W(v) zxK+9I2DkQJfL2W{@2b#uGwYp+u_$}o=4TOD@>m@QW>G^+m|IeKr_Qahuh91%p@w3_ zzvWts-|Nb~u$?B-G-^M~F1@%P+%p7eKubh@Guk*+ek!RsQK(i%GmSjcYPKMrqO(Ba z1m)=xkNLS8(K*ZPsxd#;iD!g9I!;pl4G)|MFHVH^60`1{F%ezQk>!uSZy>ppo&C&S zNM~z;PP5`+bB(ZSM#2zsTwgB{6}d~s3nh}My~w~TngoeluiG)?Y$DqyB2mXwmDaW# z`Zu!5lnQ+b|6tA^#Li)%p1=N#?3{yGX&=m${SND2@~HQ1jy-0iei;Mo$2LdxSNTwE zi1CG-04Q=Zv-R~S%gjU8k9)H>$Rqo0eyL84?8-~ZHIL}?Q11Oyd6>(^hHLRFL*9!) zBY47{je3KT6JMQmWCNxJ_^5;rIe6f|&`z2~aE%TAZsPZY2>cfRe~PJV!P-uSyakNv zQtJu7v2KtRQ{Esniy!KnmrD}8yDO2=1sZ0ZdCj^mu~b*{k-O!Gd>Eqyo-(;}kIhZP zNyN;@@E6FD%{F%))<}G}&4NO*jy=s)5dpzGSwDC1Gdv(8bX~To~Sg{>OqAyMkbf3jEm*! zCZRA{h^1NQJ%cxj<}xtln#R2dc#1YiwqX9{52y0M)H7#Q33W4yyR z3S$raNQ@klldsZ9YuSOztTa2gTWPZGMf#PpCRnCN2bwXoh^z`#G}elfCI*`9`d?)r zxL3OpsN4c(S94xX)+5CKVg^^_9jXw&S3!2g!&G)Y3TQqVJh69l%NS+yM)x~YxIIj?I0;pgx`Be&&3SwP`hz~Gs;X>ew}u0)QKL%le)U+;pwSCpxkJo zOREua53ny7(x+1pH_)|+2a-@Le6twNR@aExLR=$Px~U5*mL&#^maH{y*_m(VKT(Ep#yA6%1nzQn@GjP z<<%tWO;5M`cnP#n4|!+>5CGBLPBo)b4;E8uV~Y8cNw62g)E87E`inX-uUj9Ya$UJg zpc?i~r)ekXRxNar&h8iZJGuMq-oK_Lva8cxqCZ&!oTQAr_SFql7}n`N^e*c+UV}MPq7MZ!b%kJdSr&0ia`VJ*-V8Y_M2^hHC&U-I|w{7T+wRpHn`HB}ha z^SxzHnou1h(3bE1#&$%Le|Xpy`v6r)%+_v^5)!pieo=*^1te%oQL`7P0XE4U(*BhCHJSVuzbtM%bEPa=l5TjWS< zWY4~qJ|*GP1hGrFwwG{F*D#mM>v}|v%KyG`bS4KbyHu{c-@5A3b#lnQ4#bU9U={_v z0mLr^qkPNM(>B=2I!qa|=x_S$^u6_#N^B>AETD;6gusi~aBtE%en#M|p8sd4==Kj( zA{tY4dr3ked)PO8W@~fwROfh*z)gbjO=Z-RE;Lq+LrAln4HgNo_mMNB}cYAioAX4pxkI<>$D)AhbOfP!N^2giIdIq#D}687Mw-8P|<$e57FJT#k)>$GK#pk*+FoTp4r3m@AQ)v zfkL?#vv8}pZapm>;Cg)OrHXKX;Pwk#`=8groOB<=|CI!FsG033HF7mR6b}A~NEGho z(E=VJb`w8goG%$>B!D*k0ayZjB-KlqsVnlDr}rd9NcG<$kREcEwAGoq@g^oS6|W^e z$dy?5L{3~8W!WhBo92DXOu;NU-ZDu}O;}iv8>x=iP$<*!TT?4JlH(Ll17ALj7-fKH ziuGcGNp_hNDPFw4s}?T-b|KRT|JXqwCY{LA`o>9Pi(<@!WDP(9SpQ@O#R)fu(sCr4 zt4PeDsubCa)PrVb!M&e$kS(hqS1hsQ zJ9ZXk1C?-E?%X5%RWryZyGTr8Zccm*`Pbrt9VX^+%hd7bKKRuB4GjzjLx_i$$}5PX zfv-ASj4v1)eSU01PKiOt#WIR)>Xx@H%oZOzUWHf>B}{_TR4#f4fw3BG^V2@D<~?s+ z+5KXk-o;I)`jqn7dk&(W=w;dBHvuwr;5(m|;GqZtGeK;`54O9!l0ug%Odoy%ld#g3 z@I(QwxFOyZX4Si$Dyl6JC;W|R0@eWlH^M@gk(omT)0Zy2g`#4;k#heDWEq~68$46D z1hY&Ra*vE}?)h^ccOp?2y&wAZO~2tLR3f^=Xpf!~MLbuXny51`RnI^E9z0dU+@SW; zLG2?*WbU#m3m`tz5Ds>$Lgnew5SMCotgzJUA4d_CP)d!g(hu5VO@p`Yeu4xlk&a8F zB}2~5`i_59fU7-(eDQrx1iugHJuwBnpLeZC1FGPq-Mk;r)+A5LmdCibDtIwK`b3LK zJXpv}S4(McBPoT%WUQ{lnhKjW`maad?o>;4R7Y=@`KNVqyHjR7H0??7&Eqb@71Gnw z{^@N$7K{n;nks>|g5*+9`yMrLn1&y)ZOb+tvR5yP!kjawg*9pT_j}`Pr_M^Q<0($KXQ7fGth7TS070Q9-tHhW8qfBmG;j&4HqxqO+WY^ z*X2035QdJoN6H0G4!!csY zZrdU{G&Z4iPQ(B`zJry*{~Z%EQz?-Gy#*#S&wi$$-^vt3thgK|x{a{C-p+CPoNheH zn1ja#pDc#)An1x)2_%LTE6N)ZUkF$Et)=C=*B<)Ha_1IrFdeV8=KX`2 zhzqf?3~jUCDofQrd>+Z6FwXt!>!e|^oJPdzp)B>R)~m90#@`>h(@7F9df0<>0GXpP z=>*q)2@w4+8@^b7Tt6piO9P*PxDm4&CBu?g5Aui%SJ%p) zdNU>6TqE1b8D>a^NkZM6+npFauuq?3`xx85ung+`7}S1i+Ygz-9y~Fz0br3YVZkwb@-eU*3{BgL zO(0YM=lTn37(h-*?ZxGXFu7S-MX=HAN1psGg4}-8M{o^)K-m7wCQq|=Uk>gza`ZP! zzra!1-DlI}1Phadr-3 zL@bkhB$P=-%EPTf#r75oyOv8kVs$oP7h)7b%_d#mM5HMyvk=(dS+*`(Z*!OIagl2HTLn7AO?v?U*3%=bl0FL-W{A$KwCcYK2<%sMpVw{M z=IS@rPy6OGe@#z#cKuoXXPZN8TmsY4ul>{KyldN*uIm^=L$<;2B$!hmyhKNg)BhXm zAI(qaIDDz~uaOh~{v9WfU$GA_mIS(jS{df1*ZeYg-8V}(T+ZzKt}~Do1biY{!nKL` zanoryZ9K17y|Ich6c;PqLhof)`XPeLQmj%T@p_TKsc9Wj%YLI_2e`{dy-6aBgSOJ1 z?>K$wJ3`&9Ul_74z02Dwd%MiDw%C98I)sm$n((UBjBma}x!*K<=vAZ!ys@{xS_Q4V zR8X=0gJ@r_vqCL00n)3cqooF)!=T#nPd*Y*3nstlV~2HGrNs9K&}sD@>3Vw4?N@m8 z)_-#Q1h?SnARC}wbHDdXW88XH4NL&wMXOQ?G5=PzVk^G*$7C>J(`cg&G9&FJ=Z-W9 zq2hZIaU4w(G``HrzXS|Qlmbur#kZeA$o0iPiXHMhp7VcLhahsnUA&8Doe4f`7tgxY zfw2H%x7D7PO%T)qiol~xtfKGyCvEx~#i^olzhVoQ0O~kVvH|H!R(Gaj$*|y(4d3op z5DmaTxXG3#eI_{d^~{X&iLzL8N@R_rtk+x2?)M4n!nNWN?)Cug!28Rc8F_@Ckyet7hGn3e^`=hWaxw7b;?o6hxP z=rrSHT}ss#%1-IWt*3OMwDaaa*_hho&7+A#?@$6G%_6q|-i)4im7jHRSy=EYiB=cx zAHT6;dx{IxYHmRP6o^X{!8!W#GCqN|lU?8xpaty&ic|F$IEJUH+&KngHl1#L=sfi^ z<(~&@pI^P9JM}Uqjf0Btz86%=MV1(XD;%jQ$HjS_+C`j5WS7`pmQ2&b;(gsFW~B7c z6_DG;i)(I;vs(aT_IRj4#RuDfi;hXRte{IfFcF&88M!-5092AEe5~t4MTA~=;rQ`) zLDLG>WgfOQ0cVtKgoqblH7`F7D!9O$$f!1dolTybO+_OkTya}}M;0dJeGixm49a{r z$u5z7V(sO+Yh{gECQgogvjqbZu}$%B5Ya}aqJZn@EDf-96vd~K1ySIBb|EBp*+&yq zberrT2cJ_DI;}JkSUFt=g`#}17CU)$;r$TU%`xv2;NFPEM+6v5ZHP!NmDNT)@zv!Q zMp3WygE*}D@0(m)jraM@yNm*o+_r3Q#jqt_%Lxq&1psg@Mx>SmL^+rTK0vg@Cfu&>$5I;_r~~L#g%3x7 zST~C=<_d85DxyQJ3Yd|ksn}>%N}-Gxl7|PZn}!C|D(O@GPMUnR5tjau)f@HX!={yp zB3*VJAE55Ms8$C|QVhU@6IH*v<{$}@c{ zONeWb!0uRm&nf;Ej5lJ-3U}9ww6SVJN+z=JF>v5zOY_G`CW9k@_<=9vvJe3y9$R2$ z65>GuVoB4-w=Wlxv-wdVCz8m~tx36ObH9|DB>xzTniQ99~*c*C_7VV&ca32D~oUZG6lwtdkOa3+|GXx)okm za@Ba9e_UTzDp`}SWuyt}J~M8zc^>k}EHkk<$tP;u+qgxRnpj*}-j5lw)}-ffy(Gh` z{5ZI=XJ@6qqkp(LFlqDc1UQg;7=V~~!R+Mq@tH8)Z>PYBua;luEZG@vE~19+SE`PldeG0_Qa?4AclQijz>8<`A3=| z5vJVj>bA~Eb(7%hZl&c3Sz#81%Sq?MH3-?9P;EUkA$*27?(D~~1>NP3)S>ZUMzQkD zXMdz)tD36ku@}*Ebe?}iq;@y}B_vjU_p$Dz6Bbu6tJcdqoRi>j#8-et`?4#VYO=KQu8B{oT(o!7|J;sKvE@ z;fG-QBBcAKZps~H*=i##vnTrf19J3N96ipWF`7NUXvrJ76Y%Fvodkxf@qQADIy2O* zohq(VP3%-tWR|>1BIX#%6Qw=b#`*O_3>L4N+n!GkbD8Z7aju&pN+qz_q=dOKN#JSD zs2`J28a(9#WK-7twwa2D7*AkVrS3p}MD=XPcB{xha{40t{kb^4R{vQ5;iK_egR}w{ z$47-Z^fKaD59?e~nK{r~7t}EHa*du(3hP+5B({o_ZB`8$4G6^=9mNJ|FN&k};@V$$ z08IC3`oH)onh7|LzO*-%zC=2X1Nf~qX)z`4cqCTbr8)&5zZ5gL9ZN^kQ?kUq8hSAm zi&PCy`n~m}-o3GYgqb4}`a1Ux2{iR%{dBCq6ACPPFnG)|mM8(qZwOB^e`XPXjVs=@ zx|~xaAYyC~$$0WFIDXoCa_=6BcDi(r2WA^$)aWWp3BLfoQ=c@Of96hh&FzvSjM^1s zz7#vS9V>y^NF*C=WLQA|z&CIdMC2Y2HEvT@#Jos`=;47PnK^A)dx&5PA{=C1w$6v4 zzGKI|ey?dGTE-EzvY=LtY2Wqsw5oBYa@4dbp`*CMbhl*XlQX<`%_b(m>w@Zz>((tZ?Rm1%P5zQ+K8Hml7D)Ihz~ z9I;>+i)ox4>UO;b1gBfg?^5v>k5PT){;k_}@kSi(`i8@%&0PC@UFN(TP%>BV*M&!5 z9Uc&(asmzdK1+!%P0wRpU(Jf@sK}Sr)^Idlz2Ox#sY^NAfK{pAiw8^)86j;du`O|X zB>`}i_Wxzmi&p{k2=5pJN|xY3XPtRAS!H&=EV!(^Ks9qtu1Gy=k4)`>Ti=4~P;k~G zyYm)IO(>GKeaa>PuR)T88I<#o!y~gl6?U&nm{L4T24UG8Vg# zdy~0mY?ugagh9BUBs$%KeqAfcm3<%R5g-lC@9h;fJU8j;9UB!VRgZTZZ=DvDEnqp= zH4)i@n-KB4>CO8{EyX63KO!h4zpG(>Sm(5Fvgw&;>BBxXr_27ZO=2uvzz&=L1C#=t zT;B?VhFZ`Kx=r2-;U`(@?QDovKpJ8Tu$CmsE&%iPM{HP4nhc^~KZkjv)l_UcB+=bh zIGRbgWQOz6%+pYE)OsZuqhHX2`E5)_;Blk7>pwH^$<_TfOEm$p$rD(JNEcb8BPC3= zd6tFQ7)AjlGJ&YM)#Ka(Cu6NERnG=SetSSpQk)`Gndg6Rsud2lCmV_Od{Ht*HPBib@H{0}& z=oe=KOGfFwX}Ko+gJjTE`OGK?&Zg@<`T~&n0#zgFiw>Fa9cZK!_mpxm6mG($8F(vk zuKCMcHN4YNk127Sn32|`*Ucd0U>u-@S5cu5u`t}Oy1+&a7f5nnM`nVd;c6HK`nqE# zd6RHUl~1r&GCTp$M0x0`CkU0WFfw<>DI3PNZow%VW0I80RQA}`=d6!izLThA#_Dl%187@@b{=Woyu=xDBB;i>EU3Tcc@a* zbAM1h+a$hY^wl9?pGF3f?@kRPzaYJ6IU`Q~p0x?Gdm{Ryjzo?uF>e4OC3Bj$f!UZE zq2?Tw4@>1>##)X{C90S0q!WBNhZf__0e3UjKgwJOO4uxYBVuoo8o{y+qT18ItPO(6 zGaHpuWU#dbNpu+d<2L>2`r{SME97`t9knR;X*4$05~S4fP#N&{pV~AcuD6W2Ev9(nTWs%N8!J~~tp0-!n2qHvk85SsNmR>jv zd`_u%MKVH#vV}|niejzOK~XdB?H*< z?6fpivRtY>p&}2%e09+|a?}xzcNM4~6Ao(3t3D@Pw+{yZv*3X5I%0V_bAipmU-+}A>6Q6ZGr%(7!X7`+YoyCQN-av~idnxwLm#^fam4uPOR z!d@K&etAWw>gR4ot&3VD5gI{CEarms{yFQz(#@iTq|6lbft1}Q*OiDi=F~qt#vJc4 zx%MYnO?NCTcbMA)@~Tyh_Vk`g&e|CFbcG|Bz| zM{`&+x8N#~pF_^beu0yRK{2seeynJc8M{Od=@DmSKQ~B;0x1fQxxsB`4!^60^*O*& z`ZHUnwXVt{4Ku$Wae4s!azyeQ^e)}9ZgblHZ#LCo!&nAJ5kCf#NqJNqf3Jy!>0)^W zs2E$ka&$AJA(cb}rJ<){HdGzS3m7RUET;Um6D0ns+J-VvDH_U{fEgZG$~+9G{HPA% zxxBe^Q&(c#{elt3WGhqod5Lq1M%Y5n_c5&503IQCJIWbaH@c_<(-28o+QuKia{d*f z(J^muVerrjKfFHDb?8CL(`nys({JlDq_N$0^=AEFM2l~`I$pLFMh_IkWdj*&_5D{L z)&b7l&pEc6zL~(bb#N2mF-6sy zxN2IKDc5XBMFMZw!!K6wD>jTGTyAj_Y{#Z4hnQc{ND26GvOk;9b}MRae5b@OFYnSx z=mi0DRJjqA1!V`WMl$n}8@Tt+^0zo7rlK3-FV9q*CYg%o73krNTKFhf9Lc(MGg;QH zOvS{C5C-A};aT02@mOyIWVj=<S0%j7-dDuy6ecM7yZm_g zm#UD?FZKM&a7dhm#Uz(x4O!a>2a}d%NwM@IMy0A&z z64)Xv;5`3$marw9l{xlSOOJ|u<=2gLA`#-v$ho6k+yD4y8VS0iu(tWlpRkD3;siXD zVGh>5XeNGvciq0jrni=*OKB4-#fLl?s2{5xV{n=7rz?XIh8&oR$33T%zT)92+shr z&Z+T48V~Cf`>OY?>J&A*%S?dgY9PY&j)pkb4(3{c(V`aNjN~|`xVPVtHrMoux6Sp| zE_lV3>1N}U5mO@Wo=fDY3_i4JVygT^x-X_;gjk_(eE4+B)BzPDVRZ4~#g@zjI|#Ax z@e;f@c(bIWAI{wbESqJB+1_E!VXJazYDqg~Pa_Q$8DK{=gapxlWcDnmSe*GqMh1wVVPyW-}(#jUZAWoG#Tl5{pDm z0-HO5!xN-?;GjZ|L3}Sw&lqP(#S=ovz-ihER3$za3z|ew#=XpR%ycdJ*vnijR|AoR zvnf4+oxBAnNS-Yu09NeBcPbj8}I+{k&NYmrIdIMLg=Fs*4UDF8cQ zlZ$K*Gn+`JTvMd4*@jKOZwKZRCSrkgOZ2@jDhG8y-xmdSfEm0%--noO5x~JD0J05A zG6a%o%noSAhOrCDM(;7~yE->phj}D8Yd|dFOA7?Dj&8-jq8ft7$w82JO5ft>xg`w` z1sBK5Bh&oePt}jRCFMJ5#h()Gs7JS2OPLT%E7V6 zNrj;E(?PSVs7`?v5%JqD!DZKGnS;`Vg*6(|6J2% z>_E!Xd5iUkSj{r>_2=9m;L_YAb*o>ycIiY09TU0hdDKR}4GlP0spwS8F>|c0yzE#G zN-irN^$sX9R^Tr`bj#xpmWO)F##qpjYM~DNyiW+hbalTUF-m00RoRS;gaEOi{WnN& z>c2c+l_N^&LA=^>f8dv~y3Trkj-=h@8tta@vApzWT<9{<9CT4O!$1Vm>khmA8i4`Q zxSq}g==y?bJz0xMmPsGOYZh2~2_iu3K%69;!L&Vw9%y1}RT5B84ral}Nbk)QdJY7< z*?#Ctyk@}{I)fvQFZ9YL6CrBb@@z5xgu`0`Pm$N4vG4^~EcarC#0QmyId82$$(qTZ zB;M&^j<3r$Z|KQqOx#)+1QBovxbR5YLS8wstCyLiFOh3IrpaLE&oCu`3)ghl9WR{xp5vHk}Vu!pA5Y4Qf~$ z%P;nv$9a)1KJrJ)j<8J+IEnUl#0$lN;HN2W;bQ0-2D@L9!`O(*Yh=mH2hpOhmB&fI z*y{8nmSRk_l|VD$!m0sr6F|I4ql2DaDgUc#o+y18oL5PuiUbW0qaC9Hq;wRpAL8GS znA~72rWd2Jx}#HHc}8ks^^s&faHq9bx%C#5P!Ue8PL5P6^SCd2>!idyp+^{rfrPtVr3WTEN?ZrQ?9 zW@PILJY`BrMNEaB3U^Cs_#?F_fD)#PzXvJxC5$`4F^RAPTm^t%m1xHj?DI0jj&ALTkMzZEkfHudXIB@$ywUTysQ^-9?Y_=pTM54 zl}p9EEtg`e9g>BQXa$6<4&WB~oR>>EE=x!8Suu>ax{|9M+P)3Zn^#S0!&S(a+e0jCq{XbIZtW6EjjOWE?k$N^7iKYk)YvXH zx=qZTVHdNfI$f#gfYj33CfuFk;4Z}aD9mrt)Xy#00^=8laY=@X-1dUcl9U^-wE9vG zdAa21f#A^-S7s&XU-v)EVF_orB6dF-S7YiV6T_vr5+C4zc$AYIql!(>^e-pbukI5Tb>oI&Hi>oDmdu` zfI^as-}FH{%&wfHZ!h4@dWBOe>aBdM`VJE8w#qtiGI-#Z*JU}W8{yRR2%k&-V*P_y zeXlc$X;lylnzG!X*ZSwkh6&MyqG^fRUkSI?rz|sY>})CZ zXWsDUz?7I?C|~pC5}5nGtis=QO4h-F`0(GZ-znZzQ|giwei+p7Daq@7N(7 zR_t-5da+ZpKzgfHW*bI-3<$^r_0=h6w*gGf2{WWntw5DPZ8)^BP?dKoP!s(z^uGS^ z!hI^$QnXo+I5>o>w~B+EBG@rax1PgAXuPdr@p(4eT;(%fn8k}YRGz$t5VLT(0 zQ6#rxVsb6xj~am$P+aWkFmVN-W>6z}j=6qo;-(i&YJSE=ryd*ql8_^gT@kB`~_qP_X%MlhJFp`-&!qi%JQ`)ZadRy6>-lmA*F!-M8eg zDvQ<@pF&LcGsgS$O0X)Am?@-Dy1-+1VzDjuWABwY62-_bSA%o)*7wHC1!ZGZjy|5Jc&5-FciaYVf%d4+FFAxCmx=Y(D7NNoC z*R|HoAU7j}oO-HZVn8_(jfA+!ZA|$Q2lLDtb6fEeM-ndED3KzRqncU=qjgM8Zj%H7 z1D7w7>j$00=!|{xlq~B5-CHPm3lA0zS+9!%t;3fL6+06XKSC04bn+%%O#(otOUBP6 z^!t)(%b+6PI*go!ZG^Z28`)0in}1Yz>T`S!omVUe+kF+L@k8ska7F|V_<{%YbpTN6 ze5t6eR6aa}C1e+0yQ_kDR&HSV9lR5xlux7`$bn8nR_Luh_&&ao{0|GahnlJQs77H< zMrZ*A)LMaG0jE$kW38Qtv<7r}KC&OL{MI2-JbJ5lr2cM2DxUgK`V&2dBW6e{sk*T_ z#)nHFKV5Nt2NYG?SQS$rN$_nEbzv~$pt|k-xD~WCl_eAoCcN&TTGCdfuV9IAzFx<^ zcMI_}ngf9hUuqoJhLec82*dlyj583F}1~w4@ zEIYK??EP|UoGv|!^z#=>uBiSppjTXA8v5HTy{<{-EPY=Sn24-SJsiB%c3<%d`9SI9 zYy5xh2#&7RXIZi~<0u-}z7OXMV>~g$v^IV;V`<|nOPSo2g(A~;v7yiP)^rHKw5I^L%yAu+1kq$kT<4kQdH*G^FMIL?6QokesUv{Mwb zxN6#pb$dE|TZ~MY2)KLzJ%2~RJd5n5=Lt+Dt*7x7A#ya}F3A>GbBuWb&)4q?g?SGq zY1?@UF7%2%e??a{siOUA(nVRKLYNCaf}$ivE$l)S!!*|hDGFcKQeClqyB=3+JTH$j zarIw(sY{O^yt5XtTS48Z0_C~5;!Cl3r=LA1>yWRaxL8M~0VV(X=Z&Qp1o#MNm0R z<$0?qy>x>$XBpTcnTDp$8D<*br}g05|C)D$)Nt zSR9~B$5PN%NDqXUP%daN&plpoR29%?#eq?|d?SEFPgSY`BQGi}9=`1B4C! zV}JsPGz;_Y+2VWGjJ42ok~~2Si**AxpamVfiUOKniOlnhwPz7qKfce8ma^-r4))U7 zo@aZ2?HRT>@poMnZ-2(74=!6}#cA&ZI3dnp^GO`>*7jXCy`)CK7SGtQpuzEvhbLf_ ztj^XZ*o*5rxCY1t$(j6?%jcZs=aK90gbAbr!(4#>2mi~1I+ow^1@fO9lppdB5Y260 zALWd&qF8tFd;{@Hc26mA_E)2;aA)u|f90{?|9OZ~-@cjO-zd|ir~O?y_FO8*YW=70 zD8{#+^!>i>{!35YYt!$;v+%D9`28OHIIN7prsJ_~|6`9mx9+mX?qI_DpDFE|mp}IC z|JY;y?efRA{Et2MZ)-2Bge~^}flBxu{qp-Y`}0=OXnAS;pW6gyGle-}hZ&3sZn%?zT%L}a7-~{;fb+3NvS3X;g#q7LsIM2GsS8~8;|(Ll`b6Ft+h$c9 zFk>HW7%6VWzFDU6@e9?ksrRB6WI=)m4MSu!ORmvZg?#f7BmUn$LSM!57H;k@G_a&2 z;vmEU<1};QWa+wMCs_tWzFC2lI5p0AW3Xf(W=CO9i!(sgP03X1`jeN%D*yus<*+u8#J(OKQ%~B>hxRykKV>O0r0MH=8Y#s zu^Yd6!mL@dMdk(bNc5x03f^mL%1^5}k?VlJFtS;h;^6 zojb+0gFH#p1Ex6k1;Ko4h^cK2*APD5;Vj=GpTXBx-zJjx)q4f$e63W#(9to`ti`{I z3)H%HqhpTNxf}IO@u{sY3=X@<2j~bVCvs_S9AJv7Ld2xZT$H3zG%9u^6#y+aMnutH zQa{3;SQf{<`s}mZ({o{=Geg>bIrbQ+TX6%&`r?{ziHVM& zpCA%1^-lxQu76TMrh&}P7@ZlVN5@9a^;xE(*y#_&RdcN#oF>xeJ?Xh|^;N}v01~rl46H!KGfNMfXX?FMs^;nlH>5shUc+`|MT{F{p`eLNoZhy;c1)Ns z(m_xz0gtKYSxyBG8!HU?);0RdyQYA@>S0yzhn7=Q1REAo0Do?s;% zA!qwBA?Li>t?xM?_adN)8BRJ<)lxkYVLnQF)Ohv$CX%}V@d;h zO-;VwCh_botw|p*{je-OAI?i`mg_6+&mv!xtuo%dW^mwf7yj|Mgd|tQ-Q&byIW$nz zFjC0VOhu7e+@(i}d_FJTm6>VkpZ%km1n(`Wq`(YCB3c%j>RI(G1TL6o77F)W*)((y zf>5b3+lFcQCQ>V>t_ImN1A43{gLVX!A25Go{v&M2jtp3h#zxh_p(Q%rKdqNzT#xX`vp@>%uC~mz!6^+ zFEJA_-@s4neI38Ye!?tri&S2BLlLIg7;xpss?FS|mM|kLZ+FAvOnzBve0TW5ZRn$k?>+W4weBnOc=0WQ3%9Psp^N%tv5zk4 zYQSgMr3ark$zJs9@&Z@HQE6LpkGraJfw@!(s7*3+>Fdr*KV*y;$5E7KXiEolgqoQG za0DNDWh`!f%QXyDY@w60S3~H_=fZGiLCi?I0TJ9-jnqo|jj>>v82%vh#cC`rykm@2 z*Q0YK6amvA-ZFe}ybqTX19GL@aYcu?GD9iLHad(fPZX`pISzCM9Xsr3sEW9VMxL@X zH{l+!CSwm}n(C0*{HjuuUt3W{mXVQdURvbG}yko-lV1&zg2p10tMMEq%ZqY7%&Jt*~fcXG_H zS*{shv*uuDJfEFJAO-dd;XWJaFwe|)5z`am|71b3O6vMF(Qv!*P$solZeN0GNt&M- zXh&^Mh4GK_F_}o+Q@bvSISm$?nwCN<@vI9GXE+n-9$LqC1}KKhK#WwtG6@+?4Gd2Cq25L+_f0g30>;q_9LnN@aw?Dica<4)m80!FhU9xWNwYIivFUS( z-Ppk~XZJmZ0i(YJtFa$KrF-cHjmZLtFVG{&C}FUmkl_gvnXRMa=oc~y)XG4nsoG=m zjyly{e!70KP{^ZkT0nw0)`6ekdJ%LcqLJwvk1>ue>IjdXpN?;a@9lrOcDWcw z#akBAmJ7!<@(>|H=OywsT>M^O7kiJEoQ+ANfCS_tQrrmjCiVzKpS!tYTpLr-XDGkc z#bG?6{Omb>^Iob1N7&76bdL&p8Lwd(jnKuCFayO7HVxbPN7awp^=zu~X0j?c^Yr+` zY-qP|PU1qqWDQCU*c{y^o1&mHuYRmSmJmTx?}WY{5B#7GB1xP$t<+q3=zMM%bBxCT zE`$fvArH)!6LUEMc?~C6THwZGXXs%WZd@>3E|3K{Os*F(P)C)@i8MJO+W!q9azb2i zP$95)<6eD@b!(Dbfr)c)Z!z?cf*r7HqYQK;FzkQqoAX5G$&FBgcVjr|m7BG8DP*iNXAQa~eO82!&aXMFX=LTA}_ z6vUx{J6rMqh<{E<7|!=`)TvqBQ?kJg6_aGDMy-_&4#zvj-;SvQV$vOu)K?H)9vkpt z?(z6HF_co;7MM@A5In#TuE9gbP+E>TNj2F5AcZ!vD*QJf4en5tXwCWl^^D@jgc*Rm zzFDSif!zB8G7|{r4)>z4hg^IVkF|_r3YJd7VIZI~nhEqxCtpVv!*ZEFZhGQ}P74<@4*}KqiK)z=54|n*)IZQEu|BIS&(BZPi_*d0A&KqPtFvG3 zLby;z8Q3Ek)N21|`etYEhb$pyQSWC2`GOL3Oo#D#|A5`@%|0D?be(L^TiYI*5_NN@ z)FKzub3ric!+C4lLxBRYt>tmRpXo$@36l_C8le+AFc>)De=F6Q)8xDK7L)=|oz}#` zI9Xc>63oYHdShUpN)CK%{)7;m#w1W#ONbY%NvZE)Lpk93q~V4l`AZ#Es7ENu{j87= zL*XOlLhQiV3;1@ox=)HBJZNu7F_<|kE0{g4T7-CQvQ!Y$X!a*&;e6mG0z}O=Z(-Fn zKw0*KL6EBV`7yFHjg(}^bengXAN7^NABkVc1c^XB9d2#;N+7d7aydJ(S`zInAKM5E z8CIxNYU&9l>=r)%2@Hm8ReXCbM}NxE^BnytN7;(((54^5e%;C?BlRPkZd>mxCQeLP zs+>%r(C6uPYi|>KQlVEtAQ}S$Ne2PjPWCpk2RBJ7uDSc!-9UjR)73llSxyh9E2FJx z_>>Ynw}=Y%w9jIFKH$YZT}slwZE8GDw=2&O zS4FJ(;H;71;W{ac$%_Lw;0Fy2pM!|W!h8mCS#awk+@x?@1ONd~HWlp008^0>CfQ!7bkagva+2{5zNTRo->xboV z@`60QtO-kF1ywJ}#RF|elXGv&6*wSvQEV>j7w1qyWGwNn3V;^n;=yv@UUHBClK<7a z?=46NuLbMW-32&~cA|63xA+5)yTSsZbBSgjuheph5P$ zR31geIA|4lQ8_e80c(aW&puBKCLA%?O@5rNC-JNXI=tjKz{?J_a7JZZIEl8P*`Dsb z%`1W5_ErFZ-W{kdP@LLbvu|q{OF4ojwjvx(*I7}@)_LQZY zfrl#4SDiNbZ$T*ete4f_3Bx9VAYI<1m6Eh)@J=M#(2K}7h-zg8=4CYuh2vF3SM!QI zY6uP%iVaL16}oT7Cgr{e<2P<}TSxXNm;nf-9#C4Z@0vz?TH-2Li$rTScDAXRZKDn@ zXb{;I!3FQl(6vlarA=D|%#($%1Ly#l&U`2B6462Q3tLjNmafu+Eo>AOzA_sbf+l0v z3ZxX(=-z^s6Yq)W!VyuSE$(AXJuP7WTdr1fpVOq48`RF^E zi%7!!daJpL6H0uoJ#DobXutrRF6J!+vz<~Tmw9G{Nf8M=8CetDgtU{5c515-vJY3A za(B#+6!JE(U8M~In}eOD#F>YrF4ar}{irSSwgvT~U7;UTJX8;wl-8lL7t=aGga#6! zDzsrx)-NSxk+lGmsL$h^Dhu)HsoC>{KXOHZ_XKhwOn9Qy#)3w60#bw6gq*fnGzPNu zWsL#-sCdiC;($Aw*TnNtml~r{8e^R_Mn4*3b+9q|m!?*m$1iJ)L|N3kNge&X4X{il z&P%T;J0x&i0voUk3CgLa8O7vwTuGS-_0uG-OLRvpwl!`8g1;s)IgtR&^oTDeZAnOU z7d}p2s?brXuIqJ5VAd`W&y2so?})mTo#Fcc-a1^cqWC+Jfg$ ztBG4RY02_@f(zic4yY6Y!kv(ch|bPJxGpN$40$vWM?6>LJ~QI!B{34{P2@}QKx})D{|D)s*Glpl$z_x-k$eao?>%1i6yN>M&u1aG!s|i6tsTGHf3G=kDdD)b zGus_3-Z@>5+;6t)nMX(hJ3hg+B<|U92`M_2tQoPcOtOM{k>@GD-E-FbX;NYeE3+-@ zZ*+)-R(O&=Jn@#iL>GLXjG51%zbtu9obk*qganp4ktFOPNQk*0dL@$_9gYEQVn@q7 zY+WIg?PX`tM~PrMOS}I~9^06*RIkaF*$-@u-JOz9fDW6H4oSPj8n%4FUo`BqcKlAo zXC)Xr3)*iQs9Bw|b$gR76xH=eUY`;oODwG@90t1M4eC~AZ<0YoAbH^u6;yV75)cDd zJGR3c{q!-GCP3HMZxFl1=ACt|NL7tY=j4Z||C}mrF)>x|Oc}*Ky>RXEr%;9U`s`UQ z`Ift#nXM-EbH?^|YZ2Zl92*S~xC?TJQ3HBQteIikL0rf(6^90M3^Sw|)`Ddrx_Vai zBZ!Z%npl)AdcQnm0Aweq5gCE}lRgsyCxf{WFE)k4TnzxXU^ejwCjZmaOi%$JJ|wZ- zu8ev?4>I9jjTg8M*+TQ~*NQkW#W*7c*^RCFK2>)kM)_6!J|-%=k=j1x0NW2IhMMLY_ie!U229 zOQuHyNz68xr41heH^;CfCFn3C-gnJN(+iu#RDiEu=Lu+nhbu)h!%Mx~wWuhF}I~aCL2%qAEhg}qW@L-2p6xga>LPf-kGpS9m*vXi1 zN+q*5!L&i78Pb*D(X;k6cwbawfI-pXoa2+Kp%XwVJvtnB&t0Q zsO5o8&=3J*WgIX6Fc&VA8hrs7dP$Rnz$|HkENPnzw|)Vjds4^fa%;&rIGIj`UfO#A zEx!`Iqirfet^z&YA+4Oz1TF3vfJ=10w^rujygI4x1TcJFy+{xm<@u`5W<4U!WR{Rf zl==A=xTb)1$FnZf7-4QkJvbs}GZIzTSDHg9dQJ^ACCnB$GjEV=S%0A`ZsCLOfxaZ5 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ͽ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

$QPy+2dCNI&uAxtd#z9Vuu{w~Q+A z(xRKVBqN16x1M4#H3g#*H_e=4TqOy%tyGe4AIUM*#XHXZ)gMLG!S?HB1E3N5e9C^ zI`~Ob;1*cHigt>L=)io`1+W#rRTcJ9wQ_*|@?dyalW`sm7xtOyA!-GZGq&up& z!7vFzcDd5>kOqn}@a0w%9>=KHS7^z!ip)|KAQWyV0 zZMA*0zrus{Pc^aEU{p}AST)?J3dGMCGLJpXu`DE1ZAfDV*lmAQ?qf92R~gNezN(2N zLX|qABETQ;r;v#GrV|lFN#p^2&Htp5fE-3LMGjm`+Ri6UWbp?`XZ=|bV;ebn8?l(% zM{dNdgkE=%FIbW+QUoi;AAwvU@tfO%3$e$cDFeB)lX)Jx(CZLmzytq z=hx5)g=V#}!LqEd1n#d#?#Cdqr?RYBd)GZa-G0UJaWlp2s2=B)kBoc>cJ6N;{U{z7UE@GgvYy2&;T-3+|xzpQ!R})2aNVfUl*QD zl|D8+o7&f_5{IW#DJYRGICL;IIuBD_l%^Y8EKPW$6Q{p{!_5#JYlRGnI`XqdQM8Ay z>O^0j-HlL!HmMzE#n>rLPH;WTmYa}=lq^a4f+h9z^ChgDZ-X5Q&GuGwSF1-Gb!hQ+P^~jZ2VyI5k+=m{j zCd^*_d5=+nQjP?{RFBZzO647!chUMH#s9QD1qhoSp|(&NY?l)+#K<+lNn%RgK3p5! zv6(rX2tK&lr=3hHMuv~EYIRQr=_H=JQGgJpQ%)Sa4OL`us$M(QEBZ`Hr^!&lBFnQ9 zLL0V02B_)TDjjVN+jymyRKWF{D?Cqa1%5V+k=4(N+V+%3={k$CD($X@wl2-9)|?h- zSC(nPq$MK3+&?GFIbTW+Zku9j2yQrVZ%sHmwFuHWH6QQ9_&c}KyG`VBRXYymvZtDn z#EGz>5*JIooi?E$7c-PbNBDLL7YNp(9FQM)nyR7RBOf>*hCoz;d2UKf9$X34<$EP> z0dXx71l(eOp|lKUU*n)mJ)n;ltx-d|*wPc4g$#Jk8R7;OveMl2H{o zAN&~A!x6qeZA|>Y=V?nHT!UM5BKH{@iFi9QVe@wEj;h*zLMQ4zux-!5J$%bpX=J#E&hkWg)Ya#- z&Q2Z+bWEssKqhTASVyVDKMIJFt+&Ekhi1UY3){81@@`CTcWTgnNaQVXOb{ke@=cFb zGvt_#)Kjv(qFIM&+ru$ck%q~)mq?@cEk2q8^1V8gf^+mj!&{v;?_h$(LYBbir7w8u zt^ksEm85uBgS`yaApkvgY!-HM4sCjlrUA5Nl~zZ67c$7hbCNvg zjgQW~$aX{u-t|Hk@*R{X@AHtOYa|xm-ZM}cqQ}BO^v4Z}qh@oqxy4OEv?b`Ic{{%I zksf6N_;XfkWx{C@zXOGjYdBNaGpT2zOiK%|{vcfMaCNjoLxDPVjEvQ~-Q{D;3SU#a zBWSa&s|4el3Glgejn+uaFU#I1;mRzig-I~&K*^`k7;4ARaFhf5vyDvM$OvsF*qa7h zN*fwD+}-6KzT0I2klD2=!HGkk-95(oA~; zs;CN}C#-J`uy3H-ZCGEHulXPY_m?`o_5n>lm0tk4PeR(68TI`c*cxilqE+H#aHD@M8JT6vi$_mPrsmVG@# zqXW?dGQRB0xL&%vUgBofGbo+*Qtx&s8m;TwIFKUUw&t2>=82B$(IMYSuyFIn7FmH= zENo>*JGG}&1_q*Okb1`^Rd<~c(4l+hP}Hqy3>{wVuaMj}qA5UqadV4OoPfuYk#{r$ zO26Flx2Gu0pSsjJ(7M~UI88dls8hmmvw@TrVh%|{5FSd4Zp~r_$LMXqYLo-*KPeAc zT94(GUt@tf|ATHD_)^aonowE=?&KgZincqMuG*op$@~<#XYC_1aL0Z?mzYBlBx(b> z!XMOifN)w=y{BA06pe%4GtW}Gt|xBT6lofs@0k*xZwE8@)iHMkTA*B;u(xbrCM{N= zp&%Xq02BAysm%P%l`trk3VK_2Dcyt;TB_yhh?}Ael#tdNl97`7f^ggGw9OwPIVvP6 zV=-YyX=7=b(JVoL&1XXp+3a!MhcPH<;>fu;JsE&Z^8tQxQS)UT3-oJ7nT6& zI|Eu=(#2D}txC$Hm9d1U~()VU~4Kw8t@U2!H9~KK1;&yN@VR6<H6 z??;PmS-qfxULmH{wECtd5 zTe|*-{b#TiSR1YPs5N?l!ewgVAF<{5`o-w9V^b-I9vx$&!<8rxUJAp?6OIoK z`z<=L2}#ttX#zb@7}^NBJLPzGH%%QCf&G?Clm?{QU+74cYKThJ+%*lsogMYlR^(S? zRxvo}h?9fi5jfY8rgp#(1-rqg*u@w#AHgVWr> zjc|GK7@b(*oHqnHUBlGHl&SCwHDaES2$QHLD2bLPwbK2C5VR_3iOwk~XtuICKWu^lrm=*B`7V}A~q~^i{?PAPrD`kfa1%Cea#W~p4m9JJCBl}bpPX>2) zAQ?x5Qa%XLsk#p=qcZ@Loq;I%RB@bS0f`TCZva_=evrML`_*NngrOoFUB5F#*8+`0 zj_Y2d?L6kksAF>bbA0SV4N{g?f}yD0q!aW7axF}_ejrroip82d^fC#0-%h8CM(_Jg z_?OzDN;R5AnFGg_XX=dTSmAtKFBtb*Ye^JzP=1w2*pzyww@e)Vqh6%0(U8N!m*Ihsq$5#QBm=~2s)YSAZ-_5L-_sW*1=@DHSxcLMD<&DUGAH0+;5Es zCPu*r1)6HE*Tlaty@@c%d9>@oBrO_Rx}1=tt7xhC4ME-!emjQRj_XjgU}*4hS9nuU z)_a}lL@KU)zcu(U#N8l~4=>&sq8m?WzK>Gr>K*fFF>e~A4-Rt9@a`RTr9mbMJMIb+ z`kfOEytO*kYl1X5)`=kLQl>^7%I6>J!j;fX(iiGiv@vH;WpE7Cz4$LQc2t*3J&aGM zy}xvepMIh)#(&a8>R~LguA)FG^fZBAW-SF}%`sCt^*V-0+EY^0?^rTDSjdu7w_}o1 z(y6QEBqa4bmP+xG?e?LL#{gt9r_&l%X7tq6a!!4pC1qP{qrK(6ZaQ~NkNVLgOtkxs zT5#UTXNf5{L)+%lENTi`wYc8crflD=_fkCcbdEoAXx5u&)Qu$Em7j+TreoZG(C`j8 z558^J-lzn;XMb7U22I9_B*XOwt^?0#o>kifJgc}O4n(OfvH3(3fL-yGhHMYX>mqJ| zqi|WbkQ?+4ar<(bwvGaUaiXK3hbj5!2oDH~VBp-ZDkHHj3Zb@5+>Mm6ie676+?pkt z|Snu9_SvkDABY@7)I{V?)eML9zs0(?Nn99Jn<|;830n|Bn5I({4tS zXDn`OWO+eIV}?)3KB|fBWC}JxaPtehJ*!+>#YUf(ke!#>q6x^m?he&#LqMA{w%)(4 z%k1G(A2eIo39QQvQ|7s~yjmOUp7y*V)3$FY1F_60tMb${I14g+vw>S3L%TRY*5OPE z1g`m}5*j4EY1~XbwyYk8OS)nq+=kmJ3XUdF?!dRyLNM~`_miNpp$riHI)6AoV)sIz zRe+6ryG2l`9WsnybcCLg5`*PQ2B(ywMdu;$r}0Q<93;Q3q~me3aj#ki09{1IEpis6 zp8XxwCfj$g|64X+dD(qLREH<}r45bcXaZ3A?4n{!m5D9YgQ&M0szm)^Rfq9TLh)6-g zY-$wAy7kJ zw^l}KqY{(Of!X{1CY5RH54EmSAo~>T+!{?09DS%F&XLCqX0?O&X*CyeV zK_S#F!GjH6ZJlObZe?bB@LS(%P+77uo6$bi_x)LES)|e6mOMwvU7u24MeY@rppsnR z?r%dgS=j@wXs7#2*F;4~Hu~QxVO68SAim?R;}@y_l*UHu^tvm_k-4|^K_J61IgET9 z;Ah>Xwak0&>V2e-CV)V9(f6{Ikay~iN+^5BJ+|Xu7*C*Ta2yW!B^}XmILseC%3tgr zrEr`-dQ^eJaXzI2CLH8*L!$bpF}~V4-E1>9+M@{JFrVId8nr`1v%!d6hVbDqzv5n` zn+x-t>YkztNBR}qoI4&2;=2zV7%AHct#HJTFAyRe_{&IP^2)*k^u&@V4MT1kssAT7 z2WC`h_!N%UNj-jy{$3qUI9=dFI7D~4z=v>*4leN}9Hui<(p!_hY4rUDr7?PxduKVA zKy&z(Ebgadzq4*s7#JEtH}%T8MJUnjtKrF@Y!(LhyL-X#nIra5=EQ^bj@U=J(97>%4eyT#<_GNP zlAj#NURtU4@ifNCX&bx~hNCXpzl;{~lz&3Y2>J(&%c2rK{_K(3d{ipf52@Me=TZ(- zIxXAcs{uxUd=CGfQ@_=}SL2)Oo9YJ;>8&*8%B*37*S$2AN9PxT`L-Cgc0`L~*db2=acNt~wIPFR``rT9d#S&Q za)7%w25aNe1#4J9Cjj=@bWreWMACTW$t4|kBVwBY+G|#*2Gp(sr1ZHeMGB`3CINHJ z%K72y!@@-GTt{FpkIN?jeDqN#NTANzWC4zvKVA1S4(M%TbRYG53lb-!GY$L~6`M(9bRd!aZe1ehY$ibF?j6m@J#A676o}=BmK)J#j zRXC6dhb~Dn9H!H`5YXse+Y&8TNT}KAXqwh#`VFY@Vhsyb1%Wfp(E1T94bN%RsRHpa zZ~msAXxwR^Tp5JuG`!SXNHPO9xlF?a+FNAtw|vk6X&BV^RjRg39ES6puKB}2UbzDC zAc}8ZJ$7ywK9njvUEW z>UPV~DxEZs=D^ik&s6SYw)`?mvjSfbu~@tGg>Gog)%OE(DrJvD_AAhKCe>3vP6ZID`^i zPO>H3qNe$OV&!;fIO(;Rh#v(9`}1Q^bAUL$Ras!DUwR*v2DO84xu(N*bk*}D%Kgfh zCr7j7xGvRtzvt(Li5YrSs5~-oj4VL7iRMuJ0o#p@1~3XNx~X_Z@+kSuc@bia43&@Q zl@GHhS=#{~GF3Lu{=)q}3iGTx8Rsu@2+men=b@#v65YiTE86M2(qsB&RMEw_9s+d+G6CI3)d>G>+lzAOsFPoTb=St z#AWUy+yLi{SLNPK(@p#YbP1#7Gxvl(yb*6W>{9~Zd((kw6Ax>c?nl7pFl{8^=J8N@d>oA;4{E>BG$0E*L!JW; zp}psS+ikxV>ytGlHS;1$ezT-z&Q6E=W9r;>4~O54Lg~~~SU+91&X~H3AXU3!>N7Mo zF;PQ@WE)@EVwNRsuISqw^_i@!#&&gxPqEHInC(vu)zYd_seauFof0s4M+>C(DJGb5$@iO)>gYA*P8W&*46%=kby9$_zz8M$1i6SUu_JS2RH#Z?w3Tj&_8aUQJ6l{wRZ`iDLh zizlz8fmpk-d&h#cWnU9s&Y&iO>PefoukT!qZ8Zk+{HvIYa4L>k5?%Ps_7Ua5?Ij15 zYuOvuRWPyRyXl0UG}U?n%dCjFn=+rU?ddP~(3xvs|CiFp_PM17qainOERDByt|wtJ z>UXUDuA(e@l?B@I_7WIxy?XdWFKZ*%l;W>UI{0zxg=GmQZxU(j(ZH_VwGz?Aj=xLs zmu^j=W@<88bB~!%+e+5Oigwxh7>%RofdLaW@U&s$2s~}fY$|-jjs%=fF{pvNbTXk4 zcU%MP6T5q(Dww)UnTyM}xYnq19`2TfXwb=h`jEdaui?TJ0TCCz!rbnHRa_MwDqJ-KPe*vWXi} z$mfvF4X{0NFeG=nQM8#uiL=JEWFHT>k7!d&`WvCj5K#$bRvuAphRO?@MbKKjDl*H7 z6v^LTh*JxOD&|eM`8Ybwo4PwKis0j($NsnZk=yukVB_=34({I5)}mtqziUZU>#p*f zL7_iis?%L1bguASbWxq|qK+VjRwaqjUSpoyy%1AaHBR14^?wYM{Mf=%2uC1cU&=J{VPb8jLJ)&H&+8 z^C9_Nn-b@fuMj`s#-wv7eV;2~G}#7PjtxqKA^ic`FnZ|Rq0!0!kITCcP~?*X)>FpS z5NWVb8S0Z)rD;RR!*6!uTN$aUN1oTI#HLuNg~1TD*0jyljcX1L3?FE3?;9KH>4-|; z=N9ElP|}=IERc|`2h%9?(`P{@)Qg(F?LC-7h8v!(3e`2@dws%!ptMHh`fE0l746P) zrvS0)Y2ZENMIo+D6fKZnMa={4XgVsm zH7c!g%RL!Q6a(}xF>srUSscp_I=a?r;c@u8L>#0+gKzsiFW=fPM4bTqa}3xbxdrlU zu+fVhzxSR9YtLZ8ul-Kpmo97>DEExgy(@>xyJ&0UaPN6?vOEXGU%V8^nUS8uBkeLG zr8!Vqdi?cr=Xx^|JX0Et3v9l$HcBt=@+2xnO0~0)u}`KuI|~Ik?M(03;GmpU+Fn@s zLtKwB%x+Y}k1QrgSDa>UUIJRW(i$nzDJsF9BYdOENHhnIU-25{{IIc2`=E_&|ITf= zm6TF>phlcG*h6X}R&9UxHNjFZrK0>qkXo_4;Z{MrGvZ6}r7IA5MXaoe}2;_09n zZY?ErO2sbjaC51CkZqme22=eY+jc3YumJXOJME2Qoy=ZY=!D`k?xhV%q6;g$ z^a3~~%>_w#(w8-QrC<3bJz+_jrqgdd9~MF!AeE-mJBDMa*uzRQ>K{`3aoJB@B{ROX z4*RwG4|?58$Rp_}lQ9M{OpM>ywx&Smii#e=!_(e8sgX<}>=#&q}BYC{_$ zlnIpak&~({i4x^d^#7zoU`kmnzYd^!=pgrA(JTr-?saP1%;h=mi0Fm>H4;JV^0yGB zbDKh}d_)Ecoxs0qQt2G1(0!a#iT@frDLudmv4w8k{XqUfRgrPih?J8YM39JzCI{hH zNW!L1n&%N*u-9FcK&iov7UiSW;gL~yXGhVFhESDY{Y@*$YxF6VpRS>C`-YFJuOC~wF~c@3ONu&q=9dh@oOzKHa2jh257M!{C7*R$Mt~tcvrlLOYTaX*Y6Pn@0J$>r?e;{AiO(!8vn)uSZaTzb+nVYo$EU z>(HXNICk!bze^g3*Mu!@e^CzQ3-jP;Q%n&LCQ$^!4&ZnQAYqtA z455GJ!zaUZ(FwZy(97y4%qMRzJoWQvU+HH2tj+cPotZJcB<>Uu)Nq|u^L@IsL5fl#>r67co4+U{VX`25yoqjio9XG zMmJS(1>O*ZJB*4hi(;=sP;O>$)OG++@TEN&C+ijf3cW1Z-w{J`mtoLG0H#I}mzros zx>|~i)Y-)KE_?HqT4zdAfznYq7RoO$N#m`owuUeKBz9 ze(XDLAW;^wbX1c>qNln1SC`}? z&oqBm85%8*^mX@?_sTE?z4jcCKK@xCQpZH5T(W*4Q={u1DJ2+ca=3Bf7Z7{Y3)7^h zs^h>1Au}NUU1dVtxRGdTRdt}TZg3WOcYa=llWvfDUA0fw4bzN+YAjAU#iuNw8>C^# zSkLI*?t{E}I+_C$7kxqNj>o@Cj$aE8E03;{qJ!bEc}V5XcRC(>r@H{T3$XwGC6)CO zxspvnBB?)<86OZw_FM3hotGhZ$s3^sqjPswPVYH(I?)f49n$g!GMAd3IAeNnts?i%cjt=(0M&?U~{Ssup!9ajsL`o!DOxK+(0CwDCyBPN_i@cP{7jMU&v{gX_`q$y!j#ylHUFadP|;I^Nts%+Rzlhx)DM@1qUh@17;Jay=m zs`S9fFqxVR{>d?oZiCgzoH$K%`UJXG)A$tzP{%D$n) z9nmagdf?AgNk>V^c9+fopH?CG*xh8ylZL-(c<69>WVGT4j05-?zdVTq2I*Q+*|E_D z)T`6cEo?~+@+w}(6DZvITd}Qg`dZnKtkt1v5uFPgHc2~2Iqp~E|-opgiZ$~a* zE=Up=K(?zcfI882&Qybx^_&t50yj8I)jZj~WNK=c+4G#8+3zOHkaS#;RwDIC z&o8HAPq=W6uHv?<({BirP7{`8}4I8&(%UcQlf!$%1_Xxfy4{mc+!N zE2?pe@?*U$)%o@>qnG6wTAg&IO1A8i<8e1CdtA+wxj9Bju{qL#S6t zhrTJ^HB)0vV6J-}Pa^)G>cNVN7@hHYAqlqo6d`K%XX<2{NZn_u%aW3p99IQv2oP@J z)ewM%-|5~Hnu6TB9;5P8#hlIh|H0+nG^zho8Se~U0&p#yGtW_G-IgHNhSG?}Y>VPl zF}EOznCI8#s3e8Nwr2%%^E8ODvPWHGClfngceWgLn>8px)Fg>WwMdrt&eU~+eIv9= zB*7x7H)rU4-cUHI4iiN;bFNLu2`4_i{8xW zVgv4fWR0-|6(3uzs;(cd(lvlgz`v4|J#d(+RQ1CP(e~h=afM-witlO5-lF#EuuRKD zww)-)Y4%NZO)GaYQ$2^m|FT{|SW@r3Jqx_s zs(o;*HoB3{IwN=Q1}(+sM07V(mR2ySm!ttRRo2o%a?vz^qU!_PhKVYmzIjF(WGWj$ zTsDhRr#zu~X;@gR--+eE%yKLuQ$(T>MYj1iI!Aqn&M38+{})fCUa9E4lCLy z*m_`>SbH=FY5r-OO69lWQD~&bOXq~uySYwQ9Z5!=Ath6|WXWzn8d-YKQMv7ClomAo zn2#+P_nDZF+-E*ALsAhymkE{aq5D6nmFb2>=UiPAOA7AHYZLV$dC1$ny}4Ovuj`cu zjA0%D9*wFff7y=aIA8c`eU#^LWRY+jg^xZ(D?xmGm$|$KUbj&rbThT%KwXL9DmC!@TL&!;GW&8_!K; zsMg&lXJGwcj=Da~9VM|*6}7V~1JM)!|8!m|u&J$)q_TA=I^Pw(AO0?h+nRwSdqKwv zFIDDH_PzU>Gt#Ju?&_{O^pzeqX#;Gz(6pnUD9`e7`xtPE1 z*2tRzUR6-0TQ|~#gI*b9(XdHF!Hm2*MZR3!X9n_g`V_kDA@0USA0?lm+YdCp1q*R#3O6 zCg3Nf>Px%A{SP$5R>##k_PG@T&ja+qJ%;AUj)q01i} zNRI+FW~f&Pzcx1wtlP@Xcx}`}5rV{{vnc)KzGf(m92%oYK-!7oPd(TSrcpRbW3b&4 zk#?c@CH>7{lJThX6vU0Qzi||=Rhq%5{iP_E4Q(8SZ@IV`h#Fc72s`R&6u$IODu_gE zKCnmuF;6`Xgu4cTlo3Z9I9_qYtvlYs?!~mmj+fLajUpOy6!#9N%7E6ajUq(`OpSJ- z{Lh-==qz9YN6tRXq3oY)ss&6S(M*{6avA}^=Wn_#T*D%NZ;pGp_;zyTcOXmL2iHec z7qe3j9+E)7kam&>w&ai{Hg6Y?*^(X0rjes zS{(=2FON3oELpESz^d({as4iN?RpLXFS%5Kj`UOT>t_VAqjd|K*-=DWNd`9!SC2)L zKsxJ6m6uN8aBFfMxz#hJ@_2<(!=9Wr7$a}kl~XG6Qhy#IZ01KZ;ypIy)zqNhrepPb zGCA1#K&di4O9;W%hhAEp4CaDrBN7C}q8?F!e`Uwl(Jng6wnvP;1o`iNwd!HH%=?jC z@BFMY>@3^*lH;n#EJsAdN^s>0w+~A3PKJ6dS@FrIL|japJWiAY#f|@>lx1s>kNWEA z+LV2R{)Xo4OTZd zY{jz~VRah|Ky+@PTb6`*(I24CdY*zG-tO^-eDSru2O>Nc`$ za8%1}f$TK`O_DG-8d56(c~*I6`^rCtbIYkmFK>gNdf$R~HxMWCJXQlMtINs!q69ws)|C`ZBQ`%-(F zi)Op&cd%00q=hh97i8o>@Kdc4meZh1eb~D|s+%yaG6Q;(FKba?(A8-cC+#v@!cn70 zt2~w#y|~zcHH{D=&o2p2PBL#sWrdCI|;baSDyq};uAv?pmn_FB%m^%4z?3; z_kZn4fOU|0Kz;UPK$`Oc*z=B`1U^Zra846|yYO`<0hYC@Ll)pY`t>IPR~!_8ivZ01 z>q!81n9lzx;BQU_u=px)98Ee-XYsdg+A`^^n|T9=>0F@#e*6t5K^1h`i53#08DPEc zjlguzY6ksL(^*P%U$H*2nK*k_?T98pYX6&+qz~|d@q!QV{BR*dcRC|h3;M>`jLmPgkr9lUfrJ*HhryqzNGY*^qe$td6R(GFbKp{QS@+L|GL@Z*hEGi@!^< z3rATUO`!BM-l|eA9A!<^h0+(^uy~ZUQ5Qb7p8xN}p@fAs45~{6R3sj@Gc58BIQ_zJ9z-hpM?Zxy+iFJ{mFvlgsI;mq<4=2;tdAH6E}YR>zj>S zH#UWAx4aXS{r9$&I7($#j!h%erSDQU^~$l^F_5CDzsMR(+wIY|k{7BBY#bnudv`t9 zuUi0fi}fCTi0GfLQM9x1GXQ$&zpG9g^VS^Dt*B1|=fHoQ5FUb!Do~#Ap83&qyqIc7*viof zoZlKAThKjk$0XWfEC|TadmV>YzE3%gA;WfzQi|=6Gb^{Z^Zr%3`qy1&#lAu;e;lY^ zkD=R+#KrJ!*t5Xg@cxil2^XYIE3{Y- z37hBw&@)>A^fr;kqx3uzfO&fhaN0km^Cx=|rvUTW7U0s_lNZ-rR5AmcpPn$Dv`^fn z0%<2<{ z(|asBf%Nni5cS}Ax_t!KS#$yHa0{SmJ-)9&w_y!1Z)yQf=g-r5bRFvyaDLJluio5j zF-A{fHo@1Uz;l3K@qvbQPcb3w>XVqUwR{V)T9Z2@8a||+ z)C{dVpuLrPr)V5>KiZgn+6mW$QYnHK1{$1i^}^FF4l|(jo5nO7R$_A_;rlP554t)# z6@PtjnCxnsqj9KN1j<=0pfz`xw!5eVsEbbqB&o9soadhmymRRA%LIVle!_r^HU*Tg zG)7xwZ3pL9X952E#zYo$hSl4v-z87$meGftZ9NEoQ*3LIWa6h;^T1#CH=tvOS~~%L zUSlFQAoH$1B|w+ql$@=Ix`1_?Ve$aL4pl5BL=Vtsfm-{py5$%;f^?(SG)Sju?eLNm zi`2(~{Tid8QDO3ylC(&@4j1A2B+x$I0%}??QIE=(6V3qZr!8Qn#q4#M61dL+>z*G` z4L6oP&E3^ux`EflX<+^5$-&fcbq;X%ym@}pN()!(G!VqBIUp`?0ogk;KNhY-mcX?L ztUWDYrbQ8Tm@azl0@$k?gEs66)1ucjA{xR@g2vaI&{}8+n@&%RW)@@~c}v6EJqdAa zV+JIcErR$ZjhQ$Z!E7BD6oQR|;F}r~ZdkD`SPzG_Q-JHC$5h|Hs_Bz{hnJ_v2TxB#R_~@^X|y%SH;pHbIdc$1#CY zC5~MubrLl;iA%`OTCG;n#?tP3cjXr(Q3~a60>7d{OAY_DRZF36C?K9OkAet~nm}8% z;gRyH_(33qmw1~{%Ktm(%*;9W?!DTTwC?|xPm8>B&;8DvbLPyMne(_Q2D_?ZpyZtP zG1`k7gG!JC4E3^P$d%}V=k!i7hqokiT9P*!(d&@sJHtFad3tz--QPK8^3Bu5Onu-5 z=Fs-hM6;!%DsJj1d)J<+3)#V7>#IQJjw`p`6z4+vpzJ^PGSsd*Amirw5F|N|0}OPe z4!}6)(FZi1<0J#Uu@1nvLGJ@vw{e=0KF|O}&u5%vxGy#U);Nsw4D>`DfN>6^Uvu^r zg9q7y@?U2`t2HRjTl67a@;Ak3SJi=9tBYhQiJ^+gkWpi|$hDEa*r5clz`r?}O^kQ3 zqy(_fTfFNTX7_M1TeS|gMxFJN7--eUqUNT$Uuyx1U){l2>+8Ub^Q--edroyP!)>nv zww7fy9(6whmFobEb6`Sp!sTL^HzmVGHBXb4wcw4v#kdbA<7?m7!ZXem<2+FZUai6B zJgtwjo#4NV*@-$p$<1PmL!@nh&&62z;Uw^}{ z6*KtcX2-iI+(>DDJ#kdUc8*G4D~aeVrJ)kQtB6C%4tXyV$n1t>PCATysZK$M!ibWB?Twf zNiOa^D&j7C=&p}(GIij^%{dN_{Kg`q+*=1)oZqNu#%Y{ll>6&Ii?d&fWO&X+>^BxV^K75 z3sVeqRULqFZlTuK^9lPH>y|n&onaTty>`7~8i#OzQC?ODTAYWaXg0Yz#W0^rhKuT% zI)rh_)iAuIRp%J}NuNsWrzP(Uh;lLt(ZLLUKbcXCN-uR|Kpbn6N*!Rff1S*}5vf$= z57%>sSv{Q0GO+^})emy#=NWX>Ly7&Sqjga*^5r`iWPKfAi<(Gv)Me z;lD1*Q;%?YmD!3zw0y&Lim^8*^U(3(OuOf^iWznm_nh)c27jY65x>m?u4DhMZ52ICFwJlus{=M}){n|- z_VUg#*yDA8#<}QGP`fdJ!Or++Y31Ywh%iO-x40(NnpzYoO2D_sU z&^Y%!+6uBcfZ^_~12)c!kHR`r@zpkIb$_)Y)e}9tk-dG22oWCD!1kdfCX2|!| z0qy1nG1qSQsTe=w{m(Mk*Xsa{bI79d+8|(o(boNIqP9d8bI~9mmW#v!z04%H2(zVb zu}ENORHw*%-kHoVW+*H*Bv?d(?X+WfR=Ce4HgO{&gQytrYCD+Y<;k2AJGUMcqBx+F{z>Nv$wr zOEArN=l{DX0tEqQJ+gu$jiC^WqZK&h8Y0n zC4k^z+bZ4s*9DN(ur(bSf~A#!UIx3q4$zum20%@i(a&Ia)B#%4R07n78AV3Bw?U|0 zm@&nW_csXIgc&mo_D~(5HNy$*k2T)-yVduQt%@!i;&w zd!i29nqdYS!3#5j&spVJ!+#gEQf_WY2r~d}!i*GyZLI^erauQz8)oz~+AEV$ql#I7 zm?2yw%$Q;(pIU_3ioy)X(5TKF^EvzTiGw+2D6A;V2uonXj1+TECri=rFau)1|1C1d z*ClgK?A&@(h{B9%#{O6`4;}OMU{aVd$5@Zofmx3c)-Yp%0nhkCqC%*!bplf~$7t&t zhe{zqFT-8mAXvieXRLBE=881J3o|B}#p{z#Cf?{^wDonM){Hl(AvoaZWxVU_z^xf@ z5Uz_j`Wf<$I-u)n2o5=lj5nQ(8#VRyh8$FZP|P7bK9|fZ#?e}S%s~Q3&@s5N)UKZW>jI_tqnE+1uLHC$ zldJ(qKO^4JKx7K^81CK%!cw>}#d!BO3YS1<80_I>(3R@*JPV;;98^IAq6a{0z!fB`?Jz!W4L`j1AfcYwt_ zL;v}IitP`v;5bBC)*pvlzR`eJ%X!q8ES~Cuz zhTu44it+BR1Gi=zLbxstnPJF>>VU4R?>G*bW4z#NiJBHQ_w~jhRDn<&B0R20<`v^~ zEk6z+0VEFTW1g90-fAK18mGpMEHc{b8igux$TS0fpbp@gaR{}87l+I;=I86ct{I0A zwuwXL8Ew`7NmL|l;F_);q1rg4gW;}AhK=fH{c(u0kvOEExx8`_ZYx>>@i-aJQ;Lldf~+( zeaz#QWM0dU3`oyIamWC3IdHnTh2xM(X7l>f$4=vrY3A|1WL~NXZfdEu9J>+`h5JKiSB*l1J z>%gt)-xyqqL;4x*jyh0l#vz1i;*cVv-CGB0O?yG8HV&C$xceIg>%}26jQLQbuuU8? z$7qk&fm$;Tp@!f%WP$O{_?C!JLRpOA~F*aBHcQJES zGY+A4@ZyjZV{Wbk+f5b;>mh_~;*dT@%hZ8d(|;sX8;2Ab?(dUfqxxBY9HML_4w+#t z-(G~g4Sh{H4f=u#PtnCrjU=}u5TbLg$(_ScSoae z3AD&yuS*79nO=Bt$TahKUox-d$04NWp*UogxqSX~aSO*G^UUUFr;nY+A;EX-P*}r% z7n`=+)KV)B*{~7EGZ^vD6qy2%#~T)i5RYlbzV*8@phG-35>cM@M(#M z*U%i3OfleWGH}%N*Bg_VDujX(Ve->tW-%Vv@`Dm1fkY+2_pOe0^IvB#t4%?DBi4A8 zy$rXjVXzXH3^3x6I*@C|C8jC7z+{p^Utb5fn>`W&69aA{lWB(gSRJr6oj(I>Lz6ki zd(saQ4NX){>kmyFABjymn9X&Iuv<}V;Qp;Ca-&uDklfm)w|)(EA@koPtcnxa9* zyT6gR6i&=A;6n`qCe%4b`*AXAq6w(4AH66g_@Pz7HT*YbvRHnUV)Q)}rlgq7=F`S5 z9H;a#pIc5NKMhm{n8|@;W;)>Frke6tE|c9IzSwn=vEEpPx%G3rUZR+>p9OH3?9fj$ z(#PsRjB^h>DecWsjPrOMcyXS*hi6>)1;#n!M^WQgUE??d0a~MX*fF1Br1@mTsJUCj zG53THdE|nA{*M#2D#qrWSsNu z)!OsAry1>ib)eQTg~r{UWt^|qffqLidQw_Hdx3%0{UlKzqFT48pB-f&4t6i&=N93! zR0q47mr;%)vv_ARs~8nus%IU~+_==U!uY3&ZQ2Nz+LHjzT?aF}Jeg@?N7m33a-#bf zHj@mmBe(_}dCx_Lxwj6u8s<~o<|)Ryzaf}t(isMNs3CyHrDdeYSB^+<3k-Aa&k_}F zxqa@r#wkYMoXllOuCb@LA)mO9@o#B7pRhALzzhzY4o2z)Pcr)Jley@Kai-r(*O$%b zvG5@WNx}@K1`CBT_cez@DgEeJ>LqvLgAUWo>inOJK2VPR_?MQkp=jyMQ_OTao;fG@ zRhXCrzgPF$HePuQiB6j!Rn==5lp*adTn{L$r9(&Lh1^tt-DaBY-pOl^k8 zD?PZralEpw=U^#U$@Zs*hNwQmVaF3vpM3Tp*+hH}y*40dlM%APKda=DdGC}BAUyRV?f?OmH5w_-*m;pi;Ia(uSwdQ+RGmeV6o z*-GP_POn|?&%HF_vT1zok>%Li%<_b*b-=>7aU6k}$mcSJA$&QGU%#kLs#O>pdQrAi zpoad)-CY9EQY>XNgxTlX-l+W!_uJEuh~BVFjpQn(Q&U~BoeHCx&!j8appWIh_$;Z186)1XirSgbfQl#%J}YA?+8NK48n7Jn zGONE4mf>1QAVVX=01O@qX86@-o+DD*ae-FwlmLcf1cMhuPX|nOyy|)S;~CRMD`|#* zr;goL*V?^{)ca7-%hJ9>q+Yb*9_%8`NsYm9z2|acgkg=e&eC|W3A#azygv}M-#9-O zwN@`>f)u|v7Y|^@b$eIhK--@QNM*fsv{;Q{ns(7~MFFjk6A>;E` zcXxg9gdO@VMKkk&IPIDK{KUABk4MO4Z%}&1BNuzv-0aW^sf7@j+V7~QmqHWB7E;^+ zol?S`%9eK3Lp;lsX%!viJ=1U?TVh51)Q7l~nA4OR5E)$<1;g3Wx}IBUj=p&!pADwD zy&m{YX}3X{iM=5<*b`%ArFz~hJV-8>&V^=SA$S&u}S=%U!tO|N9Jif%wH0ztzm=(_HR>*z&C~Ce)bDQD`mfv#l#L zlP^I(CaGLGSI7sm4EKe2SZV$`akr19M}m2Vnn=aftd$41I)R#%h!fOwZZOG6vllIf zD2_>MDO;hcJC$k8mQ4Sx?fUY0es^pyQtu51f;-p6_$|g!+tVf8(RvVl^MZG=J3d?} zAq`+#SEj1gv}HLq!-dS8v_-Ynh=8Fs8$@K-#WD!*_jQX5Wl>&lDkzJh4!Ch>WF2*~ zvUpARg=OpLQrXz)T^lj|+e)QE39Z2r9KTp3sbmjT9(-V9j6Cv$t%H-QbqP|$bxJV9 z+~4v{kz&z4G0pE)(KP?saPvbadLylGHDC-W17`DDqw1J=G;8tVzJf zP|8`D_+XZWdCgiDs0=I?HibE1 z)cW(LVGrjxGHjg=Oz&NT>afpXv=YUPF%r>GS{7e&jxhp37j z`jX$hsKRv|lk_p8o3@C`Eeh_(4h~x@cV1HEwi~~ypP9@(cQIy5b5J7n+KO)rjb#r7 z!Xo>8X-K$m{bLix2fbBWCAQE0`LjHJ#Y6Iju;@lAsiqu-7n$z`FIcRqI~I+h4Gr*8mGM zd!qyF?~*KRHLH z|8MF#@fEi2a7=orzBE|&xG9~;L+Of{)Vw)0G&a&DGgY*AsTGm7jPJ$Kbbe?oYu6OZ z!7NMm);%KOfu39?JxKkD;6ZXxEtYCK6;{xr8~Lmej8I|mKu7jT={6&nEm;<*YhTPW zsjz22trG$NT3__+sCy`Hx)zKm9mf^UqPE)BFq4-vBz|uix9n=P@eH@ncL%klbgH)1 zub!)I^c^=n zvgzJqRpd=ZcdE!&5c#-A-j_YBJZHjm>i|*fc>)?6GwT)1bw8IdPliYvdWkj{rkPp# zkuc3vYTly_l5I040sxOyJ>VF5!F!-S8D5yWE5<1U{n%ZuqbqJ`-Q^U&Vuv`&9`~r$ zj{tEdO6=Zfs(7NBZmKz3O*d6NSxq+`IOoyPC1i%E1!2rpZ;4DkCde@8s<*bm_`zci zCNk*iGN7$P*`iH&IcMDtLs<9irNTH3!CBVgO|NBbMzqy*pN2CSCpTKJ)0-*d{7`ru zWN5>FC>ZeDQD@XR#`f_bLi|4Fo_n2)sj57q4GcY>S?>w-vK$<$d$QV4J*94eZ-;E< zh<}m!zUoh<6{7P2*P~s>u|#30bcY6etwwAwI!05WmS$>lozMywJ+5hpZUDCUTqY0) zKuZwaipS~K0UkC(O|k5M`TE#8$PDHTwGT6%E0^I~0xFp1_uqbO88}0QejE4C@Y|pG z2kFuDFeaPp%zg$`=LdIbb=ZjjalyGZmWY)UkWYDJW3eW^q*|`q7{{X?DQ(pbZ%%ns zH~RhAlLle;mBhuLRDqzrgEyZNStdkpDy=oyaJ&vpX?L1p9FR^;9Qd8VjTp>v+kNuw z(uT+x9bo?r62H&OSHgX_OM{?4;L%-M_)AuP{k)3!_4B-eTJ+B zAr7sO4X*^ zJj2SlV<{gr8!qMCaOGNL6N2EqmcjP-aYM9}3I#JE^s6ar$&BX4j90ivX{}MdV+9h- zV?1gMqG!;DbEUFDc2<_98O^4Prn>zs#Y-O$X$*)b3WZYO;{<83d`*S9ziD{)C?%pNS%A3{EJ#&-$Bi6beaCxAFo)YZZgi%qvak`k188D_p8kl` zwM@qBm}mILiQunV3{4bGAwTtE);s*g3KOn`Yz7I|m)t3ZR(IbO!wyfk^gsWEa9Nr`Qs%X_y0$^GB2BX>AN{0=w0x_i;w{4}S!w22iZA^W zOCzR9p;u~}ET4J7{}-wC|FC`1`qb{pW!fiO(GIR)_ncI81x8ARuF=1X8!79_usp94 zxiB=1ré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%0AismWo=@r)<@$@9r%g{& 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�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 Date: Sat, 21 Apr 2018 09:32:10 +0200 Subject: [PATCH 12/69] Document config.json authentication Works with the standard kaniko docker image --- README.md | 24 +++++++++++++++++++++++- deploy/Dockerfile | 3 +++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d6c707b5da..aebb32e24a 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,29 @@ To run kaniko in Docker, run the following command: kaniko uses Docker credential helpers to push images to a registry. -kaniko comes with support for GCR, but configuring another credential helper should allow pushing to a different registry. +kaniko comes with support for Docker `config.json` and GCR, but configuring another credential helper should allow pushing to a different registry. + +#### Pushing to Docker Hub + +Get your docker registry user and password encoded in base64 + + echo USER:PASSWORD | base64 + +Create a `config.json` file with your Docker registry url and the previous generated base64 string + +``` +{ + "auths": { + "https://index.docker.io/v1/": { + "auth": "xxxxxxxxxxxxxxx" + } + } +} +``` + +Run kaniko with the `config.json` inside `/root/.docker/config.json` + + docker run -ti --rm -v `pwd`:/workspace -v config.json:/root/.docker/config.json:ro gcr.io/kaniko-project/executor:latest --dockerfile=Dockerfile --destination=yourimagename ## Security diff --git a/deploy/Dockerfile b/deploy/Dockerfile index b251cd4112..a1b920c5de 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -17,6 +17,9 @@ FROM scratch ADD out/executor /kaniko/executor ADD files/ca-certificates.crt /kaniko/ssl/certs/ +ADD files/docker-credential-gcr /usr/local/bin/ +ADD files/config.json /root/.docker/ +RUN ["docker-credential-gcr", "config", "--token-source=env"] ENV HOME /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs From 7ceba77ef0308652c7a2e884aaa86011d92906a7 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Sun, 22 Apr 2018 19:01:27 +0200 Subject: [PATCH 13/69] README.md: fix link (#138) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6c707b5da..1603c767ee 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Please let us know if you have any feature requests or find any bugs! - [Kaniko](#kaniko) - - [How does kaniko work?](#how-does-kaniko-work?) + - [How does kaniko work?](#how-does-kaniko-work) - [Known Issues](#known-issues) - [Development](#development) - [kaniko Build Contexts](#kaniko-build-contexts) From 844d9ef0d9c0d39fbdeee17fa6bb1c466a3a5c8e Mon Sep 17 00:00:00 2001 From: dlorenc Date: Mon, 23 Apr 2018 12:50:21 -0700 Subject: [PATCH 14/69] Add whiteout handling by switching to a two-phase approach. (#139) * Add whiteout handling by switching to a two-phase approach. Also only handle hardlinks within one layer * Simplify the run test. --- Makefile | 2 +- .../dockerfiles/Dockerfile_test_mv_add | 3 ++ .../dockerfiles/Dockerfile_test_run | 6 +-- .../dockerfiles/config_test_mv_add.json | 12 +++++ .../dockerfiles/config_test_run.json | 38 +------------- integration_tests/integration_test_yaml.go | 10 +++- pkg/snapshot/layered_map.go | 20 ++++++++ pkg/snapshot/snapshot.go | 50 ++++++++++++++----- pkg/util/tar_util.go | 24 +++++++-- pkg/util/tar_util_test.go | 2 +- 10 files changed, 107 insertions(+), 60 deletions(-) create mode 100644 integration_tests/dockerfiles/Dockerfile_test_mv_add create mode 100644 integration_tests/dockerfiles/config_test_mv_add.json diff --git a/Makefile b/Makefile index a37e20622f..d913360edd 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ test: out/executor @ ./test.sh .PHONY: integration-test -integration-test: out/executor +integration-test: @ ./integration-test.sh .PHONY: images diff --git a/integration_tests/dockerfiles/Dockerfile_test_mv_add b/integration_tests/dockerfiles/Dockerfile_test_mv_add new file mode 100644 index 0000000000..60200df9cf --- /dev/null +++ b/integration_tests/dockerfiles/Dockerfile_test_mv_add @@ -0,0 +1,3 @@ +FROM busybox +ADD context/tars /tmp/tars +RUN mv /tmp/tars /foo diff --git a/integration_tests/dockerfiles/Dockerfile_test_run b/integration_tests/dockerfiles/Dockerfile_test_run index cd225fc038..66307da876 100644 --- a/integration_tests/dockerfiles/Dockerfile_test_run +++ b/integration_tests/dockerfiles/Dockerfile_test_run @@ -14,6 +14,6 @@ FROM gcr.io/google-appengine/debian9 RUN echo "hey" > /etc/foo -RUN apt-get update && apt-get install -y \ - bzr \ - cvs \ +RUN echo "baz" > /etc/baz +RUN cp /etc/baz /etc/bar +RUN rm /etc/baz diff --git a/integration_tests/dockerfiles/config_test_mv_add.json b/integration_tests/dockerfiles/config_test_mv_add.json new file mode 100644 index 0000000000..5a780d5c7e --- /dev/null +++ b/integration_tests/dockerfiles/config_test_mv_add.json @@ -0,0 +1,12 @@ +[ + { + "Image1": "gcr.io/kaniko-test/docker-test-mv-add:latest", + "Image2": "gcr.io/kaniko-test/kaniko-test-mv-add:latest", + "DiffType": "File", + "Diff": { + "Adds": null, + "Dels": null, + "Mods": null + } + } +] \ No newline at end of file diff --git a/integration_tests/dockerfiles/config_test_run.json b/integration_tests/dockerfiles/config_test_run.json index ae2b3d8f2a..fbd9764a2a 100644 --- a/integration_tests/dockerfiles/config_test_run.json +++ b/integration_tests/dockerfiles/config_test_run.json @@ -6,43 +6,7 @@ "Diff": { "Adds": null, "Dels": null, - "Mods": [ - { - "Name": "/var/log/dpkg.log", - "Size1": 57481, - "Size2": 57481 - }, - { - "Name": "/var/log/apt/term.log", - "Size1": 23671, - "Size2": 23671 - }, - { - "Name": "/var/cache/ldconfig/aux-cache", - "Size1": 8057, - "Size2": 8057 - }, - { - "Name": "/var/log/apt/history.log", - "Size1": 5661, - "Size2": 5661 - }, - { - "Name": "/var/log/alternatives.log", - "Size1": 2579, - "Size2": 2579 - }, - { - "Name": "/usr/lib/python2.7/dist-packages/keyrings/__init__.pyc", - "Size1": 140, - "Size2": 140 - }, - { - "Name": "/usr/lib/python2.7/dist-packages/lazr/__init__.pyc", - "Size1": 136, - "Size2": 136 - } - ] + "Mods": null } } ] \ No newline at end of file diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index fc01d48485..7c1d646070 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -115,6 +115,14 @@ var fileTests = []struct { kanikoContext: buildcontextPath, repo: "test-add", }, + { + description: "test mv add", + dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_mv_add", + configPath: "/workspace/integration_tests/dockerfiles/config_test_mv_add.json", + dockerContext: buildcontextPath, + kanikoContext: buildcontextPath, + repo: "test-mv-add", + }, { description: "test registry", dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_registry", @@ -280,7 +288,7 @@ func main() { } compareOutputs := step{ Name: ubuntuImage, - Args: []string{"cmp", test.configPath, containerDiffOutputFile}, + Args: []string{"cmp", "-b", test.configPath, containerDiffOutputFile}, } y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, containerDiff, catContainerDiffOutput, compareOutputs) diff --git a/pkg/snapshot/layered_map.go b/pkg/snapshot/layered_map.go index 608808ac68..e8574e9136 100644 --- a/pkg/snapshot/layered_map.go +++ b/pkg/snapshot/layered_map.go @@ -16,6 +16,11 @@ limitations under the License. package snapshot +import ( + "path/filepath" + "strings" +) + type LayeredMap struct { layers []map[string]string hasher func(string) (string, error) @@ -33,6 +38,21 @@ func (l *LayeredMap) Snapshot() { l.layers = append(l.layers, map[string]string{}) } +func (l *LayeredMap) GetFlattenedPathsForWhiteOut() map[string]struct{} { + paths := map[string]struct{}{} + for _, l := range l.layers { + for p := range l { + if strings.HasPrefix(filepath.Base(p), ".wh.") { + delete(paths, p) + } else { + paths[p] = struct{}{} + } + paths[p] = struct{}{} + } + } + return paths +} + func (l *LayeredMap) Get(s string) (string, bool) { for i := len(l.layers) - 1; i >= 0; i-- { if v, ok := l.layers[i][s]; ok { diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 1966537fb8..70cfcd117c 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -33,6 +33,7 @@ import ( type Snapshotter struct { l *LayeredMap directory string + hardlinks map[uint64]string } // NewSnapshotter creates a new snapshotter rooted at d @@ -60,10 +61,7 @@ func (s *Snapshotter) TakeSnapshot(files []string) ([]byte, error) { if err != nil { return nil, err } - contents, err := ioutil.ReadAll(buf) - if err != nil { - return nil, err - } + contents := buf.Bytes() if !filesAdded { return nil, nil } @@ -99,7 +97,7 @@ func (s *Snapshotter) TakeSnapshotOfFiles(files []string) ([]byte, error) { } if maybeAdd { filesAdded = true - util.AddToTar(file, info, w) + util.AddToTar(file, info, s.hardlinks, w) } } if !filesAdded { @@ -109,27 +107,55 @@ func (s *Snapshotter) TakeSnapshotOfFiles(files []string) ([]byte, error) { } func (s *Snapshotter) snapShotFS(f io.Writer) (bool, error) { + s.hardlinks = map[uint64]string{} s.l.Snapshot() + existingPaths := s.l.GetFlattenedPathsForWhiteOut() filesAdded := false w := tar.NewWriter(f) defer w.Close() - err := filepath.Walk(s.directory, func(path string, info os.FileInfo, err error) error { + // Save the fs state in a map to iterate over later. + memFs := map[string]os.FileInfo{} + filepath.Walk(s.directory, func(path string, info os.FileInfo, err error) error { + memFs[path] = info + return nil + }) + + // First handle whiteouts + for p := range memFs { + delete(existingPaths, p) + } + for path := range existingPaths { + // Only add the whiteout if the directory for the file still exists. + dir := filepath.Dir(path) + if _, ok := memFs[dir]; ok { + logrus.Infof("Adding whiteout for %s", path) + filesAdded = true + if err := util.Whiteout(path, w); err != nil { + return false, err + } + } + } + + // Now create the tar. + for path, info := range memFs { if util.PathInWhitelist(path, s.directory) { logrus.Debugf("Not adding %s to layer, as it's whitelisted", path) - return nil + continue } // Only add to the tar if we add it to the layeredmap. maybeAdd, err := s.l.MaybeAdd(path) if err != nil { - return err + return false, err } if maybeAdd { filesAdded = true - return util.AddToTar(path, info, w) + if err := util.AddToTar(path, info, s.hardlinks, w); err != nil { + return false, err + } } - return nil - }) - return filesAdded, err + } + + return filesAdded, nil } diff --git a/pkg/util/tar_util.go b/pkg/util/tar_util.go index 707ce6c294..c752c98c75 100644 --- a/pkg/util/tar_util.go +++ b/pkg/util/tar_util.go @@ -23,6 +23,7 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "syscall" pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" @@ -31,10 +32,8 @@ import ( "github.com/sirupsen/logrus" ) -var hardlinks = make(map[uint64]string) - // AddToTar adds the file i to tar w at path p -func AddToTar(p string, i os.FileInfo, w *tar.Writer) error { +func AddToTar(p string, i os.FileInfo, hardlinks map[uint64]string, w *tar.Writer) error { linkDst := "" if i.Mode()&os.ModeSymlink != 0 { var err error @@ -49,7 +48,7 @@ func AddToTar(p string, i os.FileInfo, w *tar.Writer) error { } hdr.Name = p - hardlink, linkDst := checkHardlink(p, i) + hardlink, linkDst := checkHardlink(p, hardlinks, i) if hardlink { hdr.Linkname = linkDst hdr.Typeflag = tar.TypeLink @@ -72,8 +71,23 @@ func AddToTar(p string, i os.FileInfo, w *tar.Writer) error { return nil } +func Whiteout(p string, w *tar.Writer) error { + dir := filepath.Dir(p) + name := ".wh." + filepath.Base(p) + + th := &tar.Header{ + Name: filepath.Join(dir, name), + Size: 0, + } + if err := w.WriteHeader(th); err != nil { + return err + } + + return nil +} + // Returns true if path is hardlink, and the link destination -func checkHardlink(p string, i os.FileInfo) (bool, string) { +func checkHardlink(p string, hardlinks map[uint64]string, i os.FileInfo) (bool, string) { hardlink := false linkDst := "" if sys := i.Sys(); sys != nil { diff --git a/pkg/util/tar_util_test.go b/pkg/util/tar_util_test.go index 053eaf7aea..1762ea6f29 100644 --- a/pkg/util/tar_util_test.go +++ b/pkg/util/tar_util_test.go @@ -101,7 +101,7 @@ func createTar(testdir string, writer io.Writer) error { if err != nil { return err } - if err := AddToTar(filePath, fi, w); err != nil { + if err := AddToTar(filePath, fi, map[uint64]string{}, w); err != nil { return err } } From 7dbc7a04a7e03a8249887474b3b5af8f3e492acc Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Mon, 23 Apr 2018 17:09:29 -0700 Subject: [PATCH 15/69] Support multi stage builds --- cmd/executor/cmd/root.go | 11 +- .../dockerfiles/Dockerfile_test_multistage | 8 + .../dockerfiles/config_test_multistage.json | 12 ++ integration_tests/integration_test_yaml.go | 8 + pkg/commands/copy.go | 15 +- pkg/commands/env.go | 6 + pkg/dockerfile/dockerfile.go | 72 ++++++++- pkg/dockerfile/dockerfile_test.go | 96 ++++++++++++ pkg/executor/executor.go | 142 +++++++++++------- pkg/util/command_util.go | 2 +- pkg/util/fs_util.go | 32 +++- test.sh | 2 +- 12 files changed, 341 insertions(+), 65 deletions(-) create mode 100644 integration_tests/dockerfiles/Dockerfile_test_multistage create mode 100644 integration_tests/dockerfiles/config_test_multistage.json create mode 100644 pkg/dockerfile/dockerfile_test.go diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 2c8e9b69aa..8a03af8314 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -23,9 +23,9 @@ import ( "github.com/genuinetools/amicontained/container" - "github.com/GoogleContainerTools/kaniko/pkg/executor" - "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/executor" + "github.com/GoogleContainerTools/kaniko/pkg/image" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -72,7 +72,12 @@ var RootCmd = &cobra.Command{ } logrus.Warn("kaniko is being run outside of a container. This can have dangerous effects on your system") } - if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil { + buildImage, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode) + if err != nil { + logrus.Error(err) + os.Exit(1) + } + if err := image.PushImage(buildImage, destination, dockerInsecureSkipTLSVerify); err != nil { logrus.Error(err) os.Exit(1) } diff --git a/integration_tests/dockerfiles/Dockerfile_test_multistage b/integration_tests/dockerfiles/Dockerfile_test_multistage new file mode 100644 index 0000000000..3833e88065 --- /dev/null +++ b/integration_tests/dockerfiles/Dockerfile_test_multistage @@ -0,0 +1,8 @@ +FROM gcr.io/distroless/base:latest +COPY . . + +FROM scratch as second +COPY --from=0 context/foo /foo + +FROM gcr.io/distroless/base:latest +COPY --from=second /foo /foo2 diff --git a/integration_tests/dockerfiles/config_test_multistage.json b/integration_tests/dockerfiles/config_test_multistage.json new file mode 100644 index 0000000000..9aa0494cb8 --- /dev/null +++ b/integration_tests/dockerfiles/config_test_multistage.json @@ -0,0 +1,12 @@ +[ + { + "Image1": "gcr.io/kaniko-test/docker-test-multistage:latest", + "Image2": "gcr.io/kaniko-test/kaniko-test-multistage:latest", + "DiffType": "File", + "Diff": { + "Adds": null, + "Dels": null, + "Mods": null + } + } +] \ No newline at end of file diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index fc01d48485..a9f09e3a4d 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -139,6 +139,14 @@ var fileTests = []struct { kanikoContext: buildcontextPath, repo: "test-scratch", }, + { + description: "test multistage", + dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_multistage", + configPath: "/workspace/integration_tests/dockerfiles/config_test_multistage.json", + dockerContext: buildcontextPath, + kanikoContext: buildcontextPath, + repo: "test-multistage", + }, } var structureTests = []struct { diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index bded4bf99c..3d617a3db1 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -17,6 +17,7 @@ limitations under the License. package commands import ( + "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" @@ -39,6 +40,11 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { logrus.Infof("cmd: copy %s", srcs) logrus.Infof("dest: %s", dest) + // Resolve from + if c.cmd.From != "" { + c.buildcontext = filepath.Join(constants.BuildContextDir, c.cmd.From) + } + // First, resolve any environment replacement resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.cmd.SourcesAndDest, config.Env, true) if err != nil { @@ -57,11 +63,18 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { if err != nil { return err } - destPath, err := util.DestinationFilepath(src, dest, config.WorkingDir) + cwd := config.WorkingDir + if cwd == "" { + cwd = constants.RootDir + } + destPath, err := util.DestinationFilepath(src, dest, cwd) if err != nil { return err } if fi.IsDir() { + if !filepath.IsAbs(dest) { + dest = filepath.Join(cwd, dest) + } if err := util.CopyDir(fullPath, dest); err != nil { return err } diff --git a/pkg/commands/env.go b/pkg/commands/env.go index acb379e23f..691315f6db 100644 --- a/pkg/commands/env.go +++ b/pkg/commands/env.go @@ -29,6 +29,12 @@ type EnvCommand struct { cmd *instructions.EnvCommand } +func NewEnvCommand(cmd *instructions.EnvCommand) EnvCommand { + return EnvCommand{ + cmd: cmd, + } +} + func (e *EnvCommand) ExecuteCommand(config *manifest.Schema2Config) error { logrus.Info("cmd: ENV") newEnvs := e.cmd.Env diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index f755a547e8..c5e91f256b 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -18,10 +18,15 @@ package dockerfile import ( "bytes" - "strings" - + "github.com/GoogleContainerTools/kaniko/pkg/commands" + "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/image" + "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/docker/docker/builder/dockerfile/parser" + "path/filepath" + "strconv" + "strings" ) // Parse parses the contents of a Dockerfile and returns a list of commands @@ -37,6 +42,25 @@ func Parse(b []byte) ([]instructions.Stage, error) { return stages, err } +// ResolveStages resolves any calls to previous stages to the number value of that stage +// Ex. --from=second_stage should be --from=1 for easier processing later on +func ResolveStages(stages []instructions.Stage) { + nameToIndex := make(map[string]string) + for i, stage := range stages { + index := strconv.Itoa(i) + nameToIndex[stage.Name] = index + nameToIndex[index] = index + for _, cmd := range stage.Commands { + switch c := cmd.(type) { + case *instructions.CopyCommand: + if c.From != "" { + c.From = nameToIndex[c.From] + } + } + } + } +} + // ParseCommands parses an array of commands into an array of instructions.Command; used for onbuild func ParseCommands(cmdArray []string) ([]instructions.Command, error) { var cmds []instructions.Command @@ -54,3 +78,47 @@ func ParseCommands(cmdArray []string) ([]instructions.Command, error) { } return cmds, nil } + +// Dependencies returns a list of files in this stage that will be needed in later stages +func Dependencies(index int, stages []instructions.Stage) ([]string, error) { + var dependencies []string + for stageIndex, stage := range stages { + if stageIndex <= index { + continue + } + ms, err := image.NewSourceImage(stage.BaseName) + if err != nil { + return nil, err + } + for _, cmd := range stage.Commands { + switch c := cmd.(type) { + case *instructions.EnvCommand: + envCommand := commands.NewEnvCommand(c) + if err := envCommand.ExecuteCommand(ms.Config()); err != nil { + return nil, err + } + case *instructions.CopyCommand: + if c.From != strconv.Itoa(index) { + continue + } + // First, resolve any environment replacement + resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.SourcesAndDest, ms.Config().Env, true) + if err != nil { + return nil, err + } + // Resolve wildcards and get a list of resolved sources + srcs, err := util.ResolveSources(resolvedEnvs, constants.RootDir) + if err != nil { + return nil, err + } + for index, src := range srcs { + if !filepath.IsAbs(src) { + srcs[index] = filepath.Join(constants.RootDir, src) + } + } + dependencies = append(dependencies, srcs...) + } + } + } + return dependencies, nil +} diff --git a/pkg/dockerfile/dockerfile_test.go b/pkg/dockerfile/dockerfile_test.go new file mode 100644 index 0000000000..4c4c7e39c6 --- /dev/null +++ b/pkg/dockerfile/dockerfile_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockerfile + +import ( + "fmt" + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "testing" +) + +var dockerfile = ` +FROM scratch +RUN echo hi > /hi + +FROM scratch AS second +COPY --from=0 /hi /hi2 + +FROM scratch +COPY --from=second /hi2 /hi3 +` + +func Test_ResolveStages(t *testing.T) { + stages, err := Parse([]byte(dockerfile)) + if err != nil { + t.Fatal(err) + } + ResolveStages(stages) + for index, stage := range stages { + if index == 0 { + continue + } + copyCmd := stage.Commands[0].(*instructions.CopyCommand) + expectedStage := strconv.Itoa(index - 1) + if copyCmd.From != expectedStage { + t.Fatalf("unexpected copy command: %s resolved to stage %s, expected %s", copyCmd.String(), copyCmd.From, expectedStage) + } + } +} + +func Test_Dependencies(t *testing.T) { + testDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + helloPath := filepath.Join(testDir, "hello") + if err := os.Mkdir(helloPath, 0755); err != nil { + t.Fatal(err) + } + + dockerfile := fmt.Sprintf(` + FROM scratch + COPY %s %s + + FROM scratch AS second + ENV hienv %s + COPY a b + COPY --from=0 /$hienv %s /hi2/ + `, helloPath, helloPath, helloPath, testDir) + + stages, err := Parse([]byte(dockerfile)) + if err != nil { + t.Fatal(err) + } + + expectedDependencies := [][]string{ + { + helloPath, + testDir, + }, + nil, + } + + for index := range stages { + actualDeps, err := Dependencies(index, stages) + testutil.CheckErrorAndDeepEqual(t, false, err, expectedDependencies[index], actualDeps) + } +} diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index ab9eacd53f..3dc14fb552 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -18,9 +18,7 @@ package executor import ( "fmt" - "io/ioutil" - "os" - + img "github.com/GoogleContainerTools/container-diff/pkg/image" "github.com/GoogleContainerTools/kaniko/pkg/commands" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" @@ -30,72 +28,76 @@ import ( "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/sirupsen/logrus" + "io/ioutil" + "os" + "path/filepath" + "strconv" ) -func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool) error { +// DoBuild executes each stage of the build +func DoBuild(dockerfilePath, srcContext, snapshotMode string) (*img.MutableSource, error) { // Parse dockerfile and unpack base image to root d, err := ioutil.ReadFile(dockerfilePath) if err != nil { - return err + return nil, err } stages, err := dockerfile.Parse(d) if err != nil { - return err - } - baseImage := stages[0].BaseName - - // Unpack file system to root - logrus.Infof("Unpacking filesystem of %s...", baseImage) - if err := util.ExtractFileSystemFromImage(baseImage); err != nil { - return err + return nil, err } + dockerfile.ResolveStages(stages) hasher, err := getHasher(snapshotMode) if err != nil { - return err - } - l := snapshot.NewLayeredMap(hasher) - snapshotter := snapshot.NewSnapshotter(l, constants.RootDir) - - // Take initial snapshot - if err := snapshotter.Init(); err != nil { - return err + return nil, err } - // Initialize source image - sourceImage, err := image.NewSourceImage(baseImage) - if err != nil { - return err - } + for index, stage := range stages { + baseImage := stage.BaseName + finalStage := index == len(stages)-1 + // Unpack file system to root + logrus.Infof("Unpacking filesystem of %s...", baseImage) + if err := util.ExtractFileSystemFromImage(baseImage); err != nil { + return nil, err + } - // Set environment variables within the image - if err := image.SetEnvVariables(sourceImage); err != nil { - return err - } + l := snapshot.NewLayeredMap(hasher) + snapshotter := snapshot.NewSnapshotter(l, constants.RootDir) - imageConfig := sourceImage.Config() - // Currently only supports single stage builds - for _, stage := range stages { + // Take initial snapshot + if err := snapshotter.Init(); err != nil { + return nil, err + } + // Initialize source image + sourceImage, err := image.NewSourceImage(baseImage) + if err != nil { + return nil, err + } + imageConfig := sourceImage.Config() if err := resolveOnBuild(&stage, imageConfig); err != nil { - return err + return nil, err } + for _, cmd := range stage.Commands { dockerCommand, err := commands.GetCommand(cmd, srcContext) if err != nil { - return err + return nil, err } if dockerCommand == nil { continue } if err := dockerCommand.ExecuteCommand(imageConfig); err != nil { - return err + return nil, err + } + if !finalStage { + continue } // Now, we get the files to snapshot from this command and take the snapshot snapshotFiles := dockerCommand.FilesToSnapshot() contents, err := snapshotter.TakeSnapshot(snapshotFiles) if err != nil { - return err + return nil, err } util.MoveVolumeWhitelistToWhitelist() if contents == nil { @@ -105,15 +107,58 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke } // Append the layer to the image if err := sourceImage.AppendLayer(contents, constants.Author); err != nil { - return err + return nil, err } } + if finalStage { + return sourceImage, nil + } + if err := saveStageDependencies(index, stages); err != nil { + return nil, err + } + // Delete the filesystem + if err := util.DeleteFilesystem(); err != nil { + return nil, err + } + } + return nil, nil +} + +func saveStageDependencies(index int, stages []instructions.Stage) error { + // First, get the files in this stage later stages will need + dependencies, err := dockerfile.Dependencies(index, stages) + logrus.Infof("saving dependencies %s", dependencies) + if err != nil { + return err } - // Push the image - if err := setDefaultEnv(); err != nil { + // Then, create the directory they will exist in + i := strconv.Itoa(index) + dependencyDir := filepath.Join(constants.BuildContextDir, i) + if err := os.MkdirAll(dependencyDir, 0755); err != nil { return err } - return image.PushImage(sourceImage, destination, dockerInsecureSkipTLSVerify) + // Now, copy over dependencies to this dir + for _, d := range dependencies { + fi, err := os.Lstat(d) + if err != nil { + return err + } + dest := filepath.Join(dependencyDir, d) + if fi.IsDir() { + if err := util.CopyDir(d, dest); err != nil { + return err + } + } else if fi.Mode()&os.ModeSymlink != 0 { + if err := util.CopySymlink(d, dest); err != nil { + return err + } + } else { + if err := util.CopyFile(d, dest); err != nil { + return err + } + } + } + return nil } func getHasher(snapshotMode string) (func(string) (string, error), error) { @@ -141,18 +186,3 @@ func resolveOnBuild(stage *instructions.Stage, config *manifest.Schema2Config) e logrus.Infof("Executing %v build triggers", len(cmds)) return nil } - -// setDefaultEnv sets default values for HOME and PATH so that -// config.json and docker-credential-gcr can be accessed -func setDefaultEnv() error { - defaultEnvs := map[string]string{ - "HOME": "/root", - "PATH": "/usr/local/bin/", - } - for key, val := range defaultEnvs { - if err := os.Setenv(key, val); err != nil { - return err - } - } - return nil -} diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 20efd19a37..c8788a4941 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -178,7 +178,7 @@ func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSources []stri } if len(resolvedSources) == 1 { - fi, err := os.Stat(filepath.Join(root, resolvedSources[0])) + fi, err := os.Lstat(filepath.Join(root, resolvedSources[0])) if err != nil { return err } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index f5c96b80b1..e32517c9ab 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -56,6 +56,33 @@ func ExtractFileSystemFromImage(img string) error { return pkgutil.GetFileSystemFromReference(ref, imgSrc, constants.RootDir, whitelist) } +// DeleteFilesystem deletes the extracted image file system +func DeleteFilesystem() error { + logrus.Info("Deleting filesystem...") + err := filepath.Walk(constants.RootDir, func(path string, info os.FileInfo, err error) error { + if PathInWhitelist(path, constants.RootDir) || ChildDirInWhitelist(path, constants.RootDir) { + logrus.Debugf("Not deleting %s, as it's whitelisted", path) + return nil + } + if path == constants.RootDir { + return nil + } + return os.RemoveAll(path) + }) + return err +} + +// ChildDirInWhitelist returns true if there is a child file or directory of the path in the whitelist +func ChildDirInWhitelist(path, directory string) bool { + for _, d := range whitelist { + dirPath := filepath.Join(directory, d) + if pkgutil.HasFilepathPrefix(dirPath, path) { + return true + } + } + return false +} + // PathInWhitelist returns true if the path is whitelisted func PathInWhitelist(path, directory string) bool { for _, c := range constants.KanikoBuildFiles { @@ -135,6 +162,9 @@ func Files(root string) ([]string, error) { var files []string logrus.Debugf("Getting files and contents at root %s", root) err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if PathInWhitelist(path, root) { + return nil + } files = append(files, path) return err }) @@ -219,7 +249,7 @@ func CopyDir(src, dest string) error { } for _, file := range files { fullPath := filepath.Join(src, file) - fi, err := os.Stat(fullPath) + fi, err := os.Lstat(fullPath) if err != nil { return err } diff --git a/test.sh b/test.sh index 1ca29155d2..a1b16b244f 100755 --- a/test.sh +++ b/test.sh @@ -21,7 +21,7 @@ GREEN='\033[0;32m' RESET='\033[0m' echo "Running go tests..." -go test -cover -v -tags "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs" -timeout 60s `go list ./... | grep -v vendor` | sed ''/PASS/s//$(printf "${GREEN}PASS${RESET}")/'' | sed ''/FAIL/s//$(printf "${RED}FAIL${RESET}")/'' +go test -cover -v -tags "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs exclude_graphdriver_overlay" -timeout 60s `go list ./... | grep -v vendor` | sed ''/PASS/s//$(printf "${GREEN}PASS${RESET}")/'' | sed ''/FAIL/s//$(printf "${RED}FAIL${RESET}")/'' GO_TEST_EXIT_CODE=${PIPESTATUS[0]} if [[ $GO_TEST_EXIT_CODE -ne 0 ]]; then exit $GO_TEST_EXIT_CODE From cf713fe0cd39745cd08cac794d4357b76acf861b Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Mon, 23 Apr 2018 18:10:34 -0700 Subject: [PATCH 16/69] fixed bug in copy --- integration_tests/dockerfiles/Dockerfile_test_multistage | 3 ++- pkg/commands/copy.go | 3 ++- pkg/dockerfile/dockerfile.go | 2 +- pkg/util/fs_util.go | 3 +++ pkg/util/fs_util_test.go | 2 -- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/integration_tests/dockerfiles/Dockerfile_test_multistage b/integration_tests/dockerfiles/Dockerfile_test_multistage index 3833e88065..18fa2d2c15 100644 --- a/integration_tests/dockerfiles/Dockerfile_test_multistage +++ b/integration_tests/dockerfiles/Dockerfile_test_multistage @@ -2,7 +2,8 @@ FROM gcr.io/distroless/base:latest COPY . . FROM scratch as second -COPY --from=0 context/foo /foo +ENV foopath context/foo +COPY --from=0 $foopath context/b* /foo/ FROM gcr.io/distroless/base:latest COPY --from=second /foo /foo2 diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 3d617a3db1..c2ca45fc2e 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -73,7 +73,8 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { } if fi.IsDir() { if !filepath.IsAbs(dest) { - dest = filepath.Join(cwd, dest) + // we need to add '/' to the end to indicate the destination is a directory + dest = filepath.Join(cwd, dest) + "/" } if err := util.CopyDir(fullPath, dest); err != nil { return err diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index c5e91f256b..8cf98910aa 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -42,7 +42,7 @@ func Parse(b []byte) ([]instructions.Stage, error) { return stages, err } -// ResolveStages resolves any calls to previous stages to the number value of that stage +// ResolveStages resolves any calls to previous stages with names to indices // Ex. --from=second_stage should be --from=1 for easier processing later on func ResolveStages(stages []instructions.Stage) { nameToIndex := make(map[string]string) diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index e32517c9ab..fa236a771d 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -144,6 +144,9 @@ func RelativeFiles(fp string, root string) ([]string, error) { fullPath := filepath.Join(root, fp) logrus.Debugf("Getting files and contents at root %s", fullPath) err := filepath.Walk(fullPath, func(path string, info os.FileInfo, err error) error { + if PathInWhitelist(path, root) { + return nil + } if err != nil { return err } diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 36583564c1..be2574d13f 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -106,10 +106,8 @@ var tests = []struct { expectedFiles: []string{ "workspace/foo/a", "workspace/foo/b", - "kaniko/file", "workspace", "workspace/foo", - "kaniko", ".", }, }, From 61d3c66b5f3779c47ce132533765a8550a53f816 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Tue, 24 Apr 2018 13:19:09 -0700 Subject: [PATCH 17/69] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1603c767ee..f3133bf89d 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ The majority of Dockerfile commands can be executed with kaniko, but we're still Multi-Stage Dockerfiles are also unsupported currently, but will be ready soon. +kaniko also does not support building Windows containers. + ## Development ### kaniko Build Contexts kaniko supports local directories and GCS buckets as build contexts. To specify a local directory, pass in the `--context` flag as an argument to the executor image. From a211c1ec71a1b48598b4e2439f71cee34b47f219 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Tue, 24 Apr 2018 14:56:30 -0700 Subject: [PATCH 18/69] Make sure to snapshot parent directories of specific files for add/copy --- pkg/commands/copy.go | 11 ++++++- pkg/snapshot/snapshot.go | 60 +++++++++++++++++++++-------------- pkg/snapshot/snapshot_test.go | 21 ++++-------- pkg/util/fs_util.go | 17 ++++++++++ pkg/util/fs_util_test.go | 32 +++++++++++++++++++ 5 files changed, 102 insertions(+), 39 deletions(-) diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index bded4bf99c..1ad9d77eca 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -17,6 +17,7 @@ limitations under the License. package commands import ( + "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" @@ -57,11 +58,19 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { if err != nil { return err } - destPath, err := util.DestinationFilepath(src, dest, config.WorkingDir) + cwd := config.WorkingDir + if cwd == "" { + cwd = constants.RootDir + } + destPath, err := util.DestinationFilepath(src, dest, cwd) if err != nil { return err } if fi.IsDir() { + if !filepath.IsAbs(dest) { + // we need to add '/' to the end to indicate the destination is a directory + dest = filepath.Join(cwd, dest) + "/" + } if err := util.CopyDir(fullPath, dest); err != nil { return err } diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 70cfcd117c..5b0a4cc1c0 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -19,10 +19,8 @@ package snapshot import ( "archive/tar" "bytes" - "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/sirupsen/logrus" - "io" "io/ioutil" "os" @@ -52,12 +50,14 @@ func (s *Snapshotter) Init() error { // TakeSnapshot takes a snapshot of the filesystem, avoiding directories in the whitelist, and creates // a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed func (s *Snapshotter) TakeSnapshot(files []string) ([]byte, error) { - if files != nil { - return s.TakeSnapshotOfFiles(files) - } - logrus.Info("Taking snapshot of full filesystem...") buf := bytes.NewBuffer([]byte{}) - filesAdded, err := s.snapShotFS(buf) + var filesAdded bool + var err error + if files == nil { + filesAdded, err = s.snapShotFS(buf) + } else { + filesAdded, err = s.snapshotFiles(buf, files) + } if err != nil { return nil, err } @@ -68,45 +68,57 @@ func (s *Snapshotter) TakeSnapshot(files []string) ([]byte, error) { return contents, err } -// TakeSnapshotOfFiles takes a snapshot of specific files +// snapshotFiles takes a snapshot of specific files // Used for ADD/COPY commands, when we know which files have changed -func (s *Snapshotter) TakeSnapshotOfFiles(files []string) ([]byte, error) { - logrus.Infof("Taking snapshot of files %v...", files) +func (s *Snapshotter) snapshotFiles(f io.Writer, files []string) (bool, error) { + s.hardlinks = map[uint64]string{} s.l.Snapshot() if len(files) == 0 { logrus.Info("No files changed in this command, skipping snapshotting.") - return nil, nil + return false, nil + } + logrus.Infof("Taking snapshot of files %v...", files) + snapshottedFiles := make(map[string]bool) + for _, file := range files { + parentDirs := util.ParentDirectories(file) + files = append(parentDirs, files...) } - buf := bytes.NewBuffer([]byte{}) - w := tar.NewWriter(buf) - defer w.Close() filesAdded := false + w := tar.NewWriter(f) + defer w.Close() + + // Now create the tar. for _, file := range files { - info, err := os.Lstat(file) - if err != nil { - return nil, err + file = filepath.Clean(file) + if val, ok := snapshottedFiles[file]; ok && val { + continue } if util.PathInWhitelist(file, s.directory) { - logrus.Debugf("Not adding %s to layer, as it is whitelisted", file) + logrus.Debugf("Not adding %s to layer, as it's whitelisted", file) continue } + snapshottedFiles[file] = true + info, err := os.Lstat(file) + if err != nil { + return false, err + } // Only add to the tar if we add it to the layeredmap. maybeAdd, err := s.l.MaybeAdd(file) if err != nil { - return nil, err + return false, err } if maybeAdd { filesAdded = true - util.AddToTar(file, info, s.hardlinks, w) + if err := util.AddToTar(file, info, s.hardlinks, w); err != nil { + return false, err + } } } - if !filesAdded { - return nil, nil - } - return ioutil.ReadAll(buf) + return filesAdded, nil } func (s *Snapshotter) snapShotFS(f io.Writer) (bool, error) { + logrus.Info("Taking snapshot of full filesystem...") s.hardlinks = map[uint64]string{} s.l.Snapshot() existingPaths := s.l.GetFlattenedPathsForWhiteOut() diff --git a/pkg/snapshot/snapshot_test.go b/pkg/snapshot/snapshot_test.go index 2def85db0e..7cee2ad118 100644 --- a/pkg/snapshot/snapshot_test.go +++ b/pkg/snapshot/snapshot_test.go @@ -149,30 +149,23 @@ func TestSnapshotFiles(t *testing.T) { if err != nil { t.Fatal(err) } - expectedContents := map[string]string{ - filepath.Join(testDir, "foo"): "newbaz1", - } + expectedFiles := []string{"/tmp", filepath.Join(testDir, "foo")} + // Check contents of the snapshot, make sure contents is equivalent to snapshotFiles reader := bytes.NewReader(contents) tr := tar.NewReader(reader) - numFiles := 0 + var actualFiles []string for { hdr, err := tr.Next() if err == io.EOF { break } - numFiles = numFiles + 1 - if _, isFile := expectedContents[hdr.Name]; !isFile { - t.Fatalf("File %s unexpectedly in tar", hdr.Name) - } - contents, _ := ioutil.ReadAll(tr) - if string(contents) != expectedContents[hdr.Name] { - t.Fatalf("Contents of %s incorrect, expected: %s, actual: %s", hdr.Name, expectedContents[hdr.Name], string(contents)) + if err != nil { + t.Fatal(err) } + actualFiles = append(actualFiles, hdr.Name) } - if numFiles != 1 { - t.Fatalf("%s was not added.", filepath.Join(testDir, "foo")) - } + testutil.CheckErrorAndDeepEqual(t, false, nil, expectedFiles, actualFiles) } func TestEmptySnapshot(t *testing.T) { diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index f5c96b80b1..e2b393d5b8 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -141,6 +141,23 @@ func Files(root string) ([]string, error) { return files, err } +// ParentDirectories returns a list of paths to all parent directories +// Ex. /some/temp/dir -> [/some, /some/temp, /some/temp/dir] +func ParentDirectories(path string) []string { + path = filepath.Clean(path) + dirs := strings.Split(path, "/") + dirPath := constants.RootDir + var paths []string + for _, dir := range dirs { + if dir == "" { + continue + } + dirPath = filepath.Join(dirPath, dir) + paths = append(paths, dirPath) + } + return paths +} + // FilepathExists returns true if the path exists func FilepathExists(path string) bool { _, err := os.Lstat(path) diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 36583564c1..7b41a44644 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -131,3 +131,35 @@ func Test_RelativeFiles(t *testing.T) { testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFiles, actualFiles) } } + +func Test_ParentDirectories(t *testing.T) { + tests := []struct { + name string + path string + expected []string + }{ + { + name: "regular path", + path: "/path/to/dir", + expected: []string{ + "/path", + "/path/to", + "/path/to/dir", + }, + }, + { + name: "current directory", + path: ".", + expected: []string{ + "/", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := ParentDirectories(tt.path) + testutil.CheckErrorAndDeepEqual(t, false, nil, tt.expected, actual) + }) + } +} From 946b11b89427675842187d1ac8dc96066f3ad911 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Wed, 25 Apr 2018 12:59:18 -0700 Subject: [PATCH 19/69] fix parent directory --- pkg/util/fs_util.go | 4 ++-- pkg/util/fs_util_test.go | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index e2b393d5b8..6e832b54bc 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -148,8 +148,8 @@ func ParentDirectories(path string) []string { dirs := strings.Split(path, "/") dirPath := constants.RootDir var paths []string - for _, dir := range dirs { - if dir == "" { + for index, dir := range dirs { + if dir == "" || index == (len(dirs)-1) { continue } dirPath = filepath.Join(dirPath, dir) diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 7b41a44644..a33d3f3bf1 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -144,15 +144,12 @@ func Test_ParentDirectories(t *testing.T) { expected: []string{ "/path", "/path/to", - "/path/to/dir", }, }, { - name: "current directory", - path: ".", - expected: []string{ - "/", - }, + name: "current directory", + path: ".", + expected: nil, }, } From 0343e6b50bc98fe16fdaba6a2dc440fb0b4c66e1 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Wed, 25 Apr 2018 14:09:42 -0700 Subject: [PATCH 20/69] Release executor based off debian for debugging --- deploy/Dockerfile_debug | 25 +++++++++++++++++++++++++ deploy/executor-release.yaml | 5 +++++ 2 files changed, 30 insertions(+) create mode 100644 deploy/Dockerfile_debug diff --git a/deploy/Dockerfile_debug b/deploy/Dockerfile_debug new file mode 100644 index 0000000000..a7af94fe5e --- /dev/null +++ b/deploy/Dockerfile_debug @@ -0,0 +1,25 @@ +# Copyright 2018 Google, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Builds the executor from debian + +FROM gcr.io/google-appengine/debian9:latest +ADD out/executor /kaniko/executor +ADD files/ca-certificates.crt /kaniko/ssl/certs/ +ADD files/docker-credential-gcr /usr/local/bin/ +ADD files/config.json /root/.docker/ +ENV HOME /root +ENV SSL_CERT_DIR=/kaniko/ssl/certs +RUN ["docker-credential-gcr", "config", "--token-source=env"] +ENTRYPOINT ["/kaniko/executor"] diff --git a/deploy/executor-release.yaml b/deploy/executor-release.yaml index c733962ba9..db3d5c5def 100644 --- a/deploy/executor-release.yaml +++ b/deploy/executor-release.yaml @@ -23,3 +23,8 @@ steps: args: ["--dockerfile=/workspace/deploy/Dockerfile", "--context=/workspace/go/src/github.com/GoogleContainerTools/kaniko/", "--destination=gcr.io/kaniko-project/executor:${COMMIT_SHA}"] + # Then, build kaniko:debug + - name: "gcr.io/kaniko-project/executor:latest" + args: ["--dockerfile=/workspace/deploy/Dockerfile_debug", + "--context=/workspace/go/src/github.com/GoogleContainerTools/kaniko/", + "--destination=gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}"] From 02f199e101fc3acd0abd341367e30753c492c938 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Wed, 25 Apr 2018 16:06:17 -0700 Subject: [PATCH 21/69] Update readme for debug image --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f3133bf89d..9e7fa25346 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Please let us know if you have any feature requests or find any bugs! - [Running kaniko in Google Container Builder](#running-kaniko-in-google-container-builder) - [Running kaniko locally](#running-kaniko-locally) - [Pushing to Different Registries](#pushing-to-different-registries) + - [Debug Image](#debug-image) - [Security](#security) - [Comparison with Other Tools](#comparison-with-other-tools) - [Community](#community) @@ -145,6 +146,10 @@ kaniko uses Docker credential helpers to push images to a registry. kaniko comes with support for GCR, but configuring another credential helper should allow pushing to a different registry. +### Debug Image + +We provide `gcr.io/kaniko-project/executor:debug` as a a version of the executor image based off a Debian image. +This provides a shell and can be useful for debugging. ## Security From cd5b744904f5ea7bb1eaa623c11c96a136a71253 Mon Sep 17 00:00:00 2001 From: dlorenc Date: Wed, 25 Apr 2018 19:21:05 -0700 Subject: [PATCH 22/69] Switch from containers/image to go-containerregistry (#140) * Vendor changes for go-containerregistry switch. * Manual changes for go-containerregistry switch. The biggest change is refactoring the tarball unpacking. * Pull more of container-diff out. * More vendor removals. * More unit tests. --- Gopkg.lock | 354 +-- Gopkg.toml | 5 - cmd/executor/cmd/root.go | 4 + deploy/Dockerfile | 1 + pkg/commands/add.go | 5 +- pkg/commands/cmd.go | 7 +- pkg/commands/cmd_test.go | 12 +- pkg/commands/commands.go | 4 +- pkg/commands/copy.go | 11 +- pkg/commands/entrypoint.go | 7 +- pkg/commands/entrypoint_test.go | 11 +- pkg/commands/env.go | 6 +- pkg/commands/env_test.go | 6 +- pkg/commands/expose.go | 9 +- pkg/commands/expose_test.go | 12 +- pkg/commands/label.go | 6 +- pkg/commands/label_test.go | 4 +- pkg/commands/onbuild.go | 4 +- pkg/commands/onbuild_test.go | 4 +- pkg/commands/run.go | 4 +- pkg/commands/user.go | 4 +- pkg/commands/user_test.go | 4 +- pkg/commands/volume.go | 4 +- pkg/commands/volume_test.go | 4 +- pkg/commands/workdir.go | 4 +- pkg/commands/workdir_test.go | 4 +- pkg/executor/executor.go | 85 +- pkg/image/image.go | 73 +- pkg/snapshot/snapshot.go | 1 + pkg/util/fs_util.go | 202 +- pkg/util/fs_util_test.go | 360 ++- pkg/util/tar_util.go | 7 +- vendor/github.com/BurntSushi/toml/COPYING | 14 - .../toml/cmd/toml-test-decoder/COPYING | 14 - .../toml/cmd/toml-test-encoder/COPYING | 14 - .../BurntSushi/toml/cmd/tomlv/COPYING | 14 - vendor/github.com/BurntSushi/toml/decode.go | 509 --- .../github.com/BurntSushi/toml/decode_meta.go | 121 - vendor/github.com/BurntSushi/toml/doc.go | 27 - vendor/github.com/BurntSushi/toml/encode.go | 568 ---- .../BurntSushi/toml/encoding_types.go | 19 - .../BurntSushi/toml/encoding_types_1.1.go | 18 - vendor/github.com/BurntSushi/toml/lex.go | 953 ------ vendor/github.com/BurntSushi/toml/parse.go | 592 ---- .../github.com/BurntSushi/toml/type_check.go | 91 - .../github.com/BurntSushi/toml/type_fields.go | 242 -- .../container-diff/LICENSE | 202 -- .../container-diff/cmd/util/output/output.go | 37 - .../pkg/image/mutable_source.go | 262 -- .../container-diff/pkg/image/proxy_types.go | 64 - .../container-diff/pkg/util/cloud_prepper.go | 76 - .../container-diff/pkg/util/daemon_prepper.go | 93 - .../container-diff/pkg/util/docker_utils.go | 123 - .../container-diff/pkg/util/fs_utils.go | 181 -- .../pkg/util/image_prep_utils.go | 288 -- .../container-diff/pkg/util/image_utils.go | 78 - .../container-diff/pkg/util/tar_prepper.go | 102 - .../container-diff/pkg/util/tar_utils.go | 224 -- .../Microsoft/go-winio/archive/tar/common.go | 344 -- .../Microsoft/go-winio/archive/tar/reader.go | 1002 ------ .../go-winio/archive/tar/stat_atim.go | 20 - .../go-winio/archive/tar/stat_atimespec.go | 20 - .../go-winio/archive/tar/stat_unix.go | 32 - .../Microsoft/go-winio/archive/tar/writer.go | 444 --- .../Microsoft/go-winio/backuptar/noop.go | 4 - .../Microsoft/go-winio/backuptar/tar.go | 439 --- vendor/github.com/Microsoft/hcsshim/LICENSE | 21 - .../Microsoft/hcsshim/activatelayer.go | 28 - .../github.com/Microsoft/hcsshim/baselayer.go | 183 -- .../github.com/Microsoft/hcsshim/callback.go | 79 - vendor/github.com/Microsoft/hcsshim/cgo.go | 7 - .../github.com/Microsoft/hcsshim/container.go | 800 ----- .../Microsoft/hcsshim/createlayer.go | 27 - .../Microsoft/hcsshim/createsandboxlayer.go | 35 - .../Microsoft/hcsshim/deactivatelayer.go | 26 - .../Microsoft/hcsshim/destroylayer.go | 27 - vendor/github.com/Microsoft/hcsshim/errors.go | 261 -- .../Microsoft/hcsshim/expandsandboxsize.go | 26 - .../Microsoft/hcsshim/exportlayer.go | 156 - .../Microsoft/hcsshim/getlayermountpath.go | 55 - .../Microsoft/hcsshim/getsharedbaseimages.go | 22 - vendor/github.com/Microsoft/hcsshim/guid.go | 19 - .../github.com/Microsoft/hcsshim/hcsshim.go | 166 - .../Microsoft/hcsshim/hnsendpoint.go | 323 -- .../github.com/Microsoft/hcsshim/hnsfuncs.go | 40 - .../Microsoft/hcsshim/hnsnetwork.go | 141 - .../github.com/Microsoft/hcsshim/hnspolicy.go | 94 - .../Microsoft/hcsshim/hnspolicylist.go | 200 -- .../Microsoft/hcsshim/importlayer.go | 212 -- .../github.com/Microsoft/hcsshim/interface.go | 188 -- .../Microsoft/hcsshim/layerexists.go | 30 - .../Microsoft/hcsshim/layerutils.go | 111 - vendor/github.com/Microsoft/hcsshim/legacy.go | 758 ----- .../github.com/Microsoft/hcsshim/legacy18.go | 7 - .../github.com/Microsoft/hcsshim/legacy19.go | 7 - .../Microsoft/hcsshim/mksyscall_windows.go | 934 ------ .../Microsoft/hcsshim/nametoguid.go | 20 - .../Microsoft/hcsshim/preparelayer.go | 46 - .../github.com/Microsoft/hcsshim/process.go | 384 --- .../Microsoft/hcsshim/processimage.go | 23 - .../Microsoft/hcsshim/unpreparelayer.go | 27 - vendor/github.com/Microsoft/hcsshim/utils.go | 33 - .../github.com/Microsoft/hcsshim/version.go | 7 - .../Microsoft/hcsshim/waithelper.go | 63 - .../github.com/Microsoft/hcsshim/zhcsshim.go | 1042 ------ vendor/github.com/beorn7/perks/LICENSE | 20 - .../beorn7/perks/quantile/stream.go | 316 -- vendor/github.com/containers/image/LICENSE | 189 -- .../github.com/containers/image/copy/copy.go | 718 ----- .../containers/image/copy/fixtures/Hello.bz2 | 1 - .../containers/image/copy/fixtures/Hello.gz | 1 - .../image/copy/fixtures/Hello.uncompressed | 1 - .../containers/image/copy/fixtures/Hello.xz | 1 - .../containers/image/copy/manifest.go | 115 - .../containers/image/copy/progress_reader.go | 28 - .../github.com/containers/image/copy/sign.go | 31 - .../image/directory/directory_dest.go | 243 -- .../image/directory/directory_src.go | 89 - .../image/directory/directory_transport.go | 187 -- .../image/directory/explicitfilepath/path.go | 56 - .../containers/image/docker/archive/dest.go | 66 - .../containers/image/docker/archive/src.go | 41 - .../image/docker/archive/transport.go | 154 - .../containers/image/docker/daemon/client.go | 69 - .../image/docker/daemon/daemon_dest.go | 135 - .../image/docker/daemon/daemon_src.go | 88 - .../image/docker/daemon/daemon_transport.go | 185 -- .../containers/image/docker/docker_client.go | 439 --- .../containers/image/docker/docker_image.go | 63 - .../image/docker/docker_image_dest.go | 463 --- .../image/docker/docker_image_src.go | 386 --- .../image/docker/docker_transport.go | 161 - .../containers/image/docker/lookaside.go | 202 -- .../docker/policyconfiguration/naming.go | 56 - .../image/docker/reference/helpers.go | 42 - .../image/docker/reference/normalize.go | 152 - .../image/docker/reference/reference.go | 433 --- .../image/docker/reference/regexp.go | 143 - .../containers/image/docker/tarfile/dest.go | 257 -- .../containers/image/docker/tarfile/doc.go | 3 - .../containers/image/docker/tarfile/src.go | 366 --- .../containers/image/docker/tarfile/types.go | 28 - .../image/docker/wwwauthenticate.go | 159 - .../containers/image/image/docker_list.go | 93 - .../containers/image/image/docker_schema1.go | 201 -- .../containers/image/image/docker_schema2.go | 347 -- .../containers/image/image/manifest.go | 67 - .../containers/image/image/memory.go | 70 - .../github.com/containers/image/image/oci.go | 199 -- .../containers/image/image/sourced.go | 106 - .../containers/image/image/unparsed.go | 102 - .../image/internal/tmpdir/tmpdir.go | 19 - .../image/manifest/docker_schema1.go | 310 -- .../image/manifest/docker_schema2.go | 251 -- .../containers/image/manifest/manifest.go | 238 -- .../containers/image/manifest/oci.go | 120 - .../containers/image/oci/archive/oci_dest.go | 131 - .../containers/image/oci/archive/oci_src.go | 95 - .../image/oci/archive/oci_transport.go | 190 -- .../containers/image/oci/internal/oci_util.go | 126 - .../containers/image/oci/layout/oci_dest.go | 294 -- .../containers/image/oci/layout/oci_src.go | 157 - .../image/oci/layout/oci_transport.go | 255 -- .../image/openshift/openshift-copies.go | 1174 ------- .../containers/image/openshift/openshift.go | 544 ---- .../image/openshift/openshift_transport.go | 156 - .../containers/image/ostree/ostree_dest.go | 456 --- .../containers/image/ostree/ostree_src.go | 354 --- .../image/ostree/ostree_transport.go | 251 -- .../image/pkg/compression/compression.go | 67 - .../image/pkg/docker/config/config.go | 295 -- .../containers/image/pkg/strslice/strslice.go | 30 - .../pkg/tlsclientconfig/tlsclientconfig.go | 102 - .../containers/image/signature/docker.go | 65 - .../manifest.json | 1 - .../dir-img-manifest-digest-error/signature-1 | 1 - .../fixtures/dir-img-mixed/manifest.json | 1 - .../fixtures/dir-img-mixed/signature-1 | 1 - .../fixtures/dir-img-mixed/signature-2 | 1 - .../dir-img-modified-manifest/signature-1 | 1 - .../fixtures/dir-img-no-manifest/signature-1 | 1 - .../fixtures/dir-img-unsigned/manifest.json | 1 - .../fixtures/dir-img-valid-2/manifest.json | 1 - .../fixtures/dir-img-valid-2/signature-1 | 1 - .../fixtures/dir-img-valid/manifest.json | 1 - .../containers/image/signature/json.go | 88 - .../containers/image/signature/mechanism.go | 85 - .../image/signature/mechanism_gpgme.go | 175 - .../image/signature/mechanism_openpgp.go | 159 - .../image/signature/policy_config.go | 688 ---- .../containers/image/signature/policy_eval.go | 289 -- .../image/signature/policy_eval_baselayer.go | 18 - .../image/signature/policy_eval_signedby.go | 131 - .../image/signature/policy_eval_simple.go | 28 - .../image/signature/policy_reference_match.go | 101 - .../image/signature/policy_types.go | 152 - .../containers/image/signature/signature.go | 280 -- .../containers/image/storage/storage_image.go | 808 ----- .../image/storage/storage_reference.go | 209 -- .../image/storage/storage_transport.go | 450 --- .../containers/image/tarball/doc.go | 48 - .../image/tarball/tarball_reference.go | 93 - .../containers/image/tarball/tarball_src.go | 260 -- .../image/tarball/tarball_transport.go | 66 - .../transports/alltransports/alltransports.go | 35 - .../image/transports/alltransports/ostree.go | 8 - .../transports/alltransports/ostree_stub.go | 9 - .../image/transports/alltransports/storage.go | 8 - .../transports/alltransports/storage_stub.go | 9 - .../containers/image/transports/stub.go | 36 - .../containers/image/transports/transports.go | 90 - .../containers/image/types/types.go | 388 --- .../containers/image/version/version.go | 18 - vendor/github.com/containers/storage/AUTHORS | 1522 --------- vendor/github.com/containers/storage/LICENSE | 191 -- vendor/github.com/containers/storage/NOTICE | 19 - .../containers/storage/containers.go | 531 ---- .../containers/storage/containers_ffjson.go | 1194 ------- .../containers/storage/drivers/aufs/aufs.go | 691 ---- .../containers/storage/drivers/aufs/dirs.go | 64 - .../containers/storage/drivers/aufs/mount.go | 21 - .../storage/drivers/aufs/mount_linux.go | 7 - .../storage/drivers/aufs/mount_unsupported.go | 12 - .../containers/storage/drivers/btrfs/btrfs.go | 677 ---- .../drivers/btrfs/dummy_unsupported.go | 3 - .../storage/drivers/btrfs/version.go | 26 - .../storage/drivers/btrfs/version_none.go | 14 - .../containers/storage/drivers/counter.go | 59 - .../storage/drivers/devmapper/device_setup.go | 236 -- .../storage/drivers/devmapper/deviceset.go | 2825 ----------------- .../drivers/devmapper/devmapper_doc.go | 106 - .../storage/drivers/devmapper/driver.go | 240 -- .../storage/drivers/devmapper/mount.go | 88 - .../containers/storage/drivers/driver.go | 285 -- .../storage/drivers/driver_freebsd.go | 23 - .../storage/drivers/driver_linux.go | 135 - .../storage/drivers/driver_solaris.go | 96 - .../storage/drivers/driver_unsupported.go | 15 - .../storage/drivers/driver_windows.go | 14 - .../containers/storage/drivers/fsdiff.go | 169 - .../storage/drivers/overlay/check.go | 102 - .../storage/drivers/overlay/mount.go | 89 - .../storage/drivers/overlay/overlay.go | 773 ----- .../drivers/overlay/overlay_unsupported.go | 3 - .../storage/drivers/overlay/randomid.go | 81 - .../drivers/overlayutils/overlayutils.go | 18 - .../storage/drivers/quota/projectquota.go | 337 -- .../storage/drivers/register/register_aufs.go | 8 - .../drivers/register/register_btrfs.go | 8 - .../drivers/register/register_devicemapper.go | 8 - .../drivers/register/register_overlay.go | 8 - .../storage/drivers/register/register_vfs.go | 6 - .../drivers/register/register_windows.go | 6 - .../storage/drivers/register/register_zfs.go | 8 - .../containers/storage/drivers/vfs/driver.go | 160 - .../storage/drivers/windows/windows.go | 965 ------ .../containers/storage/drivers/zfs/zfs.go | 426 --- .../storage/drivers/zfs/zfs_freebsd.go | 39 - .../storage/drivers/zfs/zfs_linux.go | 28 - .../storage/drivers/zfs/zfs_solaris.go | 59 - .../storage/drivers/zfs/zfs_unsupported.go | 11 - .../github.com/containers/storage/errors.go | 56 - .../storage/hack/generate-authors.sh | 15 - .../github.com/containers/storage/images.go | 673 ---- .../containers/storage/images_ffjson.go | 1202 ------- .../github.com/containers/storage/layers.go | 1041 ------ .../containers/storage/layers_ffjson.go | 1713 ---------- .../github.com/containers/storage/lockfile.go | 82 - .../containers/storage/lockfile_darwin.go | 19 - .../containers/storage/lockfile_linux.go | 20 - .../containers/storage/lockfile_unix.go | 115 - .../containers/storage/lockfile_windows.go | 40 - .../containers/storage/pkg/archive/archive.go | 1251 -------- .../storage/pkg/archive/archive_linux.go | 92 - .../storage/pkg/archive/archive_other.go | 7 - .../storage/pkg/archive/archive_unix.go | 122 - .../storage/pkg/archive/archive_windows.go | 79 - .../containers/storage/pkg/archive/changes.go | 441 --- .../storage/pkg/archive/changes_linux.go | 313 -- .../storage/pkg/archive/changes_other.go | 97 - .../storage/pkg/archive/changes_unix.go | 37 - .../storage/pkg/archive/changes_windows.go | 30 - .../containers/storage/pkg/archive/copy.go | 461 --- .../storage/pkg/archive/copy_unix.go | 11 - .../storage/pkg/archive/copy_windows.go | 9 - .../containers/storage/pkg/archive/diff.go | 256 -- .../storage/pkg/archive/example_changes.go | 97 - .../storage/pkg/archive/time_linux.go | 16 - .../storage/pkg/archive/time_unsupported.go | 16 - .../storage/pkg/archive/whiteouts.go | 23 - .../containers/storage/pkg/archive/wrap.go | 59 - .../storage/pkg/chrootarchive/archive.go | 70 - .../storage/pkg/chrootarchive/archive_unix.go | 86 - .../pkg/chrootarchive/archive_windows.go | 22 - .../storage/pkg/chrootarchive/chroot_linux.go | 108 - .../storage/pkg/chrootarchive/chroot_unix.go | 12 - .../storage/pkg/chrootarchive/diff.go | 23 - .../storage/pkg/chrootarchive/diff_unix.go | 130 - .../storage/pkg/chrootarchive/diff_windows.go | 45 - .../storage/pkg/chrootarchive/init_unix.go | 28 - .../storage/pkg/chrootarchive/init_windows.go | 4 - .../storage/pkg/devicemapper/devmapper.go | 821 ----- .../storage/pkg/devicemapper/devmapper_log.go | 121 - .../pkg/devicemapper/devmapper_wrapper.go | 252 -- .../devmapper_wrapper_deferred_remove.go | 31 - .../devicemapper/devmapper_wrapper_dynamic.go | 6 - .../devmapper_wrapper_no_deferred_remove.go | 15 - .../devicemapper/devmapper_wrapper_static.go | 6 - .../storage/pkg/devicemapper/ioctl.go | 28 - .../storage/pkg/devicemapper/log.go | 11 - .../storage/pkg/directory/directory.go | 26 - .../storage/pkg/directory/directory_unix.go | 48 - .../pkg/directory/directory_windows.go | 37 - .../storage/pkg/dmesg/dmesg_linux.go | 20 - .../storage/pkg/fileutils/fileutils.go | 298 -- .../storage/pkg/fileutils/fileutils_darwin.go | 27 - .../pkg/fileutils/fileutils_solaris.go | 7 - .../storage/pkg/fileutils/fileutils_unix.go | 22 - .../pkg/fileutils/fileutils_windows.go | 7 - .../storage/pkg/fsutils/fsutils_linux.go | 88 - .../storage/pkg/homedir/homedir_linux.go | 23 - .../storage/pkg/homedir/homedir_others.go | 13 - .../storage/pkg/homedir/homedir_unix.go | 34 - .../storage/pkg/homedir/homedir_windows.go | 24 - .../containers/storage/pkg/idtools/idtools.go | 279 -- .../storage/pkg/idtools/idtools_unix.go | 204 -- .../storage/pkg/idtools/idtools_windows.go | 25 - .../storage/pkg/idtools/usergroupadd_linux.go | 164 - .../pkg/idtools/usergroupadd_unsupported.go | 12 - .../storage/pkg/idtools/utils_unix.go | 32 - .../containers/storage/pkg/ioutils/buffer.go | 51 - .../storage/pkg/ioutils/bytespipe.go | 186 -- .../storage/pkg/ioutils/fswriters.go | 162 - .../containers/storage/pkg/ioutils/readers.go | 154 - .../storage/pkg/ioutils/temp_unix.go | 10 - .../storage/pkg/ioutils/temp_windows.go | 18 - .../storage/pkg/ioutils/writeflusher.go | 92 - .../containers/storage/pkg/ioutils/writers.go | 66 - .../containers/storage/pkg/locker/locker.go | 112 - .../storage/pkg/longpath/longpath.go | 26 - .../storage/pkg/loopback/attach_loopback.go | 157 - .../containers/storage/pkg/loopback/ioctl.go | 53 - .../storage/pkg/loopback/loop_wrapper.go | 52 - .../storage/pkg/loopback/loopback.go | 63 - .../containers/storage/pkg/mflag/LICENSE | 27 - .../containers/storage/pkg/mount/flags.go | 149 - .../storage/pkg/mount/flags_freebsd.go | 49 - .../storage/pkg/mount/flags_linux.go | 87 - .../storage/pkg/mount/flags_unsupported.go | 31 - .../containers/storage/pkg/mount/mount.go | 106 - .../storage/pkg/mount/mounter_freebsd.go | 60 - .../storage/pkg/mount/mounter_linux.go | 57 - .../storage/pkg/mount/mounter_solaris.go | 34 - .../storage/pkg/mount/mounter_unsupported.go | 11 - .../containers/storage/pkg/mount/mountinfo.go | 54 - .../storage/pkg/mount/mountinfo_freebsd.go | 41 - .../storage/pkg/mount/mountinfo_linux.go | 95 - .../storage/pkg/mount/mountinfo_solaris.go | 37 - .../pkg/mount/mountinfo_unsupported.go | 12 - .../storage/pkg/mount/mountinfo_windows.go | 6 - .../storage/pkg/mount/sharedsubtree_linux.go | 69 - .../pkg/mount/sharedsubtree_solaris.go | 58 - .../storage/pkg/parsers/kernel/kernel.go | 74 - .../pkg/parsers/kernel/kernel_darwin.go | 56 - .../storage/pkg/parsers/kernel/kernel_unix.go | 45 - .../pkg/parsers/kernel/kernel_windows.go | 70 - .../storage/pkg/parsers/kernel/uname_linux.go | 17 - .../pkg/parsers/kernel/uname_solaris.go | 14 - .../pkg/parsers/kernel/uname_unsupported.go | 18 - .../containers/storage/pkg/parsers/parsers.go | 69 - .../containers/storage/pkg/pools/pools.go | 119 - .../containers/storage/pkg/promise/promise.go | 11 - .../storage/pkg/reexec/command_linux.go | 30 - .../storage/pkg/reexec/command_unix.go | 23 - .../storage/pkg/reexec/command_unsupported.go | 12 - .../storage/pkg/reexec/command_windows.go | 23 - .../containers/storage/pkg/reexec/reexec.go | 47 - .../storage/pkg/stringid/stringid.go | 99 - .../containers/storage/pkg/system/chtimes.go | 35 - .../storage/pkg/system/chtimes_unix.go | 14 - .../storage/pkg/system/chtimes_windows.go | 28 - .../containers/storage/pkg/system/errors.go | 10 - .../containers/storage/pkg/system/exitcode.go | 33 - .../containers/storage/pkg/system/filesys.go | 67 - .../storage/pkg/system/filesys_windows.go | 298 -- .../containers/storage/pkg/system/init.go | 22 - .../storage/pkg/system/init_windows.go | 17 - .../storage/pkg/system/lcow_unix.go | 8 - .../storage/pkg/system/lcow_windows.go | 6 - .../storage/pkg/system/lstat_unix.go | 19 - .../storage/pkg/system/lstat_windows.go | 14 - .../containers/storage/pkg/system/meminfo.go | 17 - .../storage/pkg/system/meminfo_linux.go | 65 - .../storage/pkg/system/meminfo_solaris.go | 129 - .../storage/pkg/system/meminfo_unsupported.go | 8 - .../storage/pkg/system/meminfo_windows.go | 45 - .../containers/storage/pkg/system/mknod.go | 22 - .../storage/pkg/system/mknod_windows.go | 13 - .../containers/storage/pkg/system/path.go | 21 - .../storage/pkg/system/path_unix.go | 9 - .../storage/pkg/system/path_windows.go | 33 - .../storage/pkg/system/process_unix.go | 24 - .../containers/storage/pkg/system/rm.go | 80 - .../storage/pkg/system/stat_darwin.go | 13 - .../storage/pkg/system/stat_freebsd.go | 13 - .../storage/pkg/system/stat_linux.go | 19 - .../storage/pkg/system/stat_openbsd.go | 13 - .../storage/pkg/system/stat_solaris.go | 13 - .../storage/pkg/system/stat_unix.go | 60 - .../storage/pkg/system/stat_windows.go | 49 - .../storage/pkg/system/syscall_unix.go | 17 - .../storage/pkg/system/syscall_windows.go | 122 - .../containers/storage/pkg/system/umask.go | 13 - .../storage/pkg/system/umask_windows.go | 9 - .../storage/pkg/system/utimes_freebsd.go | 24 - .../storage/pkg/system/utimes_linux.go | 25 - .../storage/pkg/system/utimes_unsupported.go | 10 - .../storage/pkg/system/xattrs_linux.go | 29 - .../storage/pkg/system/xattrs_unsupported.go | 13 - .../storage/pkg/truncindex/truncindex.go | 139 - vendor/github.com/containers/storage/store.go | 2425 -------------- vendor/github.com/docker/distribution/AUTHORS | 182 -- vendor/github.com/docker/distribution/LICENSE | 202 -- .../github.com/docker/distribution/blobs.go | 257 -- .../docker/distribution/digestset/set.go | 247 -- vendor/github.com/docker/distribution/doc.go | 7 - .../github.com/docker/distribution/errors.go | 115 - .../docker/distribution/manifests.go | 125 - .../docker/distribution/metrics/prometheus.go | 13 - .../docker/distribution/reference/helpers.go | 42 - .../distribution/reference/normalize.go | 170 - .../distribution/reference/reference.go | 433 --- .../docker/distribution/reference/regexp.go | 143 - .../docker/distribution/registry.go | 113 - .../registry/api/errcode/errors.go | 267 -- .../registry/api/errcode/handler.go | 40 - .../registry/api/errcode/register.go | 138 - .../registry/api/v2/descriptors.go | 1596 ---------- .../distribution/registry/api/v2/doc.go | 9 - .../distribution/registry/api/v2/errors.go | 136 - .../registry/api/v2/headerparser.go | 161 - .../distribution/registry/api/v2/routes.go | 49 - .../distribution/registry/api/v2/urls.go | 266 -- .../registry/client/auth/challenge/addr.go | 27 - .../client/auth/challenge/authchallenge.go | 237 -- .../registry/client/blob_writer.go | 162 - .../distribution/registry/client/errors.go | 139 - .../registry/client/repository.go | 869 ----- .../registry/client/transport/http_reader.go | 251 -- .../registry/client/transport/transport.go | 147 - .../registry/storage/cache/cache.go | 35 - .../cache/cachedblobdescriptorstore.go | 129 - .../registry/storage/cache/memory/memory.go | 179 -- vendor/github.com/docker/distribution/tags.go | 27 - .../docker/docker-credential-helpers/LICENSE | 20 - .../client/client.go | 121 - .../client/command.go | 56 - .../credentials/credentials.go | 186 -- .../credentials/error.go | 102 - .../credentials/helper.go | 14 - .../credentials/version.go | 4 - vendor/github.com/docker/docker/api/common.go | 11 - .../docker/docker/api/common_unix.go | 6 - .../docker/docker/api/common_windows.go | 8 - .../docker/docker/api/types/auth.go | 22 - .../docker/docker/api/types/client.go | 390 --- .../docker/docker/api/types/configs.go | 57 - .../docker/docker/api/types/error_response.go | 13 - .../docker/docker/api/types/events/events.go | 52 - .../docker/docker/api/types/filters/parse.go | 350 -- .../docker/api/types/graph_driver_data.go | 17 - .../docker/docker/api/types/id_response.go | 13 - .../docker/api/types/image/image_history.go | 37 - .../api/types/image_delete_response_item.go | 15 - .../docker/docker/api/types/image_summary.go | 49 - .../docker/api/types/network/network.go | 108 - .../docker/docker/api/types/plugin.go | 200 -- .../docker/docker/api/types/plugin_device.go | 25 - .../docker/docker/api/types/plugin_env.go | 25 - .../docker/api/types/plugin_interface_type.go | 21 - .../docker/docker/api/types/plugin_mount.go | 37 - .../docker/api/types/plugin_responses.go | 71 - .../docker/docker/api/types/port.go | 23 - .../docker/api/types/registry/authenticate.go | 21 - .../docker/api/types/registry/registry.go | 119 - .../docker/docker/api/types/seccomp.go | 93 - .../api/types/service_update_response.go | 12 - .../docker/docker/api/types/stats.go | 181 -- .../docker/docker/api/types/swarm/common.go | 40 - .../docker/docker/api/types/swarm/config.go | 31 - .../docker/api/types/swarm/container.go | 73 - .../docker/docker/api/types/swarm/network.go | 119 - .../docker/docker/api/types/swarm/node.go | 115 - .../docker/docker/api/types/swarm/runtime.go | 19 - .../docker/api/types/swarm/runtime/gen.go | 3 - .../api/types/swarm/runtime/plugin.pb.go | 712 ----- .../docker/docker/api/types/swarm/secret.go | 32 - .../docker/docker/api/types/swarm/service.go | 124 - .../docker/docker/api/types/swarm/swarm.go | 217 -- .../docker/docker/api/types/swarm/task.go | 188 -- .../docker/api/types/time/duration_convert.go | 12 - .../docker/docker/api/types/time/timestamp.go | 122 - .../docker/docker/api/types/types.go | 587 ---- .../docker/api/types/versions/compare.go | 62 - .../docker/docker/api/types/volume.go | 69 - .../docker/api/types/volume/volumes_create.go | 29 - .../docker/api/types/volume/volumes_list.go | 23 - .../docker/docker/client/build_prune.go | 30 - .../docker/docker/client/checkpoint_create.go | 13 - .../docker/docker/client/checkpoint_delete.go | 20 - .../docker/docker/client/checkpoint_list.go | 28 - .../github.com/docker/docker/client/client.go | 383 --- .../docker/docker/client/client_unix.go | 9 - .../docker/docker/client/client_windows.go | 7 - .../docker/docker/client/config_create.go | 25 - .../docker/docker/client/config_inspect.go | 33 - .../docker/docker/client/config_list.go | 38 - .../docker/docker/client/config_remove.go | 13 - .../docker/docker/client/config_update.go | 21 - .../docker/docker/client/container_attach.go | 57 - .../docker/docker/client/container_commit.go | 55 - .../docker/docker/client/container_copy.go | 102 - .../docker/docker/client/container_create.go | 56 - .../docker/docker/client/container_diff.go | 23 - .../docker/docker/client/container_exec.go | 54 - .../docker/docker/client/container_export.go | 20 - .../docker/docker/client/container_inspect.go | 47 - .../docker/docker/client/container_kill.go | 17 - .../docker/docker/client/container_list.go | 56 - .../docker/docker/client/container_logs.go | 80 - .../docker/docker/client/container_pause.go | 10 - .../docker/docker/client/container_prune.go | 36 - .../docker/docker/client/container_remove.go | 27 - .../docker/docker/client/container_rename.go | 16 - .../docker/docker/client/container_resize.go | 29 - .../docker/docker/client/container_restart.go | 22 - .../docker/docker/client/container_start.go | 24 - .../docker/docker/client/container_stats.go | 26 - .../docker/docker/client/container_stop.go | 21 - .../docker/docker/client/container_top.go | 28 - .../docker/docker/client/container_unpause.go | 10 - .../docker/docker/client/container_update.go | 22 - .../docker/docker/client/container_wait.go | 84 - .../docker/docker/client/disk_usage.go | 26 - .../docker/client/distribution_inspect.go | 35 - .../github.com/docker/docker/client/errors.go | 133 - .../github.com/docker/docker/client/events.go | 102 - .../github.com/docker/docker/client/hijack.go | 207 -- .../docker/docker/client/image_build.go | 138 - .../docker/docker/client/image_create.go | 38 - .../docker/docker/client/image_history.go | 22 - .../docker/docker/client/image_import.go | 41 - .../docker/docker/client/image_inspect.go | 29 - .../docker/docker/client/image_list.go | 45 - .../docker/docker/client/image_load.go | 30 - .../docker/docker/client/image_prune.go | 36 - .../docker/docker/client/image_pull.go | 65 - .../docker/docker/client/image_push.go | 56 - .../docker/docker/client/image_remove.go | 31 - .../docker/docker/client/image_save.go | 22 - .../docker/docker/client/image_search.go | 51 - .../docker/docker/client/image_tag.go | 37 - .../github.com/docker/docker/client/info.go | 26 - .../docker/docker/client/interface.go | 194 -- .../docker/client/interface_experimental.go | 17 - .../docker/docker/client/interface_stable.go | 10 - .../github.com/docker/docker/client/login.go | 29 - .../docker/docker/client/network_connect.go | 18 - .../docker/docker/client/network_create.go | 25 - .../docker/client/network_disconnect.go | 14 - .../docker/docker/client/network_inspect.go | 46 - .../docker/docker/client/network_list.go | 31 - .../docker/docker/client/network_prune.go | 36 - .../docker/docker/client/network_remove.go | 10 - .../docker/docker/client/node_inspect.go | 29 - .../docker/docker/client/node_list.go | 36 - .../docker/docker/client/node_remove.go | 21 - .../docker/docker/client/node_update.go | 18 - .../github.com/docker/docker/client/ping.go | 32 - .../docker/docker/client/plugin_create.go | 26 - .../docker/docker/client/plugin_disable.go | 19 - .../docker/docker/client/plugin_enable.go | 19 - .../docker/docker/client/plugin_inspect.go | 28 - .../docker/docker/client/plugin_install.go | 113 - .../docker/docker/client/plugin_list.go | 32 - .../docker/docker/client/plugin_push.go | 17 - .../docker/docker/client/plugin_remove.go | 20 - .../docker/docker/client/plugin_set.go | 12 - .../docker/docker/client/plugin_upgrade.go | 39 - .../docker/docker/client/request.go | 262 -- .../docker/docker/client/secret_create.go | 25 - .../docker/docker/client/secret_inspect.go | 33 - .../docker/docker/client/secret_list.go | 38 - .../docker/docker/client/secret_remove.go | 13 - .../docker/docker/client/secret_update.go | 21 - .../docker/docker/client/service_create.go | 166 - .../docker/docker/client/service_inspect.go | 34 - .../docker/docker/client/service_list.go | 35 - .../docker/docker/client/service_logs.go | 52 - .../docker/docker/client/service_remove.go | 10 - .../docker/docker/client/service_update.go | 92 - .../docker/docker/client/session.go | 19 - .../docker/client/swarm_get_unlock_key.go | 21 - .../docker/docker/client/swarm_init.go | 21 - .../docker/docker/client/swarm_inspect.go | 21 - .../docker/docker/client/swarm_join.go | 13 - .../docker/docker/client/swarm_leave.go | 18 - .../docker/docker/client/swarm_unlock.go | 13 - .../docker/docker/client/swarm_update.go | 22 - .../docker/docker/client/task_inspect.go | 29 - .../docker/docker/client/task_list.go | 35 - .../docker/docker/client/task_logs.go | 52 - .../docker/docker/client/tlsconfig_clone.go | 11 - .../docker/client/tlsconfig_clone_go17.go | 33 - .../docker/docker/client/transport.go | 17 - .../github.com/docker/docker/client/utils.go | 34 - .../docker/docker/client/version.go | 21 - .../docker/docker/client/volume_create.go | 21 - .../docker/docker/client/volume_inspect.go | 42 - .../docker/docker/client/volume_list.go | 32 - .../docker/docker/client/volume_prune.go | 36 - .../docker/docker/client/volume_remove.go | 21 - .../docker/pkg/homedir/homedir_linux.go | 21 - .../docker/pkg/homedir/homedir_others.go | 13 - .../docker/docker/pkg/homedir/homedir_unix.go | 34 - .../docker/pkg/homedir/homedir_windows.go | 24 - .../go-connections/sockets/inmem_socket.go | 81 - .../docker/go-connections/sockets/proxy.go | 51 - .../docker/go-connections/sockets/sockets.go | 38 - .../go-connections/sockets/sockets_unix.go | 35 - .../go-connections/sockets/sockets_windows.go | 27 - .../go-connections/sockets/tcp_socket.go | 22 - .../go-connections/sockets/unix_socket.go | 32 - .../go-connections/tlsconfig/certpool_go17.go | 18 - .../tlsconfig/certpool_other.go | 14 - .../docker/go-connections/tlsconfig/config.go | 244 -- .../tlsconfig/config_client_ciphers.go | 17 - .../tlsconfig/config_legacy_client_ciphers.go | 15 - .../github.com/docker/go-metrics/LICENSE.code | 191 -- .../github.com/docker/go-metrics/LICENSE.docs | 425 --- vendor/github.com/docker/go-metrics/NOTICE | 16 - .../github.com/docker/go-metrics/counter.go | 52 - vendor/github.com/docker/go-metrics/docs.go | 3 - vendor/github.com/docker/go-metrics/gauge.go | 72 - .../github.com/docker/go-metrics/handler.go | 74 - .../github.com/docker/go-metrics/helpers.go | 10 - .../github.com/docker/go-metrics/namespace.go | 315 -- .../github.com/docker/go-metrics/register.go | 15 - vendor/github.com/docker/go-metrics/timer.go | 85 - vendor/github.com/docker/go-metrics/unit.go | 12 - vendor/github.com/docker/libtrust/LICENSE | 191 -- .../docker/libtrust/certificates.go | 175 - vendor/github.com/docker/libtrust/doc.go | 9 - vendor/github.com/docker/libtrust/ec_key.go | 428 --- vendor/github.com/docker/libtrust/filter.go | 50 - vendor/github.com/docker/libtrust/hash.go | 56 - vendor/github.com/docker/libtrust/jsonsign.go | 657 ---- vendor/github.com/docker/libtrust/key.go | 253 -- .../github.com/docker/libtrust/key_files.go | 255 -- .../github.com/docker/libtrust/key_manager.go | 175 - vendor/github.com/docker/libtrust/rsa_key.go | 427 --- vendor/github.com/docker/libtrust/util.go | 363 --- vendor/github.com/ghodss/yaml/LICENSE | 50 - vendor/github.com/ghodss/yaml/fields.go | 501 --- vendor/github.com/ghodss/yaml/yaml.go | 277 -- vendor/github.com/gogo/protobuf/AUTHORS | 15 - vendor/github.com/gogo/protobuf/CONTRIBUTORS | 23 - .../gogo/protobuf/GOLANG_CONTRIBUTORS | 5 - vendor/github.com/gogo/protobuf/LICENSE | 36 - .../github.com/gogo/protobuf/proto/clone.go | 234 -- .../github.com/gogo/protobuf/proto/decode.go | 978 ------ .../gogo/protobuf/proto/decode_gogo.go | 172 - .../github.com/gogo/protobuf/proto/discard.go | 151 - .../gogo/protobuf/proto/duration.go | 100 - .../gogo/protobuf/proto/duration_gogo.go | 203 -- .../github.com/gogo/protobuf/proto/encode.go | 1362 -------- .../gogo/protobuf/proto/encode_gogo.go | 350 -- .../github.com/gogo/protobuf/proto/equal.go | 300 -- .../gogo/protobuf/proto/extensions.go | 693 ---- .../gogo/protobuf/proto/extensions_gogo.go | 294 -- vendor/github.com/gogo/protobuf/proto/lib.go | 897 ------ .../gogo/protobuf/proto/lib_gogo.go | 42 - .../gogo/protobuf/proto/message_set.go | 311 -- .../gogo/protobuf/proto/pointer_reflect.go | 484 --- .../protobuf/proto/pointer_reflect_gogo.go | 85 - .../gogo/protobuf/proto/pointer_unsafe.go | 270 -- .../protobuf/proto/pointer_unsafe_gogo.go | 128 - .../gogo/protobuf/proto/properties.go | 971 ------ .../gogo/protobuf/proto/properties_gogo.go | 111 - .../gogo/protobuf/proto/skip_gogo.go | 119 - vendor/github.com/gogo/protobuf/proto/text.go | 939 ------ .../gogo/protobuf/proto/text_gogo.go | 57 - .../gogo/protobuf/proto/text_parser.go | 1013 ------ .../gogo/protobuf/proto/timestamp.go | 113 - .../gogo/protobuf/proto/timestamp_gogo.go | 229 -- .../go-containerregistry}/LICENSE | 3 +- .../google/go-containerregistry/authn/anon.go | 26 + .../google/go-containerregistry/authn/auth.go | 29 + .../go-containerregistry/authn/authn.go | 21 + .../go-containerregistry/authn/basic.go | 33 + .../go-containerregistry/authn/bearer.go | 29 + .../google/go-containerregistry/authn/doc.go | 17 + .../go-containerregistry/authn/helper.go | 94 + .../go-containerregistry/authn/keychain.go | 140 + .../google/go-containerregistry/name/check.go | 52 + .../go-containerregistry/name/digest.go | 91 + .../go-containerregistry/name/errors.go | 37 + .../google/go-containerregistry/name/ref.go | 49 + .../go-containerregistry/name/registry.go | 79 + .../go-containerregistry/name/repository.go | 99 + .../google/go-containerregistry/name/tag.go | 99 + .../google/go-containerregistry/v1/config.go | 108 + .../google/go-containerregistry/v1/doc.go | 19 + .../go-containerregistry/v1/empty/doc.go} | 10 +- .../go-containerregistry/v1/empty/image.go | 22 + .../google/go-containerregistry/v1/hash.go | 111 + .../google/go-containerregistry/v1/image.go | 58 + .../google/go-containerregistry/v1/layer.go | 37 + .../go-containerregistry/v1/manifest.go | 49 + .../go-containerregistry/v1/mutate/mutate.go | 233 ++ .../v1/partial/compressed.go | 154 + .../go-containerregistry/v1/partial/doc.go | 17 + .../go-containerregistry/v1/partial/image.go | 28 + .../v1/partial/uncompressed.go | 229 ++ .../go-containerregistry/v1/partial/with.go | 291 ++ .../go-containerregistry/v1/random}/doc.go | 8 +- .../go-containerregistry/v1/random/image.go | 110 + .../go-containerregistry/v1/remote/delete.go | 70 + .../go-containerregistry/v1/remote/doc.go | 17 + .../go-containerregistry/v1/remote/error.go | 106 + .../go-containerregistry/v1/remote/image.go | 201 ++ .../v1/remote/transport/basic.go | 47 + .../v1/remote/transport/bearer.go | 119 + .../v1/remote/transport/doc.go | 18 + .../v1/remote/transport/ping.go | 89 + .../v1/remote/transport/scheme.go | 42 + .../v1/remote/transport/scope.go | 27 + .../v1/remote/transport/transport.go | 84 + .../go-containerregistry/v1/remote/write.go | 281 ++ .../go-containerregistry/v1/tarball/doc.go | 17 + .../go-containerregistry/v1/tarball/image.go | 338 ++ .../go-containerregistry/v1/tarball/layer.go | 144 + .../go-containerregistry/v1/tarball/write.go | 122 + .../go-containerregistry/v1/types/types.go | 40 + .../v1/v1util/and_closer.go | 47 + .../go-containerregistry/v1/v1util/nop.go | 40 + .../go-containerregistry/v1/v1util/verify.go | 61 + .../go-containerregistry/v1/v1util/zip.go | 117 + .../v1/zz_deepcopy_generated.go | 232 ++ vendor/github.com/gorilla/context/LICENSE | 27 - vendor/github.com/gorilla/context/context.go | 143 - vendor/github.com/gorilla/context/doc.go | 82 - vendor/github.com/gorilla/mux/LICENSE | 27 - .../github.com/gorilla/mux/context_gorilla.go | 26 - .../github.com/gorilla/mux/context_native.go | 24 - vendor/github.com/gorilla/mux/doc.go | 307 -- vendor/github.com/gorilla/mux/middleware.go | 28 - vendor/github.com/gorilla/mux/mux.go | 585 ---- vendor/github.com/gorilla/mux/regexp.go | 332 -- vendor/github.com/gorilla/mux/route.go | 761 ----- vendor/github.com/gorilla/mux/test_helpers.go | 18 - vendor/github.com/imdario/mergo/LICENSE | 28 - vendor/github.com/imdario/mergo/doc.go | 44 - vendor/github.com/imdario/mergo/map.go | 174 - vendor/github.com/imdario/mergo/merge.go | 233 -- vendor/github.com/imdario/mergo/mergo.go | 92 - .../imdario/mergo/testdata/license.yml | 4 - vendor/github.com/mattn/go-runewidth/LICENSE | 21 - .../mattn/go-runewidth/runewidth.go | 1223 ------- .../mattn/go-runewidth/runewidth_js.go | 8 - .../mattn/go-runewidth/runewidth_posix.go | 77 - .../mattn/go-runewidth/runewidth_windows.go | 25 - vendor/github.com/mattn/go-shellwords/LICENSE | 21 - .../mattn/go-shellwords/shellwords.go | 145 - .../mattn/go-shellwords/util_posix.go | 19 - .../mattn/go-shellwords/util_windows.go | 17 - .../golang_protobuf_extensions/LICENSE | 201 -- .../golang_protobuf_extensions/NOTICE | 1 - .../pbutil/decode.go | 75 - .../pbutil/encode.go | 46 - vendor/github.com/mistifyio/go-zfs/LICENSE | 201 -- vendor/github.com/mistifyio/go-zfs/error.go | 18 - vendor/github.com/mistifyio/go-zfs/utils.go | 320 -- vendor/github.com/mistifyio/go-zfs/zfs.go | 382 --- vendor/github.com/mistifyio/go-zfs/zpool.go | 105 - vendor/github.com/mtrmac/gpgme/LICENSE | 12 - vendor/github.com/mtrmac/gpgme/callbacks.go | 42 - vendor/github.com/mtrmac/gpgme/data.go | 191 -- vendor/github.com/mtrmac/gpgme/go_gpgme.c | 89 - vendor/github.com/mtrmac/gpgme/go_gpgme.h | 37 - vendor/github.com/mtrmac/gpgme/gpgme.go | 748 ----- .../github.com/opencontainers/selinux/LICENSE | 201 -- .../selinux/go-selinux/label/label.go | 84 - .../selinux/go-selinux/label/label_selinux.go | 204 -- .../selinux/go-selinux/selinux.go | 593 ---- .../selinux/go-selinux/xattrs.go | 78 - vendor/github.com/ostreedev/ostree-go/LICENSE | 17 - .../ostree-go/pkg/glibobject/gboolean.go | 60 - .../ostree-go/pkg/glibobject/gcancellable.go | 47 - .../ostree-go/pkg/glibobject/gerror.go | 71 - .../ostree-go/pkg/glibobject/gfile.go | 52 - .../ostree-go/pkg/glibobject/gfileinfo.go | 53 - .../ostree-go/pkg/glibobject/ghashtable.go | 50 - .../pkg/glibobject/ghashtableiter.go | 50 - .../ostree-go/pkg/glibobject/glibobject.go | 27 - .../ostree-go/pkg/glibobject/glibobject.go.h | 17 - .../ostree-go/pkg/glibobject/gobject.go | 79 - .../pkg/glibobject/goptioncontext.go | 51 - .../ostree-go/pkg/glibobject/gvariant.go | 97 - .../ostree-go/pkg/otbuiltin/builtin.go | 93 - .../ostree-go/pkg/otbuiltin/builtin.go.h | 191 -- .../ostreedev/ostree-go/pkg/otbuiltin/cat.go | 1 - .../ostree-go/pkg/otbuiltin/checkout.go | 102 - .../ostree-go/pkg/otbuiltin/checksum.go | 1 - .../ostree-go/pkg/otbuiltin/commit.go | 482 --- .../ostree-go/pkg/otbuiltin/config.go | 1 - .../ostreedev/ostree-go/pkg/otbuiltin/diff.go | 1 - .../ostree-go/pkg/otbuiltin/export.go | 1 - .../ostreedev/ostree-go/pkg/otbuiltin/fsck.go | 1 - .../ostree-go/pkg/otbuiltin/gpgsign.go | 1 - .../ostreedev/ostree-go/pkg/otbuiltin/init.go | 91 - .../ostreedev/ostree-go/pkg/otbuiltin/log.go | 167 - .../ostreedev/ostree-go/pkg/otbuiltin/ls.go | 1 - .../ostree-go/pkg/otbuiltin/prune.go | 217 -- .../ostreedev/ostree-go/pkg/otbuiltin/pull.go | 1 - .../ostree-go/pkg/otbuiltin/pulllocal.go | 1 - .../ostreedev/ostree-go/pkg/otbuiltin/refs.go | 1 - .../ostree-go/pkg/otbuiltin/remote.go | 1 - .../ostree-go/pkg/otbuiltin/reset.go | 1 - .../ostree-go/pkg/otbuiltin/revparse.go | 1 - .../ostreedev/ostree-go/pkg/otbuiltin/show.go | 1 - .../ostree-go/pkg/otbuiltin/staticdelta.go | 1 - .../ostree-go/pkg/otbuiltin/summary.go | 1 - .../ostree-go/pkg/otbuiltin/trivialhttpd.go | 1 - vendor/github.com/pquerna/ffjson/LICENSE | 202 -- vendor/github.com/pquerna/ffjson/NOTICE | 8 - .../pquerna/ffjson/fflib/v1/buffer.go | 421 --- .../pquerna/ffjson/fflib/v1/buffer_nopool.go | 11 - .../pquerna/ffjson/fflib/v1/buffer_pool.go | 105 - .../pquerna/ffjson/fflib/v1/bytenum.go | 88 - .../pquerna/ffjson/fflib/v1/decimal.go | 378 --- .../pquerna/ffjson/fflib/v1/extfloat.go | 668 ---- .../pquerna/ffjson/fflib/v1/fold.go | 121 - .../pquerna/ffjson/fflib/v1/ftoa.go | 542 ---- .../pquerna/ffjson/fflib/v1/internal/atof.go | 936 ------ .../pquerna/ffjson/fflib/v1/internal/atoi.go | 213 -- .../ffjson/fflib/v1/internal/extfloat.go | 668 ---- .../pquerna/ffjson/fflib/v1/internal/ftoa.go | 475 --- .../pquerna/ffjson/fflib/v1/iota.go | 161 - .../pquerna/ffjson/fflib/v1/jsonstring.go | 512 --- .../pquerna/ffjson/fflib/v1/lexer.go | 937 ------ .../pquerna/ffjson/fflib/v1/reader.go | 512 --- .../ffjson/fflib/v1/reader_scan_generic.go | 34 - .../prometheus/client_golang/NOTICE | 23 - .../client_golang/prometheus/collector.go | 75 - .../client_golang/prometheus/counter.go | 277 -- .../client_golang/prometheus/desc.go | 188 -- .../client_golang/prometheus/doc.go | 186 -- .../prometheus/expvar_collector.go | 119 - .../client_golang/prometheus/fnv.go | 29 - .../client_golang/prometheus/gauge.go | 286 -- .../client_golang/prometheus/go_collector.go | 284 -- .../client_golang/prometheus/histogram.go | 505 --- .../client_golang/prometheus/http.go | 523 --- .../client_golang/prometheus/labels.go | 57 - .../client_golang/prometheus/metric.go | 158 - .../client_golang/prometheus/observer.go | 52 - .../prometheus/process_collector.go | 140 - .../prometheus/promhttp/delegator.go | 199 -- .../prometheus/promhttp/delegator_1_8.go | 181 -- .../prometheus/promhttp/delegator_pre_1_8.go | 44 - .../client_golang/prometheus/promhttp/http.go | 311 -- .../prometheus/promhttp/instrument_client.go | 97 - .../promhttp/instrument_client_1_8.go | 144 - .../prometheus/promhttp/instrument_server.go | 447 --- .../client_golang/prometheus/registry.go | 807 ----- .../client_golang/prometheus/summary.go | 609 ---- .../client_golang/prometheus/timer.go | 51 - .../client_golang/prometheus/untyped.go | 42 - .../client_golang/prometheus/value.go | 160 - .../client_golang/prometheus/vec.go | 469 --- .../prometheus/client_model/LICENSE | 201 -- .../github.com/prometheus/client_model/NOTICE | 5 - .../prometheus/client_model/go/metrics.pb.go | 364 --- .../prometheus/client_model/ruby/LICENSE | 201 -- vendor/github.com/prometheus/common/LICENSE | 201 -- vendor/github.com/prometheus/common/NOTICE | 5 - .../prometheus/common/expfmt/decode.go | 429 --- .../prometheus/common/expfmt/encode.go | 88 - .../prometheus/common/expfmt/expfmt.go | 38 - .../prometheus/common/expfmt/fuzz.go | 36 - .../prometheus/common/expfmt/text_create.go | 303 -- .../prometheus/common/expfmt/text_parse.go | 757 ----- .../bitbucket.org/ww/goautoneg/autoneg.go | 162 - .../prometheus/common/model/alert.go | 136 - .../prometheus/common/model/fingerprinting.go | 105 - .../github.com/prometheus/common/model/fnv.go | 42 - .../prometheus/common/model/labels.go | 210 -- .../prometheus/common/model/labelset.go | 169 - .../prometheus/common/model/metric.go | 103 - .../prometheus/common/model/signature.go | 144 - .../prometheus/common/model/silence.go | 106 - .../prometheus/common/model/time.go | 264 -- .../prometheus/common/model/value.go | 416 --- vendor/github.com/prometheus/procfs/LICENSE | 201 -- vendor/github.com/prometheus/procfs/NOTICE | 7 - .../github.com/prometheus/procfs/buddyinfo.go | 95 - vendor/github.com/prometheus/procfs/doc.go | 45 - vendor/github.com/prometheus/procfs/fs.go | 82 - .../prometheus/procfs/internal/util/parse.go | 46 - vendor/github.com/prometheus/procfs/ipvs.go | 259 -- vendor/github.com/prometheus/procfs/mdstat.go | 151 - .../prometheus/procfs/mountstats.go | 569 ---- .../github.com/prometheus/procfs/net_dev.go | 216 -- .../github.com/prometheus/procfs/nfs/nfs.go | 263 -- .../github.com/prometheus/procfs/nfs/parse.go | 317 -- .../prometheus/procfs/nfs/parse_nfs.go | 67 - .../prometheus/procfs/nfs/parse_nfsd.go | 89 - vendor/github.com/prometheus/procfs/proc.go | 238 -- .../github.com/prometheus/procfs/proc_io.go | 65 - .../prometheus/procfs/proc_limits.go | 150 - .../github.com/prometheus/procfs/proc_ns.go | 68 - .../github.com/prometheus/procfs/proc_stat.go | 188 -- vendor/github.com/prometheus/procfs/stat.go | 232 -- vendor/github.com/prometheus/procfs/xfrm.go | 187 -- .../github.com/prometheus/procfs/xfs/parse.go | 330 -- .../github.com/prometheus/procfs/xfs/xfs.go | 163 - vendor/github.com/tchap/go-patricia/AUTHORS | 3 - vendor/github.com/tchap/go-patricia/LICENSE | 20 - .../tchap/go-patricia/patricia/children.go | 325 -- .../tchap/go-patricia/patricia/patricia.go | 594 ---- vendor/github.com/vbatts/tar-split/LICENSE | 28 - .../vbatts/tar-split/archive/tar/common.go | 340 -- .../vbatts/tar-split/archive/tar/reader.go | 1064 ------- .../vbatts/tar-split/archive/tar/stat_atim.go | 20 - .../tar-split/archive/tar/stat_atimespec.go | 20 - .../vbatts/tar-split/archive/tar/stat_unix.go | 32 - .../vbatts/tar-split/archive/tar/writer.go | 416 --- .../vbatts/tar-split/tar/asm/assemble.go | 130 - .../vbatts/tar-split/tar/asm/disassemble.go | 154 - .../vbatts/tar-split/tar/asm/doc.go | 9 - .../vbatts/tar-split/tar/storage/doc.go | 12 - .../vbatts/tar-split/tar/storage/entry.go | 78 - .../vbatts/tar-split/tar/storage/getter.go | 104 - .../vbatts/tar-split/tar/storage/packer.go | 127 - vendor/golang.org/x/crypto/cast5/cast5.go | 526 --- .../x/crypto/openpgp/armor/armor.go | 219 -- .../x/crypto/openpgp/armor/encode.go | 160 - .../x/crypto/openpgp/canonical_text.go | 59 - .../x/crypto/openpgp/elgamal/elgamal.go | 122 - .../x/crypto/openpgp/errors/errors.go | 72 - vendor/golang.org/x/crypto/openpgp/keys.go | 641 ---- .../x/crypto/openpgp/packet/compressed.go | 123 - .../x/crypto/openpgp/packet/config.go | 91 - .../x/crypto/openpgp/packet/encrypted_key.go | 206 -- .../x/crypto/openpgp/packet/literal.go | 89 - .../x/crypto/openpgp/packet/ocfb.go | 143 - .../openpgp/packet/one_pass_signature.go | 73 - .../x/crypto/openpgp/packet/opaque.go | 162 - .../x/crypto/openpgp/packet/packet.go | 549 ---- .../x/crypto/openpgp/packet/private_key.go | 380 --- .../x/crypto/openpgp/packet/public_key.go | 753 ----- .../x/crypto/openpgp/packet/public_key_v3.go | 279 -- .../x/crypto/openpgp/packet/reader.go | 76 - .../x/crypto/openpgp/packet/signature.go | 731 ----- .../x/crypto/openpgp/packet/signature_v3.go | 146 - .../openpgp/packet/symmetric_key_encrypted.go | 155 - .../openpgp/packet/symmetrically_encrypted.go | 290 -- .../x/crypto/openpgp/packet/userattribute.go | 91 - .../x/crypto/openpgp/packet/userid.go | 160 - vendor/golang.org/x/crypto/openpgp/read.go | 442 --- vendor/golang.org/x/crypto/openpgp/s2k/s2k.go | 273 -- vendor/golang.org/x/crypto/openpgp/write.go | 378 --- .../golang.org/x/net/internal/socks/client.go | 168 - .../golang.org/x/net/internal/socks/socks.go | 265 -- vendor/golang.org/x/net/proxy/direct.go | 18 - vendor/golang.org/x/net/proxy/per_host.go | 140 - vendor/golang.org/x/net/proxy/proxy.go | 134 - vendor/golang.org/x/net/proxy/socks5.go | 36 - vendor/gopkg.in/cheggaaa/pb.v1/LICENSE | 12 - vendor/gopkg.in/cheggaaa/pb.v1/format.go | 118 - vendor/gopkg.in/cheggaaa/pb.v1/pb.go | 475 --- .../gopkg.in/cheggaaa/pb.v1/pb_appengine.go | 11 - vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go | 141 - vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go | 108 - vendor/gopkg.in/cheggaaa/pb.v1/pool.go | 102 - vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go | 45 - vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go | 29 - vendor/gopkg.in/cheggaaa/pb.v1/reader.go | 25 - vendor/gopkg.in/cheggaaa/pb.v1/runecount.go | 17 - vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go | 9 - .../gopkg.in/cheggaaa/pb.v1/termios_sysv.go | 13 - vendor/k8s.io/client-go/LICENSE | 202 -- .../k8s.io/client-go/util/homedir/homedir.go | 47 - 994 files changed, 5359 insertions(+), 141516 deletions(-) delete mode 100644 vendor/github.com/BurntSushi/toml/COPYING delete mode 100644 vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING delete mode 100644 vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING delete mode 100644 vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING delete mode 100644 vendor/github.com/BurntSushi/toml/decode.go delete mode 100644 vendor/github.com/BurntSushi/toml/decode_meta.go delete mode 100644 vendor/github.com/BurntSushi/toml/doc.go delete mode 100644 vendor/github.com/BurntSushi/toml/encode.go delete mode 100644 vendor/github.com/BurntSushi/toml/encoding_types.go delete mode 100644 vendor/github.com/BurntSushi/toml/encoding_types_1.1.go delete mode 100644 vendor/github.com/BurntSushi/toml/lex.go delete mode 100644 vendor/github.com/BurntSushi/toml/parse.go delete mode 100644 vendor/github.com/BurntSushi/toml/type_check.go delete mode 100644 vendor/github.com/BurntSushi/toml/type_fields.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/LICENSE delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/image/proxy_types.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/cloud_prepper.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/daemon_prepper.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/docker_utils.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/fs_utils.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_utils.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_prepper.go delete mode 100644 vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_utils.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/common.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/reader.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/stat_atim.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/stat_atimespec.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/stat_unix.go delete mode 100644 vendor/github.com/Microsoft/go-winio/archive/tar/writer.go delete mode 100644 vendor/github.com/Microsoft/go-winio/backuptar/noop.go delete mode 100644 vendor/github.com/Microsoft/go-winio/backuptar/tar.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/LICENSE delete mode 100644 vendor/github.com/Microsoft/hcsshim/activatelayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/baselayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/callback.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/cgo.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/container.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/createlayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/deactivatelayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/destroylayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/errors.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/exportlayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/getlayermountpath.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/guid.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hcsshim.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hnsendpoint.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hnsfuncs.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hnsnetwork.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hnspolicy.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/hnspolicylist.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/importlayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/interface.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/layerexists.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/layerutils.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/legacy.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/legacy18.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/legacy19.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/nametoguid.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/preparelayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/process.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/processimage.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/unpreparelayer.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/utils.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/version.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/waithelper.go delete mode 100644 vendor/github.com/Microsoft/hcsshim/zhcsshim.go delete mode 100644 vendor/github.com/beorn7/perks/LICENSE delete mode 100644 vendor/github.com/beorn7/perks/quantile/stream.go delete mode 100644 vendor/github.com/containers/image/LICENSE delete mode 100644 vendor/github.com/containers/image/copy/copy.go delete mode 120000 vendor/github.com/containers/image/copy/fixtures/Hello.bz2 delete mode 120000 vendor/github.com/containers/image/copy/fixtures/Hello.gz delete mode 120000 vendor/github.com/containers/image/copy/fixtures/Hello.uncompressed delete mode 120000 vendor/github.com/containers/image/copy/fixtures/Hello.xz delete mode 100644 vendor/github.com/containers/image/copy/manifest.go delete mode 100644 vendor/github.com/containers/image/copy/progress_reader.go delete mode 100644 vendor/github.com/containers/image/copy/sign.go delete mode 100644 vendor/github.com/containers/image/directory/directory_dest.go delete mode 100644 vendor/github.com/containers/image/directory/directory_src.go delete mode 100644 vendor/github.com/containers/image/directory/directory_transport.go delete mode 100644 vendor/github.com/containers/image/directory/explicitfilepath/path.go delete mode 100644 vendor/github.com/containers/image/docker/archive/dest.go delete mode 100644 vendor/github.com/containers/image/docker/archive/src.go delete mode 100644 vendor/github.com/containers/image/docker/archive/transport.go delete mode 100644 vendor/github.com/containers/image/docker/daemon/client.go delete mode 100644 vendor/github.com/containers/image/docker/daemon/daemon_dest.go delete mode 100644 vendor/github.com/containers/image/docker/daemon/daemon_src.go delete mode 100644 vendor/github.com/containers/image/docker/daemon/daemon_transport.go delete mode 100644 vendor/github.com/containers/image/docker/docker_client.go delete mode 100644 vendor/github.com/containers/image/docker/docker_image.go delete mode 100644 vendor/github.com/containers/image/docker/docker_image_dest.go delete mode 100644 vendor/github.com/containers/image/docker/docker_image_src.go delete mode 100644 vendor/github.com/containers/image/docker/docker_transport.go delete mode 100644 vendor/github.com/containers/image/docker/lookaside.go delete mode 100644 vendor/github.com/containers/image/docker/policyconfiguration/naming.go delete mode 100644 vendor/github.com/containers/image/docker/reference/helpers.go delete mode 100644 vendor/github.com/containers/image/docker/reference/normalize.go delete mode 100644 vendor/github.com/containers/image/docker/reference/reference.go delete mode 100644 vendor/github.com/containers/image/docker/reference/regexp.go delete mode 100644 vendor/github.com/containers/image/docker/tarfile/dest.go delete mode 100644 vendor/github.com/containers/image/docker/tarfile/doc.go delete mode 100644 vendor/github.com/containers/image/docker/tarfile/src.go delete mode 100644 vendor/github.com/containers/image/docker/tarfile/types.go delete mode 100644 vendor/github.com/containers/image/docker/wwwauthenticate.go delete mode 100644 vendor/github.com/containers/image/image/docker_list.go delete mode 100644 vendor/github.com/containers/image/image/docker_schema1.go delete mode 100644 vendor/github.com/containers/image/image/docker_schema2.go delete mode 100644 vendor/github.com/containers/image/image/manifest.go delete mode 100644 vendor/github.com/containers/image/image/memory.go delete mode 100644 vendor/github.com/containers/image/image/oci.go delete mode 100644 vendor/github.com/containers/image/image/sourced.go delete mode 100644 vendor/github.com/containers/image/image/unparsed.go delete mode 100644 vendor/github.com/containers/image/internal/tmpdir/tmpdir.go delete mode 100644 vendor/github.com/containers/image/manifest/docker_schema1.go delete mode 100644 vendor/github.com/containers/image/manifest/docker_schema2.go delete mode 100644 vendor/github.com/containers/image/manifest/manifest.go delete mode 100644 vendor/github.com/containers/image/manifest/oci.go delete mode 100644 vendor/github.com/containers/image/oci/archive/oci_dest.go delete mode 100644 vendor/github.com/containers/image/oci/archive/oci_src.go delete mode 100644 vendor/github.com/containers/image/oci/archive/oci_transport.go delete mode 100644 vendor/github.com/containers/image/oci/internal/oci_util.go delete mode 100644 vendor/github.com/containers/image/oci/layout/oci_dest.go delete mode 100644 vendor/github.com/containers/image/oci/layout/oci_src.go delete mode 100644 vendor/github.com/containers/image/oci/layout/oci_transport.go delete mode 100644 vendor/github.com/containers/image/openshift/openshift-copies.go delete mode 100644 vendor/github.com/containers/image/openshift/openshift.go delete mode 100644 vendor/github.com/containers/image/openshift/openshift_transport.go delete mode 100644 vendor/github.com/containers/image/ostree/ostree_dest.go delete mode 100644 vendor/github.com/containers/image/ostree/ostree_src.go delete mode 100644 vendor/github.com/containers/image/ostree/ostree_transport.go delete mode 100644 vendor/github.com/containers/image/pkg/compression/compression.go delete mode 100644 vendor/github.com/containers/image/pkg/docker/config/config.go delete mode 100644 vendor/github.com/containers/image/pkg/strslice/strslice.go delete mode 100644 vendor/github.com/containers/image/pkg/tlsclientconfig/tlsclientconfig.go delete mode 100644 vendor/github.com/containers/image/signature/docker.go delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/manifest.json delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/signature-1 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/manifest.json delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-1 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-2 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-modified-manifest/signature-1 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-no-manifest/signature-1 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-unsigned/manifest.json delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/manifest.json delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/signature-1 delete mode 120000 vendor/github.com/containers/image/signature/fixtures/dir-img-valid/manifest.json delete mode 100644 vendor/github.com/containers/image/signature/json.go delete mode 100644 vendor/github.com/containers/image/signature/mechanism.go delete mode 100644 vendor/github.com/containers/image/signature/mechanism_gpgme.go delete mode 100644 vendor/github.com/containers/image/signature/mechanism_openpgp.go delete mode 100644 vendor/github.com/containers/image/signature/policy_config.go delete mode 100644 vendor/github.com/containers/image/signature/policy_eval.go delete mode 100644 vendor/github.com/containers/image/signature/policy_eval_baselayer.go delete mode 100644 vendor/github.com/containers/image/signature/policy_eval_signedby.go delete mode 100644 vendor/github.com/containers/image/signature/policy_eval_simple.go delete mode 100644 vendor/github.com/containers/image/signature/policy_reference_match.go delete mode 100644 vendor/github.com/containers/image/signature/policy_types.go delete mode 100644 vendor/github.com/containers/image/signature/signature.go delete mode 100644 vendor/github.com/containers/image/storage/storage_image.go delete mode 100644 vendor/github.com/containers/image/storage/storage_reference.go delete mode 100644 vendor/github.com/containers/image/storage/storage_transport.go delete mode 100644 vendor/github.com/containers/image/tarball/doc.go delete mode 100644 vendor/github.com/containers/image/tarball/tarball_reference.go delete mode 100644 vendor/github.com/containers/image/tarball/tarball_src.go delete mode 100644 vendor/github.com/containers/image/tarball/tarball_transport.go delete mode 100644 vendor/github.com/containers/image/transports/alltransports/alltransports.go delete mode 100644 vendor/github.com/containers/image/transports/alltransports/ostree.go delete mode 100644 vendor/github.com/containers/image/transports/alltransports/ostree_stub.go delete mode 100644 vendor/github.com/containers/image/transports/alltransports/storage.go delete mode 100644 vendor/github.com/containers/image/transports/alltransports/storage_stub.go delete mode 100644 vendor/github.com/containers/image/transports/stub.go delete mode 100644 vendor/github.com/containers/image/transports/transports.go delete mode 100644 vendor/github.com/containers/image/types/types.go delete mode 100644 vendor/github.com/containers/image/version/version.go delete mode 100644 vendor/github.com/containers/storage/AUTHORS delete mode 100644 vendor/github.com/containers/storage/LICENSE delete mode 100644 vendor/github.com/containers/storage/NOTICE delete mode 100644 vendor/github.com/containers/storage/containers.go delete mode 100644 vendor/github.com/containers/storage/containers_ffjson.go delete mode 100644 vendor/github.com/containers/storage/drivers/aufs/aufs.go delete mode 100644 vendor/github.com/containers/storage/drivers/aufs/dirs.go delete mode 100644 vendor/github.com/containers/storage/drivers/aufs/mount.go delete mode 100644 vendor/github.com/containers/storage/drivers/aufs/mount_linux.go delete mode 100644 vendor/github.com/containers/storage/drivers/aufs/mount_unsupported.go delete mode 100644 vendor/github.com/containers/storage/drivers/btrfs/btrfs.go delete mode 100644 vendor/github.com/containers/storage/drivers/btrfs/dummy_unsupported.go delete mode 100644 vendor/github.com/containers/storage/drivers/btrfs/version.go delete mode 100644 vendor/github.com/containers/storage/drivers/btrfs/version_none.go delete mode 100644 vendor/github.com/containers/storage/drivers/counter.go delete mode 100644 vendor/github.com/containers/storage/drivers/devmapper/device_setup.go delete mode 100644 vendor/github.com/containers/storage/drivers/devmapper/deviceset.go delete mode 100644 vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go delete mode 100644 vendor/github.com/containers/storage/drivers/devmapper/driver.go delete mode 100644 vendor/github.com/containers/storage/drivers/devmapper/mount.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver_freebsd.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver_linux.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver_solaris.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver_unsupported.go delete mode 100644 vendor/github.com/containers/storage/drivers/driver_windows.go delete mode 100644 vendor/github.com/containers/storage/drivers/fsdiff.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlay/check.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlay/mount.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlay/overlay.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlay/overlay_unsupported.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlay/randomid.go delete mode 100644 vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go delete mode 100644 vendor/github.com/containers/storage/drivers/quota/projectquota.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_aufs.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_btrfs.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_devicemapper.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_overlay.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_vfs.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_windows.go delete mode 100644 vendor/github.com/containers/storage/drivers/register/register_zfs.go delete mode 100644 vendor/github.com/containers/storage/drivers/vfs/driver.go delete mode 100644 vendor/github.com/containers/storage/drivers/windows/windows.go delete mode 100644 vendor/github.com/containers/storage/drivers/zfs/zfs.go delete mode 100644 vendor/github.com/containers/storage/drivers/zfs/zfs_freebsd.go delete mode 100644 vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go delete mode 100644 vendor/github.com/containers/storage/drivers/zfs/zfs_solaris.go delete mode 100644 vendor/github.com/containers/storage/drivers/zfs/zfs_unsupported.go delete mode 100644 vendor/github.com/containers/storage/errors.go delete mode 100755 vendor/github.com/containers/storage/hack/generate-authors.sh delete mode 100644 vendor/github.com/containers/storage/images.go delete mode 100644 vendor/github.com/containers/storage/images_ffjson.go delete mode 100644 vendor/github.com/containers/storage/layers.go delete mode 100644 vendor/github.com/containers/storage/layers_ffjson.go delete mode 100644 vendor/github.com/containers/storage/lockfile.go delete mode 100644 vendor/github.com/containers/storage/lockfile_darwin.go delete mode 100644 vendor/github.com/containers/storage/lockfile_linux.go delete mode 100644 vendor/github.com/containers/storage/lockfile_unix.go delete mode 100644 vendor/github.com/containers/storage/lockfile_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/archive.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/archive_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/archive_other.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/archive_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/archive_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/changes.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/changes_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/changes_other.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/changes_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/changes_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/copy.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/copy_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/copy_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/diff.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/example_changes.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/time_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/time_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/whiteouts.go delete mode 100644 vendor/github.com/containers/storage/pkg/archive/wrap.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/archive.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/archive_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/archive_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/chroot_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/diff.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/diff_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/diff_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/init_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/chrootarchive/init_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_deferred_remove.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_dynamic.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_no_deferred_remove.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_static.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/ioctl.go delete mode 100644 vendor/github.com/containers/storage/pkg/devicemapper/log.go delete mode 100644 vendor/github.com/containers/storage/pkg/directory/directory.go delete mode 100644 vendor/github.com/containers/storage/pkg/directory/directory_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/directory/directory_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/dmesg/dmesg_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/fileutils/fileutils.go delete mode 100644 vendor/github.com/containers/storage/pkg/fileutils/fileutils_darwin.go delete mode 100644 vendor/github.com/containers/storage/pkg/fileutils/fileutils_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/fileutils/fileutils_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/fsutils/fsutils_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/homedir/homedir_others.go delete mode 100644 vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/idtools.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/idtools_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/idtools_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/usergroupadd_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/usergroupadd_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/idtools/utils_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/buffer.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/bytespipe.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/fswriters.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/readers.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/temp_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/temp_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/writeflusher.go delete mode 100644 vendor/github.com/containers/storage/pkg/ioutils/writers.go delete mode 100644 vendor/github.com/containers/storage/pkg/locker/locker.go delete mode 100644 vendor/github.com/containers/storage/pkg/longpath/longpath.go delete mode 100644 vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go delete mode 100644 vendor/github.com/containers/storage/pkg/loopback/ioctl.go delete mode 100644 vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go delete mode 100644 vendor/github.com/containers/storage/pkg/loopback/loopback.go delete mode 100644 vendor/github.com/containers/storage/pkg/mflag/LICENSE delete mode 100644 vendor/github.com/containers/storage/pkg/mount/flags.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/flags_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mount.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mounter_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo_freebsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/kernel.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_darwin.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/uname_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/uname_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/kernel/uname_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/parsers/parsers.go delete mode 100644 vendor/github.com/containers/storage/pkg/pools/pools.go delete mode 100644 vendor/github.com/containers/storage/pkg/promise/promise.go delete mode 100644 vendor/github.com/containers/storage/pkg/reexec/command_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/reexec/command_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/reexec/command_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/reexec/command_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/reexec/reexec.go delete mode 100644 vendor/github.com/containers/storage/pkg/stringid/stringid.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/chtimes.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/chtimes_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/chtimes_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/errors.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/exitcode.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/filesys.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/filesys_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/init.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/init_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/lcow_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/lcow_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/lstat_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/lstat_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/meminfo.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/meminfo_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/meminfo_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/meminfo_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/meminfo_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/mknod.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/mknod_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/path.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/path_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/path_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/process_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/rm.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_darwin.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_freebsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_openbsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_solaris.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/stat_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/syscall_unix.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/syscall_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/umask.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/umask_windows.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/utimes_freebsd.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/utimes_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/utimes_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/xattrs_linux.go delete mode 100644 vendor/github.com/containers/storage/pkg/system/xattrs_unsupported.go delete mode 100644 vendor/github.com/containers/storage/pkg/truncindex/truncindex.go delete mode 100644 vendor/github.com/containers/storage/store.go delete mode 100644 vendor/github.com/docker/distribution/AUTHORS delete mode 100644 vendor/github.com/docker/distribution/LICENSE delete mode 100644 vendor/github.com/docker/distribution/blobs.go delete mode 100644 vendor/github.com/docker/distribution/digestset/set.go delete mode 100644 vendor/github.com/docker/distribution/doc.go delete mode 100644 vendor/github.com/docker/distribution/errors.go delete mode 100644 vendor/github.com/docker/distribution/manifests.go delete mode 100644 vendor/github.com/docker/distribution/metrics/prometheus.go delete mode 100644 vendor/github.com/docker/distribution/reference/helpers.go delete mode 100644 vendor/github.com/docker/distribution/reference/normalize.go delete mode 100644 vendor/github.com/docker/distribution/reference/reference.go delete mode 100644 vendor/github.com/docker/distribution/reference/regexp.go delete mode 100644 vendor/github.com/docker/distribution/registry.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/errors.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/handler.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/register.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/descriptors.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/doc.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/errors.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/headerparser.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/routes.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/v2/urls.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/blob_writer.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/errors.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/repository.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/transport/http_reader.go delete mode 100644 vendor/github.com/docker/distribution/registry/client/transport/transport.go delete mode 100644 vendor/github.com/docker/distribution/registry/storage/cache/cache.go delete mode 100644 vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go delete mode 100644 vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go delete mode 100644 vendor/github.com/docker/distribution/tags.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/LICENSE delete mode 100644 vendor/github.com/docker/docker-credential-helpers/client/client.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/client/command.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/credentials/error.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/credentials/helper.go delete mode 100644 vendor/github.com/docker/docker-credential-helpers/credentials/version.go delete mode 100644 vendor/github.com/docker/docker/api/common.go delete mode 100644 vendor/github.com/docker/docker/api/common_unix.go delete mode 100644 vendor/github.com/docker/docker/api/common_windows.go delete mode 100644 vendor/github.com/docker/docker/api/types/auth.go delete mode 100644 vendor/github.com/docker/docker/api/types/client.go delete mode 100644 vendor/github.com/docker/docker/api/types/configs.go delete mode 100644 vendor/github.com/docker/docker/api/types/error_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/events/events.go delete mode 100644 vendor/github.com/docker/docker/api/types/filters/parse.go delete mode 100644 vendor/github.com/docker/docker/api/types/graph_driver_data.go delete mode 100644 vendor/github.com/docker/docker/api/types/id_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/image/image_history.go delete mode 100644 vendor/github.com/docker/docker/api/types/image_delete_response_item.go delete mode 100644 vendor/github.com/docker/docker/api/types/image_summary.go delete mode 100644 vendor/github.com/docker/docker/api/types/network/network.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_device.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_env.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_interface_type.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_mount.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_responses.go delete mode 100644 vendor/github.com/docker/docker/api/types/port.go delete mode 100644 vendor/github.com/docker/docker/api/types/registry/authenticate.go delete mode 100644 vendor/github.com/docker/docker/api/types/registry/registry.go delete mode 100644 vendor/github.com/docker/docker/api/types/seccomp.go delete mode 100644 vendor/github.com/docker/docker/api/types/service_update_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/stats.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/common.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/config.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/container.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/network.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/node.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/secret.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/service.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/swarm.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/task.go delete mode 100644 vendor/github.com/docker/docker/api/types/time/duration_convert.go delete mode 100644 vendor/github.com/docker/docker/api/types/time/timestamp.go delete mode 100644 vendor/github.com/docker/docker/api/types/types.go delete mode 100644 vendor/github.com/docker/docker/api/types/versions/compare.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume/volumes_create.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume/volumes_list.go delete mode 100644 vendor/github.com/docker/docker/client/build_prune.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_create.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_delete.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_list.go delete mode 100644 vendor/github.com/docker/docker/client/client.go delete mode 100644 vendor/github.com/docker/docker/client/client_unix.go delete mode 100644 vendor/github.com/docker/docker/client/client_windows.go delete mode 100644 vendor/github.com/docker/docker/client/config_create.go delete mode 100644 vendor/github.com/docker/docker/client/config_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/config_list.go delete mode 100644 vendor/github.com/docker/docker/client/config_remove.go delete mode 100644 vendor/github.com/docker/docker/client/config_update.go delete mode 100644 vendor/github.com/docker/docker/client/container_attach.go delete mode 100644 vendor/github.com/docker/docker/client/container_commit.go delete mode 100644 vendor/github.com/docker/docker/client/container_copy.go delete mode 100644 vendor/github.com/docker/docker/client/container_create.go delete mode 100644 vendor/github.com/docker/docker/client/container_diff.go delete mode 100644 vendor/github.com/docker/docker/client/container_exec.go delete mode 100644 vendor/github.com/docker/docker/client/container_export.go delete mode 100644 vendor/github.com/docker/docker/client/container_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/container_kill.go delete mode 100644 vendor/github.com/docker/docker/client/container_list.go delete mode 100644 vendor/github.com/docker/docker/client/container_logs.go delete mode 100644 vendor/github.com/docker/docker/client/container_pause.go delete mode 100644 vendor/github.com/docker/docker/client/container_prune.go delete mode 100644 vendor/github.com/docker/docker/client/container_remove.go delete mode 100644 vendor/github.com/docker/docker/client/container_rename.go delete mode 100644 vendor/github.com/docker/docker/client/container_resize.go delete mode 100644 vendor/github.com/docker/docker/client/container_restart.go delete mode 100644 vendor/github.com/docker/docker/client/container_start.go delete mode 100644 vendor/github.com/docker/docker/client/container_stats.go delete mode 100644 vendor/github.com/docker/docker/client/container_stop.go delete mode 100644 vendor/github.com/docker/docker/client/container_top.go delete mode 100644 vendor/github.com/docker/docker/client/container_unpause.go delete mode 100644 vendor/github.com/docker/docker/client/container_update.go delete mode 100644 vendor/github.com/docker/docker/client/container_wait.go delete mode 100644 vendor/github.com/docker/docker/client/disk_usage.go delete mode 100644 vendor/github.com/docker/docker/client/distribution_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/errors.go delete mode 100644 vendor/github.com/docker/docker/client/events.go delete mode 100644 vendor/github.com/docker/docker/client/hijack.go delete mode 100644 vendor/github.com/docker/docker/client/image_build.go delete mode 100644 vendor/github.com/docker/docker/client/image_create.go delete mode 100644 vendor/github.com/docker/docker/client/image_history.go delete mode 100644 vendor/github.com/docker/docker/client/image_import.go delete mode 100644 vendor/github.com/docker/docker/client/image_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/image_list.go delete mode 100644 vendor/github.com/docker/docker/client/image_load.go delete mode 100644 vendor/github.com/docker/docker/client/image_prune.go delete mode 100644 vendor/github.com/docker/docker/client/image_pull.go delete mode 100644 vendor/github.com/docker/docker/client/image_push.go delete mode 100644 vendor/github.com/docker/docker/client/image_remove.go delete mode 100644 vendor/github.com/docker/docker/client/image_save.go delete mode 100644 vendor/github.com/docker/docker/client/image_search.go delete mode 100644 vendor/github.com/docker/docker/client/image_tag.go delete mode 100644 vendor/github.com/docker/docker/client/info.go delete mode 100644 vendor/github.com/docker/docker/client/interface.go delete mode 100644 vendor/github.com/docker/docker/client/interface_experimental.go delete mode 100644 vendor/github.com/docker/docker/client/interface_stable.go delete mode 100644 vendor/github.com/docker/docker/client/login.go delete mode 100644 vendor/github.com/docker/docker/client/network_connect.go delete mode 100644 vendor/github.com/docker/docker/client/network_create.go delete mode 100644 vendor/github.com/docker/docker/client/network_disconnect.go delete mode 100644 vendor/github.com/docker/docker/client/network_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/network_list.go delete mode 100644 vendor/github.com/docker/docker/client/network_prune.go delete mode 100644 vendor/github.com/docker/docker/client/network_remove.go delete mode 100644 vendor/github.com/docker/docker/client/node_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/node_list.go delete mode 100644 vendor/github.com/docker/docker/client/node_remove.go delete mode 100644 vendor/github.com/docker/docker/client/node_update.go delete mode 100644 vendor/github.com/docker/docker/client/ping.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_create.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_disable.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_enable.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_install.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_list.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_push.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_remove.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_set.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_upgrade.go delete mode 100644 vendor/github.com/docker/docker/client/request.go delete mode 100644 vendor/github.com/docker/docker/client/secret_create.go delete mode 100644 vendor/github.com/docker/docker/client/secret_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/secret_list.go delete mode 100644 vendor/github.com/docker/docker/client/secret_remove.go delete mode 100644 vendor/github.com/docker/docker/client/secret_update.go delete mode 100644 vendor/github.com/docker/docker/client/service_create.go delete mode 100644 vendor/github.com/docker/docker/client/service_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/service_list.go delete mode 100644 vendor/github.com/docker/docker/client/service_logs.go delete mode 100644 vendor/github.com/docker/docker/client/service_remove.go delete mode 100644 vendor/github.com/docker/docker/client/service_update.go delete mode 100644 vendor/github.com/docker/docker/client/session.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_get_unlock_key.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_init.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_join.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_leave.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_unlock.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_update.go delete mode 100644 vendor/github.com/docker/docker/client/task_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/task_list.go delete mode 100644 vendor/github.com/docker/docker/client/task_logs.go delete mode 100644 vendor/github.com/docker/docker/client/tlsconfig_clone.go delete mode 100644 vendor/github.com/docker/docker/client/tlsconfig_clone_go17.go delete mode 100644 vendor/github.com/docker/docker/client/transport.go delete mode 100644 vendor/github.com/docker/docker/client/utils.go delete mode 100644 vendor/github.com/docker/docker/client/version.go delete mode 100644 vendor/github.com/docker/docker/client/volume_create.go delete mode 100644 vendor/github.com/docker/docker/client/volume_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/volume_list.go delete mode 100644 vendor/github.com/docker/docker/client/volume_prune.go delete mode 100644 vendor/github.com/docker/docker/client/volume_remove.go delete mode 100644 vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go delete mode 100644 vendor/github.com/docker/docker/pkg/homedir/homedir_others.go delete mode 100644 vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go delete mode 100644 vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/inmem_socket.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/proxy.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets_unix.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets_windows.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/tcp_socket.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/unix_socket.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go delete mode 100644 vendor/github.com/docker/go-metrics/LICENSE.code delete mode 100644 vendor/github.com/docker/go-metrics/LICENSE.docs delete mode 100644 vendor/github.com/docker/go-metrics/NOTICE delete mode 100644 vendor/github.com/docker/go-metrics/counter.go delete mode 100644 vendor/github.com/docker/go-metrics/docs.go delete mode 100644 vendor/github.com/docker/go-metrics/gauge.go delete mode 100644 vendor/github.com/docker/go-metrics/handler.go delete mode 100644 vendor/github.com/docker/go-metrics/helpers.go delete mode 100644 vendor/github.com/docker/go-metrics/namespace.go delete mode 100644 vendor/github.com/docker/go-metrics/register.go delete mode 100644 vendor/github.com/docker/go-metrics/timer.go delete mode 100644 vendor/github.com/docker/go-metrics/unit.go delete mode 100644 vendor/github.com/docker/libtrust/LICENSE delete mode 100644 vendor/github.com/docker/libtrust/certificates.go delete mode 100644 vendor/github.com/docker/libtrust/doc.go delete mode 100644 vendor/github.com/docker/libtrust/ec_key.go delete mode 100644 vendor/github.com/docker/libtrust/filter.go delete mode 100644 vendor/github.com/docker/libtrust/hash.go delete mode 100644 vendor/github.com/docker/libtrust/jsonsign.go delete mode 100644 vendor/github.com/docker/libtrust/key.go delete mode 100644 vendor/github.com/docker/libtrust/key_files.go delete mode 100644 vendor/github.com/docker/libtrust/key_manager.go delete mode 100644 vendor/github.com/docker/libtrust/rsa_key.go delete mode 100644 vendor/github.com/docker/libtrust/util.go delete mode 100644 vendor/github.com/ghodss/yaml/LICENSE delete mode 100644 vendor/github.com/ghodss/yaml/fields.go delete mode 100644 vendor/github.com/ghodss/yaml/yaml.go delete mode 100644 vendor/github.com/gogo/protobuf/AUTHORS delete mode 100644 vendor/github.com/gogo/protobuf/CONTRIBUTORS delete mode 100644 vendor/github.com/gogo/protobuf/GOLANG_CONTRIBUTORS delete mode 100644 vendor/github.com/gogo/protobuf/LICENSE delete mode 100644 vendor/github.com/gogo/protobuf/proto/clone.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/decode.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/decode_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/discard.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/duration.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/duration_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/encode.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/encode_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/equal.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/extensions.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/extensions_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/lib.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/lib_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/message_set.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/properties.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/properties_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/skip_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text_parser.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go rename vendor/github.com/{prometheus/client_golang => google/go-containerregistry}/LICENSE (99%) create mode 100644 vendor/github.com/google/go-containerregistry/authn/anon.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/auth.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/authn.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/basic.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/bearer.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/helper.go create mode 100644 vendor/github.com/google/go-containerregistry/authn/keychain.go create mode 100644 vendor/github.com/google/go-containerregistry/name/check.go create mode 100644 vendor/github.com/google/go-containerregistry/name/digest.go create mode 100644 vendor/github.com/google/go-containerregistry/name/errors.go create mode 100644 vendor/github.com/google/go-containerregistry/name/ref.go create mode 100644 vendor/github.com/google/go-containerregistry/name/registry.go create mode 100644 vendor/github.com/google/go-containerregistry/name/repository.go create mode 100644 vendor/github.com/google/go-containerregistry/name/tag.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/config.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/doc.go rename vendor/github.com/{prometheus/common/model/model.go => google/go-containerregistry/v1/empty/doc.go} (70%) create mode 100644 vendor/github.com/google/go-containerregistry/v1/empty/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/hash.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/layer.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/manifest.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/mutate/mutate.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/partial/compressed.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/partial/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/partial/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/partial/uncompressed.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/partial/with.go rename vendor/github.com/{matttproud/golang_protobuf_extensions/pbutil => google/go-containerregistry/v1/random}/doc.go (72%) create mode 100644 vendor/github.com/google/go-containerregistry/v1/random/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/delete.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/error.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/basic.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/bearer.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/ping.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/scheme.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/scope.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/transport/transport.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/remote/write.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/tarball/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/tarball/image.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/tarball/layer.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/tarball/write.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/types/types.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/v1util/and_closer.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/v1util/nop.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/v1util/verify.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/v1util/zip.go create mode 100644 vendor/github.com/google/go-containerregistry/v1/zz_deepcopy_generated.go delete mode 100644 vendor/github.com/gorilla/context/LICENSE delete mode 100644 vendor/github.com/gorilla/context/context.go delete mode 100644 vendor/github.com/gorilla/context/doc.go delete mode 100644 vendor/github.com/gorilla/mux/LICENSE delete mode 100644 vendor/github.com/gorilla/mux/context_gorilla.go delete mode 100644 vendor/github.com/gorilla/mux/context_native.go delete mode 100644 vendor/github.com/gorilla/mux/doc.go delete mode 100644 vendor/github.com/gorilla/mux/middleware.go delete mode 100644 vendor/github.com/gorilla/mux/mux.go delete mode 100644 vendor/github.com/gorilla/mux/regexp.go delete mode 100644 vendor/github.com/gorilla/mux/route.go delete mode 100644 vendor/github.com/gorilla/mux/test_helpers.go delete mode 100644 vendor/github.com/imdario/mergo/LICENSE delete mode 100644 vendor/github.com/imdario/mergo/doc.go delete mode 100644 vendor/github.com/imdario/mergo/map.go delete mode 100644 vendor/github.com/imdario/mergo/merge.go delete mode 100644 vendor/github.com/imdario/mergo/mergo.go delete mode 100644 vendor/github.com/imdario/mergo/testdata/license.yml delete mode 100644 vendor/github.com/mattn/go-runewidth/LICENSE delete mode 100644 vendor/github.com/mattn/go-runewidth/runewidth.go delete mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_js.go delete mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_posix.go delete mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_windows.go delete mode 100644 vendor/github.com/mattn/go-shellwords/LICENSE delete mode 100644 vendor/github.com/mattn/go-shellwords/shellwords.go delete mode 100644 vendor/github.com/mattn/go-shellwords/util_posix.go delete mode 100644 vendor/github.com/mattn/go-shellwords/util_windows.go delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go delete mode 100644 vendor/github.com/mistifyio/go-zfs/LICENSE delete mode 100644 vendor/github.com/mistifyio/go-zfs/error.go delete mode 100644 vendor/github.com/mistifyio/go-zfs/utils.go delete mode 100644 vendor/github.com/mistifyio/go-zfs/zfs.go delete mode 100644 vendor/github.com/mistifyio/go-zfs/zpool.go delete mode 100644 vendor/github.com/mtrmac/gpgme/LICENSE delete mode 100644 vendor/github.com/mtrmac/gpgme/callbacks.go delete mode 100644 vendor/github.com/mtrmac/gpgme/data.go delete mode 100644 vendor/github.com/mtrmac/gpgme/go_gpgme.c delete mode 100644 vendor/github.com/mtrmac/gpgme/go_gpgme.h delete mode 100644 vendor/github.com/mtrmac/gpgme/gpgme.go delete mode 100644 vendor/github.com/opencontainers/selinux/LICENSE delete mode 100644 vendor/github.com/opencontainers/selinux/go-selinux/label/label.go delete mode 100644 vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go delete mode 100644 vendor/github.com/opencontainers/selinux/go-selinux/selinux.go delete mode 100644 vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/LICENSE delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gboolean.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gcancellable.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gerror.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfile.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfileinfo.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtable.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtableiter.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go.h delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gobject.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/goptioncontext.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gvariant.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go.h delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/cat.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checkout.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checksum.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/commit.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/config.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/diff.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/export.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/fsck.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/gpgsign.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/init.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/log.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/ls.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/prune.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pull.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pulllocal.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/refs.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/remote.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/reset.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/revparse.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/show.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/staticdelta.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/summary.go delete mode 100644 vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/trivialhttpd.go delete mode 100644 vendor/github.com/pquerna/ffjson/LICENSE delete mode 100644 vendor/github.com/pquerna/ffjson/NOTICE delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/buffer.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/buffer_nopool.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/buffer_pool.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/bytenum.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/decimal.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/extfloat.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/fold.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/ftoa.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/internal/atof.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/internal/atoi.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/internal/extfloat.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/internal/ftoa.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/iota.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/jsonstring.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/lexer.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/reader.go delete mode 100644 vendor/github.com/pquerna/ffjson/fflib/v1/reader_scan_generic.go delete mode 100644 vendor/github.com/prometheus/client_golang/NOTICE delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/counter.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/desc.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/doc.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/fnv.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/gauge.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/histogram.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/http.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/labels.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/metric.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/observer.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/registry.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/summary.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/timer.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/untyped.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/value.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vec.go delete mode 100644 vendor/github.com/prometheus/client_model/LICENSE delete mode 100644 vendor/github.com/prometheus/client_model/NOTICE delete mode 100644 vendor/github.com/prometheus/client_model/go/metrics.pb.go delete mode 100644 vendor/github.com/prometheus/client_model/ruby/LICENSE delete mode 100644 vendor/github.com/prometheus/common/LICENSE delete mode 100644 vendor/github.com/prometheus/common/NOTICE delete mode 100644 vendor/github.com/prometheus/common/expfmt/decode.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/encode.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/expfmt.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/fuzz.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/text_create.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/text_parse.go delete mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go delete mode 100644 vendor/github.com/prometheus/common/model/alert.go delete mode 100644 vendor/github.com/prometheus/common/model/fingerprinting.go delete mode 100644 vendor/github.com/prometheus/common/model/fnv.go delete mode 100644 vendor/github.com/prometheus/common/model/labels.go delete mode 100644 vendor/github.com/prometheus/common/model/labelset.go delete mode 100644 vendor/github.com/prometheus/common/model/metric.go delete mode 100644 vendor/github.com/prometheus/common/model/signature.go delete mode 100644 vendor/github.com/prometheus/common/model/silence.go delete mode 100644 vendor/github.com/prometheus/common/model/time.go delete mode 100644 vendor/github.com/prometheus/common/model/value.go delete mode 100644 vendor/github.com/prometheus/procfs/LICENSE delete mode 100644 vendor/github.com/prometheus/procfs/NOTICE delete mode 100644 vendor/github.com/prometheus/procfs/buddyinfo.go delete mode 100644 vendor/github.com/prometheus/procfs/doc.go delete mode 100644 vendor/github.com/prometheus/procfs/fs.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/parse.go delete mode 100644 vendor/github.com/prometheus/procfs/ipvs.go delete mode 100644 vendor/github.com/prometheus/procfs/mdstat.go delete mode 100644 vendor/github.com/prometheus/procfs/mountstats.go delete mode 100644 vendor/github.com/prometheus/procfs/net_dev.go delete mode 100644 vendor/github.com/prometheus/procfs/nfs/nfs.go delete mode 100644 vendor/github.com/prometheus/procfs/nfs/parse.go delete mode 100644 vendor/github.com/prometheus/procfs/nfs/parse_nfs.go delete mode 100644 vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go delete mode 100644 vendor/github.com/prometheus/procfs/proc.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_io.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_limits.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_ns.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_stat.go delete mode 100644 vendor/github.com/prometheus/procfs/stat.go delete mode 100644 vendor/github.com/prometheus/procfs/xfrm.go delete mode 100644 vendor/github.com/prometheus/procfs/xfs/parse.go delete mode 100644 vendor/github.com/prometheus/procfs/xfs/xfs.go delete mode 100644 vendor/github.com/tchap/go-patricia/AUTHORS delete mode 100644 vendor/github.com/tchap/go-patricia/LICENSE delete mode 100644 vendor/github.com/tchap/go-patricia/patricia/children.go delete mode 100644 vendor/github.com/tchap/go-patricia/patricia/patricia.go delete mode 100644 vendor/github.com/vbatts/tar-split/LICENSE delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/common.go delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/reader.go delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/stat_atim.go delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/stat_atimespec.go delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/stat_unix.go delete mode 100644 vendor/github.com/vbatts/tar-split/archive/tar/writer.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/asm/assemble.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/asm/disassemble.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/asm/doc.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/storage/doc.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/storage/entry.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/storage/getter.go delete mode 100644 vendor/github.com/vbatts/tar-split/tar/storage/packer.go delete mode 100644 vendor/golang.org/x/crypto/cast5/cast5.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/armor/armor.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/armor/encode.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/canonical_text.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/errors/errors.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/keys.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/compressed.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/config.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/literal.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/ocfb.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/opaque.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/packet.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/private_key.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/reader.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userattribute.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userid.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/read.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/s2k/s2k.go delete mode 100644 vendor/golang.org/x/crypto/openpgp/write.go delete mode 100644 vendor/golang.org/x/net/internal/socks/client.go delete mode 100644 vendor/golang.org/x/net/internal/socks/socks.go delete mode 100644 vendor/golang.org/x/net/proxy/direct.go delete mode 100644 vendor/golang.org/x/net/proxy/per_host.go delete mode 100644 vendor/golang.org/x/net/proxy/proxy.go delete mode 100644 vendor/golang.org/x/net/proxy/socks5.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/LICENSE delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/format.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pb.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pool.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/reader.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/runecount.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go delete mode 100644 vendor/gopkg.in/cheggaaa/pb.v1/termios_sysv.go delete mode 100644 vendor/k8s.io/client-go/LICENSE delete mode 100644 vendor/k8s.io/client-go/util/homedir/homedir.go diff --git a/Gopkg.lock b/Gopkg.lock index 257a9383ed..7a899bbe10 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -15,171 +15,31 @@ revision = "29f476ffa9c4cd4fd14336b6043090ac1ad76733" version = "v0.21.0" -[[projects]] - name = "github.com/BurntSushi/toml" - packages = ["."] - revision = "b26d9c308763d68093482582cea63d69be07a0f0" - version = "v0.3.0" - -[[projects]] - branch = "master" - name = "github.com/GoogleContainerTools/container-diff" - packages = [ - "cmd/util/output", - "pkg/image", - "pkg/util" - ] - revision = "564361979f3124dd3e6d8bbec027279539c8e08b" - source = "github.com/GoogleContainerTools/container-diff" - [[projects]] name = "github.com/Microsoft/go-winio" - packages = [ - ".", - "archive/tar", - "backuptar" - ] + packages = ["."] revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f" version = "v0.4.7" -[[projects]] - name = "github.com/Microsoft/hcsshim" - packages = ["."] - revision = "45ef15484298b76abeb9513ea0ea0abd2b5b84b3" - version = "v0.6.8" - -[[projects]] - branch = "master" - name = "github.com/beorn7/perks" - packages = ["quantile"] - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - [[projects]] branch = "master" name = "github.com/containerd/continuity" packages = ["pathdriver"] revision = "c6cef34830231743494fe2969284df7b82cc0ad0" -[[projects]] - name = "github.com/containers/image" - packages = [ - "copy", - "directory", - "directory/explicitfilepath", - "docker", - "docker/archive", - "docker/daemon", - "docker/policyconfiguration", - "docker/reference", - "docker/tarfile", - "image", - "internal/tmpdir", - "manifest", - "oci/archive", - "oci/internal", - "oci/layout", - "openshift", - "ostree", - "pkg/compression", - "pkg/docker/config", - "pkg/strslice", - "pkg/tlsclientconfig", - "signature", - "storage", - "tarball", - "transports", - "transports/alltransports", - "types", - "version" - ] - revision = "495da41bd26c50be62fa07ae903ea2ee54c00283" - -[[projects]] - name = "github.com/containers/storage" - packages = [ - ".", - "drivers", - "drivers/aufs", - "drivers/btrfs", - "drivers/devmapper", - "drivers/overlay", - "drivers/overlayutils", - "drivers/quota", - "drivers/register", - "drivers/vfs", - "drivers/windows", - "drivers/zfs", - "pkg/archive", - "pkg/chrootarchive", - "pkg/devicemapper", - "pkg/directory", - "pkg/dmesg", - "pkg/fileutils", - "pkg/fsutils", - "pkg/homedir", - "pkg/idtools", - "pkg/ioutils", - "pkg/locker", - "pkg/longpath", - "pkg/loopback", - "pkg/mount", - "pkg/parsers", - "pkg/parsers/kernel", - "pkg/pools", - "pkg/promise", - "pkg/reexec", - "pkg/stringid", - "pkg/system", - "pkg/truncindex" - ] - revision = "1e5ce40cdb84ab66e26186435b1273e04b879fef" - source = "github.com/containers/storage" - -[[projects]] - name = "github.com/docker/distribution" - packages = [ - ".", - "digestset", - "metrics", - "reference", - "registry/api/errcode", - "registry/api/v2", - "registry/client", - "registry/client/auth/challenge", - "registry/client/transport", - "registry/storage/cache", - "registry/storage/cache/memory" - ] - revision = "83389a148052d74ac602f5f1d62f86ff2f3c4aa5" - source = "github.com/docker/distribution" - [[projects]] name = "github.com/docker/docker" packages = [ - "api", - "api/types", "api/types/blkiodev", "api/types/container", - "api/types/events", - "api/types/filters", - "api/types/image", "api/types/mount", - "api/types/network", - "api/types/registry", "api/types/strslice", - "api/types/swarm", - "api/types/swarm/runtime", - "api/types/time", - "api/types/versions", - "api/types/volume", "builder/dockerfile/command", "builder/dockerfile/instructions", "builder/dockerfile/parser", "builder/dockerfile/shell", - "client", "pkg/archive", "pkg/fileutils", - "pkg/homedir", "pkg/idtools", "pkg/ioutils", "pkg/longpath", @@ -190,61 +50,24 @@ revision = "b1a1234c60cf87048814aa37da523b03a7b0d344" source = "github.com/docker/docker" -[[projects]] - name = "github.com/docker/docker-credential-helpers" - packages = [ - "client", - "credentials" - ] - revision = "d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1" - version = "v0.6.0" - [[projects]] name = "github.com/docker/go-connections" - packages = [ - "nat", - "sockets", - "tlsconfig" - ] + packages = ["nat"] revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d" version = "v0.3.0" -[[projects]] - branch = "master" - name = "github.com/docker/go-metrics" - packages = ["."] - revision = "399ea8c73916000c64c2c76e8da00ca82f8387ab" - [[projects]] name = "github.com/docker/go-units" packages = ["."] revision = "47565b4f722fb6ceae66b95f853feed578a4a51c" version = "v0.3.3" -[[projects]] - branch = "master" - name = "github.com/docker/libtrust" - packages = ["."] - revision = "aabc10ec26b754e797f9028f4589c5b7bd90dc20" - [[projects]] name = "github.com/genuinetools/amicontained" packages = ["container"] revision = "fcae88544f0212fbb1e20699c41566655b68679b" version = "v0.4.0" -[[projects]] - name = "github.com/ghodss/yaml" - packages = ["."] - revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" - version = "v1.0.0" - -[[projects]] - name = "github.com/gogo/protobuf" - packages = ["proto"] - revision = "1adfc126b41513cc696b209667c8656ea7aac67c" - version = "v1.0.0" - [[projects]] name = "github.com/golang/protobuf" packages = [ @@ -258,66 +81,37 @@ revision = "925541529c1fa6821df4e44ce2723319eb2be768" version = "v1.0.0" +[[projects]] + branch = "master" + name = "github.com/google/go-containerregistry" + packages = [ + "authn", + "name", + "v1", + "v1/empty", + "v1/mutate", + "v1/partial", + "v1/random", + "v1/remote", + "v1/remote/transport", + "v1/tarball", + "v1/types", + "v1/v1util" + ] + revision = "2f7b7371197ff22ecc4578e081a73292cc32ae02" + [[projects]] name = "github.com/googleapis/gax-go" packages = ["."] revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" version = "v2.0.0" -[[projects]] - name = "github.com/gorilla/context" - packages = ["."] - revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" - version = "v1.1" - -[[projects]] - name = "github.com/gorilla/mux" - packages = ["."] - revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" - version = "v1.6.1" - -[[projects]] - name = "github.com/imdario/mergo" - packages = ["."] - revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c" - version = "v0.3.4" - [[projects]] name = "github.com/inconshreveable/mousetrap" packages = ["."] revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" -[[projects]] - name = "github.com/mattn/go-runewidth" - packages = ["."] - revision = "9e777a8366cce605130a531d2cd6363d07ad7317" - version = "v0.0.2" - -[[projects]] - name = "github.com/mattn/go-shellwords" - packages = ["."] - revision = "02e3cf038dcea8290e44424da473dd12be796a8a" - version = "v1.0.3" - -[[projects]] - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" - version = "v1.0.0" - -[[projects]] - name = "github.com/mistifyio/go-zfs" - packages = ["."] - revision = "cdc0f941c4d0e0e94d85348285568d921891e138" - version = "v2.1.1" - -[[projects]] - branch = "master" - name = "github.com/mtrmac/gpgme" - packages = ["."] - revision = "b2432428689ca58c2b8e8dea9449d3295cf96fc9" - [[projects]] name = "github.com/opencontainers/go-digest" packages = ["."] @@ -342,75 +136,12 @@ revision = "baf6536d6259209c3edfa2b22237af82942d3dfa" version = "v0.1.1" -[[projects]] - name = "github.com/opencontainers/selinux" - packages = [ - "go-selinux", - "go-selinux/label" - ] - revision = "ba1aefe8057f1d0cfb8e88d0ec1dc85925ef987d" - version = "v1.0.0-rc1" - -[[projects]] - branch = "master" - name = "github.com/ostreedev/ostree-go" - packages = [ - "pkg/glibobject", - "pkg/otbuiltin" - ] - revision = "cb6250d5a6a240b509609915842f763fd87b819d" - [[projects]] name = "github.com/pkg/errors" packages = ["."] revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" -[[projects]] - branch = "master" - name = "github.com/pquerna/ffjson" - packages = [ - "fflib/v1", - "fflib/v1/internal" - ] - revision = "d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac" - -[[projects]] - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp" - ] - revision = "a40133b69fbd73ee655606a9bf5f8b9b9bf758dd" - source = "github.com/prometheus/client_golang" - -[[projects]] - branch = "master" - name = "github.com/prometheus/client_model" - packages = ["go"] - revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" - -[[projects]] - branch = "master" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model" - ] - revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6" - -[[projects]] - branch = "master" - name = "github.com/prometheus/procfs" - packages = [ - ".", - "internal/util", - "nfs", - "xfs" - ] - revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e" - [[projects]] name = "github.com/sirupsen/logrus" packages = ["."] @@ -435,22 +166,6 @@ packages = ["capability"] revision = "33e07d32887e1e06b7c025f27ce52f62c7990bc0" -[[projects]] - name = "github.com/tchap/go-patricia" - packages = ["patricia"] - revision = "666120de432aea38ab06bd5c818f04f4129882c9" - version = "v2.2.6" - -[[projects]] - name = "github.com/vbatts/tar-split" - packages = [ - "archive/tar", - "tar/asm", - "tar/storage" - ] - revision = "38ec4ddb06dedbea0a895c4848b248eb38af221b" - version = "v0.10.2" - [[projects]] name = "go.opencensus.io" packages = [ @@ -473,16 +188,7 @@ [[projects]] branch = "master" name = "golang.org/x/crypto" - packages = [ - "cast5", - "openpgp", - "openpgp/armor", - "openpgp/elgamal", - "openpgp/errors", - "openpgp/packet", - "openpgp/s2k", - "ssh/terminal" - ] + packages = ["ssh/terminal"] revision = "e73bf333ef8920dbb52ad18d4bd38ad9d9bc76d7" [[projects]] @@ -495,10 +201,8 @@ "http2", "http2/hpack", "idna", - "internal/socks", "internal/timeseries", "lex/httplex", - "proxy", "trace" ] revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23" @@ -619,27 +323,15 @@ revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" version = "v1.11.3" -[[projects]] - name = "gopkg.in/cheggaaa/pb.v1" - packages = ["."] - revision = "72b964305fba1230d3d818711138195f22b9ceea" - version = "v1.0.22" - [[projects]] name = "gopkg.in/yaml.v2" packages = ["."] revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" -[[projects]] - name = "k8s.io/client-go" - packages = ["util/homedir"] - revision = "23781f4d6632d88e869066eaebb743857aa1ef9b" - version = "v7.0.0" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "6d64e71de2909767e347f36c90936a5f77da94f74fe2dbf84d6d44fdbcdf4fba" + inputs-digest = "9ed51a63daab2be9e4864e4d97d90ccc0f540d076f891b80f01bd3f161c9ef7a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 47af20cd96..e86b513b5c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -18,11 +18,6 @@ revision = "83389a148052d74ac602f5f1d62f86ff2f3c4aa5" source = "github.com/docker/distribution" -[[constraint]] - name = "github.com/GoogleContainerTools/container-diff" - branch = "master" - source = "github.com/GoogleContainerTools/container-diff" - [[constraint]] name = "github.com/docker/docker" revision = "b1a1234c60cf87048814aa37da523b03a7b0d344" diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 2c8e9b69aa..6a4fd546ef 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -72,6 +72,10 @@ var RootCmd = &cobra.Command{ } logrus.Warn("kaniko is being run outside of a container. This can have dangerous effects on your system") } + if err := os.Chdir("/"); err != nil { + logrus.Error(err) + os.Exit(1) + } if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil { logrus.Error(err) os.Exit(1) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index a1b920c5de..5d811327ec 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -21,6 +21,7 @@ ADD files/docker-credential-gcr /usr/local/bin/ ADD files/config.json /root/.docker/ RUN ["docker-credential-gcr", "config", "--token-source=env"] ENV HOME /root +ENV USER /root ENV PATH /usr/local/bin ENV SSL_CERT_DIR=/kaniko/ssl/certs ENTRYPOINT ["/kaniko/executor"] diff --git a/pkg/commands/add.go b/pkg/commands/add.go index 2ce4a090f8..f7264afec7 100644 --- a/pkg/commands/add.go +++ b/pkg/commands/add.go @@ -20,8 +20,9 @@ import ( "path/filepath" "strings" + "github.com/google/go-containerregistry/v1" + "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/sirupsen/logrus" ) @@ -40,7 +41,7 @@ type AddCommand struct { // - If dest doesn't end with a slash, the filepath is inferred to be / // 2. If is a local tar archive: // -If is a local tar archive, it is unpacked at the dest, as 'tar -x' would -func (a *AddCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (a *AddCommand) ExecuteCommand(config *v1.Config) error { srcs := a.cmd.SourcesAndDest[:len(a.cmd.SourcesAndDest)-1] dest := a.cmd.SourcesAndDest[len(a.cmd.SourcesAndDest)-1] diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 4d49234b20..9d53bd98e7 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -17,10 +17,11 @@ limitations under the License. package commands import ( - "github.com/containers/image/manifest" + "strings" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" - "strings" ) type CmdCommand struct { @@ -29,7 +30,7 @@ type CmdCommand struct { // ExecuteCommand executes the CMD command // Argument handling is the same as RUN. -func (c *CmdCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (c *CmdCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: CMD") var newCommand []string if c.cmd.PrependShell { diff --git a/pkg/commands/cmd_test.go b/pkg/commands/cmd_test.go index 9a0c82e8a2..a8395af691 100644 --- a/pkg/commands/cmd_test.go +++ b/pkg/commands/cmd_test.go @@ -18,32 +18,32 @@ package commands import ( "testing" + "github.com/google/go-containerregistry/v1" + "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" - "github.com/containers/image/pkg/strslice" "github.com/docker/docker/builder/dockerfile/instructions" ) var cmdTests = []struct { prependShell bool cmdLine []string - expectedCmd strslice.StrSlice + expectedCmd []string }{ { prependShell: true, cmdLine: []string{"echo", "cmd1"}, - expectedCmd: strslice.StrSlice{"/bin/sh", "-c", "echo cmd1"}, + expectedCmd: []string{"/bin/sh", "-c", "echo cmd1"}, }, { prependShell: false, cmdLine: []string{"echo", "cmd2"}, - expectedCmd: strslice.StrSlice{"echo", "cmd2"}, + expectedCmd: []string{"echo", "cmd2"}, }, } func TestExecuteCmd(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Cmd: nil, } diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index dd2de8a8ac..96a5bed02f 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -17,8 +17,8 @@ limitations under the License. package commands import ( - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -28,7 +28,7 @@ type DockerCommand interface { // 1. Making required changes to the filesystem (ex. copying files for ADD/COPY or setting ENV variables) // 2. Updating metadata fields in the config // It should not change the config history. - ExecuteCommand(*manifest.Schema2Config) error + ExecuteCommand(*v1.Config) error // The config history has a "created by" field, should return information about the command CreatedBy() string // A list of files to snapshot, empty for metadata commands or nil if we don't know diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index bded4bf99c..91e60d82da 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -17,13 +17,14 @@ limitations under the License. package commands import ( - "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" - "github.com/docker/docker/builder/dockerfile/instructions" - "github.com/sirupsen/logrus" "os" "path/filepath" "strings" + + "github.com/GoogleContainerTools/kaniko/pkg/util" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" + "github.com/sirupsen/logrus" ) type CopyCommand struct { @@ -32,7 +33,7 @@ type CopyCommand struct { snapshotFiles []string } -func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (c *CopyCommand) ExecuteCommand(config *v1.Config) error { srcs := c.cmd.SourcesAndDest[:len(c.cmd.SourcesAndDest)-1] dest := c.cmd.SourcesAndDest[len(c.cmd.SourcesAndDest)-1] diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index a7fd5f3ed3..a753dc5ee0 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -17,10 +17,11 @@ limitations under the License. package commands import ( - "github.com/containers/image/manifest" + "strings" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" - "strings" ) type EntrypointCommand struct { @@ -28,7 +29,7 @@ type EntrypointCommand struct { } // ExecuteCommand handles command processing similar to CMD and RUN, -func (e *EntrypointCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: ENTRYPOINT") var newCommand []string if e.cmd.PrependShell { diff --git a/pkg/commands/entrypoint_test.go b/pkg/commands/entrypoint_test.go index ae24e8fea2..57d28cd87b 100644 --- a/pkg/commands/entrypoint_test.go +++ b/pkg/commands/entrypoint_test.go @@ -19,31 +19,30 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" - "github.com/containers/image/pkg/strslice" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) var entrypointTests = []struct { prependShell bool cmdLine []string - expectedCmd strslice.StrSlice + expectedCmd []string }{ { prependShell: true, cmdLine: []string{"echo", "cmd1"}, - expectedCmd: strslice.StrSlice{"/bin/sh", "-c", "echo cmd1"}, + expectedCmd: []string{"/bin/sh", "-c", "echo cmd1"}, }, { prependShell: false, cmdLine: []string{"echo", "cmd2"}, - expectedCmd: strslice.StrSlice{"echo", "cmd2"}, + expectedCmd: []string{"echo", "cmd2"}, }, } func TestEntrypointExecuteCmd(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Cmd: nil, } diff --git a/pkg/commands/env.go b/pkg/commands/env.go index acb379e23f..4e576a3f89 100644 --- a/pkg/commands/env.go +++ b/pkg/commands/env.go @@ -20,8 +20,8 @@ import ( "strings" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -29,7 +29,7 @@ type EnvCommand struct { cmd *instructions.EnvCommand } -func (e *EnvCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (e *EnvCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: ENV") newEnvs := e.cmd.Env for index, pair := range newEnvs { @@ -49,7 +49,7 @@ func (e *EnvCommand) ExecuteCommand(config *manifest.Schema2Config) error { return updateConfigEnv(newEnvs, config) } -func updateConfigEnv(newEnvs []instructions.KeyValuePair, config *manifest.Schema2Config) error { +func updateConfigEnv(newEnvs []instructions.KeyValuePair, config *v1.Config) error { // First, convert config.Env array to []instruction.KeyValuePair var kvps []instructions.KeyValuePair for _, env := range config.Env { diff --git a/pkg/commands/env_test.go b/pkg/commands/env_test.go index 346d57e434..a321852eb1 100644 --- a/pkg/commands/env_test.go +++ b/pkg/commands/env_test.go @@ -19,12 +19,12 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) func TestUpdateEnvConfig(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Env: []string{ "PATH=/path/to/dir", "hey=hey", @@ -55,7 +55,7 @@ func TestUpdateEnvConfig(t *testing.T) { testutil.CheckErrorAndDeepEqual(t, false, nil, expectedEnvArray, cfg.Env) } func Test_EnvExecute(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Env: []string{ "path=/usr/", "home=/root", diff --git a/pkg/commands/expose.go b/pkg/commands/expose.go index 2dca6a5a55..b86995d75a 100644 --- a/pkg/commands/expose.go +++ b/pkg/commands/expose.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -30,12 +30,12 @@ type ExposeCommand struct { cmd *instructions.ExposeCommand } -func (r *ExposeCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (r *ExposeCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: EXPOSE") // Grab the currently exposed ports existingPorts := config.ExposedPorts if existingPorts == nil { - existingPorts = make(map[manifest.Schema2Port]struct{}) + existingPorts = make(map[string]struct{}) } // Add any new ones in for _, p := range r.cmd.Ports { @@ -53,8 +53,7 @@ func (r *ExposeCommand) ExecuteCommand(config *manifest.Schema2Config) error { return fmt.Errorf("Invalid protocol: %s", protocol) } logrus.Infof("Adding exposed port: %s", p) - var x struct{} - existingPorts[manifest.Schema2Port(p)] = x + existingPorts[p] = struct{}{} } config.ExposedPorts = existingPorts return nil diff --git a/pkg/commands/expose_test.go b/pkg/commands/expose_test.go index 8bf8184f9f..4da4c3cde8 100644 --- a/pkg/commands/expose_test.go +++ b/pkg/commands/expose_test.go @@ -20,13 +20,13 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) func TestUpdateExposedPorts(t *testing.T) { - cfg := &manifest.Schema2Config{ - ExposedPorts: manifest.Schema2PortSet{ + cfg := &v1.Config{ + ExposedPorts: map[string]struct{}{ "8080/tcp": {}, }, Env: []string{ @@ -51,7 +51,7 @@ func TestUpdateExposedPorts(t *testing.T) { }, } - expectedPorts := manifest.Schema2PortSet{ + expectedPorts := map[string]struct{}{ "8080/tcp": {}, "8081/tcp": {}, "8082/tcp": {}, @@ -66,8 +66,8 @@ func TestUpdateExposedPorts(t *testing.T) { } func TestInvalidProtocol(t *testing.T) { - cfg := &manifest.Schema2Config{ - ExposedPorts: manifest.Schema2PortSet{}, + cfg := &v1.Config{ + ExposedPorts: map[string]struct{}{}, } ports := []string{ diff --git a/pkg/commands/label.go b/pkg/commands/label.go index 60577403ab..7296d4d39c 100644 --- a/pkg/commands/label.go +++ b/pkg/commands/label.go @@ -20,8 +20,8 @@ import ( "strings" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -29,12 +29,12 @@ type LabelCommand struct { cmd *instructions.LabelCommand } -func (r *LabelCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (r *LabelCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: LABEL") return updateLabels(r.cmd.Labels, config) } -func updateLabels(labels []instructions.KeyValuePair, config *manifest.Schema2Config) error { +func updateLabels(labels []instructions.KeyValuePair, config *v1.Config) error { existingLabels := config.Labels if existingLabels == nil { existingLabels = make(map[string]string) diff --git a/pkg/commands/label_test.go b/pkg/commands/label_test.go index fd91cc5703..56a3b8069f 100644 --- a/pkg/commands/label_test.go +++ b/pkg/commands/label_test.go @@ -20,12 +20,12 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) func TestUpdateLabels(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Labels: map[string]string{ "foo": "bar", }, diff --git a/pkg/commands/onbuild.go b/pkg/commands/onbuild.go index d0e1167dea..b490e1200c 100644 --- a/pkg/commands/onbuild.go +++ b/pkg/commands/onbuild.go @@ -18,8 +18,8 @@ package commands import ( "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -28,7 +28,7 @@ type OnBuildCommand struct { } //ExecuteCommand adds the specified expression in Onbuild to the config -func (o *OnBuildCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (o *OnBuildCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: ONBUILD") logrus.Infof("args: %s", o.cmd.Expression) resolvedExpression, err := util.ResolveEnvironmentReplacement(o.cmd.Expression, config.Env, false) diff --git a/pkg/commands/onbuild_test.go b/pkg/commands/onbuild_test.go index a67450960d..4164823bc8 100644 --- a/pkg/commands/onbuild_test.go +++ b/pkg/commands/onbuild_test.go @@ -20,8 +20,8 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) var onbuildTests = []struct { @@ -50,7 +50,7 @@ var onbuildTests = []struct { func TestExecuteOnbuild(t *testing.T) { for _, test := range onbuildTests { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Env: []string{ "dir=/some/dir", }, diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 699b23dfed..849f012d75 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -23,8 +23,8 @@ import ( "strings" "syscall" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -32,7 +32,7 @@ type RunCommand struct { cmd *instructions.RunCommand } -func (r *RunCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (r *RunCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if r.cmd.PrependShell { // This is the default shell on Linux diff --git a/pkg/commands/user.go b/pkg/commands/user.go index 5ca5687dc3..f33ab92de8 100644 --- a/pkg/commands/user.go +++ b/pkg/commands/user.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -30,7 +30,7 @@ type UserCommand struct { cmd *instructions.UserCommand } -func (r *UserCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (r *UserCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: USER") u := r.cmd.User userAndGroup := strings.Split(u, ":") diff --git a/pkg/commands/user_test.go b/pkg/commands/user_test.go index 27f19ba54d..308f705ad1 100644 --- a/pkg/commands/user_test.go +++ b/pkg/commands/user_test.go @@ -19,8 +19,8 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) var userTests = []struct { @@ -82,7 +82,7 @@ var userTests = []struct { func TestUpdateUser(t *testing.T) { for _, test := range userTests { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Env: []string{ "envuser=root", "envgroup=root", diff --git a/pkg/commands/volume.go b/pkg/commands/volume.go index 31fb476a92..ae3af55269 100644 --- a/pkg/commands/volume.go +++ b/pkg/commands/volume.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -31,7 +31,7 @@ type VolumeCommand struct { snapshotFiles []string } -func (v *VolumeCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (v *VolumeCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: VOLUME") volumes := v.cmd.Volumes resolvedVolumes, err := util.ResolveEnvironmentReplacementList(volumes, config.Env, true) diff --git a/pkg/commands/volume_test.go b/pkg/commands/volume_test.go index 07b6b1d75e..9eb8c5c5e9 100644 --- a/pkg/commands/volume_test.go +++ b/pkg/commands/volume_test.go @@ -19,12 +19,12 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) func TestUpdateVolume(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ Env: []string{ "VOLUME=/etc", }, diff --git a/pkg/commands/workdir.go b/pkg/commands/workdir.go index 8972efecb7..13a4b102b7 100644 --- a/pkg/commands/workdir.go +++ b/pkg/commands/workdir.go @@ -21,8 +21,8 @@ import ( "path/filepath" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -31,7 +31,7 @@ type WorkdirCommand struct { snapshotFiles []string } -func (w *WorkdirCommand) ExecuteCommand(config *manifest.Schema2Config) error { +func (w *WorkdirCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: workdir") workdirPath := w.cmd.Path resolvedWorkingDir, err := util.ResolveEnvironmentReplacement(workdirPath, config.Env, true) diff --git a/pkg/commands/workdir_test.go b/pkg/commands/workdir_test.go index 67187c2aed..426cf47184 100644 --- a/pkg/commands/workdir_test.go +++ b/pkg/commands/workdir_test.go @@ -19,8 +19,8 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" ) // Each test here changes the same WorkingDir field in the config @@ -63,7 +63,7 @@ var workdirTests = []struct { func TestWorkdirCommand(t *testing.T) { - cfg := &manifest.Schema2Config{ + cfg := &v1.Config{ WorkingDir: "/", Env: []string{ "path=usr/", diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index ab9eacd53f..d3b2039b13 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -17,17 +17,29 @@ limitations under the License. package executor import ( + "bytes" "fmt" + "io" "io/ioutil" + "net/http" "os" + "github.com/google/go-containerregistry/v1/empty" + + "github.com/google/go-containerregistry/v1/tarball" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/mutate" + "github.com/google/go-containerregistry/v1/remote" + "github.com/GoogleContainerTools/kaniko/pkg/commands" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" "github.com/GoogleContainerTools/kaniko/pkg/image" "github.com/GoogleContainerTools/kaniko/pkg/snapshot" "github.com/GoogleContainerTools/kaniko/pkg/util" - "github.com/containers/image/manifest" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/sirupsen/logrus" ) @@ -46,8 +58,28 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke baseImage := stages[0].BaseName // Unpack file system to root + var sourceImage v1.Image + var ref name.Reference logrus.Infof("Unpacking filesystem of %s...", baseImage) - if err := util.ExtractFileSystemFromImage(baseImage); err != nil { + if baseImage == constants.NoBaseImage { + logrus.Info("No base image, nothing to extract") + sourceImage = empty.Image + } else { + // Initialize source image + ref, err = name.ParseReference(baseImage, name.WeakValidation) + if err != nil { + return err + } + auth, err := authn.DefaultKeychain.Resolve(ref.Context().Registry) + if err != nil { + return err + } + sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) + if err != nil { + return err + } + } + if err := util.GetFSFromImage(sourceImage); err != nil { return err } @@ -63,21 +95,22 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke return err } - // Initialize source image - sourceImage, err := image.NewSourceImage(baseImage) + destRef, err := name.ParseReference(destination, name.WeakValidation) if err != nil { return err } - // Set environment variables within the image if err := image.SetEnvVariables(sourceImage); err != nil { return err } - imageConfig := sourceImage.Config() + imageConfig, err := sourceImage.ConfigFile() + if err != nil { + return err + } // Currently only supports single stage builds for _, stage := range stages { - if err := resolveOnBuild(&stage, imageConfig); err != nil { + if err := resolveOnBuild(&stage, &imageConfig.Config); err != nil { return err } for _, cmd := range stage.Commands { @@ -88,7 +121,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke if dockerCommand == nil { continue } - if err := dockerCommand.ExecuteCommand(imageConfig); err != nil { + if err := dockerCommand.ExecuteCommand(&imageConfig.Config); err != nil { return err } // Now, we get the files to snapshot from this command and take the snapshot @@ -100,11 +133,25 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke util.MoveVolumeWhitelistToWhitelist() if contents == nil { logrus.Info("No files were changed, appending empty layer to config.") - sourceImage.AppendConfigHistory(constants.Author, true) continue } // Append the layer to the image - if err := sourceImage.AppendLayer(contents, constants.Author); err != nil { + opener := func() (io.ReadCloser, error) { + return ioutil.NopCloser(bytes.NewReader(contents)), nil + } + layer, err := tarball.LayerFromOpener(opener) + if err != nil { + return err + } + sourceImage, err = mutate.Append(sourceImage, + mutate.Addendum{ + Layer: layer, + History: v1.History{ + Author: constants.Author, + }, + }, + ) + if err != nil { return err } } @@ -113,7 +160,21 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke if err := setDefaultEnv(); err != nil { return err } - return image.PushImage(sourceImage, destination, dockerInsecureSkipTLSVerify) + + wo := remote.WriteOptions{} + if ref != nil { + wo.MountPaths = []name.Repository{ref.Context()} + } + pushAuth, err := authn.DefaultKeychain.Resolve(destRef.Context().Registry) + if err != nil { + return err + } + sourceImage, err = mutate.Config(sourceImage, imageConfig.Config) + if err != nil { + return err + } + + return remote.Write(destRef, sourceImage, pushAuth, http.DefaultTransport, wo) } func getHasher(snapshotMode string) (func(string) (string, error), error) { @@ -127,7 +188,7 @@ func getHasher(snapshotMode string) (func(string) (string, error), error) { return nil, fmt.Errorf("%s is not a valid snapshot mode", snapshotMode) } -func resolveOnBuild(stage *instructions.Stage, config *manifest.Schema2Config) error { +func resolveOnBuild(stage *instructions.Stage, config *v1.Config) error { if config.OnBuild == nil { return nil } diff --git a/pkg/image/image.go b/pkg/image/image.go index 6309f30970..989decce26 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -17,80 +17,27 @@ limitations under the License. package image import ( - "fmt" "os" + "strings" - "github.com/GoogleContainerTools/kaniko/pkg/version" - "github.com/containers/image/types" + "github.com/google/go-containerregistry/v1" - img "github.com/GoogleContainerTools/container-diff/pkg/image" - "github.com/GoogleContainerTools/kaniko/pkg/constants" - "github.com/containers/image/copy" - "github.com/containers/image/docker" - "github.com/containers/image/signature" - "github.com/containers/image/transports/alltransports" "github.com/sirupsen/logrus" ) -// sourceImage is the image that will be modified by the executor - -// NewSourceImage initializes the source image with the base image -func NewSourceImage(srcImg string) (*img.MutableSource, error) { - if srcImg == constants.NoBaseImage { - return img.NewMutableSource(nil) - } - logrus.Infof("Initializing source image %s", srcImg) - ref, err := docker.ParseReference("//" + srcImg) - if err != nil { - return nil, err - } - return img.NewMutableSource(ref) -} - -// PushImage pushes the final image -func PushImage(ms *img.MutableSource, destImg string, dockerInsecureSkipTLSVerify bool) error { - srcRef := &img.ProxyReference{ - ImageReference: nil, - Src: ms, - } - destRef, err := alltransports.ParseImageName("docker://" + destImg) - if err != nil { - return err - } - policyContext, err := getPolicyContext() +// SetEnvVariables sets environment variables as specified in the image +func SetEnvVariables(img v1.Image) error { + cfg, err := img.ConfigFile() if err != nil { return err } - logrus.Infof("Pushing image to %s", destImg) - - opts := ©.Options{ - DestinationCtx: &types.SystemContext{ - DockerRegistryUserAgent: fmt.Sprintf("kaniko/executor-%s", version.Version()), - DockerInsecureSkipTLSVerify: dockerInsecureSkipTLSVerify, - }, - } - return copy.Image(policyContext, destRef, srcRef, opts) -} - -// SetEnvVariables sets environment variables as specified in the image -func SetEnvVariables(ms *img.MutableSource) error { - envVars := ms.Env() - for key, val := range envVars { - if err := os.Setenv(key, val); err != nil { + envVars := cfg.Config.Env + for _, envVar := range envVars { + split := strings.SplitN(envVar, "=", 2) + if err := os.Setenv(split[0], split[1]); err != nil { return err } - logrus.Debugf("Setting environment variable %s=%s", key, val) + logrus.Infof("Setting environment variable %s", envVar) } return nil } - -func getPolicyContext() (*signature.PolicyContext, error) { - policyContext, err := signature.NewPolicyContext(&signature.Policy{ - Default: signature.PolicyRequirements{signature.NewPRInsecureAcceptAnything()}, - }) - if err != nil { - logrus.Debugf("Error retrieving policy context: %s", err) - return nil, err - } - return policyContext, nil -} diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 70cfcd117c..9da540f237 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -150,6 +150,7 @@ func (s *Snapshotter) snapShotFS(f io.Writer) (bool, error) { return false, err } if maybeAdd { + logrus.Debugf("Adding %s to layer, because it was changed.", path) filesAdded = true if err := util.AddToTar(path, info, s.hardlinks, w); err != nil { return false, err diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index f5c96b80b1..d639740dfe 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -17,6 +17,7 @@ limitations under the License. package util import ( + "archive/tar" "bufio" "io" "net/http" @@ -25,38 +26,163 @@ import ( "strings" "time" - pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" + "github.com/google/go-containerregistry/v1" + "github.com/GoogleContainerTools/kaniko/pkg/constants" - "github.com/containers/image/docker" "github.com/sirupsen/logrus" ) -var whitelist = []string{"/kaniko"} +var whitelist = []string{ + "/kaniko", + // /var/run is a special case. It's common to mount in /var/run/docker.sock or something similar + // which leads to a special mount on the /var/run/docker.sock file itself, but the directory to exist + // in the image with no way to tell if it came from the base image or not. + "/var/run", +} var volumeWhitelist = []string{} -// ExtractFileSystemFromImage pulls an image and unpacks it to a file system at root -func ExtractFileSystemFromImage(img string) error { +func GetFSFromImage(img v1.Image) error { whitelist, err := fileSystemWhitelist(constants.WhitelistPath) if err != nil { return err } - logrus.Infof("Whitelisted directories are %s", whitelist) - if img == constants.NoBaseImage { - logrus.Info("No base image, nothing to extract") - return nil - } - ref, err := docker.ParseReference("//" + img) + logrus.Infof("Mounted directories: %v", whitelist) + layers, err := img.Layers() if err != nil { return err } - imgSrc, err := ref.NewImageSource(nil) - if err != nil { - return err + + fs := map[string]struct{}{} + whiteouts := map[string]struct{}{} + + for i := len(layers) - 1; i >= 0; i-- { + logrus.Infof("Unpacking layer: %d", i) + l := layers[i] + r, err := l.Uncompressed() + if err != nil { + return err + } + tr := tar.NewReader(r) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + path := filepath.Join("/", filepath.Clean(hdr.Name)) + base := filepath.Base(path) + dir := filepath.Dir(path) + if strings.HasPrefix(base, ".wh.") { + logrus.Infof("Whiting out %s", path) + name := strings.TrimPrefix(base, ".wh.") + whiteouts[filepath.Join(dir, name)] = struct{}{} + continue + } + + if checkWhiteouts(path, whiteouts) { + logrus.Infof("Not adding %s because it is whited out", path) + continue + } + if _, ok := fs[path]; ok { + logrus.Infof("Not adding %s because it was added by a prior layer", path) + continue + } + + if checkWhitelist(path, whitelist) { + logrus.Infof("Not adding %s because it is whitelisted", path) + continue + } + fs[path] = struct{}{} + + if err := extractFile("/", hdr, tr); err != nil { + return err + } + } + } + return nil +} + +func unTar(r io.Reader, dest string) error { + tr := tar.NewReader(r) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + if err := extractFile(dest, hdr, tr); err != nil { + return err + } + } + return nil +} + +func extractFile(dest string, hdr *tar.Header, tr io.Reader) error { + path := filepath.Join(dest, filepath.Clean(hdr.Name)) + base := filepath.Base(path) + dir := filepath.Dir(path) + mode := hdr.FileInfo().Mode() + switch hdr.Typeflag { + case tar.TypeReg: + logrus.Debugf("creating file %s", path) + // It's possible a file is in the tar before it's directory. + if _, err := os.Stat(dir); os.IsNotExist(err) { + logrus.Debugf("base %s for file %s does not exist. Creating.", base, path) + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + } + currFile, err := os.Create(path) + if err != nil { + return err + } + // manually set permissions on file, since the default umask (022) will interfere + if err = os.Chmod(path, mode); err != nil { + return err + } + if _, err = io.Copy(currFile, tr); err != nil { + return err + } + currFile.Close() + + case tar.TypeDir: + logrus.Debugf("creating dir %s", path) + if err := os.MkdirAll(path, mode); err != nil { + return err + } + // In some cases, MkdirAll doesn't change the permissions, so run Chmod + if err := os.Chmod(path, mode); err != nil { + return err + } + + case tar.TypeLink: + logrus.Debugf("link from %s to %s", hdr.Linkname, path) + // The base directory for a link may not exist before it is created. + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + if err := os.Symlink(filepath.Clean(filepath.Join("/", hdr.Linkname)), path); err != nil { + return err + } + case tar.TypeSymlink: + logrus.Debugf("symlink from %s to %s", hdr.Linkname, path) + // The base directory for a symlink may not exist before it is created. + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + if err := os.Symlink(hdr.Linkname, path); err != nil { + return err + } } - return pkgutil.GetFileSystemFromReference(ref, imgSrc, constants.RootDir, whitelist) + return nil } -// PathInWhitelist returns true if the path is whitelisted func PathInWhitelist(path, directory string) bool { for _, c := range constants.KanikoBuildFiles { if path == c { @@ -65,7 +191,30 @@ func PathInWhitelist(path, directory string) bool { } for _, d := range whitelist { dirPath := filepath.Join(directory, d) - if pkgutil.HasFilepathPrefix(path, dirPath) { + if HasFilepathPrefix(path, dirPath) { + return true + } + } + return false +} + +func checkWhiteouts(path string, whiteouts map[string]struct{}) bool { + // Don't add the file if it or it's directory are whited out. + if _, ok := whiteouts[path]; ok { + return true + } + for wd := range whiteouts { + if HasFilepathPrefix(path, wd) { + logrus.Infof("Not adding %s because it's directory is whited out", path) + return true + } + } + return false +} + +func checkWhitelist(path string, whitelist []string) bool { + for _, wl := range whitelist { + if HasFilepathPrefix(path, wl) { return true } } @@ -268,3 +417,22 @@ func CopyFile(src, dest string) error { defer srcFile.Close() return CreateFile(dest, srcFile, fi.Mode()) } + +// HasFilepathPrefix checks if the given file path begins with prefix +func HasFilepathPrefix(path, prefix string) bool { + path = filepath.Clean(path) + prefix = filepath.Clean(prefix) + pathArray := strings.Split(path, "/") + prefixArray := strings.Split(prefix, "/") + + if len(pathArray) < len(prefixArray) { + return false + } + for index := range prefixArray { + if prefixArray[index] == pathArray[index] { + continue + } + return false + } + return true +} diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 36583564c1..0334d8c56c 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -17,9 +17,12 @@ limitations under the License. package util import ( + "archive/tar" + "bytes" "io/ioutil" "os" "path/filepath" + "reflect" "sort" "testing" @@ -47,7 +50,7 @@ func Test_fileSystemWhitelist(t *testing.T) { } actualWhitelist, err := fileSystemWhitelist(path) - expectedWhitelist := []string{"/kaniko", "/proc", "/dev", "/dev/pts", "/sys"} + expectedWhitelist := []string{"/kaniko", "/proc", "/dev", "/dev/pts", "/sys", "/var/run"} sort.Strings(actualWhitelist) sort.Strings(expectedWhitelist) testutil.CheckErrorAndDeepEqual(t, false, err, expectedWhitelist, actualWhitelist) @@ -131,3 +134,358 @@ func Test_RelativeFiles(t *testing.T) { testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFiles, actualFiles) } } + +func Test_checkWhiteouts(t *testing.T) { + type args struct { + path string + whiteouts map[string]struct{} + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "file whited out", + args: args{ + path: "/foo", + whiteouts: map[string]struct{}{"/foo": {}}, + }, + want: true, + }, + { + name: "directory whited out", + args: args{ + path: "/foo/bar", + whiteouts: map[string]struct{}{"/foo": {}}, + }, + want: true, + }, + { + name: "grandparent whited out", + args: args{ + path: "/foo/bar/baz", + whiteouts: map[string]struct{}{"/foo": {}}, + }, + want: true, + }, + { + name: "sibling whited out", + args: args{ + path: "/foo/bar/baz", + whiteouts: map[string]struct{}{"/foo/bat": {}}, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := checkWhiteouts(tt.args.path, tt.args.whiteouts); got != tt.want { + t.Errorf("checkWhiteouts() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_checkWhitelist(t *testing.T) { + type args struct { + path string + whitelist []string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "file whitelisted", + args: args{ + path: "/foo", + whitelist: []string{"/foo"}, + }, + want: true, + }, + { + name: "directory whitelisted", + args: args{ + path: "/foo/bar", + whitelist: []string{"/foo"}, + }, + want: true, + }, + { + name: "grandparent whitelisted", + args: args{ + path: "/foo/bar/baz", + whitelist: []string{"/foo"}, + }, + want: true, + }, + { + name: "sibling whitelisted", + args: args{ + path: "/foo/bar/baz", + whitelist: []string{"/foo/bat"}, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := checkWhitelist(tt.args.path, tt.args.whitelist); got != tt.want { + t.Errorf("checkWhitelist() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestHasFilepathPrefix(t *testing.T) { + type args struct { + path string + prefix string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "parent", + args: args{ + path: "/foo/bar", + prefix: "/foo", + }, + want: true, + }, + { + name: "nested parent", + args: args{ + path: "/foo/bar/baz", + prefix: "/foo/bar", + }, + want: true, + }, + { + name: "sibling", + args: args{ + path: "/foo/bar", + prefix: "/bar", + }, + want: false, + }, + { + name: "nested sibling", + args: args{ + path: "/foo/bar/baz", + prefix: "/foo/bar", + }, + want: true, + }, + { + name: "name prefix", + args: args{ + path: "/foo2/bar", + prefix: "/foo", + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := HasFilepathPrefix(tt.args.path, tt.args.prefix); got != tt.want { + t.Errorf("HasFilepathPrefix() = %v, want %v", got, tt.want) + } + }) + } +} + +type checker func(root string, t *testing.T) + +func fileExists(p string) checker { + return func(root string, t *testing.T) { + _, err := os.Stat(filepath.Join(root, p)) + if err != nil { + t.Fatalf("File does not exist") + } + } +} + +func fileMatches(p string, c []byte) checker { + return func(root string, t *testing.T) { + actual, err := ioutil.ReadFile(filepath.Join(root, p)) + if err != nil { + t.Fatalf("error reading file: %s", p) + } + if !reflect.DeepEqual(actual, c) { + t.Errorf("file contents do not match. %v!=%v", actual, c) + } + } +} + +func permissionsMatch(p string, perms os.FileMode) checker { + return func(root string, t *testing.T) { + fi, err := os.Stat(filepath.Join(root, p)) + if err != nil { + t.Fatalf("error statting file %s", p) + } + if fi.Mode() != perms { + t.Errorf("Permissions do not match. %s != %s", fi.Mode(), perms) + } + } +} + +func linkPointsTo(src, dst string) checker { + return func(root string, t *testing.T) { + link := filepath.Join(root, src) + got, err := os.Readlink(link) + if err != nil { + t.Fatalf("error reading link %s: %s", link, err) + } + if got != dst { + t.Errorf("link destination does not match: %s != %s", got, dst) + } + } +} + +func fileHeader(name string, contents string, mode int64) *tar.Header { + return &tar.Header{ + Name: name, + Size: int64(len(contents)), + Mode: mode, + Typeflag: tar.TypeReg, + } +} + +func linkHeader(name, linkname string) *tar.Header { + return &tar.Header{ + Name: name, + Size: 0, + Typeflag: tar.TypeSymlink, + Linkname: linkname, + } +} + +func hardlinkHeader(name, linkname string) *tar.Header { + return &tar.Header{ + Name: name, + Size: 0, + Typeflag: tar.TypeLink, + Linkname: linkname, + } +} + +func dirHeader(name string, mode int64) *tar.Header { + return &tar.Header{ + Name: name, + Size: 0, + Typeflag: tar.TypeDir, + Mode: mode, + } +} + +func TestExtractFile(t *testing.T) { + type tc struct { + name string + hdrs []*tar.Header + contents []byte + checkers []checker + } + + tcs := []tc{ + { + name: "normal file", + contents: []byte("helloworld"), + hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 0644)}, + checkers: []checker{ + fileExists("/bar"), + fileMatches("/bar", []byte("helloworld")), + permissionsMatch("/bar", 0644), + }, + }, + { + name: "normal file, directory does not exist", + contents: []byte("helloworld"), + hdrs: []*tar.Header{fileHeader("./foo/bar", "helloworld", 0644)}, + checkers: []checker{ + fileExists("/foo/bar"), + fileMatches("/foo/bar", []byte("helloworld")), + permissionsMatch("/foo/bar", 0644), + permissionsMatch("/foo", 0755|os.ModeDir), + }, + }, + { + name: "normal file, directory is created after", + contents: []byte("helloworld"), + hdrs: []*tar.Header{ + fileHeader("./foo/bar", "helloworld", 0644), + dirHeader("./foo", 0722), + }, + checkers: []checker{ + fileExists("/foo/bar"), + fileMatches("/foo/bar", []byte("helloworld")), + permissionsMatch("/foo/bar", 0644), + permissionsMatch("/foo", 0722|os.ModeDir), + }, + }, + { + name: "symlink", + hdrs: []*tar.Header{linkHeader("./bar", "bar/bat")}, + checkers: []checker{ + linkPointsTo("/bar", "bar/bat"), + }, + }, + { + name: "symlink relative path", + hdrs: []*tar.Header{linkHeader("./bar", "./foo/bar/baz")}, + checkers: []checker{ + linkPointsTo("/bar", "./foo/bar/baz"), + }, + }, + { + name: "symlink parent does not exist", + hdrs: []*tar.Header{linkHeader("./foo/bar/baz", "../../bat")}, + checkers: []checker{ + linkPointsTo("/foo/bar/baz", "../../bat"), + }, + }, + { + name: "symlink parent does not exist", + hdrs: []*tar.Header{linkHeader("./foo/bar/baz", "../../bat")}, + checkers: []checker{ + linkPointsTo("/foo/bar/baz", "../../bat"), + permissionsMatch("/foo", 0755|os.ModeDir), + permissionsMatch("/foo/bar", 0755|os.ModeDir), + }, + }, + { + name: "hardlink", + hdrs: []*tar.Header{ + fileHeader("/bin/gzip", "gzip-binary", 0751), + hardlinkHeader("/bin/uncompress", "/bin/gzip"), + }, + checkers: []checker{ + linkPointsTo("/bin/uncompress", "/bin/gzip"), + }, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + tc := tc + t.Parallel() + r, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(r) + for _, hdr := range tc.hdrs { + if err := extractFile(r, hdr, bytes.NewReader(tc.contents)); err != nil { + t.Fatal(err) + } + } + for _, checker := range tc.checkers { + checker(r, t) + } + }) + } +} diff --git a/pkg/util/tar_util.go b/pkg/util/tar_util.go index c752c98c75..baf15a60c8 100644 --- a/pkg/util/tar_util.go +++ b/pkg/util/tar_util.go @@ -26,7 +26,6 @@ import ( "path/filepath" "syscall" - pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" "github.com/docker/docker/pkg/archive" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -122,7 +121,7 @@ func UnpackLocalTarArchive(path, dest string) error { return UnpackCompressedTar(path, dest) } else if compressionLevel == archive.Bzip2 { bzr := bzip2.NewReader(file) - return pkgutil.UnTar(bzr, dest, nil) + return unTar(bzr, dest) } } if fileIsUncompressedTar(path) { @@ -131,7 +130,7 @@ func UnpackLocalTarArchive(path, dest string) error { return err } defer file.Close() - return pkgutil.UnTar(file, dest, nil) + return unTar(file, dest) } return errors.New("path does not lead to local tar archive") } @@ -195,5 +194,5 @@ func UnpackCompressedTar(path, dir string) error { return err } defer gzr.Close() - return pkgutil.UnTar(gzr, dir, nil) + return unTar(gzr, dir) } diff --git a/vendor/github.com/BurntSushi/toml/COPYING b/vendor/github.com/BurntSushi/toml/COPYING deleted file mode 100644 index 5a8e332545..0000000000 --- a/vendor/github.com/BurntSushi/toml/COPYING +++ /dev/null @@ -1,14 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING b/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING deleted file mode 100644 index 5a8e332545..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING +++ /dev/null @@ -1,14 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING b/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING deleted file mode 100644 index 5a8e332545..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING +++ /dev/null @@ -1,14 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING b/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING deleted file mode 100644 index 5a8e332545..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING +++ /dev/null @@ -1,14 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go deleted file mode 100644 index b0fd51d5b6..0000000000 --- a/vendor/github.com/BurntSushi/toml/decode.go +++ /dev/null @@ -1,509 +0,0 @@ -package toml - -import ( - "fmt" - "io" - "io/ioutil" - "math" - "reflect" - "strings" - "time" -) - -func e(format string, args ...interface{}) error { - return fmt.Errorf("toml: "+format, args...) -} - -// Unmarshaler is the interface implemented by objects that can unmarshal a -// TOML description of themselves. -type Unmarshaler interface { - UnmarshalTOML(interface{}) error -} - -// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`. -func Unmarshal(p []byte, v interface{}) error { - _, err := Decode(string(p), v) - return err -} - -// Primitive is a TOML value that hasn't been decoded into a Go value. -// When using the various `Decode*` functions, the type `Primitive` may -// be given to any value, and its decoding will be delayed. -// -// A `Primitive` value can be decoded using the `PrimitiveDecode` function. -// -// The underlying representation of a `Primitive` value is subject to change. -// Do not rely on it. -// -// N.B. Primitive values are still parsed, so using them will only avoid -// the overhead of reflection. They can be useful when you don't know the -// exact type of TOML data until run time. -type Primitive struct { - undecoded interface{} - context Key -} - -// DEPRECATED! -// -// Use MetaData.PrimitiveDecode instead. -func PrimitiveDecode(primValue Primitive, v interface{}) error { - md := MetaData{decoded: make(map[string]bool)} - return md.unify(primValue.undecoded, rvalue(v)) -} - -// PrimitiveDecode is just like the other `Decode*` functions, except it -// decodes a TOML value that has already been parsed. Valid primitive values -// can *only* be obtained from values filled by the decoder functions, -// including this method. (i.e., `v` may contain more `Primitive` -// values.) -// -// Meta data for primitive values is included in the meta data returned by -// the `Decode*` functions with one exception: keys returned by the Undecoded -// method will only reflect keys that were decoded. Namely, any keys hidden -// behind a Primitive will be considered undecoded. Executing this method will -// update the undecoded keys in the meta data. (See the example.) -func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { - md.context = primValue.context - defer func() { md.context = nil }() - return md.unify(primValue.undecoded, rvalue(v)) -} - -// Decode will decode the contents of `data` in TOML format into a pointer -// `v`. -// -// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be -// used interchangeably.) -// -// TOML arrays of tables correspond to either a slice of structs or a slice -// of maps. -// -// TOML datetimes correspond to Go `time.Time` values. -// -// All other TOML types (float, string, int, bool and array) correspond -// to the obvious Go types. -// -// An exception to the above rules is if a type implements the -// encoding.TextUnmarshaler interface. In this case, any primitive TOML value -// (floats, strings, integers, booleans and datetimes) will be converted to -// a byte string and given to the value's UnmarshalText method. See the -// Unmarshaler example for a demonstration with time duration strings. -// -// Key mapping -// -// TOML keys can map to either keys in a Go map or field names in a Go -// struct. The special `toml` struct tag may be used to map TOML keys to -// struct fields that don't match the key name exactly. (See the example.) -// A case insensitive match to struct names will be tried if an exact match -// can't be found. -// -// The mapping between TOML values and Go values is loose. That is, there -// may exist TOML values that cannot be placed into your representation, and -// there may be parts of your representation that do not correspond to -// TOML values. This loose mapping can be made stricter by using the IsDefined -// and/or Undecoded methods on the MetaData returned. -// -// This decoder will not handle cyclic types. If a cyclic type is passed, -// `Decode` will not terminate. -func Decode(data string, v interface{}) (MetaData, error) { - rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr { - return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v)) - } - if rv.IsNil() { - return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v)) - } - p, err := parse(data) - if err != nil { - return MetaData{}, err - } - md := MetaData{ - p.mapping, p.types, p.ordered, - make(map[string]bool, len(p.ordered)), nil, - } - return md, md.unify(p.mapping, indirect(rv)) -} - -// DecodeFile is just like Decode, except it will automatically read the -// contents of the file at `fpath` and decode it for you. -func DecodeFile(fpath string, v interface{}) (MetaData, error) { - bs, err := ioutil.ReadFile(fpath) - if err != nil { - return MetaData{}, err - } - return Decode(string(bs), v) -} - -// DecodeReader is just like Decode, except it will consume all bytes -// from the reader and decode it for you. -func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { - bs, err := ioutil.ReadAll(r) - if err != nil { - return MetaData{}, err - } - return Decode(string(bs), v) -} - -// unify performs a sort of type unification based on the structure of `rv`, -// which is the client representation. -// -// Any type mismatch produces an error. Finding a type that we don't know -// how to handle produces an unsupported type error. -func (md *MetaData) unify(data interface{}, rv reflect.Value) error { - - // Special case. Look for a `Primitive` value. - if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { - // Save the undecoded data and the key context into the primitive - // value. - context := make(Key, len(md.context)) - copy(context, md.context) - rv.Set(reflect.ValueOf(Primitive{ - undecoded: data, - context: context, - })) - return nil - } - - // Special case. Unmarshaler Interface support. - if rv.CanAddr() { - if v, ok := rv.Addr().Interface().(Unmarshaler); ok { - return v.UnmarshalTOML(data) - } - } - - // Special case. Handle time.Time values specifically. - // TODO: Remove this code when we decide to drop support for Go 1.1. - // This isn't necessary in Go 1.2 because time.Time satisfies the encoding - // interfaces. - if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) { - return md.unifyDatetime(data, rv) - } - - // Special case. Look for a value satisfying the TextUnmarshaler interface. - if v, ok := rv.Interface().(TextUnmarshaler); ok { - return md.unifyText(data, v) - } - // BUG(burntsushi) - // The behavior here is incorrect whenever a Go type satisfies the - // encoding.TextUnmarshaler interface but also corresponds to a TOML - // hash or array. In particular, the unmarshaler should only be applied - // to primitive TOML values. But at this point, it will be applied to - // all kinds of values and produce an incorrect error whenever those values - // are hashes or arrays (including arrays of tables). - - k := rv.Kind() - - // laziness - if k >= reflect.Int && k <= reflect.Uint64 { - return md.unifyInt(data, rv) - } - switch k { - case reflect.Ptr: - elem := reflect.New(rv.Type().Elem()) - err := md.unify(data, reflect.Indirect(elem)) - if err != nil { - return err - } - rv.Set(elem) - return nil - case reflect.Struct: - return md.unifyStruct(data, rv) - case reflect.Map: - return md.unifyMap(data, rv) - case reflect.Array: - return md.unifyArray(data, rv) - case reflect.Slice: - return md.unifySlice(data, rv) - case reflect.String: - return md.unifyString(data, rv) - case reflect.Bool: - return md.unifyBool(data, rv) - case reflect.Interface: - // we only support empty interfaces. - if rv.NumMethod() > 0 { - return e("unsupported type %s", rv.Type()) - } - return md.unifyAnything(data, rv) - case reflect.Float32: - fallthrough - case reflect.Float64: - return md.unifyFloat64(data, rv) - } - return e("unsupported type %s", rv.Kind()) -} - -func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { - tmap, ok := mapping.(map[string]interface{}) - if !ok { - if mapping == nil { - return nil - } - return e("type mismatch for %s: expected table but found %T", - rv.Type().String(), mapping) - } - - for key, datum := range tmap { - var f *field - fields := cachedTypeFields(rv.Type()) - for i := range fields { - ff := &fields[i] - if ff.name == key { - f = ff - break - } - if f == nil && strings.EqualFold(ff.name, key) { - f = ff - } - } - if f != nil { - subv := rv - for _, i := range f.index { - subv = indirect(subv.Field(i)) - } - if isUnifiable(subv) { - md.decoded[md.context.add(key).String()] = true - md.context = append(md.context, key) - if err := md.unify(datum, subv); err != nil { - return err - } - md.context = md.context[0 : len(md.context)-1] - } else if f.name != "" { - // Bad user! No soup for you! - return e("cannot write unexported field %s.%s", - rv.Type().String(), f.name) - } - } - } - return nil -} - -func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { - tmap, ok := mapping.(map[string]interface{}) - if !ok { - if tmap == nil { - return nil - } - return badtype("map", mapping) - } - if rv.IsNil() { - rv.Set(reflect.MakeMap(rv.Type())) - } - for k, v := range tmap { - md.decoded[md.context.add(k).String()] = true - md.context = append(md.context, k) - - rvkey := indirect(reflect.New(rv.Type().Key())) - rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) - if err := md.unify(v, rvval); err != nil { - return err - } - md.context = md.context[0 : len(md.context)-1] - - rvkey.SetString(k) - rv.SetMapIndex(rvkey, rvval) - } - return nil -} - -func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { - datav := reflect.ValueOf(data) - if datav.Kind() != reflect.Slice { - if !datav.IsValid() { - return nil - } - return badtype("slice", data) - } - sliceLen := datav.Len() - if sliceLen != rv.Len() { - return e("expected array length %d; got TOML array of length %d", - rv.Len(), sliceLen) - } - return md.unifySliceArray(datav, rv) -} - -func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { - datav := reflect.ValueOf(data) - if datav.Kind() != reflect.Slice { - if !datav.IsValid() { - return nil - } - return badtype("slice", data) - } - n := datav.Len() - if rv.IsNil() || rv.Cap() < n { - rv.Set(reflect.MakeSlice(rv.Type(), n, n)) - } - rv.SetLen(n) - return md.unifySliceArray(datav, rv) -} - -func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { - sliceLen := data.Len() - for i := 0; i < sliceLen; i++ { - v := data.Index(i).Interface() - sliceval := indirect(rv.Index(i)) - if err := md.unify(v, sliceval); err != nil { - return err - } - } - return nil -} - -func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error { - if _, ok := data.(time.Time); ok { - rv.Set(reflect.ValueOf(data)) - return nil - } - return badtype("time.Time", data) -} - -func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { - if s, ok := data.(string); ok { - rv.SetString(s) - return nil - } - return badtype("string", data) -} - -func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { - if num, ok := data.(float64); ok { - switch rv.Kind() { - case reflect.Float32: - fallthrough - case reflect.Float64: - rv.SetFloat(num) - default: - panic("bug") - } - return nil - } - return badtype("float", data) -} - -func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { - if num, ok := data.(int64); ok { - if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 { - switch rv.Kind() { - case reflect.Int, reflect.Int64: - // No bounds checking necessary. - case reflect.Int8: - if num < math.MinInt8 || num > math.MaxInt8 { - return e("value %d is out of range for int8", num) - } - case reflect.Int16: - if num < math.MinInt16 || num > math.MaxInt16 { - return e("value %d is out of range for int16", num) - } - case reflect.Int32: - if num < math.MinInt32 || num > math.MaxInt32 { - return e("value %d is out of range for int32", num) - } - } - rv.SetInt(num) - } else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 { - unum := uint64(num) - switch rv.Kind() { - case reflect.Uint, reflect.Uint64: - // No bounds checking necessary. - case reflect.Uint8: - if num < 0 || unum > math.MaxUint8 { - return e("value %d is out of range for uint8", num) - } - case reflect.Uint16: - if num < 0 || unum > math.MaxUint16 { - return e("value %d is out of range for uint16", num) - } - case reflect.Uint32: - if num < 0 || unum > math.MaxUint32 { - return e("value %d is out of range for uint32", num) - } - } - rv.SetUint(unum) - } else { - panic("unreachable") - } - return nil - } - return badtype("integer", data) -} - -func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { - if b, ok := data.(bool); ok { - rv.SetBool(b) - return nil - } - return badtype("boolean", data) -} - -func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { - rv.Set(reflect.ValueOf(data)) - return nil -} - -func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error { - var s string - switch sdata := data.(type) { - case TextMarshaler: - text, err := sdata.MarshalText() - if err != nil { - return err - } - s = string(text) - case fmt.Stringer: - s = sdata.String() - case string: - s = sdata - case bool: - s = fmt.Sprintf("%v", sdata) - case int64: - s = fmt.Sprintf("%d", sdata) - case float64: - s = fmt.Sprintf("%f", sdata) - default: - return badtype("primitive (string-like)", data) - } - if err := v.UnmarshalText([]byte(s)); err != nil { - return err - } - return nil -} - -// rvalue returns a reflect.Value of `v`. All pointers are resolved. -func rvalue(v interface{}) reflect.Value { - return indirect(reflect.ValueOf(v)) -} - -// indirect returns the value pointed to by a pointer. -// Pointers are followed until the value is not a pointer. -// New values are allocated for each nil pointer. -// -// An exception to this rule is if the value satisfies an interface of -// interest to us (like encoding.TextUnmarshaler). -func indirect(v reflect.Value) reflect.Value { - if v.Kind() != reflect.Ptr { - if v.CanSet() { - pv := v.Addr() - if _, ok := pv.Interface().(TextUnmarshaler); ok { - return pv - } - } - return v - } - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - return indirect(reflect.Indirect(v)) -} - -func isUnifiable(rv reflect.Value) bool { - if rv.CanSet() { - return true - } - if _, ok := rv.Interface().(TextUnmarshaler); ok { - return true - } - return false -} - -func badtype(expected string, data interface{}) error { - return e("cannot load TOML value of type %T into a Go %s", data, expected) -} diff --git a/vendor/github.com/BurntSushi/toml/decode_meta.go b/vendor/github.com/BurntSushi/toml/decode_meta.go deleted file mode 100644 index b9914a6798..0000000000 --- a/vendor/github.com/BurntSushi/toml/decode_meta.go +++ /dev/null @@ -1,121 +0,0 @@ -package toml - -import "strings" - -// MetaData allows access to meta information about TOML data that may not -// be inferrable via reflection. In particular, whether a key has been defined -// and the TOML type of a key. -type MetaData struct { - mapping map[string]interface{} - types map[string]tomlType - keys []Key - decoded map[string]bool - context Key // Used only during decoding. -} - -// IsDefined returns true if the key given exists in the TOML data. The key -// should be specified hierarchially. e.g., -// -// // access the TOML key 'a.b.c' -// IsDefined("a", "b", "c") -// -// IsDefined will return false if an empty key given. Keys are case sensitive. -func (md *MetaData) IsDefined(key ...string) bool { - if len(key) == 0 { - return false - } - - var hash map[string]interface{} - var ok bool - var hashOrVal interface{} = md.mapping - for _, k := range key { - if hash, ok = hashOrVal.(map[string]interface{}); !ok { - return false - } - if hashOrVal, ok = hash[k]; !ok { - return false - } - } - return true -} - -// Type returns a string representation of the type of the key specified. -// -// Type will return the empty string if given an empty key or a key that -// does not exist. Keys are case sensitive. -func (md *MetaData) Type(key ...string) string { - fullkey := strings.Join(key, ".") - if typ, ok := md.types[fullkey]; ok { - return typ.typeString() - } - return "" -} - -// Key is the type of any TOML key, including key groups. Use (MetaData).Keys -// to get values of this type. -type Key []string - -func (k Key) String() string { - return strings.Join(k, ".") -} - -func (k Key) maybeQuotedAll() string { - var ss []string - for i := range k { - ss = append(ss, k.maybeQuoted(i)) - } - return strings.Join(ss, ".") -} - -func (k Key) maybeQuoted(i int) string { - quote := false - for _, c := range k[i] { - if !isBareKeyChar(c) { - quote = true - break - } - } - if quote { - return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\"" - } - return k[i] -} - -func (k Key) add(piece string) Key { - newKey := make(Key, len(k)+1) - copy(newKey, k) - newKey[len(k)] = piece - return newKey -} - -// Keys returns a slice of every key in the TOML data, including key groups. -// Each key is itself a slice, where the first element is the top of the -// hierarchy and the last is the most specific. -// -// The list will have the same order as the keys appeared in the TOML data. -// -// All keys returned are non-empty. -func (md *MetaData) Keys() []Key { - return md.keys -} - -// Undecoded returns all keys that have not been decoded in the order in which -// they appear in the original TOML document. -// -// This includes keys that haven't been decoded because of a Primitive value. -// Once the Primitive value is decoded, the keys will be considered decoded. -// -// Also note that decoding into an empty interface will result in no decoding, -// and so no keys will be considered decoded. -// -// In this sense, the Undecoded keys correspond to keys in the TOML document -// that do not have a concrete type in your representation. -func (md *MetaData) Undecoded() []Key { - undecoded := make([]Key, 0, len(md.keys)) - for _, key := range md.keys { - if !md.decoded[key.String()] { - undecoded = append(undecoded, key) - } - } - return undecoded -} diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go deleted file mode 100644 index b371f396ed..0000000000 --- a/vendor/github.com/BurntSushi/toml/doc.go +++ /dev/null @@ -1,27 +0,0 @@ -/* -Package toml provides facilities for decoding and encoding TOML configuration -files via reflection. There is also support for delaying decoding with -the Primitive type, and querying the set of keys in a TOML document with the -MetaData type. - -The specification implemented: https://github.com/toml-lang/toml - -The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify -whether a file is a valid TOML document. It can also be used to print the -type of each key in a TOML document. - -Testing - -There are two important types of tests used for this package. The first is -contained inside '*_test.go' files and uses the standard Go unit testing -framework. These tests are primarily devoted to holistically testing the -decoder and encoder. - -The second type of testing is used to verify the implementation's adherence -to the TOML specification. These tests have been factored into their own -project: https://github.com/BurntSushi/toml-test - -The reason the tests are in a separate project is so that they can be used by -any implementation of TOML. Namely, it is language agnostic. -*/ -package toml diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go deleted file mode 100644 index d905c21a24..0000000000 --- a/vendor/github.com/BurntSushi/toml/encode.go +++ /dev/null @@ -1,568 +0,0 @@ -package toml - -import ( - "bufio" - "errors" - "fmt" - "io" - "reflect" - "sort" - "strconv" - "strings" - "time" -) - -type tomlEncodeError struct{ error } - -var ( - errArrayMixedElementTypes = errors.New( - "toml: cannot encode array with mixed element types") - errArrayNilElement = errors.New( - "toml: cannot encode array with nil element") - errNonString = errors.New( - "toml: cannot encode a map with non-string key type") - errAnonNonStruct = errors.New( - "toml: cannot encode an anonymous field that is not a struct") - errArrayNoTable = errors.New( - "toml: TOML array element cannot contain a table") - errNoKey = errors.New( - "toml: top-level values must be Go maps or structs") - errAnything = errors.New("") // used in testing -) - -var quotedReplacer = strings.NewReplacer( - "\t", "\\t", - "\n", "\\n", - "\r", "\\r", - "\"", "\\\"", - "\\", "\\\\", -) - -// Encoder controls the encoding of Go values to a TOML document to some -// io.Writer. -// -// The indentation level can be controlled with the Indent field. -type Encoder struct { - // A single indentation level. By default it is two spaces. - Indent string - - // hasWritten is whether we have written any output to w yet. - hasWritten bool - w *bufio.Writer -} - -// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer -// given. By default, a single indentation level is 2 spaces. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - w: bufio.NewWriter(w), - Indent: " ", - } -} - -// Encode writes a TOML representation of the Go value to the underlying -// io.Writer. If the value given cannot be encoded to a valid TOML document, -// then an error is returned. -// -// The mapping between Go values and TOML values should be precisely the same -// as for the Decode* functions. Similarly, the TextMarshaler interface is -// supported by encoding the resulting bytes as strings. (If you want to write -// arbitrary binary data then you will need to use something like base64 since -// TOML does not have any binary types.) -// -// When encoding TOML hashes (i.e., Go maps or structs), keys without any -// sub-hashes are encoded first. -// -// If a Go map is encoded, then its keys are sorted alphabetically for -// deterministic output. More control over this behavior may be provided if -// there is demand for it. -// -// Encoding Go values without a corresponding TOML representation---like map -// types with non-string keys---will cause an error to be returned. Similarly -// for mixed arrays/slices, arrays/slices with nil elements, embedded -// non-struct types and nested slices containing maps or structs. -// (e.g., [][]map[string]string is not allowed but []map[string]string is OK -// and so is []map[string][]string.) -func (enc *Encoder) Encode(v interface{}) error { - rv := eindirect(reflect.ValueOf(v)) - if err := enc.safeEncode(Key([]string{}), rv); err != nil { - return err - } - return enc.w.Flush() -} - -func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) { - defer func() { - if r := recover(); r != nil { - if terr, ok := r.(tomlEncodeError); ok { - err = terr.error - return - } - panic(r) - } - }() - enc.encode(key, rv) - return nil -} - -func (enc *Encoder) encode(key Key, rv reflect.Value) { - // Special case. Time needs to be in ISO8601 format. - // Special case. If we can marshal the type to text, then we used that. - // Basically, this prevents the encoder for handling these types as - // generic structs (or whatever the underlying type of a TextMarshaler is). - switch rv.Interface().(type) { - case time.Time, TextMarshaler: - enc.keyEqElement(key, rv) - return - } - - k := rv.Kind() - switch k { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, - reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, - reflect.Uint64, - reflect.Float32, reflect.Float64, reflect.String, reflect.Bool: - enc.keyEqElement(key, rv) - case reflect.Array, reflect.Slice: - if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) { - enc.eArrayOfTables(key, rv) - } else { - enc.keyEqElement(key, rv) - } - case reflect.Interface: - if rv.IsNil() { - return - } - enc.encode(key, rv.Elem()) - case reflect.Map: - if rv.IsNil() { - return - } - enc.eTable(key, rv) - case reflect.Ptr: - if rv.IsNil() { - return - } - enc.encode(key, rv.Elem()) - case reflect.Struct: - enc.eTable(key, rv) - default: - panic(e("unsupported type for key '%s': %s", key, k)) - } -} - -// eElement encodes any value that can be an array element (primitives and -// arrays). -func (enc *Encoder) eElement(rv reflect.Value) { - switch v := rv.Interface().(type) { - case time.Time: - // Special case time.Time as a primitive. Has to come before - // TextMarshaler below because time.Time implements - // encoding.TextMarshaler, but we need to always use UTC. - enc.wf(v.UTC().Format("2006-01-02T15:04:05Z")) - return - case TextMarshaler: - // Special case. Use text marshaler if it's available for this value. - if s, err := v.MarshalText(); err != nil { - encPanic(err) - } else { - enc.writeQuoted(string(s)) - } - return - } - switch rv.Kind() { - case reflect.Bool: - enc.wf(strconv.FormatBool(rv.Bool())) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, - reflect.Int64: - enc.wf(strconv.FormatInt(rv.Int(), 10)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, - reflect.Uint32, reflect.Uint64: - enc.wf(strconv.FormatUint(rv.Uint(), 10)) - case reflect.Float32: - enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32))) - case reflect.Float64: - enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64))) - case reflect.Array, reflect.Slice: - enc.eArrayOrSliceElement(rv) - case reflect.Interface: - enc.eElement(rv.Elem()) - case reflect.String: - enc.writeQuoted(rv.String()) - default: - panic(e("unexpected primitive type: %s", rv.Kind())) - } -} - -// By the TOML spec, all floats must have a decimal with at least one -// number on either side. -func floatAddDecimal(fstr string) string { - if !strings.Contains(fstr, ".") { - return fstr + ".0" - } - return fstr -} - -func (enc *Encoder) writeQuoted(s string) { - enc.wf("\"%s\"", quotedReplacer.Replace(s)) -} - -func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) { - length := rv.Len() - enc.wf("[") - for i := 0; i < length; i++ { - elem := rv.Index(i) - enc.eElement(elem) - if i != length-1 { - enc.wf(", ") - } - } - enc.wf("]") -} - -func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) { - if len(key) == 0 { - encPanic(errNoKey) - } - for i := 0; i < rv.Len(); i++ { - trv := rv.Index(i) - if isNil(trv) { - continue - } - panicIfInvalidKey(key) - enc.newline() - enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll()) - enc.newline() - enc.eMapOrStruct(key, trv) - } -} - -func (enc *Encoder) eTable(key Key, rv reflect.Value) { - panicIfInvalidKey(key) - if len(key) == 1 { - // Output an extra newline between top-level tables. - // (The newline isn't written if nothing else has been written though.) - enc.newline() - } - if len(key) > 0 { - enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll()) - enc.newline() - } - enc.eMapOrStruct(key, rv) -} - -func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) { - switch rv := eindirect(rv); rv.Kind() { - case reflect.Map: - enc.eMap(key, rv) - case reflect.Struct: - enc.eStruct(key, rv) - default: - panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String()) - } -} - -func (enc *Encoder) eMap(key Key, rv reflect.Value) { - rt := rv.Type() - if rt.Key().Kind() != reflect.String { - encPanic(errNonString) - } - - // Sort keys so that we have deterministic output. And write keys directly - // underneath this key first, before writing sub-structs or sub-maps. - var mapKeysDirect, mapKeysSub []string - for _, mapKey := range rv.MapKeys() { - k := mapKey.String() - if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) { - mapKeysSub = append(mapKeysSub, k) - } else { - mapKeysDirect = append(mapKeysDirect, k) - } - } - - var writeMapKeys = func(mapKeys []string) { - sort.Strings(mapKeys) - for _, mapKey := range mapKeys { - mrv := rv.MapIndex(reflect.ValueOf(mapKey)) - if isNil(mrv) { - // Don't write anything for nil fields. - continue - } - enc.encode(key.add(mapKey), mrv) - } - } - writeMapKeys(mapKeysDirect) - writeMapKeys(mapKeysSub) -} - -func (enc *Encoder) eStruct(key Key, rv reflect.Value) { - // Write keys for fields directly under this key first, because if we write - // a field that creates a new table, then all keys under it will be in that - // table (not the one we're writing here). - rt := rv.Type() - var fieldsDirect, fieldsSub [][]int - var addFields func(rt reflect.Type, rv reflect.Value, start []int) - addFields = func(rt reflect.Type, rv reflect.Value, start []int) { - for i := 0; i < rt.NumField(); i++ { - f := rt.Field(i) - // skip unexported fields - if f.PkgPath != "" && !f.Anonymous { - continue - } - frv := rv.Field(i) - if f.Anonymous { - t := f.Type - switch t.Kind() { - case reflect.Struct: - // Treat anonymous struct fields with - // tag names as though they are not - // anonymous, like encoding/json does. - if getOptions(f.Tag).name == "" { - addFields(t, frv, f.Index) - continue - } - case reflect.Ptr: - if t.Elem().Kind() == reflect.Struct && - getOptions(f.Tag).name == "" { - if !frv.IsNil() { - addFields(t.Elem(), frv.Elem(), f.Index) - } - continue - } - // Fall through to the normal field encoding logic below - // for non-struct anonymous fields. - } - } - - if typeIsHash(tomlTypeOfGo(frv)) { - fieldsSub = append(fieldsSub, append(start, f.Index...)) - } else { - fieldsDirect = append(fieldsDirect, append(start, f.Index...)) - } - } - } - addFields(rt, rv, nil) - - var writeFields = func(fields [][]int) { - for _, fieldIndex := range fields { - sft := rt.FieldByIndex(fieldIndex) - sf := rv.FieldByIndex(fieldIndex) - if isNil(sf) { - // Don't write anything for nil fields. - continue - } - - opts := getOptions(sft.Tag) - if opts.skip { - continue - } - keyName := sft.Name - if opts.name != "" { - keyName = opts.name - } - if opts.omitempty && isEmpty(sf) { - continue - } - if opts.omitzero && isZero(sf) { - continue - } - - enc.encode(key.add(keyName), sf) - } - } - writeFields(fieldsDirect) - writeFields(fieldsSub) -} - -// tomlTypeName returns the TOML type name of the Go value's type. It is -// used to determine whether the types of array elements are mixed (which is -// forbidden). If the Go value is nil, then it is illegal for it to be an array -// element, and valueIsNil is returned as true. - -// Returns the TOML type of a Go value. The type may be `nil`, which means -// no concrete TOML type could be found. -func tomlTypeOfGo(rv reflect.Value) tomlType { - if isNil(rv) || !rv.IsValid() { - return nil - } - switch rv.Kind() { - case reflect.Bool: - return tomlBool - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, - reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, - reflect.Uint64: - return tomlInteger - case reflect.Float32, reflect.Float64: - return tomlFloat - case reflect.Array, reflect.Slice: - if typeEqual(tomlHash, tomlArrayType(rv)) { - return tomlArrayHash - } - return tomlArray - case reflect.Ptr, reflect.Interface: - return tomlTypeOfGo(rv.Elem()) - case reflect.String: - return tomlString - case reflect.Map: - return tomlHash - case reflect.Struct: - switch rv.Interface().(type) { - case time.Time: - return tomlDatetime - case TextMarshaler: - return tomlString - default: - return tomlHash - } - default: - panic("unexpected reflect.Kind: " + rv.Kind().String()) - } -} - -// tomlArrayType returns the element type of a TOML array. The type returned -// may be nil if it cannot be determined (e.g., a nil slice or a zero length -// slize). This function may also panic if it finds a type that cannot be -// expressed in TOML (such as nil elements, heterogeneous arrays or directly -// nested arrays of tables). -func tomlArrayType(rv reflect.Value) tomlType { - if isNil(rv) || !rv.IsValid() || rv.Len() == 0 { - return nil - } - firstType := tomlTypeOfGo(rv.Index(0)) - if firstType == nil { - encPanic(errArrayNilElement) - } - - rvlen := rv.Len() - for i := 1; i < rvlen; i++ { - elem := rv.Index(i) - switch elemType := tomlTypeOfGo(elem); { - case elemType == nil: - encPanic(errArrayNilElement) - case !typeEqual(firstType, elemType): - encPanic(errArrayMixedElementTypes) - } - } - // If we have a nested array, then we must make sure that the nested - // array contains ONLY primitives. - // This checks arbitrarily nested arrays. - if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) { - nest := tomlArrayType(eindirect(rv.Index(0))) - if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) { - encPanic(errArrayNoTable) - } - } - return firstType -} - -type tagOptions struct { - skip bool // "-" - name string - omitempty bool - omitzero bool -} - -func getOptions(tag reflect.StructTag) tagOptions { - t := tag.Get("toml") - if t == "-" { - return tagOptions{skip: true} - } - var opts tagOptions - parts := strings.Split(t, ",") - opts.name = parts[0] - for _, s := range parts[1:] { - switch s { - case "omitempty": - opts.omitempty = true - case "omitzero": - opts.omitzero = true - } - } - return opts -} - -func isZero(rv reflect.Value) bool { - switch rv.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return rv.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return rv.Uint() == 0 - case reflect.Float32, reflect.Float64: - return rv.Float() == 0.0 - } - return false -} - -func isEmpty(rv reflect.Value) bool { - switch rv.Kind() { - case reflect.Array, reflect.Slice, reflect.Map, reflect.String: - return rv.Len() == 0 - case reflect.Bool: - return !rv.Bool() - } - return false -} - -func (enc *Encoder) newline() { - if enc.hasWritten { - enc.wf("\n") - } -} - -func (enc *Encoder) keyEqElement(key Key, val reflect.Value) { - if len(key) == 0 { - encPanic(errNoKey) - } - panicIfInvalidKey(key) - enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) - enc.eElement(val) - enc.newline() -} - -func (enc *Encoder) wf(format string, v ...interface{}) { - if _, err := fmt.Fprintf(enc.w, format, v...); err != nil { - encPanic(err) - } - enc.hasWritten = true -} - -func (enc *Encoder) indentStr(key Key) string { - return strings.Repeat(enc.Indent, len(key)-1) -} - -func encPanic(err error) { - panic(tomlEncodeError{err}) -} - -func eindirect(v reflect.Value) reflect.Value { - switch v.Kind() { - case reflect.Ptr, reflect.Interface: - return eindirect(v.Elem()) - default: - return v - } -} - -func isNil(rv reflect.Value) bool { - switch rv.Kind() { - case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: - return rv.IsNil() - default: - return false - } -} - -func panicIfInvalidKey(key Key) { - for _, k := range key { - if len(k) == 0 { - encPanic(e("Key '%s' is not a valid table name. Key names "+ - "cannot be empty.", key.maybeQuotedAll())) - } - } -} - -func isValidKeyName(s string) bool { - return len(s) != 0 -} diff --git a/vendor/github.com/BurntSushi/toml/encoding_types.go b/vendor/github.com/BurntSushi/toml/encoding_types.go deleted file mode 100644 index d36e1dd600..0000000000 --- a/vendor/github.com/BurntSushi/toml/encoding_types.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build go1.2 - -package toml - -// In order to support Go 1.1, we define our own TextMarshaler and -// TextUnmarshaler types. For Go 1.2+, we just alias them with the -// standard library interfaces. - -import ( - "encoding" -) - -// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here -// so that Go 1.1 can be supported. -type TextMarshaler encoding.TextMarshaler - -// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined -// here so that Go 1.1 can be supported. -type TextUnmarshaler encoding.TextUnmarshaler diff --git a/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go b/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go deleted file mode 100644 index e8d503d046..0000000000 --- a/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !go1.2 - -package toml - -// These interfaces were introduced in Go 1.2, so we add them manually when -// compiling for Go 1.1. - -// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here -// so that Go 1.1 can be supported. -type TextMarshaler interface { - MarshalText() (text []byte, err error) -} - -// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined -// here so that Go 1.1 can be supported. -type TextUnmarshaler interface { - UnmarshalText(text []byte) error -} diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go deleted file mode 100644 index 6dee7fc792..0000000000 --- a/vendor/github.com/BurntSushi/toml/lex.go +++ /dev/null @@ -1,953 +0,0 @@ -package toml - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -type itemType int - -const ( - itemError itemType = iota - itemNIL // used in the parser to indicate no type - itemEOF - itemText - itemString - itemRawString - itemMultilineString - itemRawMultilineString - itemBool - itemInteger - itemFloat - itemDatetime - itemArray // the start of an array - itemArrayEnd - itemTableStart - itemTableEnd - itemArrayTableStart - itemArrayTableEnd - itemKeyStart - itemCommentStart - itemInlineTableStart - itemInlineTableEnd -) - -const ( - eof = 0 - comma = ',' - tableStart = '[' - tableEnd = ']' - arrayTableStart = '[' - arrayTableEnd = ']' - tableSep = '.' - keySep = '=' - arrayStart = '[' - arrayEnd = ']' - commentStart = '#' - stringStart = '"' - stringEnd = '"' - rawStringStart = '\'' - rawStringEnd = '\'' - inlineTableStart = '{' - inlineTableEnd = '}' -) - -type stateFn func(lx *lexer) stateFn - -type lexer struct { - input string - start int - pos int - line int - state stateFn - items chan item - - // Allow for backing up up to three runes. - // This is necessary because TOML contains 3-rune tokens (""" and '''). - prevWidths [3]int - nprev int // how many of prevWidths are in use - // If we emit an eof, we can still back up, but it is not OK to call - // next again. - atEOF bool - - // A stack of state functions used to maintain context. - // The idea is to reuse parts of the state machine in various places. - // For example, values can appear at the top level or within arbitrarily - // nested arrays. The last state on the stack is used after a value has - // been lexed. Similarly for comments. - stack []stateFn -} - -type item struct { - typ itemType - val string - line int -} - -func (lx *lexer) nextItem() item { - for { - select { - case item := <-lx.items: - return item - default: - lx.state = lx.state(lx) - } - } -} - -func lex(input string) *lexer { - lx := &lexer{ - input: input, - state: lexTop, - line: 1, - items: make(chan item, 10), - stack: make([]stateFn, 0, 10), - } - return lx -} - -func (lx *lexer) push(state stateFn) { - lx.stack = append(lx.stack, state) -} - -func (lx *lexer) pop() stateFn { - if len(lx.stack) == 0 { - return lx.errorf("BUG in lexer: no states to pop") - } - last := lx.stack[len(lx.stack)-1] - lx.stack = lx.stack[0 : len(lx.stack)-1] - return last -} - -func (lx *lexer) current() string { - return lx.input[lx.start:lx.pos] -} - -func (lx *lexer) emit(typ itemType) { - lx.items <- item{typ, lx.current(), lx.line} - lx.start = lx.pos -} - -func (lx *lexer) emitTrim(typ itemType) { - lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line} - lx.start = lx.pos -} - -func (lx *lexer) next() (r rune) { - if lx.atEOF { - panic("next called after EOF") - } - if lx.pos >= len(lx.input) { - lx.atEOF = true - return eof - } - - if lx.input[lx.pos] == '\n' { - lx.line++ - } - lx.prevWidths[2] = lx.prevWidths[1] - lx.prevWidths[1] = lx.prevWidths[0] - if lx.nprev < 3 { - lx.nprev++ - } - r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) - lx.prevWidths[0] = w - lx.pos += w - return r -} - -// ignore skips over the pending input before this point. -func (lx *lexer) ignore() { - lx.start = lx.pos -} - -// backup steps back one rune. Can be called only twice between calls to next. -func (lx *lexer) backup() { - if lx.atEOF { - lx.atEOF = false - return - } - if lx.nprev < 1 { - panic("backed up too far") - } - w := lx.prevWidths[0] - lx.prevWidths[0] = lx.prevWidths[1] - lx.prevWidths[1] = lx.prevWidths[2] - lx.nprev-- - lx.pos -= w - if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' { - lx.line-- - } -} - -// accept consumes the next rune if it's equal to `valid`. -func (lx *lexer) accept(valid rune) bool { - if lx.next() == valid { - return true - } - lx.backup() - return false -} - -// peek returns but does not consume the next rune in the input. -func (lx *lexer) peek() rune { - r := lx.next() - lx.backup() - return r -} - -// skip ignores all input that matches the given predicate. -func (lx *lexer) skip(pred func(rune) bool) { - for { - r := lx.next() - if pred(r) { - continue - } - lx.backup() - lx.ignore() - return - } -} - -// errorf stops all lexing by emitting an error and returning `nil`. -// Note that any value that is a character is escaped if it's a special -// character (newlines, tabs, etc.). -func (lx *lexer) errorf(format string, values ...interface{}) stateFn { - lx.items <- item{ - itemError, - fmt.Sprintf(format, values...), - lx.line, - } - return nil -} - -// lexTop consumes elements at the top level of TOML data. -func lexTop(lx *lexer) stateFn { - r := lx.next() - if isWhitespace(r) || isNL(r) { - return lexSkip(lx, lexTop) - } - switch r { - case commentStart: - lx.push(lexTop) - return lexCommentStart - case tableStart: - return lexTableStart - case eof: - if lx.pos > lx.start { - return lx.errorf("unexpected EOF") - } - lx.emit(itemEOF) - return nil - } - - // At this point, the only valid item can be a key, so we back up - // and let the key lexer do the rest. - lx.backup() - lx.push(lexTopEnd) - return lexKeyStart -} - -// lexTopEnd is entered whenever a top-level item has been consumed. (A value -// or a table.) It must see only whitespace, and will turn back to lexTop -// upon a newline. If it sees EOF, it will quit the lexer successfully. -func lexTopEnd(lx *lexer) stateFn { - r := lx.next() - switch { - case r == commentStart: - // a comment will read to a newline for us. - lx.push(lexTop) - return lexCommentStart - case isWhitespace(r): - return lexTopEnd - case isNL(r): - lx.ignore() - return lexTop - case r == eof: - lx.emit(itemEOF) - return nil - } - return lx.errorf("expected a top-level item to end with a newline, "+ - "comment, or EOF, but got %q instead", r) -} - -// lexTable lexes the beginning of a table. Namely, it makes sure that -// it starts with a character other than '.' and ']'. -// It assumes that '[' has already been consumed. -// It also handles the case that this is an item in an array of tables. -// e.g., '[[name]]'. -func lexTableStart(lx *lexer) stateFn { - if lx.peek() == arrayTableStart { - lx.next() - lx.emit(itemArrayTableStart) - lx.push(lexArrayTableEnd) - } else { - lx.emit(itemTableStart) - lx.push(lexTableEnd) - } - return lexTableNameStart -} - -func lexTableEnd(lx *lexer) stateFn { - lx.emit(itemTableEnd) - return lexTopEnd -} - -func lexArrayTableEnd(lx *lexer) stateFn { - if r := lx.next(); r != arrayTableEnd { - return lx.errorf("expected end of table array name delimiter %q, "+ - "but got %q instead", arrayTableEnd, r) - } - lx.emit(itemArrayTableEnd) - return lexTopEnd -} - -func lexTableNameStart(lx *lexer) stateFn { - lx.skip(isWhitespace) - switch r := lx.peek(); { - case r == tableEnd || r == eof: - return lx.errorf("unexpected end of table name " + - "(table names cannot be empty)") - case r == tableSep: - return lx.errorf("unexpected table separator " + - "(table names cannot be empty)") - case r == stringStart || r == rawStringStart: - lx.ignore() - lx.push(lexTableNameEnd) - return lexValue // reuse string lexing - default: - return lexBareTableName - } -} - -// lexBareTableName lexes the name of a table. It assumes that at least one -// valid character for the table has already been read. -func lexBareTableName(lx *lexer) stateFn { - r := lx.next() - if isBareKeyChar(r) { - return lexBareTableName - } - lx.backup() - lx.emit(itemText) - return lexTableNameEnd -} - -// lexTableNameEnd reads the end of a piece of a table name, optionally -// consuming whitespace. -func lexTableNameEnd(lx *lexer) stateFn { - lx.skip(isWhitespace) - switch r := lx.next(); { - case isWhitespace(r): - return lexTableNameEnd - case r == tableSep: - lx.ignore() - return lexTableNameStart - case r == tableEnd: - return lx.pop() - default: - return lx.errorf("expected '.' or ']' to end table name, "+ - "but got %q instead", r) - } -} - -// lexKeyStart consumes a key name up until the first non-whitespace character. -// lexKeyStart will ignore whitespace. -func lexKeyStart(lx *lexer) stateFn { - r := lx.peek() - switch { - case r == keySep: - return lx.errorf("unexpected key separator %q", keySep) - case isWhitespace(r) || isNL(r): - lx.next() - return lexSkip(lx, lexKeyStart) - case r == stringStart || r == rawStringStart: - lx.ignore() - lx.emit(itemKeyStart) - lx.push(lexKeyEnd) - return lexValue // reuse string lexing - default: - lx.ignore() - lx.emit(itemKeyStart) - return lexBareKey - } -} - -// lexBareKey consumes the text of a bare key. Assumes that the first character -// (which is not whitespace) has not yet been consumed. -func lexBareKey(lx *lexer) stateFn { - switch r := lx.next(); { - case isBareKeyChar(r): - return lexBareKey - case isWhitespace(r): - lx.backup() - lx.emit(itemText) - return lexKeyEnd - case r == keySep: - lx.backup() - lx.emit(itemText) - return lexKeyEnd - default: - return lx.errorf("bare keys cannot contain %q", r) - } -} - -// lexKeyEnd consumes the end of a key and trims whitespace (up to the key -// separator). -func lexKeyEnd(lx *lexer) stateFn { - switch r := lx.next(); { - case r == keySep: - return lexSkip(lx, lexValue) - case isWhitespace(r): - return lexSkip(lx, lexKeyEnd) - default: - return lx.errorf("expected key separator %q, but got %q instead", - keySep, r) - } -} - -// lexValue starts the consumption of a value anywhere a value is expected. -// lexValue will ignore whitespace. -// After a value is lexed, the last state on the next is popped and returned. -func lexValue(lx *lexer) stateFn { - // We allow whitespace to precede a value, but NOT newlines. - // In array syntax, the array states are responsible for ignoring newlines. - r := lx.next() - switch { - case isWhitespace(r): - return lexSkip(lx, lexValue) - case isDigit(r): - lx.backup() // avoid an extra state and use the same as above - return lexNumberOrDateStart - } - switch r { - case arrayStart: - lx.ignore() - lx.emit(itemArray) - return lexArrayValue - case inlineTableStart: - lx.ignore() - lx.emit(itemInlineTableStart) - return lexInlineTableValue - case stringStart: - if lx.accept(stringStart) { - if lx.accept(stringStart) { - lx.ignore() // Ignore """ - return lexMultilineString - } - lx.backup() - } - lx.ignore() // ignore the '"' - return lexString - case rawStringStart: - if lx.accept(rawStringStart) { - if lx.accept(rawStringStart) { - lx.ignore() // Ignore """ - return lexMultilineRawString - } - lx.backup() - } - lx.ignore() // ignore the "'" - return lexRawString - case '+', '-': - return lexNumberStart - case '.': // special error case, be kind to users - return lx.errorf("floats must start with a digit, not '.'") - } - if unicode.IsLetter(r) { - // Be permissive here; lexBool will give a nice error if the - // user wrote something like - // x = foo - // (i.e. not 'true' or 'false' but is something else word-like.) - lx.backup() - return lexBool - } - return lx.errorf("expected value but found %q instead", r) -} - -// lexArrayValue consumes one value in an array. It assumes that '[' or ',' -// have already been consumed. All whitespace and newlines are ignored. -func lexArrayValue(lx *lexer) stateFn { - r := lx.next() - switch { - case isWhitespace(r) || isNL(r): - return lexSkip(lx, lexArrayValue) - case r == commentStart: - lx.push(lexArrayValue) - return lexCommentStart - case r == comma: - return lx.errorf("unexpected comma") - case r == arrayEnd: - // NOTE(caleb): The spec isn't clear about whether you can have - // a trailing comma or not, so we'll allow it. - return lexArrayEnd - } - - lx.backup() - lx.push(lexArrayValueEnd) - return lexValue -} - -// lexArrayValueEnd consumes everything between the end of an array value and -// the next value (or the end of the array): it ignores whitespace and newlines -// and expects either a ',' or a ']'. -func lexArrayValueEnd(lx *lexer) stateFn { - r := lx.next() - switch { - case isWhitespace(r) || isNL(r): - return lexSkip(lx, lexArrayValueEnd) - case r == commentStart: - lx.push(lexArrayValueEnd) - return lexCommentStart - case r == comma: - lx.ignore() - return lexArrayValue // move on to the next value - case r == arrayEnd: - return lexArrayEnd - } - return lx.errorf( - "expected a comma or array terminator %q, but got %q instead", - arrayEnd, r, - ) -} - -// lexArrayEnd finishes the lexing of an array. -// It assumes that a ']' has just been consumed. -func lexArrayEnd(lx *lexer) stateFn { - lx.ignore() - lx.emit(itemArrayEnd) - return lx.pop() -} - -// lexInlineTableValue consumes one key/value pair in an inline table. -// It assumes that '{' or ',' have already been consumed. Whitespace is ignored. -func lexInlineTableValue(lx *lexer) stateFn { - r := lx.next() - switch { - case isWhitespace(r): - return lexSkip(lx, lexInlineTableValue) - case isNL(r): - return lx.errorf("newlines not allowed within inline tables") - case r == commentStart: - lx.push(lexInlineTableValue) - return lexCommentStart - case r == comma: - return lx.errorf("unexpected comma") - case r == inlineTableEnd: - return lexInlineTableEnd - } - lx.backup() - lx.push(lexInlineTableValueEnd) - return lexKeyStart -} - -// lexInlineTableValueEnd consumes everything between the end of an inline table -// key/value pair and the next pair (or the end of the table): -// it ignores whitespace and expects either a ',' or a '}'. -func lexInlineTableValueEnd(lx *lexer) stateFn { - r := lx.next() - switch { - case isWhitespace(r): - return lexSkip(lx, lexInlineTableValueEnd) - case isNL(r): - return lx.errorf("newlines not allowed within inline tables") - case r == commentStart: - lx.push(lexInlineTableValueEnd) - return lexCommentStart - case r == comma: - lx.ignore() - return lexInlineTableValue - case r == inlineTableEnd: - return lexInlineTableEnd - } - return lx.errorf("expected a comma or an inline table terminator %q, "+ - "but got %q instead", inlineTableEnd, r) -} - -// lexInlineTableEnd finishes the lexing of an inline table. -// It assumes that a '}' has just been consumed. -func lexInlineTableEnd(lx *lexer) stateFn { - lx.ignore() - lx.emit(itemInlineTableEnd) - return lx.pop() -} - -// lexString consumes the inner contents of a string. It assumes that the -// beginning '"' has already been consumed and ignored. -func lexString(lx *lexer) stateFn { - r := lx.next() - switch { - case r == eof: - return lx.errorf("unexpected EOF") - case isNL(r): - return lx.errorf("strings cannot contain newlines") - case r == '\\': - lx.push(lexString) - return lexStringEscape - case r == stringEnd: - lx.backup() - lx.emit(itemString) - lx.next() - lx.ignore() - return lx.pop() - } - return lexString -} - -// lexMultilineString consumes the inner contents of a string. It assumes that -// the beginning '"""' has already been consumed and ignored. -func lexMultilineString(lx *lexer) stateFn { - switch lx.next() { - case eof: - return lx.errorf("unexpected EOF") - case '\\': - return lexMultilineStringEscape - case stringEnd: - if lx.accept(stringEnd) { - if lx.accept(stringEnd) { - lx.backup() - lx.backup() - lx.backup() - lx.emit(itemMultilineString) - lx.next() - lx.next() - lx.next() - lx.ignore() - return lx.pop() - } - lx.backup() - } - } - return lexMultilineString -} - -// lexRawString consumes a raw string. Nothing can be escaped in such a string. -// It assumes that the beginning "'" has already been consumed and ignored. -func lexRawString(lx *lexer) stateFn { - r := lx.next() - switch { - case r == eof: - return lx.errorf("unexpected EOF") - case isNL(r): - return lx.errorf("strings cannot contain newlines") - case r == rawStringEnd: - lx.backup() - lx.emit(itemRawString) - lx.next() - lx.ignore() - return lx.pop() - } - return lexRawString -} - -// lexMultilineRawString consumes a raw string. Nothing can be escaped in such -// a string. It assumes that the beginning "'''" has already been consumed and -// ignored. -func lexMultilineRawString(lx *lexer) stateFn { - switch lx.next() { - case eof: - return lx.errorf("unexpected EOF") - case rawStringEnd: - if lx.accept(rawStringEnd) { - if lx.accept(rawStringEnd) { - lx.backup() - lx.backup() - lx.backup() - lx.emit(itemRawMultilineString) - lx.next() - lx.next() - lx.next() - lx.ignore() - return lx.pop() - } - lx.backup() - } - } - return lexMultilineRawString -} - -// lexMultilineStringEscape consumes an escaped character. It assumes that the -// preceding '\\' has already been consumed. -func lexMultilineStringEscape(lx *lexer) stateFn { - // Handle the special case first: - if isNL(lx.next()) { - return lexMultilineString - } - lx.backup() - lx.push(lexMultilineString) - return lexStringEscape(lx) -} - -func lexStringEscape(lx *lexer) stateFn { - r := lx.next() - switch r { - case 'b': - fallthrough - case 't': - fallthrough - case 'n': - fallthrough - case 'f': - fallthrough - case 'r': - fallthrough - case '"': - fallthrough - case '\\': - return lx.pop() - case 'u': - return lexShortUnicodeEscape - case 'U': - return lexLongUnicodeEscape - } - return lx.errorf("invalid escape character %q; only the following "+ - "escape characters are allowed: "+ - `\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX`, r) -} - -func lexShortUnicodeEscape(lx *lexer) stateFn { - var r rune - for i := 0; i < 4; i++ { - r = lx.next() - if !isHexadecimal(r) { - return lx.errorf(`expected four hexadecimal digits after '\u', `+ - "but got %q instead", lx.current()) - } - } - return lx.pop() -} - -func lexLongUnicodeEscape(lx *lexer) stateFn { - var r rune - for i := 0; i < 8; i++ { - r = lx.next() - if !isHexadecimal(r) { - return lx.errorf(`expected eight hexadecimal digits after '\U', `+ - "but got %q instead", lx.current()) - } - } - return lx.pop() -} - -// lexNumberOrDateStart consumes either an integer, a float, or datetime. -func lexNumberOrDateStart(lx *lexer) stateFn { - r := lx.next() - if isDigit(r) { - return lexNumberOrDate - } - switch r { - case '_': - return lexNumber - case 'e', 'E': - return lexFloat - case '.': - return lx.errorf("floats must start with a digit, not '.'") - } - return lx.errorf("expected a digit but got %q", r) -} - -// lexNumberOrDate consumes either an integer, float or datetime. -func lexNumberOrDate(lx *lexer) stateFn { - r := lx.next() - if isDigit(r) { - return lexNumberOrDate - } - switch r { - case '-': - return lexDatetime - case '_': - return lexNumber - case '.', 'e', 'E': - return lexFloat - } - - lx.backup() - lx.emit(itemInteger) - return lx.pop() -} - -// lexDatetime consumes a Datetime, to a first approximation. -// The parser validates that it matches one of the accepted formats. -func lexDatetime(lx *lexer) stateFn { - r := lx.next() - if isDigit(r) { - return lexDatetime - } - switch r { - case '-', 'T', ':', '.', 'Z': - return lexDatetime - } - - lx.backup() - lx.emit(itemDatetime) - return lx.pop() -} - -// lexNumberStart consumes either an integer or a float. It assumes that a sign -// has already been read, but that *no* digits have been consumed. -// lexNumberStart will move to the appropriate integer or float states. -func lexNumberStart(lx *lexer) stateFn { - // We MUST see a digit. Even floats have to start with a digit. - r := lx.next() - if !isDigit(r) { - if r == '.' { - return lx.errorf("floats must start with a digit, not '.'") - } - return lx.errorf("expected a digit but got %q", r) - } - return lexNumber -} - -// lexNumber consumes an integer or a float after seeing the first digit. -func lexNumber(lx *lexer) stateFn { - r := lx.next() - if isDigit(r) { - return lexNumber - } - switch r { - case '_': - return lexNumber - case '.', 'e', 'E': - return lexFloat - } - - lx.backup() - lx.emit(itemInteger) - return lx.pop() -} - -// lexFloat consumes the elements of a float. It allows any sequence of -// float-like characters, so floats emitted by the lexer are only a first -// approximation and must be validated by the parser. -func lexFloat(lx *lexer) stateFn { - r := lx.next() - if isDigit(r) { - return lexFloat - } - switch r { - case '_', '.', '-', '+', 'e', 'E': - return lexFloat - } - - lx.backup() - lx.emit(itemFloat) - return lx.pop() -} - -// lexBool consumes a bool string: 'true' or 'false. -func lexBool(lx *lexer) stateFn { - var rs []rune - for { - r := lx.next() - if !unicode.IsLetter(r) { - lx.backup() - break - } - rs = append(rs, r) - } - s := string(rs) - switch s { - case "true", "false": - lx.emit(itemBool) - return lx.pop() - } - return lx.errorf("expected value but found %q instead", s) -} - -// lexCommentStart begins the lexing of a comment. It will emit -// itemCommentStart and consume no characters, passing control to lexComment. -func lexCommentStart(lx *lexer) stateFn { - lx.ignore() - lx.emit(itemCommentStart) - return lexComment -} - -// lexComment lexes an entire comment. It assumes that '#' has been consumed. -// It will consume *up to* the first newline character, and pass control -// back to the last state on the stack. -func lexComment(lx *lexer) stateFn { - r := lx.peek() - if isNL(r) || r == eof { - lx.emit(itemText) - return lx.pop() - } - lx.next() - return lexComment -} - -// lexSkip ignores all slurped input and moves on to the next state. -func lexSkip(lx *lexer, nextState stateFn) stateFn { - return func(lx *lexer) stateFn { - lx.ignore() - return nextState - } -} - -// isWhitespace returns true if `r` is a whitespace character according -// to the spec. -func isWhitespace(r rune) bool { - return r == '\t' || r == ' ' -} - -func isNL(r rune) bool { - return r == '\n' || r == '\r' -} - -func isDigit(r rune) bool { - return r >= '0' && r <= '9' -} - -func isHexadecimal(r rune) bool { - return (r >= '0' && r <= '9') || - (r >= 'a' && r <= 'f') || - (r >= 'A' && r <= 'F') -} - -func isBareKeyChar(r rune) bool { - return (r >= 'A' && r <= 'Z') || - (r >= 'a' && r <= 'z') || - (r >= '0' && r <= '9') || - r == '_' || - r == '-' -} - -func (itype itemType) String() string { - switch itype { - case itemError: - return "Error" - case itemNIL: - return "NIL" - case itemEOF: - return "EOF" - case itemText: - return "Text" - case itemString, itemRawString, itemMultilineString, itemRawMultilineString: - return "String" - case itemBool: - return "Bool" - case itemInteger: - return "Integer" - case itemFloat: - return "Float" - case itemDatetime: - return "DateTime" - case itemTableStart: - return "TableStart" - case itemTableEnd: - return "TableEnd" - case itemKeyStart: - return "KeyStart" - case itemArray: - return "Array" - case itemArrayEnd: - return "ArrayEnd" - case itemCommentStart: - return "CommentStart" - } - panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype))) -} - -func (item item) String() string { - return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) -} diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go deleted file mode 100644 index 50869ef926..0000000000 --- a/vendor/github.com/BurntSushi/toml/parse.go +++ /dev/null @@ -1,592 +0,0 @@ -package toml - -import ( - "fmt" - "strconv" - "strings" - "time" - "unicode" - "unicode/utf8" -) - -type parser struct { - mapping map[string]interface{} - types map[string]tomlType - lx *lexer - - // A list of keys in the order that they appear in the TOML data. - ordered []Key - - // the full key for the current hash in scope - context Key - - // the base key name for everything except hashes - currentKey string - - // rough approximation of line number - approxLine int - - // A map of 'key.group.names' to whether they were created implicitly. - implicits map[string]bool -} - -type parseError string - -func (pe parseError) Error() string { - return string(pe) -} - -func parse(data string) (p *parser, err error) { - defer func() { - if r := recover(); r != nil { - var ok bool - if err, ok = r.(parseError); ok { - return - } - panic(r) - } - }() - - p = &parser{ - mapping: make(map[string]interface{}), - types: make(map[string]tomlType), - lx: lex(data), - ordered: make([]Key, 0), - implicits: make(map[string]bool), - } - for { - item := p.next() - if item.typ == itemEOF { - break - } - p.topLevel(item) - } - - return p, nil -} - -func (p *parser) panicf(format string, v ...interface{}) { - msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s", - p.approxLine, p.current(), fmt.Sprintf(format, v...)) - panic(parseError(msg)) -} - -func (p *parser) next() item { - it := p.lx.nextItem() - if it.typ == itemError { - p.panicf("%s", it.val) - } - return it -} - -func (p *parser) bug(format string, v ...interface{}) { - panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) -} - -func (p *parser) expect(typ itemType) item { - it := p.next() - p.assertEqual(typ, it.typ) - return it -} - -func (p *parser) assertEqual(expected, got itemType) { - if expected != got { - p.bug("Expected '%s' but got '%s'.", expected, got) - } -} - -func (p *parser) topLevel(item item) { - switch item.typ { - case itemCommentStart: - p.approxLine = item.line - p.expect(itemText) - case itemTableStart: - kg := p.next() - p.approxLine = kg.line - - var key Key - for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() { - key = append(key, p.keyString(kg)) - } - p.assertEqual(itemTableEnd, kg.typ) - - p.establishContext(key, false) - p.setType("", tomlHash) - p.ordered = append(p.ordered, key) - case itemArrayTableStart: - kg := p.next() - p.approxLine = kg.line - - var key Key - for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() { - key = append(key, p.keyString(kg)) - } - p.assertEqual(itemArrayTableEnd, kg.typ) - - p.establishContext(key, true) - p.setType("", tomlArrayHash) - p.ordered = append(p.ordered, key) - case itemKeyStart: - kname := p.next() - p.approxLine = kname.line - p.currentKey = p.keyString(kname) - - val, typ := p.value(p.next()) - p.setValue(p.currentKey, val) - p.setType(p.currentKey, typ) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) - p.currentKey = "" - default: - p.bug("Unexpected type at top level: %s", item.typ) - } -} - -// Gets a string for a key (or part of a key in a table name). -func (p *parser) keyString(it item) string { - switch it.typ { - case itemText: - return it.val - case itemString, itemMultilineString, - itemRawString, itemRawMultilineString: - s, _ := p.value(it) - return s.(string) - default: - p.bug("Unexpected key type: %s", it.typ) - panic("unreachable") - } -} - -// value translates an expected value from the lexer into a Go value wrapped -// as an empty interface. -func (p *parser) value(it item) (interface{}, tomlType) { - switch it.typ { - case itemString: - return p.replaceEscapes(it.val), p.typeOfPrimitive(it) - case itemMultilineString: - trimmed := stripFirstNewline(stripEscapedWhitespace(it.val)) - return p.replaceEscapes(trimmed), p.typeOfPrimitive(it) - case itemRawString: - return it.val, p.typeOfPrimitive(it) - case itemRawMultilineString: - return stripFirstNewline(it.val), p.typeOfPrimitive(it) - case itemBool: - switch it.val { - case "true": - return true, p.typeOfPrimitive(it) - case "false": - return false, p.typeOfPrimitive(it) - } - p.bug("Expected boolean value, but got '%s'.", it.val) - case itemInteger: - if !numUnderscoresOK(it.val) { - p.panicf("Invalid integer %q: underscores must be surrounded by digits", - it.val) - } - val := strings.Replace(it.val, "_", "", -1) - num, err := strconv.ParseInt(val, 10, 64) - if err != nil { - // Distinguish integer values. Normally, it'd be a bug if the lexer - // provides an invalid integer, but it's possible that the number is - // out of range of valid values (which the lexer cannot determine). - // So mark the former as a bug but the latter as a legitimate user - // error. - if e, ok := err.(*strconv.NumError); ok && - e.Err == strconv.ErrRange { - - p.panicf("Integer '%s' is out of the range of 64-bit "+ - "signed integers.", it.val) - } else { - p.bug("Expected integer value, but got '%s'.", it.val) - } - } - return num, p.typeOfPrimitive(it) - case itemFloat: - parts := strings.FieldsFunc(it.val, func(r rune) bool { - switch r { - case '.', 'e', 'E': - return true - } - return false - }) - for _, part := range parts { - if !numUnderscoresOK(part) { - p.panicf("Invalid float %q: underscores must be "+ - "surrounded by digits", it.val) - } - } - if !numPeriodsOK(it.val) { - // As a special case, numbers like '123.' or '1.e2', - // which are valid as far as Go/strconv are concerned, - // must be rejected because TOML says that a fractional - // part consists of '.' followed by 1+ digits. - p.panicf("Invalid float %q: '.' must be followed "+ - "by one or more digits", it.val) - } - val := strings.Replace(it.val, "_", "", -1) - num, err := strconv.ParseFloat(val, 64) - if err != nil { - if e, ok := err.(*strconv.NumError); ok && - e.Err == strconv.ErrRange { - - p.panicf("Float '%s' is out of the range of 64-bit "+ - "IEEE-754 floating-point numbers.", it.val) - } else { - p.panicf("Invalid float value: %q", it.val) - } - } - return num, p.typeOfPrimitive(it) - case itemDatetime: - var t time.Time - var ok bool - var err error - for _, format := range []string{ - "2006-01-02T15:04:05Z07:00", - "2006-01-02T15:04:05", - "2006-01-02", - } { - t, err = time.ParseInLocation(format, it.val, time.Local) - if err == nil { - ok = true - break - } - } - if !ok { - p.panicf("Invalid TOML Datetime: %q.", it.val) - } - return t, p.typeOfPrimitive(it) - case itemArray: - array := make([]interface{}, 0) - types := make([]tomlType, 0) - - for it = p.next(); it.typ != itemArrayEnd; it = p.next() { - if it.typ == itemCommentStart { - p.expect(itemText) - continue - } - - val, typ := p.value(it) - array = append(array, val) - types = append(types, typ) - } - return array, p.typeOfArray(types) - case itemInlineTableStart: - var ( - hash = make(map[string]interface{}) - outerContext = p.context - outerKey = p.currentKey - ) - - p.context = append(p.context, p.currentKey) - p.currentKey = "" - for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() { - if it.typ != itemKeyStart { - p.bug("Expected key start but instead found %q, around line %d", - it.val, p.approxLine) - } - if it.typ == itemCommentStart { - p.expect(itemText) - continue - } - - // retrieve key - k := p.next() - p.approxLine = k.line - kname := p.keyString(k) - - // retrieve value - p.currentKey = kname - val, typ := p.value(p.next()) - // make sure we keep metadata up to date - p.setType(kname, typ) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) - hash[kname] = val - } - p.context = outerContext - p.currentKey = outerKey - return hash, tomlHash - } - p.bug("Unexpected value type: %s", it.typ) - panic("unreachable") -} - -// numUnderscoresOK checks whether each underscore in s is surrounded by -// characters that are not underscores. -func numUnderscoresOK(s string) bool { - accept := false - for _, r := range s { - if r == '_' { - if !accept { - return false - } - accept = false - continue - } - accept = true - } - return accept -} - -// numPeriodsOK checks whether every period in s is followed by a digit. -func numPeriodsOK(s string) bool { - period := false - for _, r := range s { - if period && !isDigit(r) { - return false - } - period = r == '.' - } - return !period -} - -// establishContext sets the current context of the parser, -// where the context is either a hash or an array of hashes. Which one is -// set depends on the value of the `array` parameter. -// -// Establishing the context also makes sure that the key isn't a duplicate, and -// will create implicit hashes automatically. -func (p *parser) establishContext(key Key, array bool) { - var ok bool - - // Always start at the top level and drill down for our context. - hashContext := p.mapping - keyContext := make(Key, 0) - - // We only need implicit hashes for key[0:-1] - for _, k := range key[0 : len(key)-1] { - _, ok = hashContext[k] - keyContext = append(keyContext, k) - - // No key? Make an implicit hash and move on. - if !ok { - p.addImplicit(keyContext) - hashContext[k] = make(map[string]interface{}) - } - - // If the hash context is actually an array of tables, then set - // the hash context to the last element in that array. - // - // Otherwise, it better be a table, since this MUST be a key group (by - // virtue of it not being the last element in a key). - switch t := hashContext[k].(type) { - case []map[string]interface{}: - hashContext = t[len(t)-1] - case map[string]interface{}: - hashContext = t - default: - p.panicf("Key '%s' was already created as a hash.", keyContext) - } - } - - p.context = keyContext - if array { - // If this is the first element for this array, then allocate a new - // list of tables for it. - k := key[len(key)-1] - if _, ok := hashContext[k]; !ok { - hashContext[k] = make([]map[string]interface{}, 0, 5) - } - - // Add a new table. But make sure the key hasn't already been used - // for something else. - if hash, ok := hashContext[k].([]map[string]interface{}); ok { - hashContext[k] = append(hash, make(map[string]interface{})) - } else { - p.panicf("Key '%s' was already created and cannot be used as "+ - "an array.", keyContext) - } - } else { - p.setValue(key[len(key)-1], make(map[string]interface{})) - } - p.context = append(p.context, key[len(key)-1]) -} - -// setValue sets the given key to the given value in the current context. -// It will make sure that the key hasn't already been defined, account for -// implicit key groups. -func (p *parser) setValue(key string, value interface{}) { - var tmpHash interface{} - var ok bool - - hash := p.mapping - keyContext := make(Key, 0) - for _, k := range p.context { - keyContext = append(keyContext, k) - if tmpHash, ok = hash[k]; !ok { - p.bug("Context for key '%s' has not been established.", keyContext) - } - switch t := tmpHash.(type) { - case []map[string]interface{}: - // The context is a table of hashes. Pick the most recent table - // defined as the current hash. - hash = t[len(t)-1] - case map[string]interface{}: - hash = t - default: - p.bug("Expected hash to have type 'map[string]interface{}', but "+ - "it has '%T' instead.", tmpHash) - } - } - keyContext = append(keyContext, key) - - if _, ok := hash[key]; ok { - // Typically, if the given key has already been set, then we have - // to raise an error since duplicate keys are disallowed. However, - // it's possible that a key was previously defined implicitly. In this - // case, it is allowed to be redefined concretely. (See the - // `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.) - // - // But we have to make sure to stop marking it as an implicit. (So that - // another redefinition provokes an error.) - // - // Note that since it has already been defined (as a hash), we don't - // want to overwrite it. So our business is done. - if p.isImplicit(keyContext) { - p.removeImplicit(keyContext) - return - } - - // Otherwise, we have a concrete key trying to override a previous - // key, which is *always* wrong. - p.panicf("Key '%s' has already been defined.", keyContext) - } - hash[key] = value -} - -// setType sets the type of a particular value at a given key. -// It should be called immediately AFTER setValue. -// -// Note that if `key` is empty, then the type given will be applied to the -// current context (which is either a table or an array of tables). -func (p *parser) setType(key string, typ tomlType) { - keyContext := make(Key, 0, len(p.context)+1) - for _, k := range p.context { - keyContext = append(keyContext, k) - } - if len(key) > 0 { // allow type setting for hashes - keyContext = append(keyContext, key) - } - p.types[keyContext.String()] = typ -} - -// addImplicit sets the given Key as having been created implicitly. -func (p *parser) addImplicit(key Key) { - p.implicits[key.String()] = true -} - -// removeImplicit stops tagging the given key as having been implicitly -// created. -func (p *parser) removeImplicit(key Key) { - p.implicits[key.String()] = false -} - -// isImplicit returns true if the key group pointed to by the key was created -// implicitly. -func (p *parser) isImplicit(key Key) bool { - return p.implicits[key.String()] -} - -// current returns the full key name of the current context. -func (p *parser) current() string { - if len(p.currentKey) == 0 { - return p.context.String() - } - if len(p.context) == 0 { - return p.currentKey - } - return fmt.Sprintf("%s.%s", p.context, p.currentKey) -} - -func stripFirstNewline(s string) string { - if len(s) == 0 || s[0] != '\n' { - return s - } - return s[1:] -} - -func stripEscapedWhitespace(s string) string { - esc := strings.Split(s, "\\\n") - if len(esc) > 1 { - for i := 1; i < len(esc); i++ { - esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace) - } - } - return strings.Join(esc, "") -} - -func (p *parser) replaceEscapes(str string) string { - var replaced []rune - s := []byte(str) - r := 0 - for r < len(s) { - if s[r] != '\\' { - c, size := utf8.DecodeRune(s[r:]) - r += size - replaced = append(replaced, c) - continue - } - r += 1 - if r >= len(s) { - p.bug("Escape sequence at end of string.") - return "" - } - switch s[r] { - default: - p.bug("Expected valid escape code after \\, but got %q.", s[r]) - return "" - case 'b': - replaced = append(replaced, rune(0x0008)) - r += 1 - case 't': - replaced = append(replaced, rune(0x0009)) - r += 1 - case 'n': - replaced = append(replaced, rune(0x000A)) - r += 1 - case 'f': - replaced = append(replaced, rune(0x000C)) - r += 1 - case 'r': - replaced = append(replaced, rune(0x000D)) - r += 1 - case '"': - replaced = append(replaced, rune(0x0022)) - r += 1 - case '\\': - replaced = append(replaced, rune(0x005C)) - r += 1 - case 'u': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+5). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(s[r+1 : r+5]) - replaced = append(replaced, escaped) - r += 5 - case 'U': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+9). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(s[r+1 : r+9]) - replaced = append(replaced, escaped) - r += 9 - } - } - return string(replaced) -} - -func (p *parser) asciiEscapeToUnicode(bs []byte) rune { - s := string(bs) - hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) - if err != nil { - p.bug("Could not parse '%s' as a hexadecimal number, but the "+ - "lexer claims it's OK: %s", s, err) - } - if !utf8.ValidRune(rune(hex)) { - p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s) - } - return rune(hex) -} - -func isStringType(ty itemType) bool { - return ty == itemString || ty == itemMultilineString || - ty == itemRawString || ty == itemRawMultilineString -} diff --git a/vendor/github.com/BurntSushi/toml/type_check.go b/vendor/github.com/BurntSushi/toml/type_check.go deleted file mode 100644 index c73f8afc1a..0000000000 --- a/vendor/github.com/BurntSushi/toml/type_check.go +++ /dev/null @@ -1,91 +0,0 @@ -package toml - -// tomlType represents any Go type that corresponds to a TOML type. -// While the first draft of the TOML spec has a simplistic type system that -// probably doesn't need this level of sophistication, we seem to be militating -// toward adding real composite types. -type tomlType interface { - typeString() string -} - -// typeEqual accepts any two types and returns true if they are equal. -func typeEqual(t1, t2 tomlType) bool { - if t1 == nil || t2 == nil { - return false - } - return t1.typeString() == t2.typeString() -} - -func typeIsHash(t tomlType) bool { - return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash) -} - -type tomlBaseType string - -func (btype tomlBaseType) typeString() string { - return string(btype) -} - -func (btype tomlBaseType) String() string { - return btype.typeString() -} - -var ( - tomlInteger tomlBaseType = "Integer" - tomlFloat tomlBaseType = "Float" - tomlDatetime tomlBaseType = "Datetime" - tomlString tomlBaseType = "String" - tomlBool tomlBaseType = "Bool" - tomlArray tomlBaseType = "Array" - tomlHash tomlBaseType = "Hash" - tomlArrayHash tomlBaseType = "ArrayHash" -) - -// typeOfPrimitive returns a tomlType of any primitive value in TOML. -// Primitive values are: Integer, Float, Datetime, String and Bool. -// -// Passing a lexer item other than the following will cause a BUG message -// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime. -func (p *parser) typeOfPrimitive(lexItem item) tomlType { - switch lexItem.typ { - case itemInteger: - return tomlInteger - case itemFloat: - return tomlFloat - case itemDatetime: - return tomlDatetime - case itemString: - return tomlString - case itemMultilineString: - return tomlString - case itemRawString: - return tomlString - case itemRawMultilineString: - return tomlString - case itemBool: - return tomlBool - } - p.bug("Cannot infer primitive type of lex item '%s'.", lexItem) - panic("unreachable") -} - -// typeOfArray returns a tomlType for an array given a list of types of its -// values. -// -// In the current spec, if an array is homogeneous, then its type is always -// "Array". If the array is not homogeneous, an error is generated. -func (p *parser) typeOfArray(types []tomlType) tomlType { - // Empty arrays are cool. - if len(types) == 0 { - return tomlArray - } - - theType := types[0] - for _, t := range types[1:] { - if !typeEqual(theType, t) { - p.panicf("Array contains values of type '%s' and '%s', but "+ - "arrays must be homogeneous.", theType, t) - } - } - return tomlArray -} diff --git a/vendor/github.com/BurntSushi/toml/type_fields.go b/vendor/github.com/BurntSushi/toml/type_fields.go deleted file mode 100644 index 608997c22f..0000000000 --- a/vendor/github.com/BurntSushi/toml/type_fields.go +++ /dev/null @@ -1,242 +0,0 @@ -package toml - -// Struct field handling is adapted from code in encoding/json: -// -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the Go distribution. - -import ( - "reflect" - "sort" - "sync" -) - -// A field represents a single field found in a struct. -type field struct { - name string // the name of the field (`toml` tag included) - tag bool // whether field has a `toml` tag - index []int // represents the depth of an anonymous field - typ reflect.Type // the type of the field -} - -// byName sorts field by name, breaking ties with depth, -// then breaking ties with "name came from toml tag", then -// breaking ties with index sequence. -type byName []field - -func (x byName) Len() int { return len(x) } - -func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - -func (x byName) Less(i, j int) bool { - if x[i].name != x[j].name { - return x[i].name < x[j].name - } - if len(x[i].index) != len(x[j].index) { - return len(x[i].index) < len(x[j].index) - } - if x[i].tag != x[j].tag { - return x[i].tag - } - return byIndex(x).Less(i, j) -} - -// byIndex sorts field by index sequence. -type byIndex []field - -func (x byIndex) Len() int { return len(x) } - -func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - -func (x byIndex) Less(i, j int) bool { - for k, xik := range x[i].index { - if k >= len(x[j].index) { - return false - } - if xik != x[j].index[k] { - return xik < x[j].index[k] - } - } - return len(x[i].index) < len(x[j].index) -} - -// typeFields returns a list of fields that TOML should recognize for the given -// type. The algorithm is breadth-first search over the set of structs to -// include - the top struct and then any reachable anonymous structs. -func typeFields(t reflect.Type) []field { - // Anonymous fields to explore at the current level and the next. - current := []field{} - next := []field{{typ: t}} - - // Count of queued names for current level and the next. - count := map[reflect.Type]int{} - nextCount := map[reflect.Type]int{} - - // Types already visited at an earlier level. - visited := map[reflect.Type]bool{} - - // Fields found. - var fields []field - - for len(next) > 0 { - current, next = next, current[:0] - count, nextCount = nextCount, map[reflect.Type]int{} - - for _, f := range current { - if visited[f.typ] { - continue - } - visited[f.typ] = true - - // Scan f.typ for fields to include. - for i := 0; i < f.typ.NumField(); i++ { - sf := f.typ.Field(i) - if sf.PkgPath != "" && !sf.Anonymous { // unexported - continue - } - opts := getOptions(sf.Tag) - if opts.skip { - continue - } - index := make([]int, len(f.index)+1) - copy(index, f.index) - index[len(f.index)] = i - - ft := sf.Type - if ft.Name() == "" && ft.Kind() == reflect.Ptr { - // Follow pointer. - ft = ft.Elem() - } - - // Record found field and index sequence. - if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { - tagged := opts.name != "" - name := opts.name - if name == "" { - name = sf.Name - } - fields = append(fields, field{name, tagged, index, ft}) - if count[f.typ] > 1 { - // If there were multiple instances, add a second, - // so that the annihilation code will see a duplicate. - // It only cares about the distinction between 1 or 2, - // so don't bother generating any more copies. - fields = append(fields, fields[len(fields)-1]) - } - continue - } - - // Record new anonymous struct to explore in next round. - nextCount[ft]++ - if nextCount[ft] == 1 { - f := field{name: ft.Name(), index: index, typ: ft} - next = append(next, f) - } - } - } - } - - sort.Sort(byName(fields)) - - // Delete all fields that are hidden by the Go rules for embedded fields, - // except that fields with TOML tags are promoted. - - // The fields are sorted in primary order of name, secondary order - // of field index length. Loop over names; for each name, delete - // hidden fields by choosing the one dominant field that survives. - out := fields[:0] - for advance, i := 0, 0; i < len(fields); i += advance { - // One iteration per name. - // Find the sequence of fields with the name of this first field. - fi := fields[i] - name := fi.name - for advance = 1; i+advance < len(fields); advance++ { - fj := fields[i+advance] - if fj.name != name { - break - } - } - if advance == 1 { // Only one field with this name - out = append(out, fi) - continue - } - dominant, ok := dominantField(fields[i : i+advance]) - if ok { - out = append(out, dominant) - } - } - - fields = out - sort.Sort(byIndex(fields)) - - return fields -} - -// dominantField looks through the fields, all of which are known to -// have the same name, to find the single field that dominates the -// others using Go's embedding rules, modified by the presence of -// TOML tags. If there are multiple top-level fields, the boolean -// will be false: This condition is an error in Go and we skip all -// the fields. -func dominantField(fields []field) (field, bool) { - // The fields are sorted in increasing index-length order. The winner - // must therefore be one with the shortest index length. Drop all - // longer entries, which is easy: just truncate the slice. - length := len(fields[0].index) - tagged := -1 // Index of first tagged field. - for i, f := range fields { - if len(f.index) > length { - fields = fields[:i] - break - } - if f.tag { - if tagged >= 0 { - // Multiple tagged fields at the same level: conflict. - // Return no field. - return field{}, false - } - tagged = i - } - } - if tagged >= 0 { - return fields[tagged], true - } - // All remaining fields have the same length. If there's more than one, - // we have a conflict (two fields named "X" at the same level) and we - // return no field. - if len(fields) > 1 { - return field{}, false - } - return fields[0], true -} - -var fieldCache struct { - sync.RWMutex - m map[reflect.Type][]field -} - -// cachedTypeFields is like typeFields but uses a cache to avoid repeated work. -func cachedTypeFields(t reflect.Type) []field { - fieldCache.RLock() - f := fieldCache.m[t] - fieldCache.RUnlock() - if f != nil { - return f - } - - // Compute fields without lock. - // Might duplicate effort but won't hold other computations back. - f = typeFields(t) - if f == nil { - f = []field{} - } - - fieldCache.Lock() - if fieldCache.m == nil { - fieldCache.m = map[reflect.Type][]field{} - } - fieldCache.m[t] = f - fieldCache.Unlock() - return f -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/LICENSE b/vendor/github.com/GoogleContainerTools/container-diff/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go b/vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go deleted file mode 100644 index c7c1623d65..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/cmd/util/output/output.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package output - -import ( - "fmt" - "github.com/spf13/cobra" - "os" -) - -var quiet bool - -// PrintToStdErr prints to stderr if quiet flag isn't enabled -func PrintToStdErr(output string, vars ...interface{}) { - if !quiet { - fmt.Fprintf(os.Stderr, output, vars...) - } -} - -// AddFlags adds quiet flag to suppress output to stderr -func AddFlags(cmd *cobra.Command) { - cmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "Suppress output to stderr.") -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go deleted file mode 100644 index 8dd8c3e231..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/mutable_source.go +++ /dev/null @@ -1,262 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package image - -import ( - "bytes" - "compress/gzip" - "encoding/json" - "github.com/containers/image/docker" - img "github.com/containers/image/image" - "github.com/containers/image/types" - "io" - "io/ioutil" - "strings" - "time" - - "github.com/containers/image/manifest" - digest "github.com/opencontainers/go-digest" -) - -type MutableSource struct { - ProxySource - mfst *manifest.Schema2 - cfg *manifest.Schema2Image - extraBlobs map[string][]byte - extraLayers []digest.Digest -} - -func NewMutableSource(r types.ImageReference) (*MutableSource, error) { - if r == nil { - return MutableSourceFromScratch() - } - src, err := r.NewImageSource(nil) - if err != nil { - return nil, err - } - img, err := r.NewImage(nil) - if err != nil { - return nil, err - } - - ms := &MutableSource{ - ProxySource: ProxySource{ - Ref: r, - ImageSource: src, - img: img, - }, - extraBlobs: make(map[string][]byte), - } - if err := ms.populateManifestAndConfig(); err != nil { - return nil, err - } - return ms, nil -} - -func MutableSourceFromScratch() (*MutableSource, error) { - config := &manifest.Schema2Image{ - Schema2V1Image: manifest.Schema2V1Image{ - Config: &manifest.Schema2Config{}, - }, - RootFS: &manifest.Schema2RootFS{}, - History: []manifest.Schema2History{}, - } - ref, err := docker.ParseReference("//scratch") - if err != nil { - return nil, err - } - src, err := ref.NewImageSource(nil) - if err != nil { - return nil, err - } - ms := &MutableSource{ - ProxySource: ProxySource{ - Ref: &ProxyReference{ - ImageReference: ref, - }, - ImageSource: src, - }, - extraBlobs: make(map[string][]byte), - cfg: config, - mfst: &manifest.Schema2{ - SchemaVersion: 2, - MediaType: manifest.DockerV2Schema2MediaType, - }, - } - return ms, nil -} - -// Manifest marshals the stored manifest to the byte format. -func (m *MutableSource) GetManifest(_ *digest.Digest) ([]byte, string, error) { - if err := m.saveConfig(); err != nil { - return nil, "", err - } - s, err := json.Marshal(m.mfst) - if err != nil { - return nil, "", err - } - return s, manifest.DockerV2Schema2MediaType, err -} - -// populateManifestAndConfig parses the raw manifest and configs, storing them on the struct. -func (m *MutableSource) populateManifestAndConfig() error { - context := &types.SystemContext{ - OSChoice: "linux", - ArchitectureChoice: "amd64", - } - image, err := m.ProxySource.Ref.NewImage(context) - if err != nil { - return err - } - defer image.Close() - // First get manifest - mfstBytes, mfstType, err := image.Manifest() - if err != nil { - return err - } - - if mfstType == manifest.DockerV2ListMediaType { - // We need to select a manifest digest from the manifest list - unparsedImage := img.UnparsedInstance(m.ImageSource, nil) - - mfstDigest, err := img.ChooseManifestInstanceFromManifestList(context, unparsedImage) - if err != nil { - return err - } - mfstBytes, _, err = m.ProxySource.GetManifest(&mfstDigest) - if err != nil { - return err - } - } - - m.mfst, err = manifest.Schema2FromManifest(mfstBytes) - if err != nil { - return err - } - - // Now, get config - configBlob, err := image.ConfigBlob() - if err != nil { - return err - } - return json.Unmarshal(configBlob, &m.cfg) -} - -// GetBlob first checks the stored "extra" blobs, then proxies the call to the original source. -func (m *MutableSource) GetBlob(bi types.BlobInfo) (io.ReadCloser, int64, error) { - if b, ok := m.extraBlobs[bi.Digest.String()]; ok { - return ioutil.NopCloser(bytes.NewReader(b)), int64(len(b)), nil - } - return m.ImageSource.GetBlob(bi) -} - -func gzipBytes(b []byte) ([]byte, error) { - buf := bytes.NewBuffer([]byte{}) - w := gzip.NewWriter(buf) - _, err := w.Write(b) - w.Close() - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// appendLayer appends an uncompressed blob to the image, preserving the invariants required across the config and manifest. -func (m *MutableSource) AppendLayer(content []byte, author string) error { - compressedBlob, err := gzipBytes(content) - if err != nil { - return err - } - - dgst := digest.FromBytes(compressedBlob) - - // Add the layer to the manifest. - descriptor := manifest.Schema2Descriptor{ - MediaType: manifest.DockerV2Schema2LayerMediaType, - Size: int64(len(content)), - Digest: dgst, - } - m.mfst.LayersDescriptors = append(m.mfst.LayersDescriptors, descriptor) - - m.extraBlobs[dgst.String()] = compressedBlob - m.extraLayers = append(m.extraLayers, dgst) - - // Also add it to the config. - diffID := digest.FromBytes(content) - m.cfg.RootFS.DiffIDs = append(m.cfg.RootFS.DiffIDs, diffID) - m.AppendConfigHistory(author, false) - return nil -} - -// saveConfig marshals the stored image config, and updates the references to it in the manifest. -func (m *MutableSource) saveConfig() error { - cfgBlob, err := json.Marshal(m.cfg) - if err != nil { - return err - } - - cfgDigest := digest.FromBytes(cfgBlob) - m.extraBlobs[cfgDigest.String()] = cfgBlob - m.mfst.ConfigDescriptor = manifest.Schema2Descriptor{ - MediaType: manifest.DockerV2Schema2ConfigMediaType, - Size: int64(len(cfgBlob)), - Digest: cfgDigest, - } - return nil -} - -// Env returns a map of environment variables stored in the image config -// Converts each variable from a string of the form KEY=VALUE to a map of KEY:VALUE -func (m *MutableSource) Env() map[string]string { - envArray := m.cfg.Schema2V1Image.Config.Env - envMap := make(map[string]string) - for _, env := range envArray { - entry := strings.Split(env, "=") - envMap[entry[0]] = entry[1] - } - return envMap -} - -// SetEnv takes a map of environment variables, and converts them to an array of strings -// in the form KEY=VALUE, and then sets the image config -func (m *MutableSource) SetEnv(envMap map[string]string, author string) { - envArray := []string{} - for key, value := range envMap { - entry := key + "=" + value - envArray = append(envArray, entry) - } - m.cfg.Schema2V1Image.Config.Env = envArray - m.AppendConfigHistory(author, true) -} - -func (m *MutableSource) Config() *manifest.Schema2Config { - return m.cfg.Schema2V1Image.Config -} - -func (m *MutableSource) SetConfig(config *manifest.Schema2Config, author string, emptyLayer bool) { - m.cfg.Schema2V1Image.Config = config - m.AppendConfigHistory(author, emptyLayer) -} - -func (m *MutableSource) AppendConfigHistory(author string, emptyLayer bool) { - history := manifest.Schema2History{ - Created: time.Now(), - Author: author, - EmptyLayer: emptyLayer, - } - m.cfg.History = append(m.cfg.History, history) -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/proxy_types.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/proxy_types.go deleted file mode 100644 index 36e13b4b3b..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/image/proxy_types.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package image - -import ( - "github.com/containers/image/types" -) - -// ProxySource is a type that implements types.ImageSource by proxying all calls to an underlying implementation. -type ProxySource struct { - Ref types.ImageReference - types.ImageSource - img types.Image -} - -func NewProxySource(ref types.ImageReference) (*ProxySource, error) { - src, err := ref.NewImageSource(nil) - if err != nil { - return nil, err - } - defer src.Close() - img, err := ref.NewImage(nil) - if err != nil { - return nil, err - } - - return &ProxySource{ - Ref: ref, - img: img, - ImageSource: src, - }, nil -} - -func (p *ProxySource) Reference() types.ImageReference { - return p.Ref -} - -func (p *ProxySource) LayerInfosForCopy() []types.BlobInfo { - return nil -} - -// ProxyReference implements types.Reference by proxying calls to an underlying implementation. -type ProxyReference struct { - types.ImageReference - Src types.ImageSource -} - -func (p *ProxyReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return p.Src, nil -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/cloud_prepper.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/cloud_prepper.go deleted file mode 100644 index e77655111e..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/cloud_prepper.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "io/ioutil" - "strings" - - "github.com/containers/image/docker" - "github.com/containers/image/types" - "github.com/docker/docker/client" -) - -// CloudPrepper prepares images sourced from a Cloud registry -type CloudPrepper struct { - Source string - Client *client.Client - ImageSource types.ImageSource -} - -func (p *CloudPrepper) Name() string { - return "Cloud Registry" -} - -func (p *CloudPrepper) GetSource() string { - return p.Source -} - -func (p *CloudPrepper) SetSource(source string) { - p.Source = source -} - -func (p *CloudPrepper) GetImage() (Image, error) { - image, err := getImage(p) - image.Type = ImageTypeCloud - return image, err -} - -func (p *CloudPrepper) GetFileSystem() (string, error) { - ref, err := docker.ParseReference("//" + p.Source) - if err != nil { - return "", err - } - sanitizedName := strings.Replace(p.Source, ":", "", -1) - sanitizedName = strings.Replace(sanitizedName, "/", "", -1) - - path, err := ioutil.TempDir("", sanitizedName) - if err != nil { - return "", err - } - - return path, GetFileSystemFromReference(ref, p.ImageSource, path, nil) -} - -func (p *CloudPrepper) GetConfig() (ConfigSchema, error) { - ref, err := docker.ParseReference("//" + p.Source) - if err != nil { - return ConfigSchema{}, err - } - - return getConfigFromReference(ref, p.Source) -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/daemon_prepper.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/daemon_prepper.go deleted file mode 100644 index b3269b3ca4..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/daemon_prepper.go +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "context" - "io/ioutil" - "strings" - - "github.com/containers/image/docker/daemon" - - "github.com/docker/docker/client" - "github.com/sirupsen/logrus" -) - -type DaemonPrepper struct { - Source string - Client *client.Client -} - -func (p *DaemonPrepper) Name() string { - return "Local Daemon" -} - -func (p *DaemonPrepper) GetSource() string { - return p.Source -} - -func (p *DaemonPrepper) SetSource(source string) { - p.Source = source -} - -func (p *DaemonPrepper) GetImage() (Image, error) { - image, err := getImage(p) - image.Type = ImageTypeDaemon - return image, err -} - -func (p *DaemonPrepper) GetFileSystem() (string, error) { - ref, err := daemon.ParseReference(p.Source) - if err != nil { - return "", err - } - - src, err := ref.NewImageSource(nil) - if err != nil { - return "", err - } - defer src.Close() - - sanitizedName := strings.Replace(p.Source, ":", "", -1) - sanitizedName = strings.Replace(sanitizedName, "/", "", -1) - - path, err := ioutil.TempDir("", sanitizedName) - if err != nil { - return "", err - } - return path, GetFileSystemFromReference(ref, src, path, nil) -} - -func (p *DaemonPrepper) GetConfig() (ConfigSchema, error) { - ref, err := daemon.ParseReference(p.Source) - if err != nil { - return ConfigSchema{}, err - } - return getConfigFromReference(ref, p.Source) -} - -func (p *DaemonPrepper) GetHistory() []ImageHistoryItem { - history, err := p.Client.ImageHistory(context.Background(), p.Source) - if err != nil { - logrus.Errorf("Could not obtain image history for %s: %s", p.Source, err) - } - historyItems := []ImageHistoryItem{} - for _, item := range history { - historyItems = append(historyItems, ImageHistoryItem{CreatedBy: item.CreatedBy}) - } - return historyItems -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/docker_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/docker_utils.go deleted file mode 100644 index eca0e53cd8..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/docker_utils.go +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "archive/tar" - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "strings" - - "github.com/docker/docker/client" -) - -type Event struct { - Status string `json:"status"` - Error string `json:"error"` - Progress string `json:"progress"` - ProgressDetail struct { - Current int `json:"current"` - Total int `json:"total"` - } `json:"progressDetail"` -} - -func NewClient() (*client.Client, error) { - cli, err := client.NewEnvClient() - if err != nil { - return nil, fmt.Errorf("Error getting docker client: %s", err) - } - cli.NegotiateAPIVersion(context.Background()) - - return cli, nil -} - -func getLayersFromManifest(r io.Reader) ([]string, error) { - type Manifest struct { - Layers []string - } - - manifestJSON, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - - var imageManifest []Manifest - if err := json.Unmarshal(manifestJSON, &imageManifest); err != nil { - return []string{}, fmt.Errorf("Could not unmarshal manifest to get layer order: %s", err) - } - return imageManifest[0].Layers, nil -} - -func unpackDockerSave(tarPath string, target string) error { - if _, ok := os.Stat(target); ok != nil { - os.MkdirAll(target, 0775) - } - f, err := os.Open(tarPath) - if err != nil { - return err - } - - tr := tar.NewReader(f) - - // Unpack the layers into a map, since we need to sort out the order later. - var layers []string - layerMap := map[string][]byte{} - for { - hdr, err := tr.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - // Docker save contains files and directories. Ignore the directories. - // We care about the layers and the manifest. The layers look like: - // $SHA/layer.tar - // and they are referenced that way in the manifest. - switch t := hdr.Typeflag; t { - case tar.TypeReg: - if hdr.Name == "manifest.json" { - layers, err = getLayersFromManifest(tr) - if err != nil { - return err - } - } else if strings.HasSuffix(hdr.Name, ".tar") { - layerMap[hdr.Name], err = ioutil.ReadAll(tr) - if err != nil { - return err - } - } - case tar.TypeDir: - continue - default: - return fmt.Errorf("unsupported file type %v found in file %s tar %s", t, hdr.Name, tarPath) - } - } - - for _, layer := range layers { - if err = UnTar(bytes.NewReader(layerMap[layer]), target, nil); err != nil { - return fmt.Errorf("Could not unpack layer %s: %s", layer, err) - } - } - return nil -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/fs_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/fs_utils.go deleted file mode 100644 index e7d7541d23..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/fs_utils.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "bytes" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" -) - -// Directory stores a representation of a file directory. -type Directory struct { - Root string - Content []string -} - -type DirectoryEntry struct { - Name string - Size int64 -} - -func GetSize(path string) int64 { - stat, err := os.Stat(path) - if err != nil { - logrus.Errorf("Could not obtain size for %s: %s", path, err) - return -1 - } - if stat.IsDir() { - size, err := getDirectorySize(path) - if err != nil { - logrus.Errorf("Could not obtain directory size for %s: %s", path, err) - } - return size - } - return stat.Size() -} - -//GetFileContents returns the contents of a file at the specified path -func GetFileContents(path string) (*string, error) { - if _, err := os.Stat(path); os.IsNotExist(err) { - return nil, err - } - - contents, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - strContents := string(contents) - //If file is empty, return nil - if strContents == "" { - return nil, nil - } - return &strContents, nil -} - -func getDirectorySize(path string) (int64, error) { - var size int64 - err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { - if !info.IsDir() { - size += info.Size() - } - return err - }) - return size, err -} - -// GetDirectoryContents converts the directory starting at the provided path into a Directory struct. -func GetDirectory(path string, deep bool) (Directory, error) { - var directory Directory - directory.Root = path - var err error - if deep { - walkFn := func(currPath string, info os.FileInfo, err error) error { - newContent := strings.TrimPrefix(currPath, directory.Root) - if newContent != "" { - directory.Content = append(directory.Content, newContent) - } - return nil - } - - err = filepath.Walk(path, walkFn) - } else { - contents, err := ioutil.ReadDir(path) - if err != nil { - return directory, err - } - - for _, file := range contents { - fileName := "/" + file.Name() - directory.Content = append(directory.Content, fileName) - } - } - return directory, err -} - -func GetDirectoryEntries(d Directory) []DirectoryEntry { - return CreateDirectoryEntries(d.Root, d.Content) -} - -func CreateDirectoryEntries(root string, entryNames []string) (entries []DirectoryEntry) { - for _, name := range entryNames { - entryPath := filepath.Join(root, name) - size := GetSize(entryPath) - - entry := DirectoryEntry{ - Name: name, - Size: size, - } - entries = append(entries, entry) - } - return entries -} - -func CheckSameFile(f1name, f2name string) (bool, error) { - // Check first if files differ in size and immediately return - f1stat, err := os.Stat(f1name) - if err != nil { - return false, err - } - f2stat, err := os.Stat(f2name) - if err != nil { - return false, err - } - - if f1stat.Size() != f2stat.Size() { - return false, nil - } - - // Next, check file contents - f1, err := ioutil.ReadFile(f1name) - if err != nil { - return false, err - } - f2, err := ioutil.ReadFile(f2name) - if err != nil { - return false, err - } - - if !bytes.Equal(f1, f2) { - return false, nil - } - return true, nil -} - -// HasFilepathPrefix checks if the given file path begins with prefix -func HasFilepathPrefix(path, prefix string) bool { - path = filepath.Clean(path) - prefix = filepath.Clean(prefix) - pathArray := strings.Split(path, "/") - prefixArray := strings.Split(prefix, "/") - - if len(pathArray) < len(prefixArray) { - return false - } - for index := range prefixArray { - if prefixArray[index] == pathArray[index] { - continue - } - return false - } - return true -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go deleted file mode 100644 index 47cff2e1dd..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_prep_utils.go +++ /dev/null @@ -1,288 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "archive/tar" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "sort" - "strings" - - "github.com/GoogleContainerTools/container-diff/cmd/util/output" - "github.com/containers/image/docker" - "github.com/containers/image/manifest" - "github.com/containers/image/pkg/compression" - "github.com/containers/image/types" - "github.com/sirupsen/logrus" -) - -type Prepper interface { - Name() string - GetConfig() (ConfigSchema, error) - GetFileSystem() (string, error) - GetImage() (Image, error) - GetSource() string - SetSource(string) -} - -type ImageType int - -const ( - ImageTypeTar ImageType = iota - ImageTypeDaemon - ImageTypeCloud -) - -type Image struct { - Source string - FSPath string - Config ConfigSchema - Type ImageType -} - -func (i *Image) IsTar() bool { - return i.Type == ImageTypeTar -} - -func (i *Image) IsDaemon() bool { - return i.Type == ImageTypeDaemon -} - -func (i *Image) IsCloud() bool { - return i.Type == ImageTypeCloud -} - -func (i *Image) GetRemoteDigest() (string, error) { - ref, err := docker.ParseReference("//" + i.Source) - if err != nil { - return "", err - } - return getDigestFromReference(ref, i.Source) -} - -func (i *Image) GetName() string { - return strings.Split(i.Source, ":")[0] -} - -type ImageHistoryItem struct { - CreatedBy string `json:"created_by"` -} - -type ConfigObject struct { - Hostname string - Domainname string - User string - AttachStdin bool - AttachStdout bool - AttachStderr bool - ExposedPorts map[string]struct{} `json:"ExposedPorts"` - Tty bool - OpenStdin bool - StdinOnce bool - Env []string `json:"Env"` - Cmd []string `json:"Cmd"` - // Healthcheck *HealthConfig - ArgsEscaped bool `json:",omitempty"` - Image string - Volumes map[string]struct{} `json:"Volumes"` - Workdir string `json:"WorkingDir"` - Entrypoint []string `json:"Entrypoint"` - NetworkDisabled bool `json:",omitempty"` - MacAddress string `json:",omitempty"` - OnBuild []string - Labels map[string]string `json:"Labels"` - StopSignal string `json:",omitempty"` - StopTimeout *int `json:",omitempty"` - Shell []string `json:",omitempty"` -} - -func (c ConfigObject) AsList() []string { - return []string{ - fmt.Sprintf("Hostname: %s", c.Hostname), - fmt.Sprintf("Domainname: %s", c.Domainname), - fmt.Sprintf("User: %s", c.User), - fmt.Sprintf("AttachStdin: %t", c.AttachStdin), - fmt.Sprintf("AttachStdout: %t", c.AttachStdout), - fmt.Sprintf("AttachStderr: %t", c.AttachStderr), - fmt.Sprintf("ExposedPorts: %v", sortMap(c.ExposedPorts)), - fmt.Sprintf("Tty: %t", c.Tty), - fmt.Sprintf("OpenStdin: %t", c.OpenStdin), - fmt.Sprintf("StdinOnce: %t", c.StdinOnce), - fmt.Sprintf("Env: %s", strings.Join(c.Env, ",")), - fmt.Sprintf("Cmd: %s", strings.Join(c.Cmd, ",")), - fmt.Sprintf("ArgsEscaped: %t", c.ArgsEscaped), - fmt.Sprintf("Image: %s", c.Image), - fmt.Sprintf("Volumes: %v", sortMap(c.Volumes)), - fmt.Sprintf("Workdir: %s", c.Workdir), - fmt.Sprintf("Entrypoint: %s", strings.Join(c.Entrypoint, ",")), - fmt.Sprintf("NetworkDisabled: %t", c.NetworkDisabled), - fmt.Sprintf("MacAddress: %s", c.MacAddress), - fmt.Sprintf("OnBuild: %s", strings.Join(c.OnBuild, ",")), - fmt.Sprintf("Labels: %v", c.Labels), - fmt.Sprintf("StopSignal: %s", c.StopSignal), - fmt.Sprintf("StopTimeout: %d", c.StopTimeout), - fmt.Sprintf("Shell: %s", strings.Join(c.Shell, ",")), - } -} - -type ConfigSchema struct { - Config ConfigObject `json:"config"` - History []ImageHistoryItem `json:"history"` -} - -func getImage(p Prepper) (Image, error) { - // see if the image name has tag provided, if not add latest as tag - if !IsTar(p.GetSource()) && !HasTag(p.GetSource()) { - p.SetSource(p.GetSource() + LatestTag) - } - output.PrintToStdErr("Retrieving image %s from source %s\n", p.GetSource(), p.Name()) - imgPath, err := p.GetFileSystem() - if err != nil { - // return image with FSPath so it can be cleaned up - return Image{ - FSPath: imgPath, - }, err - } - - config, err := p.GetConfig() - if err != nil { - logrus.Error("Error retrieving History: ", err) - } - - logrus.Infof("Finished prepping image %s", p.GetSource()) - return Image{ - Source: p.GetSource(), - FSPath: imgPath, - Config: config, - }, nil -} - -func getImageFromTar(tarPath string) (string, error) { - logrus.Info("Extracting image tar to obtain image file system") - tempPath, err := ioutil.TempDir("", ".container-diff") - if err != nil { - return "", err - } - return tempPath, unpackDockerSave(tarPath, tempPath) -} - -func GetFileSystemFromReference(ref types.ImageReference, imgSrc types.ImageSource, path string, whitelist []string) error { - var err error - if imgSrc == nil { - imgSrc, err = ref.NewImageSource(nil) - } - if err != nil { - return err - } - defer imgSrc.Close() - img, err := ref.NewImage(nil) - if err != nil { - return err - } - defer img.Close() - for _, b := range img.LayerInfos() { - bi, _, err := imgSrc.GetBlob(b) - if err != nil { - return err - } - defer bi.Close() - f, reader, err := compression.DetectCompression(bi) - if err != nil { - return err - } - // Decompress if necessary. - if f != nil { - reader, err = f(reader) - if err != nil { - return err - } - } - tr := tar.NewReader(reader) - if err := unpackTar(tr, path, whitelist); err != nil { - return err - } - } - return nil -} - -func getDigestFromReference(ref types.ImageReference, source string) (string, error) { - img, err := ref.NewImage(nil) - if err != nil { - logrus.Errorf("Error referencing image %s from registry: %s", source, err) - return "", errors.New("Could not obtain image digest") - } - defer img.Close() - - rawManifest, _, err := img.Manifest() - if err != nil { - logrus.Errorf("Error referencing image %s from registry: %s", source, err) - return "", errors.New("Could not obtain image digest") - } - - digest, err := manifest.Digest(rawManifest) - if err != nil { - logrus.Errorf("Error referencing image %s from registry: %s", source, err) - return "", errors.New("Could not obtain image digest") - } - - return digest.String(), nil -} - -func getConfigFromReference(ref types.ImageReference, source string) (ConfigSchema, error) { - img, err := ref.NewImage(nil) - if err != nil { - logrus.Errorf("Error referencing image %s from registry: %s", source, err) - return ConfigSchema{}, errors.New("Could not obtain image config") - } - defer img.Close() - - configBlob, err := img.ConfigBlob() - if err != nil { - logrus.Errorf("Error obtaining config blob for image %s from registry: %s", source, err) - return ConfigSchema{}, errors.New("Could not obtain image config") - } - - var config ConfigSchema - err = json.Unmarshal(configBlob, &config) - if err != nil { - logrus.Errorf("Error with config file struct for image %s: %s", source, err) - return ConfigSchema{}, errors.New("Could not obtain image config") - } - return config, nil -} - -func CleanupImage(image Image) { - if image.FSPath != "" { - logrus.Infof("Removing image filesystem directory %s from system", image.FSPath) - if err := os.RemoveAll(image.FSPath); err != nil { - logrus.Warn(err.Error()) - } - } -} - -func sortMap(m map[string]struct{}) string { - pairs := make([]string, 0) - for key := range m { - pairs = append(pairs, fmt.Sprintf("%s:%s", key, m[key])) - } - sort.Strings(pairs) - return strings.Join(pairs, " ") -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_utils.go deleted file mode 100644 index 95901d7844..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/image_utils.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "io" - "io/ioutil" - "os" - "path/filepath" - "regexp" - - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -const LatestTag string = ":latest" - -func GetImageLayers(pathToImage string) []string { - layers := []string{} - contents, err := ioutil.ReadDir(pathToImage) - if err != nil { - logrus.Error(err.Error()) - } - - for _, file := range contents { - if file.IsDir() { - layers = append(layers, file.Name()) - } - } - return layers -} - -// copyToFile writes the content of the reader to the specified file -func copyToFile(outfile string, r io.Reader) error { - // We use sequential file access here to avoid depleting the standby list - // on Windows. On Linux, this is a call directly to ioutil.TempFile - tmpFile, err := system.TempFileSequential(filepath.Dir(outfile), ".docker_temp_") - if err != nil { - return err - } - - tmpPath := tmpFile.Name() - - _, err = io.Copy(tmpFile, r) - tmpFile.Close() - - if err != nil { - os.Remove(tmpPath) - return err - } - - if err = os.Rename(tmpPath, outfile); err != nil { - os.Remove(tmpPath) - return err - } - - return nil -} - -// checks to see if an image string contains a tag. -func HasTag(image string) bool { - tagRegex := regexp.MustCompile(".*:[^/]+$") - return tagRegex.MatchString(image) -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_prepper.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_prepper.go deleted file mode 100644 index 948916cd68..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_prepper.go +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "encoding/json" - "errors" - "github.com/containers/image/docker/tarfile" - "github.com/docker/docker/client" - "github.com/sirupsen/logrus" - "io/ioutil" - "os" - "path/filepath" -) - -type TarPrepper struct { - Source string - Client *client.Client -} - -func (p *TarPrepper) Name() string { - return "Tar Archive" -} - -func (p *TarPrepper) GetSource() string { - return p.Source -} - -func (p *TarPrepper) SetSource(source string) { - p.Source = source -} - -func (p *TarPrepper) GetImage() (Image, error) { - image, err := getImage(p) - image.Type = ImageTypeTar - return image, err -} - -func (p *TarPrepper) GetFileSystem() (string, error) { - return getImageFromTar(p.Source) -} - -func (p *TarPrepper) GetConfig() (ConfigSchema, error) { - tempDir, err := ioutil.TempDir("", ".container-diff") - if err != nil { - return ConfigSchema{}, nil - } - defer os.RemoveAll(tempDir) - f, err := os.Open(p.Source) - if err != nil { - return ConfigSchema{}, err - } - defer f.Close() - if err := UnTar(f, tempDir, nil); err != nil { - return ConfigSchema{}, err - } - - var config ConfigSchema - // First open the manifest, then find the referenced config. - manifestPath := filepath.Join(tempDir, "manifest.json") - contents, err := ioutil.ReadFile(manifestPath) - if err != nil { - return ConfigSchema{}, err - } - - manifests := []tarfile.ManifestItem{} - if err := json.Unmarshal(contents, &manifests); err != nil { - return ConfigSchema{}, err - } - - if len(manifests) != 1 { - return ConfigSchema{}, errors.New("specified tar file contains multiple images") - } - - cfgFilename := filepath.Join(tempDir, manifests[0].Config) - file, err := ioutil.ReadFile(cfgFilename) - if err != nil { - logrus.Errorf("Could not read config file %s: %s", cfgFilename, err) - return ConfigSchema{}, errors.New("Could not obtain image config") - } - err = json.Unmarshal(file, &config) - if err != nil { - logrus.Errorf("Could not marshal config file %s: %s", cfgFilename, err) - return ConfigSchema{}, errors.New("Could not obtain image config") - } - - return config, nil -} diff --git a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_utils.go b/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_utils.go deleted file mode 100644 index 1cb9cc09dc..0000000000 --- a/vendor/github.com/GoogleContainerTools/container-diff/pkg/util/tar_utils.go +++ /dev/null @@ -1,224 +0,0 @@ -/* -Copyright 2018 Google, Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "archive/tar" - "fmt" - "io" - "os" - "path/filepath" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// Map of target:linkname -var hardlinks = make(map[string]string) - -type OriginalPerm struct { - path string - perm os.FileMode -} - -func unpackTar(tr *tar.Reader, path string, whitelist []string) error { - originalPerms := make([]OriginalPerm, 0) - for { - header, err := tr.Next() - if err == io.EOF { - // end of tar archive - break - } - if err != nil { - logrus.Error("Error getting next tar header") - return err - } - if strings.Contains(header.Name, ".wh.") { - rmPath := filepath.Clean(filepath.Join(path, header.Name)) - // Remove the .wh file if it was extracted. - if _, err := os.Stat(rmPath); !os.IsNotExist(err) { - if err := os.Remove(rmPath); err != nil { - logrus.Error(err) - } - } - - // Remove the whited-out path. - newName := strings.Replace(rmPath, ".wh.", "", 1) - if err = os.RemoveAll(newName); err != nil { - logrus.Error(err) - } - continue - } - target := filepath.Clean(filepath.Join(path, header.Name)) - // Make sure the target isn't part of the whitelist - if checkWhitelist(target, whitelist) { - continue - } - mode := header.FileInfo().Mode() - switch header.Typeflag { - - // if its a dir and it doesn't exist create it - case tar.TypeDir: - if _, err := os.Stat(target); os.IsNotExist(err) { - if mode.Perm()&(1<<(uint(7))) == 0 { - logrus.Debugf("Write permission bit not set on %s by default; setting manually", target) - originalMode := mode - mode = mode | (1 << uint(7)) - // keep track of original file permission to reset later - originalPerms = append(originalPerms, OriginalPerm{ - path: target, - perm: originalMode, - }) - } - logrus.Debugf("Creating directory %s with permissions %v", target, mode) - if err := os.MkdirAll(target, mode); err != nil { - return err - } - // In some cases, MkdirAll doesn't change the permissions, so run Chmod - if err := os.Chmod(target, mode); err != nil { - return err - } - } - - // if it's a file create it - case tar.TypeReg: - // It's possible for a file to be included before the directory it's in is created. - baseDir := filepath.Dir(target) - if _, err := os.Stat(baseDir); os.IsNotExist(err) { - logrus.Debugf("baseDir %s for file %s does not exist. Creating.", baseDir, target) - if err := os.MkdirAll(baseDir, 0755); err != nil { - return err - } - } - // It's possible we end up creating files that can't be overwritten based on their permissions. - // Explicitly delete an existing file before continuing. - if _, err := os.Stat(target); !os.IsNotExist(err) { - logrus.Debugf("Removing %s for overwrite.", target) - if err := os.Remove(target); err != nil { - return err - } - } - - logrus.Debugf("Creating file %s with permissions %v", target, mode) - currFile, err := os.Create(target) - if err != nil { - logrus.Errorf("Error creating file %s %s", target, err) - return err - } - // manually set permissions on file, since the default umask (022) will interfere - if err = os.Chmod(target, mode); err != nil { - logrus.Errorf("Error updating file permissions on %s", target) - return err - } - _, err = io.Copy(currFile, tr) - if err != nil { - return err - } - currFile.Close() - case tar.TypeSymlink: - // It's possible we end up creating files that can't be overwritten based on their permissions. - // Explicitly delete an existing file before continuing. - if _, err := os.Stat(target); !os.IsNotExist(err) { - logrus.Debugf("Removing %s to create symlink.", target) - if err := os.RemoveAll(target); err != nil { - logrus.Debugf("Unable to remove %s: %s", target, err) - } - } - - if err = os.Symlink(header.Linkname, target); err != nil { - logrus.Errorf("Failed to create symlink between %s and %s: %s", header.Linkname, target, err) - } - case tar.TypeLink: - linkname := filepath.Clean(filepath.Join(path, header.Linkname)) - // Check if the linkname already exists - if _, err := os.Stat(linkname); !os.IsNotExist(err) { - // If it exists, create the hard link - resolveHardlink(linkname, target) - } else { - hardlinks[target] = linkname - } - } - } - - for target, linkname := range hardlinks { - logrus.Info("Resolving hard links.") - if _, err := os.Stat(linkname); !os.IsNotExist(err) { - // If it exists, create the hard link - if err := resolveHardlink(linkname, target); err != nil { - return errors.Wrap(err, fmt.Sprintf("Unable to create hard link from %s to %s", linkname, target)) - } - } - } - - // reset all original file - for _, perm := range originalPerms { - if err := os.Chmod(perm.path, perm.perm); err != nil { - return err - } - } - return nil -} - -func resolveHardlink(linkname, target string) error { - if err := os.Link(linkname, target); err != nil { - return err - } - logrus.Debugf("Created hard link from %s to %s", linkname, target) - return nil -} - -func checkWhitelist(target string, whitelist []string) bool { - for _, w := range whitelist { - if HasFilepathPrefix(target, w) { - logrus.Debugf("Not extracting %s, as it has prefix %s which is whitelisted", target, w) - return true - } - } - return false -} - -// UnTar takes in a path to a tar file and writes the untarred version to the provided target. -// Only untars one level, does not untar nested tars. -func UnTar(r io.Reader, target string, whitelist []string) error { - if _, ok := os.Stat(target); ok != nil { - os.MkdirAll(target, 0775) - } - - tr := tar.NewReader(r) - if err := unpackTar(tr, target, whitelist); err != nil { - return err - } - return nil -} - -func IsTar(path string) bool { - return filepath.Ext(path) == ".tar" || - filepath.Ext(path) == ".tar.gz" || - filepath.Ext(path) == ".tgz" -} - -func CheckTar(image string) bool { - if strings.TrimSuffix(image, ".tar") == image { - return false - } - if _, err := os.Stat(image); err != nil { - logrus.Errorf("%s does not exist", image) - return false - } - return true -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/common.go b/vendor/github.com/Microsoft/go-winio/archive/tar/common.go deleted file mode 100644 index 0378401c0d..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/common.go +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tar implements access to tar archives. -// It aims to cover most of the variations, including those produced -// by GNU and BSD tars. -// -// References: -// http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 -// http://www.gnu.org/software/tar/manual/html_node/Standard.html -// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html -package tar - -import ( - "bytes" - "errors" - "fmt" - "os" - "path" - "time" -) - -const ( - blockSize = 512 - - // Types - TypeReg = '0' // regular file - TypeRegA = '\x00' // regular file - TypeLink = '1' // hard link - TypeSymlink = '2' // symbolic link - TypeChar = '3' // character device node - TypeBlock = '4' // block device node - TypeDir = '5' // directory - TypeFifo = '6' // fifo node - TypeCont = '7' // reserved - TypeXHeader = 'x' // extended header - TypeXGlobalHeader = 'g' // global extended header - TypeGNULongName = 'L' // Next file has a long name - TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name - TypeGNUSparse = 'S' // sparse file -) - -// A Header represents a single header in a tar archive. -// Some fields may not be populated. -type Header struct { - Name string // name of header file entry - Mode int64 // permission and mode bits - Uid int // user id of owner - Gid int // group id of owner - Size int64 // length in bytes - ModTime time.Time // modified time - Typeflag byte // type of header entry - Linkname string // target name of link - Uname string // user name of owner - Gname string // group name of owner - Devmajor int64 // major number of character or block device - Devminor int64 // minor number of character or block device - AccessTime time.Time // access time - ChangeTime time.Time // status change time - CreationTime time.Time // creation time - Xattrs map[string]string - Winheaders map[string]string -} - -// File name constants from the tar spec. -const ( - fileNameSize = 100 // Maximum number of bytes in a standard tar name. - fileNamePrefixSize = 155 // Maximum number of ustar extension bytes. -) - -// FileInfo returns an os.FileInfo for the Header. -func (h *Header) FileInfo() os.FileInfo { - return headerFileInfo{h} -} - -// headerFileInfo implements os.FileInfo. -type headerFileInfo struct { - h *Header -} - -func (fi headerFileInfo) Size() int64 { return fi.h.Size } -func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } -func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } -func (fi headerFileInfo) Sys() interface{} { return fi.h } - -// Name returns the base name of the file. -func (fi headerFileInfo) Name() string { - if fi.IsDir() { - return path.Base(path.Clean(fi.h.Name)) - } - return path.Base(fi.h.Name) -} - -// Mode returns the permission and mode bits for the headerFileInfo. -func (fi headerFileInfo) Mode() (mode os.FileMode) { - // Set file permission bits. - mode = os.FileMode(fi.h.Mode).Perm() - - // Set setuid, setgid and sticky bits. - if fi.h.Mode&c_ISUID != 0 { - // setuid - mode |= os.ModeSetuid - } - if fi.h.Mode&c_ISGID != 0 { - // setgid - mode |= os.ModeSetgid - } - if fi.h.Mode&c_ISVTX != 0 { - // sticky - mode |= os.ModeSticky - } - - // Set file mode bits. - // clear perm, setuid, setgid and sticky bits. - m := os.FileMode(fi.h.Mode) &^ 07777 - if m == c_ISDIR { - // directory - mode |= os.ModeDir - } - if m == c_ISFIFO { - // named pipe (FIFO) - mode |= os.ModeNamedPipe - } - if m == c_ISLNK { - // symbolic link - mode |= os.ModeSymlink - } - if m == c_ISBLK { - // device file - mode |= os.ModeDevice - } - if m == c_ISCHR { - // Unix character device - mode |= os.ModeDevice - mode |= os.ModeCharDevice - } - if m == c_ISSOCK { - // Unix domain socket - mode |= os.ModeSocket - } - - switch fi.h.Typeflag { - case TypeSymlink: - // symbolic link - mode |= os.ModeSymlink - case TypeChar: - // character device node - mode |= os.ModeDevice - mode |= os.ModeCharDevice - case TypeBlock: - // block device node - mode |= os.ModeDevice - case TypeDir: - // directory - mode |= os.ModeDir - case TypeFifo: - // fifo node - mode |= os.ModeNamedPipe - } - - return mode -} - -// sysStat, if non-nil, populates h from system-dependent fields of fi. -var sysStat func(fi os.FileInfo, h *Header) error - -// Mode constants from the tar spec. -const ( - c_ISUID = 04000 // Set uid - c_ISGID = 02000 // Set gid - c_ISVTX = 01000 // Save text (sticky bit) - c_ISDIR = 040000 // Directory - c_ISFIFO = 010000 // FIFO - c_ISREG = 0100000 // Regular file - c_ISLNK = 0120000 // Symbolic link - c_ISBLK = 060000 // Block special file - c_ISCHR = 020000 // Character special file - c_ISSOCK = 0140000 // Socket -) - -// Keywords for the PAX Extended Header -const ( - paxAtime = "atime" - paxCharset = "charset" - paxComment = "comment" - paxCtime = "ctime" // please note that ctime is not a valid pax header. - paxCreationTime = "LIBARCHIVE.creationtime" - paxGid = "gid" - paxGname = "gname" - paxLinkpath = "linkpath" - paxMtime = "mtime" - paxPath = "path" - paxSize = "size" - paxUid = "uid" - paxUname = "uname" - paxXattr = "SCHILY.xattr." - paxWindows = "MSWINDOWS." - paxNone = "" -) - -// FileInfoHeader creates a partially-populated Header from fi. -// If fi describes a symlink, FileInfoHeader records link as the link target. -// If fi describes a directory, a slash is appended to the name. -// Because os.FileInfo's Name method returns only the base name of -// the file it describes, it may be necessary to modify the Name field -// of the returned header to provide the full path name of the file. -func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { - if fi == nil { - return nil, errors.New("tar: FileInfo is nil") - } - fm := fi.Mode() - h := &Header{ - Name: fi.Name(), - ModTime: fi.ModTime(), - Mode: int64(fm.Perm()), // or'd with c_IS* constants later - } - switch { - case fm.IsRegular(): - h.Mode |= c_ISREG - h.Typeflag = TypeReg - h.Size = fi.Size() - case fi.IsDir(): - h.Typeflag = TypeDir - h.Mode |= c_ISDIR - h.Name += "/" - case fm&os.ModeSymlink != 0: - h.Typeflag = TypeSymlink - h.Mode |= c_ISLNK - h.Linkname = link - case fm&os.ModeDevice != 0: - if fm&os.ModeCharDevice != 0 { - h.Mode |= c_ISCHR - h.Typeflag = TypeChar - } else { - h.Mode |= c_ISBLK - h.Typeflag = TypeBlock - } - case fm&os.ModeNamedPipe != 0: - h.Typeflag = TypeFifo - h.Mode |= c_ISFIFO - case fm&os.ModeSocket != 0: - h.Mode |= c_ISSOCK - default: - return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) - } - if fm&os.ModeSetuid != 0 { - h.Mode |= c_ISUID - } - if fm&os.ModeSetgid != 0 { - h.Mode |= c_ISGID - } - if fm&os.ModeSticky != 0 { - h.Mode |= c_ISVTX - } - // If possible, populate additional fields from OS-specific - // FileInfo fields. - if sys, ok := fi.Sys().(*Header); ok { - // This FileInfo came from a Header (not the OS). Use the - // original Header to populate all remaining fields. - h.Uid = sys.Uid - h.Gid = sys.Gid - h.Uname = sys.Uname - h.Gname = sys.Gname - h.AccessTime = sys.AccessTime - h.ChangeTime = sys.ChangeTime - if sys.Xattrs != nil { - h.Xattrs = make(map[string]string) - for k, v := range sys.Xattrs { - h.Xattrs[k] = v - } - } - if sys.Typeflag == TypeLink { - // hard link - h.Typeflag = TypeLink - h.Size = 0 - h.Linkname = sys.Linkname - } - } - if sysStat != nil { - return h, sysStat(fi, h) - } - return h, nil -} - -var zeroBlock = make([]byte, blockSize) - -// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values. -// We compute and return both. -func checksum(header []byte) (unsigned int64, signed int64) { - for i := 0; i < len(header); i++ { - if i == 148 { - // The chksum field (header[148:156]) is special: it should be treated as space bytes. - unsigned += ' ' * 8 - signed += ' ' * 8 - i += 7 - continue - } - unsigned += int64(header[i]) - signed += int64(int8(header[i])) - } - return -} - -type slicer []byte - -func (sp *slicer) next(n int) (b []byte) { - s := *sp - b, *sp = s[0:n], s[n:] - return -} - -func isASCII(s string) bool { - for _, c := range s { - if c >= 0x80 { - return false - } - } - return true -} - -func toASCII(s string) string { - if isASCII(s) { - return s - } - var buf bytes.Buffer - for _, c := range s { - if c < 0x80 { - buf.WriteByte(byte(c)) - } - } - return buf.String() -} - -// isHeaderOnlyType checks if the given type flag is of the type that has no -// data section even if a size is specified. -func isHeaderOnlyType(flag byte) bool { - switch flag { - case TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, TypeFifo: - return true - default: - return false - } -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/reader.go b/vendor/github.com/Microsoft/go-winio/archive/tar/reader.go deleted file mode 100644 index e210c618a1..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/reader.go +++ /dev/null @@ -1,1002 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tar - -// TODO(dsymonds): -// - pax extensions - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "math" - "os" - "strconv" - "strings" - "time" -) - -var ( - ErrHeader = errors.New("archive/tar: invalid tar header") -) - -const maxNanoSecondIntSize = 9 - -// A Reader provides sequential access to the contents of a tar archive. -// A tar archive consists of a sequence of files. -// The Next method advances to the next file in the archive (including the first), -// and then it can be treated as an io.Reader to access the file's data. -type Reader struct { - r io.Reader - err error - pad int64 // amount of padding (ignored) after current file entry - curr numBytesReader // reader for current file entry - hdrBuff [blockSize]byte // buffer to use in readHeader -} - -type parser struct { - err error // Last error seen -} - -// A numBytesReader is an io.Reader with a numBytes method, returning the number -// of bytes remaining in the underlying encoded data. -type numBytesReader interface { - io.Reader - numBytes() int64 -} - -// A regFileReader is a numBytesReader for reading file data from a tar archive. -type regFileReader struct { - r io.Reader // underlying reader - nb int64 // number of unread bytes for current file entry -} - -// A sparseFileReader is a numBytesReader for reading sparse file data from a -// tar archive. -type sparseFileReader struct { - rfr numBytesReader // Reads the sparse-encoded file data - sp []sparseEntry // The sparse map for the file - pos int64 // Keeps track of file position - total int64 // Total size of the file -} - -// A sparseEntry holds a single entry in a sparse file's sparse map. -// -// Sparse files are represented using a series of sparseEntrys. -// Despite the name, a sparseEntry represents an actual data fragment that -// references data found in the underlying archive stream. All regions not -// covered by a sparseEntry are logically filled with zeros. -// -// For example, if the underlying raw file contains the 10-byte data: -// var compactData = "abcdefgh" -// -// And the sparse map has the following entries: -// var sp = []sparseEntry{ -// {offset: 2, numBytes: 5} // Data fragment for [2..7] -// {offset: 18, numBytes: 3} // Data fragment for [18..21] -// } -// -// Then the content of the resulting sparse file with a "real" size of 25 is: -// var sparseData = "\x00"*2 + "abcde" + "\x00"*11 + "fgh" + "\x00"*4 -type sparseEntry struct { - offset int64 // Starting position of the fragment - numBytes int64 // Length of the fragment -} - -// Keywords for GNU sparse files in a PAX extended header -const ( - paxGNUSparseNumBlocks = "GNU.sparse.numblocks" - paxGNUSparseOffset = "GNU.sparse.offset" - paxGNUSparseNumBytes = "GNU.sparse.numbytes" - paxGNUSparseMap = "GNU.sparse.map" - paxGNUSparseName = "GNU.sparse.name" - paxGNUSparseMajor = "GNU.sparse.major" - paxGNUSparseMinor = "GNU.sparse.minor" - paxGNUSparseSize = "GNU.sparse.size" - paxGNUSparseRealSize = "GNU.sparse.realsize" -) - -// Keywords for old GNU sparse headers -const ( - oldGNUSparseMainHeaderOffset = 386 - oldGNUSparseMainHeaderIsExtendedOffset = 482 - oldGNUSparseMainHeaderNumEntries = 4 - oldGNUSparseExtendedHeaderIsExtendedOffset = 504 - oldGNUSparseExtendedHeaderNumEntries = 21 - oldGNUSparseOffsetSize = 12 - oldGNUSparseNumBytesSize = 12 -) - -// NewReader creates a new Reader reading from r. -func NewReader(r io.Reader) *Reader { return &Reader{r: r} } - -// Next advances to the next entry in the tar archive. -// -// io.EOF is returned at the end of the input. -func (tr *Reader) Next() (*Header, error) { - if tr.err != nil { - return nil, tr.err - } - - var hdr *Header - var extHdrs map[string]string - - // Externally, Next iterates through the tar archive as if it is a series of - // files. Internally, the tar format often uses fake "files" to add meta - // data that describes the next file. These meta data "files" should not - // normally be visible to the outside. As such, this loop iterates through - // one or more "header files" until it finds a "normal file". -loop: - for { - tr.err = tr.skipUnread() - if tr.err != nil { - return nil, tr.err - } - - hdr = tr.readHeader() - if tr.err != nil { - return nil, tr.err - } - - // Check for PAX/GNU special headers and files. - switch hdr.Typeflag { - case TypeXHeader: - extHdrs, tr.err = parsePAX(tr) - if tr.err != nil { - return nil, tr.err - } - continue loop // This is a meta header affecting the next header - case TypeGNULongName, TypeGNULongLink: - var realname []byte - realname, tr.err = ioutil.ReadAll(tr) - if tr.err != nil { - return nil, tr.err - } - - // Convert GNU extensions to use PAX headers. - if extHdrs == nil { - extHdrs = make(map[string]string) - } - var p parser - switch hdr.Typeflag { - case TypeGNULongName: - extHdrs[paxPath] = p.parseString(realname) - case TypeGNULongLink: - extHdrs[paxLinkpath] = p.parseString(realname) - } - if p.err != nil { - tr.err = p.err - return nil, tr.err - } - continue loop // This is a meta header affecting the next header - default: - mergePAX(hdr, extHdrs) - - // Check for a PAX format sparse file - sp, err := tr.checkForGNUSparsePAXHeaders(hdr, extHdrs) - if err != nil { - tr.err = err - return nil, err - } - if sp != nil { - // Current file is a PAX format GNU sparse file. - // Set the current file reader to a sparse file reader. - tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size) - if tr.err != nil { - return nil, tr.err - } - } - break loop // This is a file, so stop - } - } - return hdr, nil -} - -// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then -// this function reads the sparse map and returns it. Unknown sparse formats are ignored, causing the file to -// be treated as a regular file. -func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]string) ([]sparseEntry, error) { - var sparseFormat string - - // Check for sparse format indicators - major, majorOk := headers[paxGNUSparseMajor] - minor, minorOk := headers[paxGNUSparseMinor] - sparseName, sparseNameOk := headers[paxGNUSparseName] - _, sparseMapOk := headers[paxGNUSparseMap] - sparseSize, sparseSizeOk := headers[paxGNUSparseSize] - sparseRealSize, sparseRealSizeOk := headers[paxGNUSparseRealSize] - - // Identify which, if any, sparse format applies from which PAX headers are set - if majorOk && minorOk { - sparseFormat = major + "." + minor - } else if sparseNameOk && sparseMapOk { - sparseFormat = "0.1" - } else if sparseSizeOk { - sparseFormat = "0.0" - } else { - // Not a PAX format GNU sparse file. - return nil, nil - } - - // Check for unknown sparse format - if sparseFormat != "0.0" && sparseFormat != "0.1" && sparseFormat != "1.0" { - return nil, nil - } - - // Update hdr from GNU sparse PAX headers - if sparseNameOk { - hdr.Name = sparseName - } - if sparseSizeOk { - realSize, err := strconv.ParseInt(sparseSize, 10, 0) - if err != nil { - return nil, ErrHeader - } - hdr.Size = realSize - } else if sparseRealSizeOk { - realSize, err := strconv.ParseInt(sparseRealSize, 10, 0) - if err != nil { - return nil, ErrHeader - } - hdr.Size = realSize - } - - // Set up the sparse map, according to the particular sparse format in use - var sp []sparseEntry - var err error - switch sparseFormat { - case "0.0", "0.1": - sp, err = readGNUSparseMap0x1(headers) - case "1.0": - sp, err = readGNUSparseMap1x0(tr.curr) - } - return sp, err -} - -// mergePAX merges well known headers according to PAX standard. -// In general headers with the same name as those found -// in the header struct overwrite those found in the header -// struct with higher precision or longer values. Esp. useful -// for name and linkname fields. -func mergePAX(hdr *Header, headers map[string]string) error { - for k, v := range headers { - switch k { - case paxPath: - hdr.Name = v - case paxLinkpath: - hdr.Linkname = v - case paxGname: - hdr.Gname = v - case paxUname: - hdr.Uname = v - case paxUid: - uid, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Uid = int(uid) - case paxGid: - gid, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Gid = int(gid) - case paxAtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.AccessTime = t - case paxMtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.ModTime = t - case paxCtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.ChangeTime = t - case paxCreationTime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.CreationTime = t - case paxSize: - size, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Size = int64(size) - default: - if strings.HasPrefix(k, paxXattr) { - if hdr.Xattrs == nil { - hdr.Xattrs = make(map[string]string) - } - hdr.Xattrs[k[len(paxXattr):]] = v - } else if strings.HasPrefix(k, paxWindows) { - if hdr.Winheaders == nil { - hdr.Winheaders = make(map[string]string) - } - hdr.Winheaders[k[len(paxWindows):]] = v - } - } - } - return nil -} - -// parsePAXTime takes a string of the form %d.%d as described in -// the PAX specification. -func parsePAXTime(t string) (time.Time, error) { - buf := []byte(t) - pos := bytes.IndexByte(buf, '.') - var seconds, nanoseconds int64 - var err error - if pos == -1 { - seconds, err = strconv.ParseInt(t, 10, 0) - if err != nil { - return time.Time{}, err - } - } else { - seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0) - if err != nil { - return time.Time{}, err - } - nano_buf := string(buf[pos+1:]) - // Pad as needed before converting to a decimal. - // For example .030 -> .030000000 -> 30000000 nanoseconds - if len(nano_buf) < maxNanoSecondIntSize { - // Right pad - nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf)) - } else if len(nano_buf) > maxNanoSecondIntSize { - // Right truncate - nano_buf = nano_buf[:maxNanoSecondIntSize] - } - nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0) - if err != nil { - return time.Time{}, err - } - } - ts := time.Unix(seconds, nanoseconds) - return ts, nil -} - -// parsePAX parses PAX headers. -// If an extended header (type 'x') is invalid, ErrHeader is returned -func parsePAX(r io.Reader) (map[string]string, error) { - buf, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - sbuf := string(buf) - - // For GNU PAX sparse format 0.0 support. - // This function transforms the sparse format 0.0 headers into sparse format 0.1 headers. - var sparseMap bytes.Buffer - - headers := make(map[string]string) - // Each record is constructed as - // "%d %s=%s\n", length, keyword, value - for len(sbuf) > 0 { - key, value, residual, err := parsePAXRecord(sbuf) - if err != nil { - return nil, ErrHeader - } - sbuf = residual - - keyStr := string(key) - if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes { - // GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map. - sparseMap.WriteString(value) - sparseMap.Write([]byte{','}) - } else { - // Normal key. Set the value in the headers map. - headers[keyStr] = string(value) - } - } - if sparseMap.Len() != 0 { - // Add sparse info to headers, chopping off the extra comma - sparseMap.Truncate(sparseMap.Len() - 1) - headers[paxGNUSparseMap] = sparseMap.String() - } - return headers, nil -} - -// parsePAXRecord parses the input PAX record string into a key-value pair. -// If parsing is successful, it will slice off the currently read record and -// return the remainder as r. -// -// A PAX record is of the following form: -// "%d %s=%s\n" % (size, key, value) -func parsePAXRecord(s string) (k, v, r string, err error) { - // The size field ends at the first space. - sp := strings.IndexByte(s, ' ') - if sp == -1 { - return "", "", s, ErrHeader - } - - // Parse the first token as a decimal integer. - n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int - if perr != nil || n < 5 || int64(len(s)) < n { - return "", "", s, ErrHeader - } - - // Extract everything between the space and the final newline. - rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:] - if nl != "\n" { - return "", "", s, ErrHeader - } - - // The first equals separates the key from the value. - eq := strings.IndexByte(rec, '=') - if eq == -1 { - return "", "", s, ErrHeader - } - return rec[:eq], rec[eq+1:], rem, nil -} - -// parseString parses bytes as a NUL-terminated C-style string. -// If a NUL byte is not found then the whole slice is returned as a string. -func (*parser) parseString(b []byte) string { - n := 0 - for n < len(b) && b[n] != 0 { - n++ - } - return string(b[0:n]) -} - -// parseNumeric parses the input as being encoded in either base-256 or octal. -// This function may return negative numbers. -// If parsing fails or an integer overflow occurs, err will be set. -func (p *parser) parseNumeric(b []byte) int64 { - // Check for base-256 (binary) format first. - // If the first bit is set, then all following bits constitute a two's - // complement encoded number in big-endian byte order. - if len(b) > 0 && b[0]&0x80 != 0 { - // Handling negative numbers relies on the following identity: - // -a-1 == ^a - // - // If the number is negative, we use an inversion mask to invert the - // data bytes and treat the value as an unsigned number. - var inv byte // 0x00 if positive or zero, 0xff if negative - if b[0]&0x40 != 0 { - inv = 0xff - } - - var x uint64 - for i, c := range b { - c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing - if i == 0 { - c &= 0x7f // Ignore signal bit in first byte - } - if (x >> 56) > 0 { - p.err = ErrHeader // Integer overflow - return 0 - } - x = x<<8 | uint64(c) - } - if (x >> 63) > 0 { - p.err = ErrHeader // Integer overflow - return 0 - } - if inv == 0xff { - return ^int64(x) - } - return int64(x) - } - - // Normal case is base-8 (octal) format. - return p.parseOctal(b) -} - -func (p *parser) parseOctal(b []byte) int64 { - // Because unused fields are filled with NULs, we need - // to skip leading NULs. Fields may also be padded with - // spaces or NULs. - // So we remove leading and trailing NULs and spaces to - // be sure. - b = bytes.Trim(b, " \x00") - - if len(b) == 0 { - return 0 - } - x, perr := strconv.ParseUint(p.parseString(b), 8, 64) - if perr != nil { - p.err = ErrHeader - } - return int64(x) -} - -// skipUnread skips any unread bytes in the existing file entry, as well as any -// alignment padding. It returns io.ErrUnexpectedEOF if any io.EOF is -// encountered in the data portion; it is okay to hit io.EOF in the padding. -// -// Note that this function still works properly even when sparse files are being -// used since numBytes returns the bytes remaining in the underlying io.Reader. -func (tr *Reader) skipUnread() error { - dataSkip := tr.numBytes() // Number of data bytes to skip - totalSkip := dataSkip + tr.pad // Total number of bytes to skip - tr.curr, tr.pad = nil, 0 - - // If possible, Seek to the last byte before the end of the data section. - // Do this because Seek is often lazy about reporting errors; this will mask - // the fact that the tar stream may be truncated. We can rely on the - // io.CopyN done shortly afterwards to trigger any IO errors. - var seekSkipped int64 // Number of bytes skipped via Seek - if sr, ok := tr.r.(io.Seeker); ok && dataSkip > 1 { - // Not all io.Seeker can actually Seek. For example, os.Stdin implements - // io.Seeker, but calling Seek always returns an error and performs - // no action. Thus, we try an innocent seek to the current position - // to see if Seek is really supported. - pos1, err := sr.Seek(0, os.SEEK_CUR) - if err == nil { - // Seek seems supported, so perform the real Seek. - pos2, err := sr.Seek(dataSkip-1, os.SEEK_CUR) - if err != nil { - tr.err = err - return tr.err - } - seekSkipped = pos2 - pos1 - } - } - - var copySkipped int64 // Number of bytes skipped via CopyN - copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped) - if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip { - tr.err = io.ErrUnexpectedEOF - } - return tr.err -} - -func (tr *Reader) verifyChecksum(header []byte) bool { - if tr.err != nil { - return false - } - - var p parser - given := p.parseOctal(header[148:156]) - unsigned, signed := checksum(header) - return p.err == nil && (given == unsigned || given == signed) -} - -// readHeader reads the next block header and assumes that the underlying reader -// is already aligned to a block boundary. -// -// The err will be set to io.EOF only when one of the following occurs: -// * Exactly 0 bytes are read and EOF is hit. -// * Exactly 1 block of zeros is read and EOF is hit. -// * At least 2 blocks of zeros are read. -func (tr *Reader) readHeader() *Header { - header := tr.hdrBuff[:] - copy(header, zeroBlock) - - if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil { - return nil // io.EOF is okay here - } - - // Two blocks of zero bytes marks the end of the archive. - if bytes.Equal(header, zeroBlock[0:blockSize]) { - if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil { - return nil // io.EOF is okay here - } - if bytes.Equal(header, zeroBlock[0:blockSize]) { - tr.err = io.EOF - } else { - tr.err = ErrHeader // zero block and then non-zero block - } - return nil - } - - if !tr.verifyChecksum(header) { - tr.err = ErrHeader - return nil - } - - // Unpack - var p parser - hdr := new(Header) - s := slicer(header) - - hdr.Name = p.parseString(s.next(100)) - hdr.Mode = p.parseNumeric(s.next(8)) - hdr.Uid = int(p.parseNumeric(s.next(8))) - hdr.Gid = int(p.parseNumeric(s.next(8))) - hdr.Size = p.parseNumeric(s.next(12)) - hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0) - s.next(8) // chksum - hdr.Typeflag = s.next(1)[0] - hdr.Linkname = p.parseString(s.next(100)) - - // The remainder of the header depends on the value of magic. - // The original (v7) version of tar had no explicit magic field, - // so its magic bytes, like the rest of the block, are NULs. - magic := string(s.next(8)) // contains version field as well. - var format string - switch { - case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988) - if string(header[508:512]) == "tar\x00" { - format = "star" - } else { - format = "posix" - } - case magic == "ustar \x00": // old GNU tar - format = "gnu" - } - - switch format { - case "posix", "gnu", "star": - hdr.Uname = p.parseString(s.next(32)) - hdr.Gname = p.parseString(s.next(32)) - devmajor := s.next(8) - devminor := s.next(8) - if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock { - hdr.Devmajor = p.parseNumeric(devmajor) - hdr.Devminor = p.parseNumeric(devminor) - } - var prefix string - switch format { - case "posix", "gnu": - prefix = p.parseString(s.next(155)) - case "star": - prefix = p.parseString(s.next(131)) - hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0) - hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0) - } - if len(prefix) > 0 { - hdr.Name = prefix + "/" + hdr.Name - } - } - - if p.err != nil { - tr.err = p.err - return nil - } - - nb := hdr.Size - if isHeaderOnlyType(hdr.Typeflag) { - nb = 0 - } - if nb < 0 { - tr.err = ErrHeader - return nil - } - - // Set the current file reader. - tr.pad = -nb & (blockSize - 1) // blockSize is a power of two - tr.curr = ®FileReader{r: tr.r, nb: nb} - - // Check for old GNU sparse format entry. - if hdr.Typeflag == TypeGNUSparse { - // Get the real size of the file. - hdr.Size = p.parseNumeric(header[483:495]) - if p.err != nil { - tr.err = p.err - return nil - } - - // Read the sparse map. - sp := tr.readOldGNUSparseMap(header) - if tr.err != nil { - return nil - } - - // Current file is a GNU sparse file. Update the current file reader. - tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size) - if tr.err != nil { - return nil - } - } - - return hdr -} - -// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format. -// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries, -// then one or more extension headers are used to store the rest of the sparse map. -func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry { - var p parser - isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0 - spCap := oldGNUSparseMainHeaderNumEntries - if isExtended { - spCap += oldGNUSparseExtendedHeaderNumEntries - } - sp := make([]sparseEntry, 0, spCap) - s := slicer(header[oldGNUSparseMainHeaderOffset:]) - - // Read the four entries from the main tar header - for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ { - offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize)) - numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize)) - if p.err != nil { - tr.err = p.err - return nil - } - if offset == 0 && numBytes == 0 { - break - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - - for isExtended { - // There are more entries. Read an extension header and parse its entries. - sparseHeader := make([]byte, blockSize) - if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil { - return nil - } - isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0 - s = slicer(sparseHeader) - for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ { - offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize)) - numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize)) - if p.err != nil { - tr.err = p.err - return nil - } - if offset == 0 && numBytes == 0 { - break - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - } - return sp -} - -// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format -// version 1.0. The format of the sparse map consists of a series of -// newline-terminated numeric fields. The first field is the number of entries -// and is always present. Following this are the entries, consisting of two -// fields (offset, numBytes). This function must stop reading at the end -// boundary of the block containing the last newline. -// -// Note that the GNU manual says that numeric values should be encoded in octal -// format. However, the GNU tar utility itself outputs these values in decimal. -// As such, this library treats values as being encoded in decimal. -func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) { - var cntNewline int64 - var buf bytes.Buffer - var blk = make([]byte, blockSize) - - // feedTokens copies data in numBlock chunks from r into buf until there are - // at least cnt newlines in buf. It will not read more blocks than needed. - var feedTokens = func(cnt int64) error { - for cntNewline < cnt { - if _, err := io.ReadFull(r, blk); err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return err - } - buf.Write(blk) - for _, c := range blk { - if c == '\n' { - cntNewline++ - } - } - } - return nil - } - - // nextToken gets the next token delimited by a newline. This assumes that - // at least one newline exists in the buffer. - var nextToken = func() string { - cntNewline-- - tok, _ := buf.ReadString('\n') - return tok[:len(tok)-1] // Cut off newline - } - - // Parse for the number of entries. - // Use integer overflow resistant math to check this. - if err := feedTokens(1); err != nil { - return nil, err - } - numEntries, err := strconv.ParseInt(nextToken(), 10, 0) // Intentionally parse as native int - if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) { - return nil, ErrHeader - } - - // Parse for all member entries. - // numEntries is trusted after this since a potential attacker must have - // committed resources proportional to what this library used. - if err := feedTokens(2 * numEntries); err != nil { - return nil, err - } - sp := make([]sparseEntry, 0, numEntries) - for i := int64(0); i < numEntries; i++ { - offset, err := strconv.ParseInt(nextToken(), 10, 64) - if err != nil { - return nil, ErrHeader - } - numBytes, err := strconv.ParseInt(nextToken(), 10, 64) - if err != nil { - return nil, ErrHeader - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - return sp, nil -} - -// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format -// version 0.1. The sparse map is stored in the PAX headers. -func readGNUSparseMap0x1(extHdrs map[string]string) ([]sparseEntry, error) { - // Get number of entries. - // Use integer overflow resistant math to check this. - numEntriesStr := extHdrs[paxGNUSparseNumBlocks] - numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0) // Intentionally parse as native int - if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) { - return nil, ErrHeader - } - - // There should be two numbers in sparseMap for each entry. - sparseMap := strings.Split(extHdrs[paxGNUSparseMap], ",") - if int64(len(sparseMap)) != 2*numEntries { - return nil, ErrHeader - } - - // Loop through the entries in the sparse map. - // numEntries is trusted now. - sp := make([]sparseEntry, 0, numEntries) - for i := int64(0); i < numEntries; i++ { - offset, err := strconv.ParseInt(sparseMap[2*i], 10, 64) - if err != nil { - return nil, ErrHeader - } - numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 64) - if err != nil { - return nil, ErrHeader - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - return sp, nil -} - -// numBytes returns the number of bytes left to read in the current file's entry -// in the tar archive, or 0 if there is no current file. -func (tr *Reader) numBytes() int64 { - if tr.curr == nil { - // No current file, so no bytes - return 0 - } - return tr.curr.numBytes() -} - -// Read reads from the current entry in the tar archive. -// It returns 0, io.EOF when it reaches the end of that entry, -// until Next is called to advance to the next entry. -// -// Calling Read on special types like TypeLink, TypeSymLink, TypeChar, -// TypeBlock, TypeDir, and TypeFifo returns 0, io.EOF regardless of what -// the Header.Size claims. -func (tr *Reader) Read(b []byte) (n int, err error) { - if tr.err != nil { - return 0, tr.err - } - if tr.curr == nil { - return 0, io.EOF - } - - n, err = tr.curr.Read(b) - if err != nil && err != io.EOF { - tr.err = err - } - return -} - -func (rfr *regFileReader) Read(b []byte) (n int, err error) { - if rfr.nb == 0 { - // file consumed - return 0, io.EOF - } - if int64(len(b)) > rfr.nb { - b = b[0:rfr.nb] - } - n, err = rfr.r.Read(b) - rfr.nb -= int64(n) - - if err == io.EOF && rfr.nb > 0 { - err = io.ErrUnexpectedEOF - } - return -} - -// numBytes returns the number of bytes left to read in the file's data in the tar archive. -func (rfr *regFileReader) numBytes() int64 { - return rfr.nb -} - -// newSparseFileReader creates a new sparseFileReader, but validates all of the -// sparse entries before doing so. -func newSparseFileReader(rfr numBytesReader, sp []sparseEntry, total int64) (*sparseFileReader, error) { - if total < 0 { - return nil, ErrHeader // Total size cannot be negative - } - - // Validate all sparse entries. These are the same checks as performed by - // the BSD tar utility. - for i, s := range sp { - switch { - case s.offset < 0 || s.numBytes < 0: - return nil, ErrHeader // Negative values are never okay - case s.offset > math.MaxInt64-s.numBytes: - return nil, ErrHeader // Integer overflow with large length - case s.offset+s.numBytes > total: - return nil, ErrHeader // Region extends beyond the "real" size - case i > 0 && sp[i-1].offset+sp[i-1].numBytes > s.offset: - return nil, ErrHeader // Regions can't overlap and must be in order - } - } - return &sparseFileReader{rfr: rfr, sp: sp, total: total}, nil -} - -// readHole reads a sparse hole ending at endOffset. -func (sfr *sparseFileReader) readHole(b []byte, endOffset int64) int { - n64 := endOffset - sfr.pos - if n64 > int64(len(b)) { - n64 = int64(len(b)) - } - n := int(n64) - for i := 0; i < n; i++ { - b[i] = 0 - } - sfr.pos += n64 - return n -} - -// Read reads the sparse file data in expanded form. -func (sfr *sparseFileReader) Read(b []byte) (n int, err error) { - // Skip past all empty fragments. - for len(sfr.sp) > 0 && sfr.sp[0].numBytes == 0 { - sfr.sp = sfr.sp[1:] - } - - // If there are no more fragments, then it is possible that there - // is one last sparse hole. - if len(sfr.sp) == 0 { - // This behavior matches the BSD tar utility. - // However, GNU tar stops returning data even if sfr.total is unmet. - if sfr.pos < sfr.total { - return sfr.readHole(b, sfr.total), nil - } - return 0, io.EOF - } - - // In front of a data fragment, so read a hole. - if sfr.pos < sfr.sp[0].offset { - return sfr.readHole(b, sfr.sp[0].offset), nil - } - - // In a data fragment, so read from it. - // This math is overflow free since we verify that offset and numBytes can - // be safely added when creating the sparseFileReader. - endPos := sfr.sp[0].offset + sfr.sp[0].numBytes // End offset of fragment - bytesLeft := endPos - sfr.pos // Bytes left in fragment - if int64(len(b)) > bytesLeft { - b = b[:bytesLeft] - } - - n, err = sfr.rfr.Read(b) - sfr.pos += int64(n) - if err == io.EOF { - if sfr.pos < endPos { - err = io.ErrUnexpectedEOF // There was supposed to be more data - } else if sfr.pos < sfr.total { - err = nil // There is still an implicit sparse hole at the end - } - } - - if sfr.pos == endPos { - sfr.sp = sfr.sp[1:] // We are done with this fragment, so pop it - } - return n, err -} - -// numBytes returns the number of bytes left to read in the sparse file's -// sparse-encoded data in the tar archive. -func (sfr *sparseFileReader) numBytes() int64 { - return sfr.rfr.numBytes() -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atim.go b/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atim.go deleted file mode 100644 index cf9cc79c59..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atim.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux dragonfly openbsd solaris - -package tar - -import ( - "syscall" - "time" -) - -func statAtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Atim.Unix()) -} - -func statCtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Ctim.Unix()) -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atimespec.go b/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atimespec.go deleted file mode 100644 index 6f17dbe307..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_atimespec.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin freebsd netbsd - -package tar - -import ( - "syscall" - "time" -) - -func statAtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Atimespec.Unix()) -} - -func statCtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Ctimespec.Unix()) -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_unix.go b/vendor/github.com/Microsoft/go-winio/archive/tar/stat_unix.go deleted file mode 100644 index cb843db4cf..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/stat_unix.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux darwin dragonfly freebsd openbsd netbsd solaris - -package tar - -import ( - "os" - "syscall" -) - -func init() { - sysStat = statUnix -} - -func statUnix(fi os.FileInfo, h *Header) error { - sys, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return nil - } - h.Uid = int(sys.Uid) - h.Gid = int(sys.Gid) - // TODO(bradfitz): populate username & group. os/user - // doesn't cache LookupId lookups, and lacks group - // lookup functions. - h.AccessTime = statAtime(sys) - h.ChangeTime = statCtime(sys) - // TODO(bradfitz): major/minor device numbers? - return nil -} diff --git a/vendor/github.com/Microsoft/go-winio/archive/tar/writer.go b/vendor/github.com/Microsoft/go-winio/archive/tar/writer.go deleted file mode 100644 index 30d7e606d6..0000000000 --- a/vendor/github.com/Microsoft/go-winio/archive/tar/writer.go +++ /dev/null @@ -1,444 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tar - -// TODO(dsymonds): -// - catch more errors (no first header, etc.) - -import ( - "bytes" - "errors" - "fmt" - "io" - "path" - "sort" - "strconv" - "strings" - "time" -) - -var ( - ErrWriteTooLong = errors.New("archive/tar: write too long") - ErrFieldTooLong = errors.New("archive/tar: header field too long") - ErrWriteAfterClose = errors.New("archive/tar: write after close") - errInvalidHeader = errors.New("archive/tar: header field too long or contains invalid values") -) - -// A Writer provides sequential writing of a tar archive in POSIX.1 format. -// A tar archive consists of a sequence of files. -// Call WriteHeader to begin a new file, and then call Write to supply that file's data, -// writing at most hdr.Size bytes in total. -type Writer struct { - w io.Writer - err error - nb int64 // number of unwritten bytes for current file entry - pad int64 // amount of padding to write after current file entry - closed bool - usedBinary bool // whether the binary numeric field extension was used - preferPax bool // use pax header instead of binary numeric header - hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header - paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header -} - -type formatter struct { - err error // Last error seen -} - -// NewWriter creates a new Writer writing to w. -func NewWriter(w io.Writer) *Writer { return &Writer{w: w, preferPax: true} } - -// Flush finishes writing the current file (optional). -func (tw *Writer) Flush() error { - if tw.nb > 0 { - tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb) - return tw.err - } - - n := tw.nb + tw.pad - for n > 0 && tw.err == nil { - nr := n - if nr > blockSize { - nr = blockSize - } - var nw int - nw, tw.err = tw.w.Write(zeroBlock[0:nr]) - n -= int64(nw) - } - tw.nb = 0 - tw.pad = 0 - return tw.err -} - -// Write s into b, terminating it with a NUL if there is room. -func (f *formatter) formatString(b []byte, s string) { - if len(s) > len(b) { - f.err = ErrFieldTooLong - return - } - ascii := toASCII(s) - copy(b, ascii) - if len(ascii) < len(b) { - b[len(ascii)] = 0 - } -} - -// Encode x as an octal ASCII string and write it into b with leading zeros. -func (f *formatter) formatOctal(b []byte, x int64) { - s := strconv.FormatInt(x, 8) - // leading zeros, but leave room for a NUL. - for len(s)+1 < len(b) { - s = "0" + s - } - f.formatString(b, s) -} - -// fitsInBase256 reports whether x can be encoded into n bytes using base-256 -// encoding. Unlike octal encoding, base-256 encoding does not require that the -// string ends with a NUL character. Thus, all n bytes are available for output. -// -// If operating in binary mode, this assumes strict GNU binary mode; which means -// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is -// equivalent to the sign bit in two's complement form. -func fitsInBase256(n int, x int64) bool { - var binBits = uint(n-1) * 8 - return n >= 9 || (x >= -1<= 0; i-- { - b[i] = byte(x) - x >>= 8 - } - b[0] |= 0x80 // Highest bit indicates binary format - return - } - - f.formatOctal(b, 0) // Last resort, just write zero - f.err = ErrFieldTooLong -} - -var ( - minTime = time.Unix(0, 0) - // There is room for 11 octal digits (33 bits) of mtime. - maxTime = minTime.Add((1<<33 - 1) * time.Second) -) - -// WriteHeader writes hdr and prepares to accept the file's contents. -// WriteHeader calls Flush if it is not the first header. -// Calling after a Close will return ErrWriteAfterClose. -func (tw *Writer) WriteHeader(hdr *Header) error { - return tw.writeHeader(hdr, true) -} - -// WriteHeader writes hdr and prepares to accept the file's contents. -// WriteHeader calls Flush if it is not the first header. -// Calling after a Close will return ErrWriteAfterClose. -// As this method is called internally by writePax header to allow it to -// suppress writing the pax header. -func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { - if tw.closed { - return ErrWriteAfterClose - } - if tw.err == nil { - tw.Flush() - } - if tw.err != nil { - return tw.err - } - - // a map to hold pax header records, if any are needed - paxHeaders := make(map[string]string) - - // TODO(shanemhansen): we might want to use PAX headers for - // subsecond time resolution, but for now let's just capture - // too long fields or non ascii characters - - var f formatter - var header []byte - - // We need to select which scratch buffer to use carefully, - // since this method is called recursively to write PAX headers. - // If allowPax is true, this is the non-recursive call, and we will use hdrBuff. - // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is - // already being used by the non-recursive call, so we must use paxHdrBuff. - header = tw.hdrBuff[:] - if !allowPax { - header = tw.paxHdrBuff[:] - } - copy(header, zeroBlock) - s := slicer(header) - - // Wrappers around formatter that automatically sets paxHeaders if the - // argument extends beyond the capacity of the input byte slice. - var formatString = func(b []byte, s string, paxKeyword string) { - needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s) - if needsPaxHeader { - paxHeaders[paxKeyword] = s - return - } - f.formatString(b, s) - } - var formatNumeric = func(b []byte, x int64, paxKeyword string) { - // Try octal first. - s := strconv.FormatInt(x, 8) - if len(s) < len(b) { - f.formatOctal(b, x) - return - } - - // If it is too long for octal, and PAX is preferred, use a PAX header. - if paxKeyword != paxNone && tw.preferPax { - f.formatOctal(b, 0) - s := strconv.FormatInt(x, 10) - paxHeaders[paxKeyword] = s - return - } - - tw.usedBinary = true - f.formatNumeric(b, x) - } - var formatTime = func(b []byte, t time.Time, paxKeyword string) { - var unixTime int64 - if !t.Before(minTime) && !t.After(maxTime) { - unixTime = t.Unix() - } - formatNumeric(b, unixTime, paxNone) - - // Write a PAX header if the time didn't fit precisely. - if paxKeyword != "" && tw.preferPax && allowPax && (t.Nanosecond() != 0 || !t.Before(minTime) || !t.After(maxTime)) { - paxHeaders[paxKeyword] = formatPAXTime(t) - } - } - - // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax - pathHeaderBytes := s.next(fileNameSize) - - formatString(pathHeaderBytes, hdr.Name, paxPath) - - f.formatOctal(s.next(8), hdr.Mode) // 100:108 - formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116 - formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124 - formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136 - formatTime(s.next(12), hdr.ModTime, paxMtime) // 136:148 - s.next(8) // chksum (148:156) - s.next(1)[0] = hdr.Typeflag // 156:157 - - formatString(s.next(100), hdr.Linkname, paxLinkpath) - - copy(s.next(8), []byte("ustar\x0000")) // 257:265 - formatString(s.next(32), hdr.Uname, paxUname) // 265:297 - formatString(s.next(32), hdr.Gname, paxGname) // 297:329 - formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337 - formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345 - - // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax - prefixHeaderBytes := s.next(155) - formatString(prefixHeaderBytes, "", paxNone) // 345:500 prefix - - // Use the GNU magic instead of POSIX magic if we used any GNU extensions. - if tw.usedBinary { - copy(header[257:265], []byte("ustar \x00")) - } - - _, paxPathUsed := paxHeaders[paxPath] - // try to use a ustar header when only the name is too long - if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed { - prefix, suffix, ok := splitUSTARPath(hdr.Name) - if ok { - // Since we can encode in USTAR format, disable PAX header. - delete(paxHeaders, paxPath) - - // Update the path fields - formatString(pathHeaderBytes, suffix, paxNone) - formatString(prefixHeaderBytes, prefix, paxNone) - } - } - - // The chksum field is terminated by a NUL and a space. - // This is different from the other octal fields. - chksum, _ := checksum(header) - f.formatOctal(header[148:155], chksum) // Never fails - header[155] = ' ' - - // Check if there were any formatting errors. - if f.err != nil { - tw.err = f.err - return tw.err - } - - if allowPax { - if !hdr.AccessTime.IsZero() { - paxHeaders[paxAtime] = formatPAXTime(hdr.AccessTime) - } - if !hdr.ChangeTime.IsZero() { - paxHeaders[paxCtime] = formatPAXTime(hdr.ChangeTime) - } - if !hdr.CreationTime.IsZero() { - paxHeaders[paxCreationTime] = formatPAXTime(hdr.CreationTime) - } - for k, v := range hdr.Xattrs { - paxHeaders[paxXattr+k] = v - } - for k, v := range hdr.Winheaders { - paxHeaders[paxWindows+k] = v - } - } - - if len(paxHeaders) > 0 { - if !allowPax { - return errInvalidHeader - } - if err := tw.writePAXHeader(hdr, paxHeaders); err != nil { - return err - } - } - tw.nb = int64(hdr.Size) - tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize - - _, tw.err = tw.w.Write(header) - return tw.err -} - -func formatPAXTime(t time.Time) string { - sec := t.Unix() - usec := t.Nanosecond() - s := strconv.FormatInt(sec, 10) - if usec != 0 { - s = fmt.Sprintf("%s.%09d", s, usec) - } - return s -} - -// splitUSTARPath splits a path according to USTAR prefix and suffix rules. -// If the path is not splittable, then it will return ("", "", false). -func splitUSTARPath(name string) (prefix, suffix string, ok bool) { - length := len(name) - if length <= fileNameSize || !isASCII(name) { - return "", "", false - } else if length > fileNamePrefixSize+1 { - length = fileNamePrefixSize + 1 - } else if name[length-1] == '/' { - length-- - } - - i := strings.LastIndex(name[:length], "/") - nlen := len(name) - i - 1 // nlen is length of suffix - plen := i // plen is length of prefix - if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize { - return "", "", false - } - return name[:i], name[i+1:], true -} - -// writePaxHeader writes an extended pax header to the -// archive. -func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error { - // Prepare extended header - ext := new(Header) - ext.Typeflag = TypeXHeader - // Setting ModTime is required for reader parsing to - // succeed, and seems harmless enough. - ext.ModTime = hdr.ModTime - // The spec asks that we namespace our pseudo files - // with the current pid. However, this results in differing outputs - // for identical inputs. As such, the constant 0 is now used instead. - // golang.org/issue/12358 - dir, file := path.Split(hdr.Name) - fullName := path.Join(dir, "PaxHeaders.0", file) - - ascii := toASCII(fullName) - if len(ascii) > 100 { - ascii = ascii[:100] - } - ext.Name = ascii - // Construct the body - var buf bytes.Buffer - - // Keys are sorted before writing to body to allow deterministic output. - var keys []string - for k := range paxHeaders { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - fmt.Fprint(&buf, formatPAXRecord(k, paxHeaders[k])) - } - - ext.Size = int64(len(buf.Bytes())) - if err := tw.writeHeader(ext, false); err != nil { - return err - } - if _, err := tw.Write(buf.Bytes()); err != nil { - return err - } - if err := tw.Flush(); err != nil { - return err - } - return nil -} - -// formatPAXRecord formats a single PAX record, prefixing it with the -// appropriate length. -func formatPAXRecord(k, v string) string { - const padding = 3 // Extra padding for ' ', '=', and '\n' - size := len(k) + len(v) + padding - size += len(strconv.Itoa(size)) - record := fmt.Sprintf("%d %s=%s\n", size, k, v) - - // Final adjustment if adding size field increased the record size. - if len(record) != size { - size = len(record) - record = fmt.Sprintf("%d %s=%s\n", size, k, v) - } - return record -} - -// Write writes to the current entry in the tar archive. -// Write returns the error ErrWriteTooLong if more than -// hdr.Size bytes are written after WriteHeader. -func (tw *Writer) Write(b []byte) (n int, err error) { - if tw.closed { - err = ErrWriteAfterClose - return - } - overwrite := false - if int64(len(b)) > tw.nb { - b = b[0:tw.nb] - overwrite = true - } - n, err = tw.w.Write(b) - tw.nb -= int64(n) - if err == nil && overwrite { - err = ErrWriteTooLong - return - } - tw.err = err - return -} - -// Close closes the tar archive, flushing any unwritten -// data to the underlying writer. -func (tw *Writer) Close() error { - if tw.err != nil || tw.closed { - return tw.err - } - tw.Flush() - tw.closed = true - if tw.err != nil { - return tw.err - } - - // trailer: two zero blocks - for i := 0; i < 2; i++ { - _, tw.err = tw.w.Write(zeroBlock) - if tw.err != nil { - break - } - } - return tw.err -} diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/noop.go b/vendor/github.com/Microsoft/go-winio/backuptar/noop.go deleted file mode 100644 index d39eccf023..0000000000 --- a/vendor/github.com/Microsoft/go-winio/backuptar/noop.go +++ /dev/null @@ -1,4 +0,0 @@ -// +build !windows -// This file only exists to allow go get on non-Windows platforms. - -package backuptar diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/tar.go b/vendor/github.com/Microsoft/go-winio/backuptar/tar.go deleted file mode 100644 index 53da908f14..0000000000 --- a/vendor/github.com/Microsoft/go-winio/backuptar/tar.go +++ /dev/null @@ -1,439 +0,0 @@ -// +build windows - -package backuptar - -import ( - "encoding/base64" - "errors" - "fmt" - "io" - "io/ioutil" - "path/filepath" - "strconv" - "strings" - "syscall" - "time" - - "github.com/Microsoft/go-winio" - "github.com/Microsoft/go-winio/archive/tar" // until archive/tar supports pax extensions in its interface -) - -const ( - c_ISUID = 04000 // Set uid - c_ISGID = 02000 // Set gid - c_ISVTX = 01000 // Save text (sticky bit) - c_ISDIR = 040000 // Directory - c_ISFIFO = 010000 // FIFO - c_ISREG = 0100000 // Regular file - c_ISLNK = 0120000 // Symbolic link - c_ISBLK = 060000 // Block special file - c_ISCHR = 020000 // Character special file - c_ISSOCK = 0140000 // Socket -) - -const ( - hdrFileAttributes = "fileattr" - hdrSecurityDescriptor = "sd" - hdrRawSecurityDescriptor = "rawsd" - hdrMountPoint = "mountpoint" - hdrEaPrefix = "xattr." -) - -func writeZeroes(w io.Writer, count int64) error { - buf := make([]byte, 8192) - c := len(buf) - for i := int64(0); i < count; i += int64(c) { - if int64(c) > count-i { - c = int(count - i) - } - _, err := w.Write(buf[:c]) - if err != nil { - return err - } - } - return nil -} - -func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error { - curOffset := int64(0) - for { - bhdr, err := br.Next() - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - if err != nil { - return err - } - if bhdr.Id != winio.BackupSparseBlock { - return fmt.Errorf("unexpected stream %d", bhdr.Id) - } - - // archive/tar does not support writing sparse files - // so just write zeroes to catch up to the current offset. - err = writeZeroes(t, bhdr.Offset-curOffset) - if bhdr.Size == 0 { - break - } - n, err := io.Copy(t, br) - if err != nil { - return err - } - curOffset = bhdr.Offset + n - } - return nil -} - -// BasicInfoHeader creates a tar header from basic file information. -func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *tar.Header { - hdr := &tar.Header{ - Name: filepath.ToSlash(name), - Size: size, - Typeflag: tar.TypeReg, - ModTime: time.Unix(0, fileInfo.LastWriteTime.Nanoseconds()), - ChangeTime: time.Unix(0, fileInfo.ChangeTime.Nanoseconds()), - AccessTime: time.Unix(0, fileInfo.LastAccessTime.Nanoseconds()), - CreationTime: time.Unix(0, fileInfo.CreationTime.Nanoseconds()), - Winheaders: make(map[string]string), - } - hdr.Winheaders[hdrFileAttributes] = fmt.Sprintf("%d", fileInfo.FileAttributes) - - if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - hdr.Mode |= c_ISDIR - hdr.Size = 0 - hdr.Typeflag = tar.TypeDir - } - return hdr -} - -// WriteTarFileFromBackupStream writes a file to a tar writer using data from a Win32 backup stream. -// -// This encodes Win32 metadata as tar pax vendor extensions starting with MSWINDOWS. -// -// The additional Win32 metadata is: -// -// MSWINDOWS.fileattr: The Win32 file attributes, as a decimal value -// -// MSWINDOWS.rawsd: The Win32 security descriptor, in raw binary format -// -// MSWINDOWS.mountpoint: If present, this is a mount point and not a symlink, even though the type is '2' (symlink) -func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error { - name = filepath.ToSlash(name) - hdr := BasicInfoHeader(name, size, fileInfo) - - // If r can be seeked, then this function is two-pass: pass 1 collects the - // tar header data, and pass 2 copies the data stream. If r cannot be - // seeked, then some header data (in particular EAs) will be silently lost. - var ( - restartPos int64 - err error - ) - sr, readTwice := r.(io.Seeker) - if readTwice { - if restartPos, err = sr.Seek(0, io.SeekCurrent); err != nil { - readTwice = false - } - } - - br := winio.NewBackupStreamReader(r) - var dataHdr *winio.BackupHeader - for dataHdr == nil { - bhdr, err := br.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - switch bhdr.Id { - case winio.BackupData: - hdr.Mode |= c_ISREG - if !readTwice { - dataHdr = bhdr - } - case winio.BackupSecurity: - sd, err := ioutil.ReadAll(br) - if err != nil { - return err - } - hdr.Winheaders[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd) - - case winio.BackupReparseData: - hdr.Mode |= c_ISLNK - hdr.Typeflag = tar.TypeSymlink - reparseBuffer, err := ioutil.ReadAll(br) - rp, err := winio.DecodeReparsePoint(reparseBuffer) - if err != nil { - return err - } - if rp.IsMountPoint { - hdr.Winheaders[hdrMountPoint] = "1" - } - hdr.Linkname = rp.Target - - case winio.BackupEaData: - eab, err := ioutil.ReadAll(br) - if err != nil { - return err - } - eas, err := winio.DecodeExtendedAttributes(eab) - if err != nil { - return err - } - for _, ea := range eas { - // Use base64 encoding for the binary value. Note that there - // is no way to encode the EA's flags, since their use doesn't - // make any sense for persisted EAs. - hdr.Winheaders[hdrEaPrefix+ea.Name] = base64.StdEncoding.EncodeToString(ea.Value) - } - - case winio.BackupAlternateData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData: - // ignore these streams - default: - return fmt.Errorf("%s: unknown stream ID %d", name, bhdr.Id) - } - } - - err = t.WriteHeader(hdr) - if err != nil { - return err - } - - if readTwice { - // Get back to the data stream. - if _, err = sr.Seek(restartPos, io.SeekStart); err != nil { - return err - } - for dataHdr == nil { - bhdr, err := br.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - if bhdr.Id == winio.BackupData { - dataHdr = bhdr - } - } - } - - if dataHdr != nil { - // A data stream was found. Copy the data. - if (dataHdr.Attributes & winio.StreamSparseAttributes) == 0 { - if size != dataHdr.Size { - return fmt.Errorf("%s: mismatch between file size %d and header size %d", name, size, dataHdr.Size) - } - _, err = io.Copy(t, br) - if err != nil { - return err - } - } else { - err = copySparse(t, br) - if err != nil { - return err - } - } - } - - // Look for streams after the data stream. The only ones we handle are alternate data streams. - // Other streams may have metadata that could be serialized, but the tar header has already - // been written. In practice, this means that we don't get EA or TXF metadata. - for { - bhdr, err := br.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - switch bhdr.Id { - case winio.BackupAlternateData: - altName := bhdr.Name - if strings.HasSuffix(altName, ":$DATA") { - altName = altName[:len(altName)-len(":$DATA")] - } - if (bhdr.Attributes & winio.StreamSparseAttributes) == 0 { - hdr = &tar.Header{ - Name: name + altName, - Mode: hdr.Mode, - Typeflag: tar.TypeReg, - Size: bhdr.Size, - ModTime: hdr.ModTime, - AccessTime: hdr.AccessTime, - ChangeTime: hdr.ChangeTime, - } - err = t.WriteHeader(hdr) - if err != nil { - return err - } - _, err = io.Copy(t, br) - if err != nil { - return err - } - - } else { - // Unsupported for now, since the size of the alternate stream is not present - // in the backup stream until after the data has been read. - return errors.New("tar of sparse alternate data streams is unsupported") - } - case winio.BackupEaData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData: - // ignore these streams - default: - return fmt.Errorf("%s: unknown stream ID %d after data", name, bhdr.Id) - } - } - return nil -} - -// FileInfoFromHeader retrieves basic Win32 file information from a tar header, using the additional metadata written by -// WriteTarFileFromBackupStream. -func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *winio.FileBasicInfo, err error) { - name = hdr.Name - if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { - size = hdr.Size - } - fileInfo = &winio.FileBasicInfo{ - LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()), - LastWriteTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()), - ChangeTime: syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()), - CreationTime: syscall.NsecToFiletime(hdr.CreationTime.UnixNano()), - } - if attrStr, ok := hdr.Winheaders[hdrFileAttributes]; ok { - attr, err := strconv.ParseUint(attrStr, 10, 32) - if err != nil { - return "", 0, nil, err - } - fileInfo.FileAttributes = uintptr(attr) - } else { - if hdr.Typeflag == tar.TypeDir { - fileInfo.FileAttributes |= syscall.FILE_ATTRIBUTE_DIRECTORY - } - } - return -} - -// WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple -// tar file entries in order to collect all the alternate data streams for the file, it returns the next -// tar file that was not processed, or io.EOF is there are no more. -func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) { - bw := winio.NewBackupStreamWriter(w) - var sd []byte - var err error - // Maintaining old SDDL-based behavior for backward compatibility. All new tar headers written - // by this library will have raw binary for the security descriptor. - if sddl, ok := hdr.Winheaders[hdrSecurityDescriptor]; ok { - sd, err = winio.SddlToSecurityDescriptor(sddl) - if err != nil { - return nil, err - } - } - if sdraw, ok := hdr.Winheaders[hdrRawSecurityDescriptor]; ok { - sd, err = base64.StdEncoding.DecodeString(sdraw) - if err != nil { - return nil, err - } - } - if len(sd) != 0 { - bhdr := winio.BackupHeader{ - Id: winio.BackupSecurity, - Size: int64(len(sd)), - } - err := bw.WriteHeader(&bhdr) - if err != nil { - return nil, err - } - _, err = bw.Write(sd) - if err != nil { - return nil, err - } - } - var eas []winio.ExtendedAttribute - for k, v := range hdr.Winheaders { - if !strings.HasPrefix(k, hdrEaPrefix) { - continue - } - data, err := base64.StdEncoding.DecodeString(v) - if err != nil { - return nil, err - } - eas = append(eas, winio.ExtendedAttribute{ - Name: k[len(hdrEaPrefix):], - Value: data, - }) - } - if len(eas) != 0 { - eadata, err := winio.EncodeExtendedAttributes(eas) - if err != nil { - return nil, err - } - bhdr := winio.BackupHeader{ - Id: winio.BackupEaData, - Size: int64(len(eadata)), - } - err = bw.WriteHeader(&bhdr) - if err != nil { - return nil, err - } - _, err = bw.Write(eadata) - if err != nil { - return nil, err - } - } - if hdr.Typeflag == tar.TypeSymlink { - _, isMountPoint := hdr.Winheaders[hdrMountPoint] - rp := winio.ReparsePoint{ - Target: filepath.FromSlash(hdr.Linkname), - IsMountPoint: isMountPoint, - } - reparse := winio.EncodeReparsePoint(&rp) - bhdr := winio.BackupHeader{ - Id: winio.BackupReparseData, - Size: int64(len(reparse)), - } - err := bw.WriteHeader(&bhdr) - if err != nil { - return nil, err - } - _, err = bw.Write(reparse) - if err != nil { - return nil, err - } - } - if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { - bhdr := winio.BackupHeader{ - Id: winio.BackupData, - Size: hdr.Size, - } - err := bw.WriteHeader(&bhdr) - if err != nil { - return nil, err - } - _, err = io.Copy(bw, t) - if err != nil { - return nil, err - } - } - // Copy all the alternate data streams and return the next non-ADS header. - for { - ahdr, err := t.Next() - if err != nil { - return nil, err - } - if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") { - return ahdr, nil - } - bhdr := winio.BackupHeader{ - Id: winio.BackupAlternateData, - Size: ahdr.Size, - Name: ahdr.Name[len(hdr.Name):] + ":$DATA", - } - err = bw.WriteHeader(&bhdr) - if err != nil { - return nil, err - } - _, err = io.Copy(bw, t) - if err != nil { - return nil, err - } - } -} diff --git a/vendor/github.com/Microsoft/hcsshim/LICENSE b/vendor/github.com/Microsoft/hcsshim/LICENSE deleted file mode 100644 index 49d21669ae..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/activatelayer.go b/vendor/github.com/Microsoft/hcsshim/activatelayer.go deleted file mode 100644 index 6d824d7a79..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/activatelayer.go +++ /dev/null @@ -1,28 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// ActivateLayer will find the layer with the given id and mount it's filesystem. -// For a read/write layer, the mounted filesystem will appear as a volume on the -// host, while a read-only layer is generally expected to be a no-op. -// An activated layer must later be deactivated via DeactivateLayer. -func ActivateLayer(info DriverInfo, id string) error { - title := "hcsshim::ActivateLayer " - logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = activateLayer(&infop, id) - if err != nil { - err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/baselayer.go b/vendor/github.com/Microsoft/hcsshim/baselayer.go deleted file mode 100644 index 9babd4e18a..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/baselayer.go +++ /dev/null @@ -1,183 +0,0 @@ -package hcsshim - -import ( - "errors" - "os" - "path/filepath" - "syscall" - - "github.com/Microsoft/go-winio" -) - -type baseLayerWriter struct { - root string - f *os.File - bw *winio.BackupFileWriter - err error - hasUtilityVM bool - dirInfo []dirInfo -} - -type dirInfo struct { - path string - fileInfo winio.FileBasicInfo -} - -// reapplyDirectoryTimes reapplies directory modification, creation, etc. times -// after processing of the directory tree has completed. The times are expected -// to be ordered such that parent directories come before child directories. -func reapplyDirectoryTimes(dis []dirInfo) error { - for i := range dis { - di := &dis[len(dis)-i-1] // reverse order: process child directories first - f, err := winio.OpenForBackup(di.path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING) - if err != nil { - return err - } - - err = winio.SetFileBasicInfo(f, &di.fileInfo) - f.Close() - if err != nil { - return err - } - } - return nil -} - -func (w *baseLayerWriter) closeCurrentFile() error { - if w.f != nil { - err := w.bw.Close() - err2 := w.f.Close() - w.f = nil - w.bw = nil - if err != nil { - return err - } - if err2 != nil { - return err2 - } - } - return nil -} - -func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) { - defer func() { - if err != nil { - w.err = err - } - }() - - err = w.closeCurrentFile() - if err != nil { - return err - } - - if filepath.ToSlash(name) == `UtilityVM/Files` { - w.hasUtilityVM = true - } - - path := filepath.Join(w.root, name) - path, err = makeLongAbsPath(path) - if err != nil { - return err - } - - var f *os.File - defer func() { - if f != nil { - f.Close() - } - }() - - createmode := uint32(syscall.CREATE_NEW) - if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - err := os.Mkdir(path, 0) - if err != nil && !os.IsExist(err) { - return err - } - createmode = syscall.OPEN_EXISTING - if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - w.dirInfo = append(w.dirInfo, dirInfo{path, *fileInfo}) - } - } - - mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY) - f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode) - if err != nil { - return makeError(err, "Failed to OpenForBackup", path) - } - - err = winio.SetFileBasicInfo(f, fileInfo) - if err != nil { - return makeError(err, "Failed to SetFileBasicInfo", path) - } - - w.f = f - w.bw = winio.NewBackupFileWriter(f, true) - f = nil - return nil -} - -func (w *baseLayerWriter) AddLink(name string, target string) (err error) { - defer func() { - if err != nil { - w.err = err - } - }() - - err = w.closeCurrentFile() - if err != nil { - return err - } - - linkpath, err := makeLongAbsPath(filepath.Join(w.root, name)) - if err != nil { - return err - } - - linktarget, err := makeLongAbsPath(filepath.Join(w.root, target)) - if err != nil { - return err - } - - return os.Link(linktarget, linkpath) -} - -func (w *baseLayerWriter) Remove(name string) error { - return errors.New("base layer cannot have tombstones") -} - -func (w *baseLayerWriter) Write(b []byte) (int, error) { - n, err := w.bw.Write(b) - if err != nil { - w.err = err - } - return n, err -} - -func (w *baseLayerWriter) Close() error { - err := w.closeCurrentFile() - if err != nil { - return err - } - if w.err == nil { - // Restore the file times of all the directories, since they may have - // been modified by creating child directories. - err = reapplyDirectoryTimes(w.dirInfo) - if err != nil { - return err - } - - err = ProcessBaseLayer(w.root) - if err != nil { - return err - } - - if w.hasUtilityVM { - err = ProcessUtilityVMImage(filepath.Join(w.root, "UtilityVM")) - if err != nil { - return err - } - } - } - return w.err -} diff --git a/vendor/github.com/Microsoft/hcsshim/callback.go b/vendor/github.com/Microsoft/hcsshim/callback.go deleted file mode 100644 index e8c2b00c8a..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/callback.go +++ /dev/null @@ -1,79 +0,0 @@ -package hcsshim - -import ( - "sync" - "syscall" -) - -var ( - nextCallback uintptr - callbackMap = map[uintptr]*notifcationWatcherContext{} - callbackMapLock = sync.RWMutex{} - - notificationWatcherCallback = syscall.NewCallback(notificationWatcher) - - // Notifications for HCS_SYSTEM handles - hcsNotificationSystemExited hcsNotification = 0x00000001 - hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002 - hcsNotificationSystemStartCompleted hcsNotification = 0x00000003 - hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004 - hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005 - - // Notifications for HCS_PROCESS handles - hcsNotificationProcessExited hcsNotification = 0x00010000 - - // Common notifications - hcsNotificationInvalid hcsNotification = 0x00000000 - hcsNotificationServiceDisconnect hcsNotification = 0x01000000 -) - -type hcsNotification uint32 -type notificationChannel chan error - -type notifcationWatcherContext struct { - channels notificationChannels - handle hcsCallback -} - -type notificationChannels map[hcsNotification]notificationChannel - -func newChannels() notificationChannels { - channels := make(notificationChannels) - - channels[hcsNotificationSystemExited] = make(notificationChannel, 1) - channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1) - channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1) - channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1) - channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1) - channels[hcsNotificationProcessExited] = make(notificationChannel, 1) - channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1) - return channels -} -func closeChannels(channels notificationChannels) { - close(channels[hcsNotificationSystemExited]) - close(channels[hcsNotificationSystemCreateCompleted]) - close(channels[hcsNotificationSystemStartCompleted]) - close(channels[hcsNotificationSystemPauseCompleted]) - close(channels[hcsNotificationSystemResumeCompleted]) - close(channels[hcsNotificationProcessExited]) - close(channels[hcsNotificationServiceDisconnect]) -} - -func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { - var result error - if int32(notificationStatus) < 0 { - result = syscall.Errno(win32FromHresult(notificationStatus)) - } - - callbackMapLock.RLock() - context := callbackMap[callbackNumber] - callbackMapLock.RUnlock() - - if context == nil { - return 0 - } - - context.channels[notificationType] <- result - - return 0 -} diff --git a/vendor/github.com/Microsoft/hcsshim/cgo.go b/vendor/github.com/Microsoft/hcsshim/cgo.go deleted file mode 100644 index 2003332330..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/cgo.go +++ /dev/null @@ -1,7 +0,0 @@ -package hcsshim - -import "C" - -// This import is needed to make the library compile as CGO because HCSSHIM -// only works with CGO due to callbacks from HCS comming back from a C thread -// which is not supported without CGO. See https://github.com/golang/go/issues/10973 diff --git a/vendor/github.com/Microsoft/hcsshim/container.go b/vendor/github.com/Microsoft/hcsshim/container.go deleted file mode 100644 index 3354f70efc..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/container.go +++ /dev/null @@ -1,800 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "fmt" - "os" - "sync" - "syscall" - "time" - - "github.com/sirupsen/logrus" -) - -var ( - defaultTimeout = time.Minute * 4 -) - -const ( - pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}` - statisticsQuery = `{ "PropertyTypes" : ["Statistics"]}` - processListQuery = `{ "PropertyTypes" : ["ProcessList"]}` - mappedVirtualDiskQuery = `{ "PropertyTypes" : ["MappedVirtualDisk"]}` -) - -type container struct { - handleLock sync.RWMutex - handle hcsSystem - id string - callbackNumber uintptr -} - -// ContainerProperties holds the properties for a container and the processes running in that container -type ContainerProperties struct { - ID string `json:"Id"` - Name string - SystemType string - Owner string - SiloGUID string `json:"SiloGuid,omitempty"` - RuntimeID string `json:"RuntimeId,omitempty"` - IsRuntimeTemplate bool `json:",omitempty"` - RuntimeImagePath string `json:",omitempty"` - Stopped bool `json:",omitempty"` - ExitType string `json:",omitempty"` - AreUpdatesPending bool `json:",omitempty"` - ObRoot string `json:",omitempty"` - Statistics Statistics `json:",omitempty"` - ProcessList []ProcessListItem `json:",omitempty"` - MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"` -} - -// MemoryStats holds the memory statistics for a container -type MemoryStats struct { - UsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"` - UsageCommitPeakBytes uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"` - UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` -} - -// ProcessorStats holds the processor statistics for a container -type ProcessorStats struct { - TotalRuntime100ns uint64 `json:",omitempty"` - RuntimeUser100ns uint64 `json:",omitempty"` - RuntimeKernel100ns uint64 `json:",omitempty"` -} - -// StorageStats holds the storage statistics for a container -type StorageStats struct { - ReadCountNormalized uint64 `json:",omitempty"` - ReadSizeBytes uint64 `json:",omitempty"` - WriteCountNormalized uint64 `json:",omitempty"` - WriteSizeBytes uint64 `json:",omitempty"` -} - -// NetworkStats holds the network statistics for a container -type NetworkStats struct { - BytesReceived uint64 `json:",omitempty"` - BytesSent uint64 `json:",omitempty"` - PacketsReceived uint64 `json:",omitempty"` - PacketsSent uint64 `json:",omitempty"` - DroppedPacketsIncoming uint64 `json:",omitempty"` - DroppedPacketsOutgoing uint64 `json:",omitempty"` - EndpointId string `json:",omitempty"` - InstanceId string `json:",omitempty"` -} - -// Statistics is the structure returned by a statistics call on a container -type Statistics struct { - Timestamp time.Time `json:",omitempty"` - ContainerStartTime time.Time `json:",omitempty"` - Uptime100ns uint64 `json:",omitempty"` - Memory MemoryStats `json:",omitempty"` - Processor ProcessorStats `json:",omitempty"` - Storage StorageStats `json:",omitempty"` - Network []NetworkStats `json:",omitempty"` -} - -// ProcessList is the structure of an item returned by a ProcessList call on a container -type ProcessListItem struct { - CreateTimestamp time.Time `json:",omitempty"` - ImageName string `json:",omitempty"` - KernelTime100ns uint64 `json:",omitempty"` - MemoryCommitBytes uint64 `json:",omitempty"` - MemoryWorkingSetPrivateBytes uint64 `json:",omitempty"` - MemoryWorkingSetSharedBytes uint64 `json:",omitempty"` - ProcessId uint32 `json:",omitempty"` - UserTime100ns uint64 `json:",omitempty"` -} - -// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container -type MappedVirtualDiskController struct { - MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"` -} - -// Type of Request Support in ModifySystem -type RequestType string - -// Type of Resource Support in ModifySystem -type ResourceType string - -// RequestType const -const ( - Add RequestType = "Add" - Remove RequestType = "Remove" - Network ResourceType = "Network" -) - -// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system -// Supported resource types are Network and Request Types are Add/Remove -type ResourceModificationRequestResponse struct { - Resource ResourceType `json:"ResourceType"` - Data interface{} `json:"Settings"` - Request RequestType `json:"RequestType,omitempty"` -} - -// createContainerAdditionalJSON is read from the environment at initialisation -// time. It allows an environment variable to define additional JSON which -// is merged in the CreateContainer call to HCS. -var createContainerAdditionalJSON string - -func init() { - createContainerAdditionalJSON = os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON") -} - -// CreateContainer creates a new container with the given configuration but does not start it. -func CreateContainer(id string, c *ContainerConfig) (Container, error) { - return createContainerWithJSON(id, c, "") -} - -// CreateContainerWithJSON creates a new container with the given configuration but does not start it. -// It is identical to CreateContainer except that optional additional JSON can be merged before passing to HCS. -func CreateContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) { - return createContainerWithJSON(id, c, additionalJSON) -} - -func createContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) { - operation := "CreateContainer" - title := "HCSShim::" + operation - - container := &container{ - id: id, - } - - configurationb, err := json.Marshal(c) - if err != nil { - return nil, err - } - - configuration := string(configurationb) - logrus.Debugf(title+" id=%s config=%s", id, configuration) - - // Merge any additional JSON. Priority is given to what is passed in explicitly, - // falling back to what's set in the environment. - if additionalJSON == "" && createContainerAdditionalJSON != "" { - additionalJSON = createContainerAdditionalJSON - } - if additionalJSON != "" { - configurationMap := map[string]interface{}{} - if err := json.Unmarshal([]byte(configuration), &configurationMap); err != nil { - return nil, fmt.Errorf("failed to unmarshal %s: %s", configuration, err) - } - - additionalMap := map[string]interface{}{} - if err := json.Unmarshal([]byte(additionalJSON), &additionalMap); err != nil { - return nil, fmt.Errorf("failed to unmarshal %s: %s", additionalJSON, err) - } - - mergedMap := mergeMaps(additionalMap, configurationMap) - mergedJSON, err := json.Marshal(mergedMap) - if err != nil { - return nil, fmt.Errorf("failed to marshal merged configuration map %+v: %s", mergedMap, err) - } - - configuration = string(mergedJSON) - logrus.Debugf(title+" id=%s merged config=%s", id, configuration) - } - - var ( - resultp *uint16 - identity syscall.Handle - ) - createError := hcsCreateComputeSystem(id, configuration, identity, &container.handle, &resultp) - - if createError == nil || IsPending(createError) { - if err := container.registerCallback(); err != nil { - // Terminate the container if it still exists. We're okay to ignore a failure here. - container.Terminate() - return nil, makeContainerError(container, operation, "", err) - } - } - - err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) - if err != nil { - if err == ErrTimeout { - // Terminate the container if it still exists. We're okay to ignore a failure here. - container.Terminate() - } - return nil, makeContainerError(container, operation, configuration, err) - } - - logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle) - return container, nil -} - -// mergeMaps recursively merges map `fromMap` into map `ToMap`. Any pre-existing values -// in ToMap are overwritten. Values in fromMap are added to ToMap. -// From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang -func mergeMaps(fromMap, ToMap interface{}) interface{} { - switch fromMap := fromMap.(type) { - case map[string]interface{}: - ToMap, ok := ToMap.(map[string]interface{}) - if !ok { - return fromMap - } - for keyToMap, valueToMap := range ToMap { - if valueFromMap, ok := fromMap[keyToMap]; ok { - fromMap[keyToMap] = mergeMaps(valueFromMap, valueToMap) - } else { - fromMap[keyToMap] = valueToMap - } - } - case nil: - // merge(nil, map[string]interface{...}) -> map[string]interface{...} - ToMap, ok := ToMap.(map[string]interface{}) - if ok { - return ToMap - } - } - return fromMap -} - -// OpenContainer opens an existing container by ID. -func OpenContainer(id string) (Container, error) { - operation := "OpenContainer" - title := "HCSShim::" + operation - logrus.Debugf(title+" id=%s", id) - - container := &container{ - id: id, - } - - var ( - handle hcsSystem - resultp *uint16 - ) - err := hcsOpenComputeSystem(id, &handle, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - container.handle = handle - - if err := container.registerCallback(); err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle) - return container, nil -} - -// GetContainers gets a list of the containers on the system that match the query -func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) { - operation := "GetContainers" - title := "HCSShim::" + operation - - queryb, err := json.Marshal(q) - if err != nil { - return nil, err - } - - query := string(queryb) - logrus.Debugf(title+" query=%s", query) - - var ( - resultp *uint16 - computeSystemsp *uint16 - ) - err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, err - } - - if computeSystemsp == nil { - return nil, ErrUnexpectedValue - } - computeSystemsRaw := convertAndFreeCoTaskMemBytes(computeSystemsp) - computeSystems := []ContainerProperties{} - if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { - return nil, err - } - - logrus.Debugf(title + " succeeded") - return computeSystems, nil -} - -// Start synchronously starts the container. -func (container *container) Start() error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Start" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsStartComputeSystem(container.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// Shutdown requests a container shutdown, if IsPending() on the error returned is true, -// it may not actually be shut down until Wait() succeeds. -func (container *container) Shutdown() error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Shutdown" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsShutdownComputeSystem(container.handle, "", &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// Terminate requests a container terminate, if IsPending() on the error returned is true, -// it may not actually be shut down until Wait() succeeds. -func (container *container) Terminate() error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Terminate" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsTerminateComputeSystem(container.handle, "", &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// Wait synchronously waits for the container to shutdown or terminate. -func (container *container) Wait() error { - operation := "Wait" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. -// If the timeout expires, IsTimeout(err) == true -func (container *container) WaitTimeout(timeout time.Duration) error { - operation := "WaitTimeout" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -func (container *container) properties(query string) (*ContainerProperties, error) { - var ( - resultp *uint16 - propertiesp *uint16 - ) - err := hcsGetComputeSystemProperties(container.handle, query, &propertiesp, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, err - } - - if propertiesp == nil { - return nil, ErrUnexpectedValue - } - propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp) - properties := &ContainerProperties{} - if err := json.Unmarshal(propertiesRaw, properties); err != nil { - return nil, err - } - return properties, nil -} - -// HasPendingUpdates returns true if the container has updates pending to install -func (container *container) HasPendingUpdates() (bool, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "HasPendingUpdates" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return false, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - properties, err := container.properties(pendingUpdatesQuery) - if err != nil { - return false, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return properties.AreUpdatesPending, nil -} - -// Statistics returns statistics for the container -func (container *container) Statistics() (Statistics, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Statistics" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return Statistics{}, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - properties, err := container.properties(statisticsQuery) - if err != nil { - return Statistics{}, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return properties.Statistics, nil -} - -// ProcessList returns an array of ProcessListItems for the container -func (container *container) ProcessList() ([]ProcessListItem, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "ProcessList" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - properties, err := container.properties(processListQuery) - if err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return properties.ProcessList, nil -} - -// MappedVirtualDisks returns a map of the controllers and the disks mapped -// to a container. -// -// Example of JSON returned by the query. -//{ -// "Id":"1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3_svm", -// "SystemType":"Container", -// "RuntimeOsType":"Linux", -// "RuntimeId":"00000000-0000-0000-0000-000000000000", -// "State":"Running", -// "MappedVirtualDiskControllers":{ -// "0":{ -// "MappedVirtualDisks":{ -// "2":{ -// "HostPath":"C:\\lcow\\lcow\\scratch\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3.vhdx", -// "ContainerPath":"/mnt/gcs/LinuxServiceVM/scratch", -// "Lun":2, -// "CreateInUtilityVM":true -// }, -// "3":{ -// "HostPath":"C:\\lcow\\lcow\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3\\sandbox.vhdx", -// "Lun":3, -// "CreateInUtilityVM":true, -// "AttachOnly":true -// } -// } -// } -// } -//} -func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "MappedVirtualDiskList" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - properties, err := container.properties(mappedVirtualDiskQuery) - if err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return properties.MappedVirtualDiskControllers, nil -} - -// Pause pauses the execution of the container. This feature is not enabled in TP5. -func (container *container) Pause() error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Pause" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsPauseComputeSystem(container.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// Resume resumes the execution of the container. This feature is not enabled in TP5. -func (container *container) Resume() error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Resume" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsResumeComputeSystem(container.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) - if err != nil { - return makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -// CreateProcess launches a new process within the container. -func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "CreateProcess" - title := "HCSShim::Container::" + operation - var ( - processInfo hcsProcessInformation - processHandle hcsProcess - resultp *uint16 - ) - - if container.handle == 0 { - return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - // If we are not emulating a console, ignore any console size passed to us - if !c.EmulateConsole { - c.ConsoleSize[0] = 0 - c.ConsoleSize[1] = 0 - } - - configurationb, err := json.Marshal(c) - if err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - configuration := string(configurationb) - logrus.Debugf(title+" id=%s config=%s", container.id, configuration) - - err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, makeContainerError(container, operation, configuration, err) - } - - process := &process{ - handle: processHandle, - processID: int(processInfo.ProcessId), - container: container, - cachedPipes: &cachedPipes{ - stdIn: processInfo.StdInput, - stdOut: processInfo.StdOutput, - stdErr: processInfo.StdError, - }, - } - - if err := process.registerCallback(); err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s processid=%d", container.id, process.processID) - return process, nil -} - -// OpenProcess gets an interface to an existing process within the container. -func (container *container) OpenProcess(pid int) (Process, error) { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "OpenProcess" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s, processid=%d", container.id, pid) - var ( - processHandle hcsProcess - resultp *uint16 - ) - - if container.handle == 0 { - return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - process := &process{ - handle: processHandle, - processID: pid, - container: container, - } - - if err := process.registerCallback(); err != nil { - return nil, makeContainerError(container, operation, "", err) - } - - logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID) - return process, nil -} - -// Close cleans up any state associated with the container but does not terminate or wait for it. -func (container *container) Close() error { - container.handleLock.Lock() - defer container.handleLock.Unlock() - operation := "Close" - title := "HCSShim::Container::" + operation - logrus.Debugf(title+" id=%s", container.id) - - // Don't double free this - if container.handle == 0 { - return nil - } - - if err := container.unregisterCallback(); err != nil { - return makeContainerError(container, operation, "", err) - } - - if err := hcsCloseComputeSystem(container.handle); err != nil { - return makeContainerError(container, operation, "", err) - } - - container.handle = 0 - - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} - -func (container *container) registerCallback() error { - context := ¬ifcationWatcherContext{ - channels: newChannels(), - } - - callbackMapLock.Lock() - callbackNumber := nextCallback - nextCallback++ - callbackMap[callbackNumber] = context - callbackMapLock.Unlock() - - var callbackHandle hcsCallback - err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) - if err != nil { - return err - } - context.handle = callbackHandle - container.callbackNumber = callbackNumber - - return nil -} - -func (container *container) unregisterCallback() error { - callbackNumber := container.callbackNumber - - callbackMapLock.RLock() - context := callbackMap[callbackNumber] - callbackMapLock.RUnlock() - - if context == nil { - return nil - } - - handle := context.handle - - if handle == 0 { - return nil - } - - // hcsUnregisterComputeSystemCallback has its own syncronization - // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. - err := hcsUnregisterComputeSystemCallback(handle) - if err != nil { - return err - } - - closeChannels(context.channels) - - callbackMapLock.Lock() - callbackMap[callbackNumber] = nil - callbackMapLock.Unlock() - - handle = 0 - - return nil -} - -// Modifies the System by sending a request to HCS -func (container *container) Modify(config *ResourceModificationRequestResponse) error { - container.handleLock.RLock() - defer container.handleLock.RUnlock() - operation := "Modify" - title := "HCSShim::Container::" + operation - - if container.handle == 0 { - return makeContainerError(container, operation, "", ErrAlreadyClosed) - } - - requestJSON, err := json.Marshal(config) - if err != nil { - return err - } - - requestString := string(requestJSON) - logrus.Debugf(title+" id=%s request=%s", container.id, requestString) - - var resultp *uint16 - err = hcsModifyComputeSystem(container.handle, requestString, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeContainerError(container, operation, "", err) - } - logrus.Debugf(title+" succeeded id=%s", container.id) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/createlayer.go b/vendor/github.com/Microsoft/hcsshim/createlayer.go deleted file mode 100644 index 035d9c3947..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/createlayer.go +++ /dev/null @@ -1,27 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// CreateLayer creates a new, empty, read-only layer on the filesystem based on -// the parent layer provided. -func CreateLayer(info DriverInfo, id, parent string) error { - title := "hcsshim::CreateLayer " - logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = createLayer(&infop, id, parent) - if err != nil { - err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+" - succeeded id=%s parent=%s flavour=%d", id, parent, info.Flavour) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go b/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go deleted file mode 100644 index 7a6a8854cf..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go +++ /dev/null @@ -1,35 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// CreateSandboxLayer creates and populates new read-write layer for use by a container. -// This requires both the id of the direct parent layer, as well as the full list -// of paths to all parent layers up to the base (and including the direct parent -// whose id was provided). -func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { - title := "hcsshim::CreateSandboxLayer " - logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId) - - // Generate layer descriptors - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return err - } - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = createSandboxLayer(&infop, layerId, parentId, layers) - if err != nil { - err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"- succeeded layerId=%s parentId=%s", layerId, parentId) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go b/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go deleted file mode 100644 index fd785030fb..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go +++ /dev/null @@ -1,26 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// DeactivateLayer will dismount a layer that was mounted via ActivateLayer. -func DeactivateLayer(info DriverInfo, id string) error { - title := "hcsshim::DeactivateLayer " - logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = deactivateLayer(&infop, id) - if err != nil { - err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/destroylayer.go b/vendor/github.com/Microsoft/hcsshim/destroylayer.go deleted file mode 100644 index b1e3b89fc7..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/destroylayer.go +++ /dev/null @@ -1,27 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// DestroyLayer will remove the on-disk files representing the layer with the given -// id, including that layer's containing folder, if any. -func DestroyLayer(info DriverInfo, id string) error { - title := "hcsshim::DestroyLayer " - logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = destroyLayer(&infop, id) - if err != nil { - err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go deleted file mode 100644 index c0c6cac87c..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/errors.go +++ /dev/null @@ -1,261 +0,0 @@ -package hcsshim - -import ( - "errors" - "fmt" - "syscall" -) - -var ( - // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists - ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e) - - // ErrElementNotFound is an error encountered when the object being referenced does not exist - ErrElementNotFound = syscall.Errno(0x490) - - // ErrElementNotFound is an error encountered when the object being referenced does not exist - ErrNotSupported = syscall.Errno(0x32) - - // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported - // decimal -2147024883 / hex 0x8007000d - ErrInvalidData = syscall.Errno(0xd) - - // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed - ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed") - - // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method - ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed") - - // ErrInvalidNotificationType is an error encountered when an invalid notification type is used - ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type") - - // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation - ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") - - // ErrTimeout is an error encountered when waiting on a notification times out - ErrTimeout = errors.New("hcsshim: timeout waiting for notification") - - // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for - // a different expected notification - ErrUnexpectedContainerExit = errors.New("unexpected container exit") - - // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service - // is lost while waiting for a notification - ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") - - // ErrUnexpectedValue is an error encountered when hcs returns an invalid value - ErrUnexpectedValue = errors.New("unexpected value returned from hcs") - - // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container - ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110) - - // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously - ErrVmcomputeOperationPending = syscall.Errno(0xC0370103) - - // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation - ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105) - - // ErrProcNotFound is an error encountered when the the process cannot be found - ErrProcNotFound = syscall.Errno(0x7f) - - // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2 - // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3. - ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5) - - // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management - ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d) - - // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message - ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b) - - // ErrNotSupported is an error encountered when hcs doesn't support the request - ErrPlatformNotSupported = errors.New("unsupported platform request") -) - -type EndpointNotFoundError struct { - EndpointName string -} - -func (e EndpointNotFoundError) Error() string { - return fmt.Sprintf("Endpoint %s not found", e.EndpointName) -} - -type NetworkNotFoundError struct { - NetworkName string -} - -func (e NetworkNotFoundError) Error() string { - return fmt.Sprintf("Network %s not found", e.NetworkName) -} - -// ProcessError is an error encountered in HCS during an operation on a Process object -type ProcessError struct { - Process *process - Operation string - ExtraInfo string - Err error -} - -// ContainerError is an error encountered in HCS during an operation on a Container object -type ContainerError struct { - Container *container - Operation string - ExtraInfo string - Err error -} - -func (e *ContainerError) Error() string { - if e == nil { - return "" - } - - if e.Container == nil { - return "unexpected nil container for error: " + e.Err.Error() - } - - s := "container " + e.Container.id - - if e.Operation != "" { - s += " encountered an error during " + e.Operation - } - - switch e.Err.(type) { - case nil: - break - case syscall.Errno: - s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err)) - default: - s += fmt.Sprintf(": %s", e.Err.Error()) - } - - if e.ExtraInfo != "" { - s += " extra info: " + e.ExtraInfo - } - - return s -} - -func makeContainerError(container *container, operation string, extraInfo string, err error) error { - // Don't double wrap errors - if _, ok := err.(*ContainerError); ok { - return err - } - containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err} - return containerError -} - -func (e *ProcessError) Error() string { - if e == nil { - return "" - } - - if e.Process == nil { - return "Unexpected nil process for error: " + e.Err.Error() - } - - s := fmt.Sprintf("process %d", e.Process.processID) - - if e.Process.container != nil { - s += " in container " + e.Process.container.id - } - - if e.Operation != "" { - s += " encountered an error during " + e.Operation - } - - switch e.Err.(type) { - case nil: - break - case syscall.Errno: - s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err)) - default: - s += fmt.Sprintf(": %s", e.Err.Error()) - } - - return s -} - -func makeProcessError(process *process, operation string, extraInfo string, err error) error { - // Don't double wrap errors - if _, ok := err.(*ProcessError); ok { - return err - } - processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err} - return processError -} - -// IsNotExist checks if an error is caused by the Container or Process not existing. -// Note: Currently, ErrElementNotFound can mean that a Process has either -// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist -// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. -func IsNotExist(err error) bool { - err = getInnerError(err) - if _, ok := err.(EndpointNotFoundError); ok { - return true - } - if _, ok := err.(NetworkNotFoundError); ok { - return true - } - return err == ErrComputeSystemDoesNotExist || - err == ErrElementNotFound || - err == ErrProcNotFound -} - -// IsAlreadyClosed checks if an error is caused by the Container or Process having been -// already closed by a call to the Close() method. -func IsAlreadyClosed(err error) bool { - err = getInnerError(err) - return err == ErrAlreadyClosed -} - -// IsPending returns a boolean indicating whether the error is that -// the requested operation is being completed in the background. -func IsPending(err error) bool { - err = getInnerError(err) - return err == ErrVmcomputeOperationPending -} - -// IsTimeout returns a boolean indicating whether the error is caused by -// a timeout waiting for the operation to complete. -func IsTimeout(err error) bool { - err = getInnerError(err) - return err == ErrTimeout -} - -// IsAlreadyStopped returns a boolean indicating whether the error is caused by -// a Container or Process being already stopped. -// Note: Currently, ErrElementNotFound can mean that a Process has either -// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist -// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. -func IsAlreadyStopped(err error) bool { - err = getInnerError(err) - return err == ErrVmcomputeAlreadyStopped || - err == ErrElementNotFound || - err == ErrProcNotFound -} - -// IsNotSupported returns a boolean indicating whether the error is caused by -// unsupported platform requests -// Note: Currently Unsupported platform requests can be mean either -// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage -// is thrown from the Platform -func IsNotSupported(err error) bool { - err = getInnerError(err) - // If Platform doesn't recognize or support the request sent, below errors are seen - return err == ErrVmcomputeInvalidJSON || - err == ErrInvalidData || - err == ErrNotSupported || - err == ErrVmcomputeUnknownMessage -} - -func getInnerError(err error) error { - switch pe := err.(type) { - case nil: - return nil - case *ContainerError: - err = pe.Err - case *ProcessError: - err = pe.Err - } - return err -} diff --git a/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go b/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go deleted file mode 100644 index 6946c6a84f..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go +++ /dev/null @@ -1,26 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// ExpandSandboxSize expands the size of a layer to at least size bytes. -func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error { - title := "hcsshim::ExpandSandboxSize " - logrus.Debugf(title+"layerId=%s size=%d", layerId, size) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = expandSandboxSize(&infop, layerId, size) - if err != nil { - err = makeErrorf(err, title, "layerId=%s size=%d", layerId, size) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"- succeeded layerId=%s size=%d", layerId, size) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/exportlayer.go b/vendor/github.com/Microsoft/hcsshim/exportlayer.go deleted file mode 100644 index d7025f20ba..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/exportlayer.go +++ /dev/null @@ -1,156 +0,0 @@ -package hcsshim - -import ( - "io" - "io/ioutil" - "os" - "syscall" - - "github.com/Microsoft/go-winio" - "github.com/sirupsen/logrus" -) - -// ExportLayer will create a folder at exportFolderPath and fill that folder with -// the transport format version of the layer identified by layerId. This transport -// format includes any metadata required for later importing the layer (using -// ImportLayer), and requires the full list of parent layer paths in order to -// perform the export. -func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error { - title := "hcsshim::ExportLayer " - logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath) - - // Generate layer descriptors - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return err - } - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = exportLayer(&infop, layerId, exportFolderPath, layers) - if err != nil { - err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath) - return nil -} - -type LayerReader interface { - Next() (string, int64, *winio.FileBasicInfo, error) - Read(b []byte) (int, error) - Close() error -} - -// FilterLayerReader provides an interface for extracting the contents of an on-disk layer. -type FilterLayerReader struct { - context uintptr -} - -// Next reads the next available file from a layer, ensuring that parent directories are always read -// before child files and directories. -// -// Next returns the file's relative path, size, and basic file metadata. Read() should be used to -// extract a Win32 backup stream with the remainder of the metadata and the data. -func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) { - var fileNamep *uint16 - fileInfo := &winio.FileBasicInfo{} - var deleted uint32 - var fileSize int64 - err := exportLayerNext(r.context, &fileNamep, fileInfo, &fileSize, &deleted) - if err != nil { - if err == syscall.ERROR_NO_MORE_FILES { - err = io.EOF - } else { - err = makeError(err, "ExportLayerNext", "") - } - return "", 0, nil, err - } - fileName := convertAndFreeCoTaskMemString(fileNamep) - if deleted != 0 { - fileInfo = nil - } - if fileName[0] == '\\' { - fileName = fileName[1:] - } - return fileName, fileSize, fileInfo, nil -} - -// Read reads from the current file's Win32 backup stream. -func (r *FilterLayerReader) Read(b []byte) (int, error) { - var bytesRead uint32 - err := exportLayerRead(r.context, b, &bytesRead) - if err != nil { - return 0, makeError(err, "ExportLayerRead", "") - } - if bytesRead == 0 { - return 0, io.EOF - } - return int(bytesRead), nil -} - -// Close frees resources associated with the layer reader. It will return an -// error if there was an error while reading the layer or of the layer was not -// completely read. -func (r *FilterLayerReader) Close() (err error) { - if r.context != 0 { - err = exportLayerEnd(r.context) - if err != nil { - err = makeError(err, "ExportLayerEnd", "") - } - r.context = 0 - } - return -} - -// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer. -// The caller must have taken the SeBackupPrivilege privilege -// to call this and any methods on the resulting LayerReader. -func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) { - if procExportLayerBegin.Find() != nil { - // The new layer reader is not available on this Windows build. Fall back to the - // legacy export code path. - path, err := ioutil.TempDir("", "hcs") - if err != nil { - return nil, err - } - err = ExportLayer(info, layerID, path, parentLayerPaths) - if err != nil { - os.RemoveAll(path) - return nil, err - } - return &legacyLayerReaderWrapper{newLegacyLayerReader(path)}, nil - } - - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return nil, err - } - infop, err := convertDriverInfo(info) - if err != nil { - return nil, err - } - r := &FilterLayerReader{} - err = exportLayerBegin(&infop, layerID, layers, &r.context) - if err != nil { - return nil, makeError(err, "ExportLayerBegin", "") - } - return r, err -} - -type legacyLayerReaderWrapper struct { - *legacyLayerReader -} - -func (r *legacyLayerReaderWrapper) Close() error { - err := r.legacyLayerReader.Close() - os.RemoveAll(r.root) - return err -} diff --git a/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go b/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go deleted file mode 100644 index 89f8079d0f..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go +++ /dev/null @@ -1,55 +0,0 @@ -package hcsshim - -import ( - "syscall" - - "github.com/sirupsen/logrus" -) - -// GetLayerMountPath will look for a mounted layer with the given id and return -// the path at which that layer can be accessed. This path may be a volume path -// if the layer is a mounted read-write layer, otherwise it is expected to be the -// folder path at which the layer is stored. -func GetLayerMountPath(info DriverInfo, id string) (string, error) { - title := "hcsshim::GetLayerMountPath " - logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return "", err - } - - var mountPathLength uintptr - mountPathLength = 0 - - // Call the procedure itself. - logrus.Debugf("Calling proc (1)") - err = getLayerMountPath(&infop, id, &mountPathLength, nil) - if err != nil { - err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return "", err - } - - // Allocate a mount path of the returned length. - if mountPathLength == 0 { - return "", nil - } - mountPathp := make([]uint16, mountPathLength) - mountPathp[0] = 0 - - // Call the procedure again - logrus.Debugf("Calling proc (2)") - err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0]) - if err != nil { - err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return "", err - } - - path := syscall.UTF16ToString(mountPathp[0:]) - logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path) - return path, nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go b/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go deleted file mode 100644 index 05d3d9532a..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go +++ /dev/null @@ -1,22 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// GetSharedBaseImages will enumerate the images stored in the common central -// image store and return descriptive info about those images for the purpose -// of registering them with the graphdriver, graph, and tagstore. -func GetSharedBaseImages() (imageData string, err error) { - title := "hcsshim::GetSharedBaseImages " - - logrus.Debugf("Calling proc") - var buffer *uint16 - err = getBaseImages(&buffer) - if err != nil { - err = makeError(err, title, "") - logrus.Error(err) - return - } - imageData = convertAndFreeCoTaskMemString(buffer) - logrus.Debugf(title+" - succeeded output=%s", imageData) - return -} diff --git a/vendor/github.com/Microsoft/hcsshim/guid.go b/vendor/github.com/Microsoft/hcsshim/guid.go deleted file mode 100644 index 620aba123c..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/guid.go +++ /dev/null @@ -1,19 +0,0 @@ -package hcsshim - -import ( - "crypto/sha1" - "fmt" -) - -type GUID [16]byte - -func NewGUID(source string) *GUID { - h := sha1.Sum([]byte(source)) - var g GUID - copy(g[0:], h[0:16]) - return &g -} - -func (g *GUID) ToString() string { - return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:]) -} diff --git a/vendor/github.com/Microsoft/hcsshim/hcsshim.go b/vendor/github.com/Microsoft/hcsshim/hcsshim.go deleted file mode 100644 index 236ba1fa30..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hcsshim.go +++ /dev/null @@ -1,166 +0,0 @@ -// Shim for the Host Compute Service (HCS) to manage Windows Server -// containers and Hyper-V containers. - -package hcsshim - -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/sirupsen/logrus" -) - -//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go - -//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree -//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId - -//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? -//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? -//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? -//sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? -//sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize? -//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? -//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? -//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? -//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? -//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? -//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? -//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? -//sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid? -//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? -//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? -//sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage? -//sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage? - -//sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin? -//sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext? -//sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite? -//sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd? - -//sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin? -//sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext? -//sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead? -//sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd? - -//sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems? -//sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem? -//sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem? -//sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem? -//sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem? -//sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem? -//sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem? -//sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem? -//sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem? -//sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties? -//sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem? -//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback? -//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback? - -//sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess? -//sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess? -//sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess? -//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess? -//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo? -//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties? -//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess? -//sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties? -//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback? -//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback? - -//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings? - -//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? - -const ( - // Specific user-visible exit codes - WaitErrExecFailed = 32767 - - ERROR_GEN_FAILURE = syscall.Errno(31) - ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115) - WSAEINVAL = syscall.Errno(10022) - - // Timeout on wait calls - TimeoutInfinite = 0xFFFFFFFF -) - -type HcsError struct { - title string - rest string - Err error -} - -type hcsSystem syscall.Handle -type hcsProcess syscall.Handle -type hcsCallback syscall.Handle - -type hcsProcessInformation struct { - ProcessId uint32 - Reserved uint32 - StdInput syscall.Handle - StdOutput syscall.Handle - StdError syscall.Handle -} - -func makeError(err error, title, rest string) error { - // Pass through DLL errors directly since they do not originate from HCS. - if _, ok := err.(*syscall.DLLError); ok { - return err - } - return &HcsError{title, rest, err} -} - -func makeErrorf(err error, title, format string, a ...interface{}) error { - return makeError(err, title, fmt.Sprintf(format, a...)) -} - -func win32FromError(err error) uint32 { - if herr, ok := err.(*HcsError); ok { - return win32FromError(herr.Err) - } - if code, ok := err.(syscall.Errno); ok { - return uint32(code) - } - return uint32(ERROR_GEN_FAILURE) -} - -func win32FromHresult(hr uintptr) uintptr { - if hr&0x1fff0000 == 0x00070000 { - return hr & 0xffff - } - return hr -} - -func (e *HcsError) Error() string { - s := e.title - if len(s) > 0 && s[len(s)-1] != ' ' { - s += " " - } - s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err)) - if e.rest != "" { - if e.rest[0] != ' ' { - s += " " - } - s += e.rest - } - return s -} - -func convertAndFreeCoTaskMemString(buffer *uint16) string { - str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:]) - coTaskMemFree(unsafe.Pointer(buffer)) - return str -} - -func convertAndFreeCoTaskMemBytes(buffer *uint16) []byte { - return []byte(convertAndFreeCoTaskMemString(buffer)) -} - -func processHcsResult(err error, resultp *uint16) error { - if resultp != nil { - result := convertAndFreeCoTaskMemString(resultp) - logrus.Debugf("Result: %s", result) - } - return err -} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go deleted file mode 100644 index 7e516f8a2e..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go +++ /dev/null @@ -1,323 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "net" - - "github.com/sirupsen/logrus" -) - -// HNSEndpoint represents a network endpoint in HNS -type HNSEndpoint struct { - Id string `json:"ID,omitempty"` - Name string `json:",omitempty"` - VirtualNetwork string `json:",omitempty"` - VirtualNetworkName string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` - MacAddress string `json:",omitempty"` - IPAddress net.IP `json:",omitempty"` - DNSSuffix string `json:",omitempty"` - DNSServerList string `json:",omitempty"` - GatewayAddress string `json:",omitempty"` - EnableInternalDNS bool `json:",omitempty"` - DisableICC bool `json:",omitempty"` - PrefixLength uint8 `json:",omitempty"` - IsRemoteEndpoint bool `json:",omitempty"` -} - -//SystemType represents the type of the system on which actions are done -type SystemType string - -// SystemType const -const ( - ContainerType SystemType = "Container" - VirtualMachineType SystemType = "VirtualMachine" - HostType SystemType = "Host" -) - -// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system -// Supported resource types are Network and Request Types are Add/Remove -type EndpointAttachDetachRequest struct { - ContainerID string `json:"ContainerId,omitempty"` - SystemType SystemType `json:"SystemType"` - CompartmentID uint16 `json:"CompartmentId,omitempty"` - VirtualNICName string `json:"VirtualNicName,omitempty"` -} - -// EndpointResquestResponse is object to get the endpoint request response -type EndpointResquestResponse struct { - Success bool - Error string -} - -// HNSEndpointRequest makes a HNS call to modify/query a network endpoint -func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { - endpoint := &HNSEndpoint{} - err := hnsCall(method, "/endpoints/"+path, request, &endpoint) - if err != nil { - return nil, err - } - - return endpoint, nil -} - -// HNSListEndpointRequest makes a HNS call to query the list of available endpoints -func HNSListEndpointRequest() ([]HNSEndpoint, error) { - var endpoint []HNSEndpoint - err := hnsCall("GET", "/endpoints/", "", &endpoint) - if err != nil { - return nil, err - } - - return endpoint, nil -} - -// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container -func HotAttachEndpoint(containerID string, endpointID string) error { - return modifyNetworkEndpoint(containerID, endpointID, Add) -} - -// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container -func HotDetachEndpoint(containerID string, endpointID string) error { - return modifyNetworkEndpoint(containerID, endpointID, Remove) -} - -// ModifyContainer corresponding to the container id, by sending a request -func modifyContainer(id string, request *ResourceModificationRequestResponse) error { - container, err := OpenContainer(id) - if err != nil { - if IsNotExist(err) { - return ErrComputeSystemDoesNotExist - } - return getInnerError(err) - } - defer container.Close() - err = container.Modify(request) - if err != nil { - if IsNotSupported(err) { - return ErrPlatformNotSupported - } - return getInnerError(err) - } - - return nil -} - -func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { - requestMessage := &ResourceModificationRequestResponse{ - Resource: Network, - Request: request, - Data: endpointID, - } - err := modifyContainer(containerID, requestMessage) - - if err != nil { - return err - } - - return nil -} - -// GetHNSEndpointByID get the Endpoint by ID -func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { - return HNSEndpointRequest("GET", endpointID, "") -} - -// GetHNSEndpointByName gets the endpoint filtered by Name -func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { - hnsResponse, err := HNSListEndpointRequest() - if err != nil { - return nil, err - } - for _, hnsEndpoint := range hnsResponse { - if hnsEndpoint.Name == endpointName { - return &hnsEndpoint, nil - } - } - return nil, EndpointNotFoundError{EndpointName: endpointName} -} - -// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods -func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { - operation := "Create" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - jsonString, err := json.Marshal(endpoint) - if err != nil { - return nil, err - } - return HNSEndpointRequest("POST", "", string(jsonString)) -} - -// Delete Endpoint by sending EndpointRequest to HNS -func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { - operation := "Delete" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - return HNSEndpointRequest("DELETE", endpoint.Id, "") -} - -// Update Endpoint -func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { - operation := "Update" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - jsonString, err := json.Marshal(endpoint) - if err != nil { - return nil, err - } - err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) - - return endpoint, err -} - -// ContainerHotAttach attaches an endpoint to a running container -func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { - operation := "ContainerHotAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) - - return modifyNetworkEndpoint(containerID, endpoint.Id, Add) -} - -// ContainerHotDetach detaches an endpoint from a running container -func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { - operation := "ContainerHotDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) - - return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) -} - -// ApplyACLPolicy applies a set of ACL Policies on the Endpoint -func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { - operation := "ApplyACLPolicy" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - for _, policy := range policies { - if policy == nil { - continue - } - jsonString, err := json.Marshal(policy) - if err != nil { - return err - } - endpoint.Policies = append(endpoint.Policies, jsonString) - } - - _, err := endpoint.Update() - return err -} - -// ContainerAttach attaches an endpoint to container -func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { - operation := "ContainerAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - ContainerID: containerID, - CompartmentID: compartmentID, - SystemType: ContainerType, - } - response := &EndpointResquestResponse{} - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) -} - -// ContainerDetach detaches an endpoint from container -func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { - operation := "ContainerDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - ContainerID: containerID, - SystemType: ContainerType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} - -// HostAttach attaches a nic on the host -func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { - operation := "HostAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - CompartmentID: compartmentID, - SystemType: HostType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) - -} - -// HostDetach detaches a nic on the host -func (endpoint *HNSEndpoint) HostDetach() error { - operation := "HostDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - SystemType: HostType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} - -// VirtualMachineNICAttach attaches a endpoint to a virtual machine -func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { - operation := "VirtualMachineNicAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - VirtualNICName: virtualMachineNICName, - SystemType: VirtualMachineType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) -} - -// VirtualMachineNICDetach detaches a endpoint from a virtual machine -func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { - operation := "VirtualMachineNicDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - SystemType: VirtualMachineType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go b/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go deleted file mode 100644 index 2c1b979ae8..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go +++ /dev/null @@ -1,40 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "fmt" - - "github.com/sirupsen/logrus" -) - -func hnsCall(method, path, request string, returnResponse interface{}) error { - var responseBuffer *uint16 - logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request) - - err := _hnsCall(method, path, request, &responseBuffer) - if err != nil { - return makeError(err, "hnsCall ", "") - } - response := convertAndFreeCoTaskMemString(responseBuffer) - - hnsresponse := &hnsResponse{} - if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil { - return err - } - - if !hnsresponse.Success { - return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error) - } - - if len(hnsresponse.Output) == 0 { - return nil - } - - logrus.Debugf("Network Response : %s", hnsresponse.Output) - err = json.Unmarshal(hnsresponse.Output, returnResponse) - if err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go deleted file mode 100644 index 04c1b59196..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go +++ /dev/null @@ -1,141 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "net" - - "github.com/sirupsen/logrus" -) - -// Subnet is assoicated with a network and represents a list -// of subnets available to the network -type Subnet struct { - AddressPrefix string `json:",omitempty"` - GatewayAddress string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` -} - -// MacPool is assoicated with a network and represents a list -// of macaddresses available to the network -type MacPool struct { - StartMacAddress string `json:",omitempty"` - EndMacAddress string `json:",omitempty"` -} - -// HNSNetwork represents a network in HNS -type HNSNetwork struct { - Id string `json:"ID,omitempty"` - Name string `json:",omitempty"` - Type string `json:",omitempty"` - NetworkAdapterName string `json:",omitempty"` - SourceMac string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` - MacPools []MacPool `json:",omitempty"` - Subnets []Subnet `json:",omitempty"` - DNSSuffix string `json:",omitempty"` - DNSServerList string `json:",omitempty"` - DNSServerCompartment uint32 `json:",omitempty"` - ManagementIP string `json:",omitempty"` - AutomaticDNS bool `json:",omitempty"` -} - -type hnsNetworkResponse struct { - Success bool - Error string - Output HNSNetwork -} - -type hnsResponse struct { - Success bool - Error string - Output json.RawMessage -} - -// HNSNetworkRequest makes a call into HNS to update/query a single network -func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { - var network HNSNetwork - err := hnsCall(method, "/networks/"+path, request, &network) - if err != nil { - return nil, err - } - - return &network, nil -} - -// HNSListNetworkRequest makes a HNS call to query the list of available networks -func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { - var network []HNSNetwork - err := hnsCall(method, "/networks/"+path, request, &network) - if err != nil { - return nil, err - } - - return network, nil -} - -// GetHNSNetworkByID -func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { - return HNSNetworkRequest("GET", networkID, "") -} - -// GetHNSNetworkName filtered by Name -func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { - hsnnetworks, err := HNSListNetworkRequest("GET", "", "") - if err != nil { - return nil, err - } - for _, hnsnetwork := range hsnnetworks { - if hnsnetwork.Name == networkName { - return &hnsnetwork, nil - } - } - return nil, NetworkNotFoundError{NetworkName: networkName} -} - -// Create Network by sending NetworkRequest to HNS. -func (network *HNSNetwork) Create() (*HNSNetwork, error) { - operation := "Create" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - - jsonString, err := json.Marshal(network) - if err != nil { - return nil, err - } - return HNSNetworkRequest("POST", "", string(jsonString)) -} - -// Delete Network by sending NetworkRequest to HNS -func (network *HNSNetwork) Delete() (*HNSNetwork, error) { - operation := "Delete" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - - return HNSNetworkRequest("DELETE", network.Id, "") -} - -// Creates an endpoint on the Network. -func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { - return &HNSEndpoint{ - VirtualNetwork: network.Id, - IPAddress: ipAddress, - MacAddress: string(macAddress), - } -} - -func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { - operation := "CreateEndpoint" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) - - endpoint.VirtualNetwork = network.Id - return endpoint.Create() -} - -func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { - operation := "CreateRemoteEndpoint" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - endpoint.IsRemoteEndpoint = true - return network.CreateEndpoint(endpoint) -} diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go deleted file mode 100644 index 65b8e93d9b..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go +++ /dev/null @@ -1,94 +0,0 @@ -package hcsshim - -// Type of Request Support in ModifySystem -type PolicyType string - -// RequestType const -const ( - Nat PolicyType = "NAT" - ACL PolicyType = "ACL" - PA PolicyType = "PA" - VLAN PolicyType = "VLAN" - VSID PolicyType = "VSID" - VNet PolicyType = "VNET" - L2Driver PolicyType = "L2Driver" - Isolation PolicyType = "Isolation" - QOS PolicyType = "QOS" - OutboundNat PolicyType = "OutBoundNAT" - ExternalLoadBalancer PolicyType = "ELB" - Route PolicyType = "ROUTE" -) - -type NatPolicy struct { - Type PolicyType `json:"Type"` - Protocol string - InternalPort uint16 - ExternalPort uint16 -} - -type QosPolicy struct { - Type PolicyType `json:"Type"` - MaximumOutgoingBandwidthInBytes uint64 -} - -type IsolationPolicy struct { - Type PolicyType `json:"Type"` - VLAN uint - VSID uint - InDefaultIsolation bool -} - -type VlanPolicy struct { - Type PolicyType `json:"Type"` - VLAN uint -} - -type VsidPolicy struct { - Type PolicyType `json:"Type"` - VSID uint -} - -type PaPolicy struct { - Type PolicyType `json:"Type"` - PA string `json:"PA"` -} - -type OutboundNatPolicy struct { - Policy - VIP string `json:"VIP,omitempty"` - Exceptions []string `json:"ExceptionList,omitempty"` -} - -type ActionType string -type DirectionType string -type RuleType string - -const ( - Allow ActionType = "Allow" - Block ActionType = "Block" - - In DirectionType = "In" - Out DirectionType = "Out" - - Host RuleType = "Host" - Switch RuleType = "Switch" -) - -type ACLPolicy struct { - Type PolicyType `json:"Type"` - Protocol uint16 - InternalPort uint16 - Action ActionType - Direction DirectionType - LocalAddresses string - RemoteAddresses string - LocalPort uint16 - RemotePort uint16 - RuleType RuleType `json:"RuleType,omitempty"` - Priority uint16 - ServiceName string -} - -type Policy struct { - Type PolicyType `json:"Type"` -} diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go deleted file mode 100644 index bbd7e1edb0..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go +++ /dev/null @@ -1,200 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - - "github.com/sirupsen/logrus" -) - -// RoutePolicy is a structure defining schema for Route based Policy -type RoutePolicy struct { - Policy - DestinationPrefix string `json:"DestinationPrefix,omitempty"` - NextHop string `json:"NextHop,omitempty"` - EncapEnabled bool `json:"NeedEncap,omitempty"` -} - -// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy -type ELBPolicy struct { - LBPolicy - SourceVIP string `json:"SourceVIP,omitempty"` - VIPs []string `json:"VIPs,omitempty"` - ILB bool `json:"ILB,omitempty"` -} - -// LBPolicy is a structure defining schema for LoadBalancing based Policy -type LBPolicy struct { - Policy - Protocol uint16 `json:"Protocol,omitempty"` - InternalPort uint16 - ExternalPort uint16 -} - -// PolicyList is a structure defining schema for Policy list request -type PolicyList struct { - ID string `json:"ID,omitempty"` - EndpointReferences []string `json:"References,omitempty"` - Policies []json.RawMessage `json:"Policies,omitempty"` -} - -// HNSPolicyListRequest makes a call into HNS to update/query a single network -func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { - var policy PolicyList - err := hnsCall(method, "/policylists/"+path, request, &policy) - if err != nil { - return nil, err - } - - return &policy, nil -} - -// HNSListPolicyListRequest gets all the policy list -func HNSListPolicyListRequest() ([]PolicyList, error) { - var plist []PolicyList - err := hnsCall("GET", "/policylists/", "", &plist) - if err != nil { - return nil, err - } - - return plist, nil -} - -// PolicyListRequest makes a HNS call to modify/query a network policy list -func PolicyListRequest(method, path, request string) (*PolicyList, error) { - policylist := &PolicyList{} - err := hnsCall(method, "/policylists/"+path, request, &policylist) - if err != nil { - return nil, err - } - - return policylist, nil -} - -// GetPolicyListByID get the policy list by ID -func GetPolicyListByID(policyListID string) (*PolicyList, error) { - return PolicyListRequest("GET", policyListID, "") -} - -// Create PolicyList by sending PolicyListRequest to HNS. -func (policylist *PolicyList) Create() (*PolicyList, error) { - operation := "Create" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s", policylist.ID) - jsonString, err := json.Marshal(policylist) - if err != nil { - return nil, err - } - return PolicyListRequest("POST", "", string(jsonString)) -} - -// Delete deletes PolicyList -func (policylist *PolicyList) Delete() (*PolicyList, error) { - operation := "Delete" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s", policylist.ID) - - return PolicyListRequest("DELETE", policylist.ID, "") -} - -// AddEndpoint add an endpoint to a Policy List -func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { - operation := "AddEndpoint" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) - - _, err := policylist.Delete() - if err != nil { - return nil, err - } - - // Add Endpoint to the Existing List - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - - return policylist.Create() -} - -// RemoveEndpoint removes an endpoint from the Policy List -func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { - operation := "RemoveEndpoint" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) - - _, err := policylist.Delete() - if err != nil { - return nil, err - } - - elementToRemove := "/endpoints/" + endpoint.Id - - var references []string - - for _, endpointReference := range policylist.EndpointReferences { - if endpointReference == elementToRemove { - continue - } - references = append(references, endpointReference) - } - policylist.EndpointReferences = references - return policylist.Create() -} - -// AddLoadBalancer policy list for the specified endpoints -func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { - operation := "AddLoadBalancer" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) - - policylist := &PolicyList{} - - elbPolicy := &ELBPolicy{ - SourceVIP: sourceVIP, - ILB: isILB, - } - - if len(vip) > 0 { - elbPolicy.VIPs = []string{vip} - } - elbPolicy.Type = ExternalLoadBalancer - elbPolicy.Protocol = protocol - elbPolicy.InternalPort = internalPort - elbPolicy.ExternalPort = externalPort - - for _, endpoint := range endpoints { - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - } - - jsonString, err := json.Marshal(elbPolicy) - if err != nil { - return nil, err - } - policylist.Policies = append(policylist.Policies, jsonString) - return policylist.Create() -} - -// AddRoute adds route policy list for the specified endpoints -func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { - operation := "AddRoute" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) - - policylist := &PolicyList{} - - rPolicy := &RoutePolicy{ - DestinationPrefix: destinationPrefix, - NextHop: nextHop, - EncapEnabled: encapEnabled, - } - rPolicy.Type = Route - - for _, endpoint := range endpoints { - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - } - - jsonString, err := json.Marshal(rPolicy) - if err != nil { - return nil, err - } - - policylist.Policies = append(policylist.Policies, jsonString) - return policylist.Create() -} diff --git a/vendor/github.com/Microsoft/hcsshim/importlayer.go b/vendor/github.com/Microsoft/hcsshim/importlayer.go deleted file mode 100644 index 3aed14376a..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/importlayer.go +++ /dev/null @@ -1,212 +0,0 @@ -package hcsshim - -import ( - "errors" - "io/ioutil" - "os" - "path/filepath" - - "github.com/Microsoft/go-winio" - "github.com/sirupsen/logrus" -) - -// ImportLayer will take the contents of the folder at importFolderPath and import -// that into a layer with the id layerId. Note that in order to correctly populate -// the layer and interperet the transport format, all parent layers must already -// be present on the system at the paths provided in parentLayerPaths. -func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error { - title := "hcsshim::ImportLayer " - logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerID, importFolderPath) - - // Generate layer descriptors - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return err - } - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = importLayer(&infop, layerID, importFolderPath, layers) - if err != nil { - err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerID, info.Flavour, importFolderPath) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerID, importFolderPath) - return nil -} - -// LayerWriter is an interface that supports writing a new container image layer. -type LayerWriter interface { - // Add adds a file to the layer with given metadata. - Add(name string, fileInfo *winio.FileBasicInfo) error - // AddLink adds a hard link to the layer. The target must already have been added. - AddLink(name string, target string) error - // Remove removes a file that was present in a parent layer from the layer. - Remove(name string) error - // Write writes data to the current file. The data must be in the format of a Win32 - // backup stream. - Write(b []byte) (int, error) - // Close finishes the layer writing process and releases any resources. - Close() error -} - -// FilterLayerWriter provides an interface to write the contents of a layer to the file system. -type FilterLayerWriter struct { - context uintptr -} - -// Add adds a file or directory to the layer. The file's parent directory must have already been added. -// -// name contains the file's relative path. fileInfo contains file times and file attributes; the rest -// of the file metadata and the file data must be written as a Win32 backup stream to the Write() method. -// winio.BackupStreamWriter can be used to facilitate this. -func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error { - if name[0] != '\\' { - name = `\` + name - } - err := importLayerNext(w.context, name, fileInfo) - if err != nil { - return makeError(err, "ImportLayerNext", "") - } - return nil -} - -// AddLink adds a hard link to the layer. The target of the link must have already been added. -func (w *FilterLayerWriter) AddLink(name string, target string) error { - return errors.New("hard links not yet supported") -} - -// Remove removes a file from the layer. The file must have been present in the parent layer. -// -// name contains the file's relative path. -func (w *FilterLayerWriter) Remove(name string) error { - if name[0] != '\\' { - name = `\` + name - } - err := importLayerNext(w.context, name, nil) - if err != nil { - return makeError(err, "ImportLayerNext", "") - } - return nil -} - -// Write writes more backup stream data to the current file. -func (w *FilterLayerWriter) Write(b []byte) (int, error) { - err := importLayerWrite(w.context, b) - if err != nil { - err = makeError(err, "ImportLayerWrite", "") - return 0, err - } - return len(b), err -} - -// Close completes the layer write operation. The error must be checked to ensure that the -// operation was successful. -func (w *FilterLayerWriter) Close() (err error) { - if w.context != 0 { - err = importLayerEnd(w.context) - if err != nil { - err = makeError(err, "ImportLayerEnd", "") - } - w.context = 0 - } - return -} - -type legacyLayerWriterWrapper struct { - *legacyLayerWriter - info DriverInfo - layerID string - path string - parentLayerPaths []string -} - -func (r *legacyLayerWriterWrapper) Close() error { - defer os.RemoveAll(r.root) - err := r.legacyLayerWriter.Close() - if err != nil { - return err - } - - // Use the original path here because ImportLayer does not support long paths for the source in TP5. - // But do use a long path for the destination to work around another bug with directories - // with MAX_PATH - 12 < length < MAX_PATH. - info := r.info - fullPath, err := makeLongAbsPath(filepath.Join(info.HomeDir, r.layerID)) - if err != nil { - return err - } - - info.HomeDir = "" - if err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths); err != nil { - return err - } - // Add any hard links that were collected. - for _, lnk := range r.PendingLinks { - if err = os.Remove(lnk.Path); err != nil && !os.IsNotExist(err) { - return err - } - if err = os.Link(lnk.Target, lnk.Path); err != nil { - return err - } - } - // Prepare the utility VM for use if one is present in the layer. - if r.HasUtilityVM { - err = ProcessUtilityVMImage(filepath.Join(fullPath, "UtilityVM")) - if err != nil { - return err - } - } - return nil -} - -// NewLayerWriter returns a new layer writer for creating a layer on disk. -// The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges -// to call this and any methods on the resulting LayerWriter. -func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) { - if len(parentLayerPaths) == 0 { - // This is a base layer. It gets imported differently. - return &baseLayerWriter{ - root: filepath.Join(info.HomeDir, layerID), - }, nil - } - - if procImportLayerBegin.Find() != nil { - // The new layer reader is not available on this Windows build. Fall back to the - // legacy export code path. - path, err := ioutil.TempDir("", "hcs") - if err != nil { - return nil, err - } - return &legacyLayerWriterWrapper{ - legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)), - info: info, - layerID: layerID, - path: path, - parentLayerPaths: parentLayerPaths, - }, nil - } - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return nil, err - } - - infop, err := convertDriverInfo(info) - if err != nil { - return nil, err - } - - w := &FilterLayerWriter{} - err = importLayerBegin(&infop, layerID, layers, &w.context) - if err != nil { - return nil, makeError(err, "ImportLayerStart", "") - } - return w, nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/interface.go b/vendor/github.com/Microsoft/hcsshim/interface.go deleted file mode 100644 index e21f30025a..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/interface.go +++ /dev/null @@ -1,188 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "io" - "time" -) - -// ProcessConfig is used as both the input of Container.CreateProcess -// and to convert the parameters to JSON for passing onto the HCS -type ProcessConfig struct { - ApplicationName string `json:",omitempty"` - CommandLine string `json:",omitempty"` - CommandArgs []string `json:",omitempty"` // Used by Linux Containers on Windows - User string `json:",omitempty"` - WorkingDirectory string `json:",omitempty"` - Environment map[string]string `json:",omitempty"` - EmulateConsole bool `json:",omitempty"` - CreateStdInPipe bool `json:",omitempty"` - CreateStdOutPipe bool `json:",omitempty"` - CreateStdErrPipe bool `json:",omitempty"` - ConsoleSize [2]uint `json:",omitempty"` - CreateInUtilityVm bool `json:",omitempty"` // Used by Linux Containers on Windows - OCISpecification *json.RawMessage `json:",omitempty"` // Used by Linux Containers on Windows -} - -type Layer struct { - ID string - Path string -} - -type MappedDir struct { - HostPath string - ContainerPath string - ReadOnly bool - BandwidthMaximum uint64 - IOPSMaximum uint64 - CreateInUtilityVM bool -} - -type MappedPipe struct { - HostPath string - ContainerPipeName string -} - -type HvRuntime struct { - ImagePath string `json:",omitempty"` - SkipTemplate bool `json:",omitempty"` - LinuxInitrdFile string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM - LinuxKernelFile string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM - LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode - BootSource string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD - WritableBootSource bool `json:",omitempty"` // Linux Utility VM booting from VHD -} - -type MappedVirtualDisk struct { - HostPath string `json:",omitempty"` // Path to VHD on the host - ContainerPath string // Platform-specific mount point path in the container - CreateInUtilityVM bool `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Cache string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing" - AttachOnly bool `json:",omitempty:` -} - -// ContainerConfig is used as both the input of CreateContainer -// and to convert the parameters to JSON for passing onto the HCS -type ContainerConfig struct { - SystemType string // HCS requires this to be hard-coded to "Container" - Name string // Name of the container. We use the docker ID. - Owner string `json:",omitempty"` // The management platform that created this container - VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID} - IgnoreFlushesDuringBoot bool `json:",omitempty"` // Optimization hint for container startup in Windows - LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID - Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID - Credentials string `json:",omitempty"` // Credentials information - ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container. - ProcessorWeight uint64 `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares. - ProcessorMaximum int64 `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit. - StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS - StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second - StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller - MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes - HostName string `json:",omitempty"` // Hostname - MappedDirectories []MappedDir `json:",omitempty"` // List of mapped directories (volumes/mounts) - MappedPipes []MappedPipe `json:",omitempty"` // List of mapped Windows named pipes - HvPartition bool // True if it a Hyper-V Container - NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with. - EndpointList []string `json:",omitempty"` // List of networking endpoints to be attached to container - HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM - Servicing bool `json:",omitempty"` // True if this container is for servicing - AllowUnqualifiedDNSQuery bool `json:",omitempty"` // True to allow unqualified DNS name resolution - DNSSearchList string `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution - ContainerType string `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise. - TerminateOnLastHandleClosed bool `json:",omitempty"` // Should HCS terminate the container once all handles have been closed - MappedVirtualDisks []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start -} - -type ComputeSystemQuery struct { - IDs []string `json:"Ids,omitempty"` - Types []string `json:",omitempty"` - Names []string `json:",omitempty"` - Owners []string `json:",omitempty"` -} - -// Container represents a created (but not necessarily running) container. -type Container interface { - // Start synchronously starts the container. - Start() error - - // Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds. - Shutdown() error - - // Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds. - Terminate() error - - // Waits synchronously waits for the container to shutdown or terminate. - Wait() error - - // WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It - // returns false if timeout occurs. - WaitTimeout(time.Duration) error - - // Pause pauses the execution of a container. - Pause() error - - // Resume resumes the execution of a container. - Resume() error - - // HasPendingUpdates returns true if the container has updates pending to install. - HasPendingUpdates() (bool, error) - - // Statistics returns statistics for a container. - Statistics() (Statistics, error) - - // ProcessList returns details for the processes in a container. - ProcessList() ([]ProcessListItem, error) - - // MappedVirtualDisks returns virtual disks mapped to a utility VM, indexed by controller - MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) - - // CreateProcess launches a new process within the container. - CreateProcess(c *ProcessConfig) (Process, error) - - // OpenProcess gets an interface to an existing process within the container. - OpenProcess(pid int) (Process, error) - - // Close cleans up any state associated with the container but does not terminate or wait for it. - Close() error - - // Modify the System - Modify(config *ResourceModificationRequestResponse) error -} - -// Process represents a running or exited process. -type Process interface { - // Pid returns the process ID of the process within the container. - Pid() int - - // Kill signals the process to terminate but does not wait for it to finish terminating. - Kill() error - - // Wait waits for the process to exit. - Wait() error - - // WaitTimeout waits for the process to exit or the duration to elapse. It returns - // false if timeout occurs. - WaitTimeout(time.Duration) error - - // ExitCode returns the exit code of the process. The process must have - // already terminated. - ExitCode() (int, error) - - // ResizeConsole resizes the console of the process. - ResizeConsole(width, height uint16) error - - // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing - // these pipes does not close the underlying pipes; it should be possible to - // call this multiple times to get multiple interfaces. - Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) - - // CloseStdin closes the write side of the stdin pipe so that the process is - // notified on the read side that there is no more data in stdin. - CloseStdin() error - - // Close cleans up any state associated with the process but does not kill - // or wait on it. - Close() error -} diff --git a/vendor/github.com/Microsoft/hcsshim/layerexists.go b/vendor/github.com/Microsoft/hcsshim/layerexists.go deleted file mode 100644 index fe46f404c3..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/layerexists.go +++ /dev/null @@ -1,30 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// LayerExists will return true if a layer with the given id exists and is known -// to the system. -func LayerExists(info DriverInfo, id string) (bool, error) { - title := "hcsshim::LayerExists " - logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return false, err - } - - // Call the procedure itself. - var exists uint32 - - err = layerExists(&infop, id, &exists) - if err != nil { - err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) - logrus.Error(err) - return false, err - } - - logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists) - return exists != 0, nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/layerutils.go b/vendor/github.com/Microsoft/hcsshim/layerutils.go deleted file mode 100644 index c0e5503773..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/layerutils.go +++ /dev/null @@ -1,111 +0,0 @@ -package hcsshim - -// This file contains utility functions to support storage (graph) related -// functionality. - -import ( - "path/filepath" - "syscall" - - "github.com/sirupsen/logrus" -) - -/* To pass into syscall, we need a struct matching the following: -enum GraphDriverType -{ - DiffDriver, - FilterDriver -}; - -struct DriverInfo { - GraphDriverType Flavour; - LPCWSTR HomeDir; -}; -*/ -type DriverInfo struct { - Flavour int - HomeDir string -} - -type driverInfo struct { - Flavour int - HomeDirp *uint16 -} - -func convertDriverInfo(info DriverInfo) (driverInfo, error) { - homedirp, err := syscall.UTF16PtrFromString(info.HomeDir) - if err != nil { - logrus.Debugf("Failed conversion of home to pointer for driver info: %s", err.Error()) - return driverInfo{}, err - } - - return driverInfo{ - Flavour: info.Flavour, - HomeDirp: homedirp, - }, nil -} - -/* To pass into syscall, we need a struct matching the following: -typedef struct _WC_LAYER_DESCRIPTOR { - - // - // The ID of the layer - // - - GUID LayerId; - - // - // Additional flags - // - - union { - struct { - ULONG Reserved : 31; - ULONG Dirty : 1; // Created from sandbox as a result of snapshot - }; - ULONG Value; - } Flags; - - // - // Path to the layer root directory, null-terminated - // - - PCWSTR Path; - -} WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR; -*/ -type WC_LAYER_DESCRIPTOR struct { - LayerId GUID - Flags uint32 - Pathp *uint16 -} - -func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, error) { - // Array of descriptors that gets constructed. - var layers []WC_LAYER_DESCRIPTOR - - for i := 0; i < len(parentLayerPaths); i++ { - // Create a layer descriptor, using the folder name - // as the source for a GUID LayerId - _, folderName := filepath.Split(parentLayerPaths[i]) - g, err := NameToGuid(folderName) - if err != nil { - logrus.Debugf("Failed to convert name to guid %s", err) - return nil, err - } - - p, err := syscall.UTF16PtrFromString(parentLayerPaths[i]) - if err != nil { - logrus.Debugf("Failed conversion of parentLayerPath to pointer %s", err) - return nil, err - } - - layers = append(layers, WC_LAYER_DESCRIPTOR{ - LayerId: g, - Flags: 0, - Pathp: p, - }) - } - - return layers, nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/legacy.go b/vendor/github.com/Microsoft/hcsshim/legacy.go deleted file mode 100644 index 673a4f8795..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/legacy.go +++ /dev/null @@ -1,758 +0,0 @@ -package hcsshim - -import ( - "bufio" - "encoding/binary" - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "syscall" - - "github.com/Microsoft/go-winio" -) - -var errorIterationCanceled = errors.New("") - -var mutatedUtilityVMFiles = map[string]bool{ - `EFI\Microsoft\Boot\BCD`: true, - `EFI\Microsoft\Boot\BCD.LOG`: true, - `EFI\Microsoft\Boot\BCD.LOG1`: true, - `EFI\Microsoft\Boot\BCD.LOG2`: true, -} - -const ( - filesPath = `Files` - hivesPath = `Hives` - utilityVMPath = `UtilityVM` - utilityVMFilesPath = `UtilityVM\Files` -) - -func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) { - return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition) -} - -func makeLongAbsPath(path string) (string, error) { - if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) { - return path, nil - } - if !filepath.IsAbs(path) { - absPath, err := filepath.Abs(path) - if err != nil { - return "", err - } - path = absPath - } - if strings.HasPrefix(path, `\\`) { - return `\\?\UNC\` + path[2:], nil - } - return `\\?\` + path, nil -} - -func hasPathPrefix(p, prefix string) bool { - return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\' -} - -type fileEntry struct { - path string - fi os.FileInfo - err error -} - -type legacyLayerReader struct { - root string - result chan *fileEntry - proceed chan bool - currentFile *os.File - backupReader *winio.BackupFileReader -} - -// newLegacyLayerReader returns a new LayerReader that can read the Windows -// container layer transport format from disk. -func newLegacyLayerReader(root string) *legacyLayerReader { - r := &legacyLayerReader{ - root: root, - result: make(chan *fileEntry), - proceed: make(chan bool), - } - go r.walk() - return r -} - -func readTombstones(path string) (map[string]([]string), error) { - tf, err := os.Open(filepath.Join(path, "tombstones.txt")) - if err != nil { - return nil, err - } - defer tf.Close() - s := bufio.NewScanner(tf) - if !s.Scan() || s.Text() != "\xef\xbb\xbfVersion 1.0" { - return nil, errors.New("Invalid tombstones file") - } - - ts := make(map[string]([]string)) - for s.Scan() { - t := filepath.Join(filesPath, s.Text()[1:]) // skip leading `\` - dir := filepath.Dir(t) - ts[dir] = append(ts[dir], t) - } - if err = s.Err(); err != nil { - return nil, err - } - - return ts, nil -} - -func (r *legacyLayerReader) walkUntilCancelled() error { - root, err := makeLongAbsPath(r.root) - if err != nil { - return err - } - - r.root = root - ts, err := readTombstones(r.root) - if err != nil { - return err - } - - err = filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - // Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048. - // Handle failure from what may be a golang bug in the conversion of - // UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat - // which is called by filepath.Walk will fail when a filename contains - // unicode characters. Skip the recycle bin regardless which is goodness. - if strings.HasPrefix(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) { - return filepath.SkipDir - } - - if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") { - return nil - } - - r.result <- &fileEntry{path, info, nil} - if !<-r.proceed { - return errorIterationCanceled - } - - // List all the tombstones. - if info.IsDir() { - relPath, err := filepath.Rel(r.root, path) - if err != nil { - return err - } - if dts, ok := ts[relPath]; ok { - for _, t := range dts { - r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil} - if !<-r.proceed { - return errorIterationCanceled - } - } - } - } - return nil - }) - if err == errorIterationCanceled { - return nil - } - if err == nil { - return io.EOF - } - return err -} - -func (r *legacyLayerReader) walk() { - defer close(r.result) - if !<-r.proceed { - return - } - - err := r.walkUntilCancelled() - if err != nil { - for { - r.result <- &fileEntry{err: err} - if !<-r.proceed { - return - } - } - } -} - -func (r *legacyLayerReader) reset() { - if r.backupReader != nil { - r.backupReader.Close() - r.backupReader = nil - } - if r.currentFile != nil { - r.currentFile.Close() - r.currentFile = nil - } -} - -func findBackupStreamSize(r io.Reader) (int64, error) { - br := winio.NewBackupStreamReader(r) - for { - hdr, err := br.Next() - if err != nil { - if err == io.EOF { - err = nil - } - return 0, err - } - if hdr.Id == winio.BackupData { - return hdr.Size, nil - } - } -} - -func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) { - r.reset() - r.proceed <- true - fe := <-r.result - if fe == nil { - err = errors.New("LegacyLayerReader closed") - return - } - if fe.err != nil { - err = fe.err - return - } - - path, err = filepath.Rel(r.root, fe.path) - if err != nil { - return - } - - if fe.fi == nil { - // This is a tombstone. Return a nil fileInfo. - return - } - - if fe.fi.IsDir() && hasPathPrefix(path, filesPath) { - fe.path += ".$wcidirs$" - } - - f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING) - if err != nil { - return - } - defer func() { - if f != nil { - f.Close() - } - }() - - fileInfo, err = winio.GetFileBasicInfo(f) - if err != nil { - return - } - - if !hasPathPrefix(path, filesPath) { - size = fe.fi.Size() - r.backupReader = winio.NewBackupFileReader(f, false) - if path == hivesPath || path == filesPath { - // The Hives directory has a non-deterministic file time because of the - // nature of the import process. Use the times from System_Delta. - var g *os.File - g, err = os.Open(filepath.Join(r.root, hivesPath, `System_Delta`)) - if err != nil { - return - } - attr := fileInfo.FileAttributes - fileInfo, err = winio.GetFileBasicInfo(g) - g.Close() - if err != nil { - return - } - fileInfo.FileAttributes = attr - } - - // The creation time and access time get reset for files outside of the Files path. - fileInfo.CreationTime = fileInfo.LastWriteTime - fileInfo.LastAccessTime = fileInfo.LastWriteTime - - } else { - // The file attributes are written before the backup stream. - var attr uint32 - err = binary.Read(f, binary.LittleEndian, &attr) - if err != nil { - return - } - fileInfo.FileAttributes = uintptr(attr) - beginning := int64(4) - - // Find the accurate file size. - if !fe.fi.IsDir() { - size, err = findBackupStreamSize(f) - if err != nil { - err = &os.PathError{Op: "findBackupStreamSize", Path: fe.path, Err: err} - return - } - } - - // Return back to the beginning of the backup stream. - _, err = f.Seek(beginning, 0) - if err != nil { - return - } - } - - r.currentFile = f - f = nil - return -} - -func (r *legacyLayerReader) Read(b []byte) (int, error) { - if r.backupReader == nil { - if r.currentFile == nil { - return 0, io.EOF - } - return r.currentFile.Read(b) - } - return r.backupReader.Read(b) -} - -func (r *legacyLayerReader) Seek(offset int64, whence int) (int64, error) { - if r.backupReader == nil { - if r.currentFile == nil { - return 0, errors.New("no current file") - } - return r.currentFile.Seek(offset, whence) - } - return 0, errors.New("seek not supported on this stream") -} - -func (r *legacyLayerReader) Close() error { - r.proceed <- false - <-r.result - r.reset() - return nil -} - -type pendingLink struct { - Path, Target string -} - -type legacyLayerWriter struct { - root string - parentRoots []string - destRoot string - currentFile *os.File - backupWriter *winio.BackupFileWriter - tombstones []string - pathFixed bool - HasUtilityVM bool - uvmDi []dirInfo - addedFiles map[string]bool - PendingLinks []pendingLink -} - -// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer -// transport format to disk. -func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) *legacyLayerWriter { - return &legacyLayerWriter{ - root: root, - parentRoots: parentRoots, - destRoot: destRoot, - addedFiles: make(map[string]bool), - } -} - -func (w *legacyLayerWriter) init() error { - if !w.pathFixed { - path, err := makeLongAbsPath(w.root) - if err != nil { - return err - } - for i, p := range w.parentRoots { - w.parentRoots[i], err = makeLongAbsPath(p) - if err != nil { - return err - } - } - destPath, err := makeLongAbsPath(w.destRoot) - if err != nil { - return err - } - w.root = path - w.destRoot = destPath - w.pathFixed = true - } - return nil -} - -func (w *legacyLayerWriter) initUtilityVM() error { - if !w.HasUtilityVM { - err := os.Mkdir(filepath.Join(w.destRoot, utilityVMPath), 0) - if err != nil { - return err - } - // Server 2016 does not support multiple layers for the utility VM, so - // clone the utility VM from the parent layer into this layer. Use hard - // links to avoid unnecessary copying, since most of the files are - // immutable. - err = cloneTree(filepath.Join(w.parentRoots[0], utilityVMFilesPath), filepath.Join(w.destRoot, utilityVMFilesPath), mutatedUtilityVMFiles) - if err != nil { - return fmt.Errorf("cloning the parent utility VM image failed: %s", err) - } - w.HasUtilityVM = true - } - return nil -} - -func (w *legacyLayerWriter) reset() { - if w.backupWriter != nil { - w.backupWriter.Close() - w.backupWriter = nil - } - if w.currentFile != nil { - w.currentFile.Close() - w.currentFile = nil - } -} - -// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata -func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) { - createDisposition := uint32(syscall.CREATE_NEW) - if isDir { - err = os.Mkdir(destPath, 0) - if err != nil { - return nil, err - } - createDisposition = syscall.OPEN_EXISTING - } - - src, err := openFileOrDir(srcPath, syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, syscall.OPEN_EXISTING) - if err != nil { - return nil, err - } - defer src.Close() - srcr := winio.NewBackupFileReader(src, true) - defer srcr.Close() - - fileInfo, err = winio.GetFileBasicInfo(src) - if err != nil { - return nil, err - } - - dest, err := openFileOrDir(destPath, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition) - if err != nil { - return nil, err - } - defer dest.Close() - - err = winio.SetFileBasicInfo(dest, fileInfo) - if err != nil { - return nil, err - } - - destw := winio.NewBackupFileWriter(dest, true) - defer func() { - cerr := destw.Close() - if err == nil { - err = cerr - } - }() - - _, err = io.Copy(destw, srcr) - if err != nil { - return nil, err - } - - return fileInfo, nil -} - -// cloneTree clones a directory tree using hard links. It skips hard links for -// the file names in the provided map and just copies those files. -func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error { - var di []dirInfo - err := filepath.Walk(srcPath, func(srcFilePath string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - relPath, err := filepath.Rel(srcPath, srcFilePath) - if err != nil { - return err - } - destFilePath := filepath.Join(destPath, relPath) - - fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes - // Directories, reparse points, and files that will be mutated during - // utility VM import must be copied. All other files can be hard linked. - isReparsePoint := fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 - // In go1.9, FileInfo.IsDir() returns false if the directory is also a symlink. - // See: https://github.com/golang/go/commit/1989921aef60c83e6f9127a8448fb5ede10e9acc - // Fixes the problem by checking syscall.FILE_ATTRIBUTE_DIRECTORY directly - isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 - - if isDir || isReparsePoint || mutatedFiles[relPath] { - fi, err := copyFileWithMetadata(srcFilePath, destFilePath, isDir) - if err != nil { - return err - } - if isDir && !isReparsePoint { - di = append(di, dirInfo{path: destFilePath, fileInfo: *fi}) - } - } else { - err = os.Link(srcFilePath, destFilePath) - if err != nil { - return err - } - } - - // Don't recurse on reparse points in go1.8 and older. Filepath.Walk - // handles this in go1.9 and newer. - if isDir && isReparsePoint && shouldSkipDirectoryReparse { - return filepath.SkipDir - } - - return nil - }) - if err != nil { - return err - } - - return reapplyDirectoryTimes(di) -} - -func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error { - w.reset() - err := w.init() - if err != nil { - return err - } - - if name == utilityVMPath { - return w.initUtilityVM() - } - - if hasPathPrefix(name, utilityVMPath) { - if !w.HasUtilityVM { - return errors.New("missing UtilityVM directory") - } - if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath { - return errors.New("invalid UtilityVM layer") - } - path := filepath.Join(w.destRoot, name) - createDisposition := uint32(syscall.OPEN_EXISTING) - if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - st, err := os.Lstat(path) - if err != nil && !os.IsNotExist(err) { - return err - } - if st != nil { - // Delete the existing file/directory if it is not the same type as this directory. - existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes - if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { - if err = os.RemoveAll(path); err != nil { - return err - } - st = nil - } - } - if st == nil { - if err = os.Mkdir(path, 0); err != nil { - return err - } - } - if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - w.uvmDi = append(w.uvmDi, dirInfo{path: path, fileInfo: *fileInfo}) - } - } else { - // Overwrite any existing hard link. - err = os.Remove(path) - if err != nil && !os.IsNotExist(err) { - return err - } - createDisposition = syscall.CREATE_NEW - } - - f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition) - if err != nil { - return err - } - defer func() { - if f != nil { - f.Close() - os.Remove(path) - } - }() - - err = winio.SetFileBasicInfo(f, fileInfo) - if err != nil { - return err - } - - w.backupWriter = winio.NewBackupFileWriter(f, true) - w.currentFile = f - w.addedFiles[name] = true - f = nil - return nil - } - - path := filepath.Join(w.root, name) - if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - err := os.Mkdir(path, 0) - if err != nil { - return err - } - path += ".$wcidirs$" - } - - f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW) - if err != nil { - return err - } - defer func() { - if f != nil { - f.Close() - os.Remove(path) - } - }() - - strippedFi := *fileInfo - strippedFi.FileAttributes = 0 - err = winio.SetFileBasicInfo(f, &strippedFi) - if err != nil { - return err - } - - if hasPathPrefix(name, hivesPath) { - w.backupWriter = winio.NewBackupFileWriter(f, false) - } else { - // The file attributes are written before the stream. - err = binary.Write(f, binary.LittleEndian, uint32(fileInfo.FileAttributes)) - if err != nil { - return err - } - } - - w.currentFile = f - w.addedFiles[name] = true - f = nil - return nil -} - -func (w *legacyLayerWriter) AddLink(name string, target string) error { - w.reset() - err := w.init() - if err != nil { - return err - } - - var roots []string - if hasPathPrefix(target, filesPath) { - // Look for cross-layer hard link targets in the parent layers, since - // nothing is in the destination path yet. - roots = w.parentRoots - } else if hasPathPrefix(target, utilityVMFilesPath) { - // Since the utility VM is fully cloned into the destination path - // already, look for cross-layer hard link targets directly in the - // destination path. - roots = []string{w.destRoot} - } - - if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) { - return errors.New("invalid hard link in layer") - } - - // Find to try the target of the link in a previously added file. If that - // fails, search in parent layers. - var selectedRoot string - if _, ok := w.addedFiles[target]; ok { - selectedRoot = w.destRoot - } else { - for _, r := range roots { - if _, err = os.Lstat(filepath.Join(r, target)); err != nil { - if !os.IsNotExist(err) { - return err - } - } else { - selectedRoot = r - break - } - } - if selectedRoot == "" { - return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target) - } - } - // The link can't be written until after the ImportLayer call. - w.PendingLinks = append(w.PendingLinks, pendingLink{ - Path: filepath.Join(w.destRoot, name), - Target: filepath.Join(selectedRoot, target), - }) - w.addedFiles[name] = true - return nil -} - -func (w *legacyLayerWriter) Remove(name string) error { - if hasPathPrefix(name, filesPath) { - w.tombstones = append(w.tombstones, name[len(filesPath)+1:]) - } else if hasPathPrefix(name, utilityVMFilesPath) { - err := w.initUtilityVM() - if err != nil { - return err - } - // Make sure the path exists; os.RemoveAll will not fail if the file is - // already gone, and this needs to be a fatal error for diagnostics - // purposes. - path := filepath.Join(w.destRoot, name) - if _, err := os.Lstat(path); err != nil { - return err - } - err = os.RemoveAll(path) - if err != nil { - return err - } - } else { - return fmt.Errorf("invalid tombstone %s", name) - } - - return nil -} - -func (w *legacyLayerWriter) Write(b []byte) (int, error) { - if w.backupWriter == nil { - if w.currentFile == nil { - return 0, errors.New("closed") - } - return w.currentFile.Write(b) - } - return w.backupWriter.Write(b) -} - -func (w *legacyLayerWriter) Close() error { - w.reset() - err := w.init() - if err != nil { - return err - } - tf, err := os.Create(filepath.Join(w.root, "tombstones.txt")) - if err != nil { - return err - } - defer tf.Close() - _, err = tf.Write([]byte("\xef\xbb\xbfVersion 1.0\n")) - if err != nil { - return err - } - for _, t := range w.tombstones { - _, err = tf.Write([]byte(filepath.Join(`\`, t) + "\n")) - if err != nil { - return err - } - } - if w.HasUtilityVM { - err = reapplyDirectoryTimes(w.uvmDi) - if err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/legacy18.go b/vendor/github.com/Microsoft/hcsshim/legacy18.go deleted file mode 100644 index 578552f913..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/legacy18.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !go1.9 - -package hcsshim - -// Due to a bug in go1.8 and before, directory reparse points need to be skipped -// during filepath.Walk. This is fixed in go1.9 -var shouldSkipDirectoryReparse = true diff --git a/vendor/github.com/Microsoft/hcsshim/legacy19.go b/vendor/github.com/Microsoft/hcsshim/legacy19.go deleted file mode 100644 index 6aa1dc0584..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/legacy19.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build go1.9 - -package hcsshim - -// Due to a bug in go1.8 and before, directory reparse points need to be skipped -// during filepath.Walk. This is fixed in go1.9 -var shouldSkipDirectoryReparse = false diff --git a/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go deleted file mode 100644 index 82393ca367..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go +++ /dev/null @@ -1,934 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -mksyscall_windows generates windows system call bodies - -It parses all files specified on command line containing function -prototypes (like syscall_windows.go) and prints system call bodies -to standard output. - -The prototypes are marked by lines beginning with "//sys" and read -like func declarations if //sys is replaced by func, but: - -* The parameter lists must give a name for each argument. This - includes return parameters. - -* The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - -* If the return parameter is an error number, it must be named err. - -* If go func name needs to be different from it's winapi dll name, - the winapi name could be specified at the end, after "=" sign, like - //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA - -* Each function that returns err needs to supply a condition, that - return value of winapi will be tested against to detect failure. - This would set err to windows "last-error", otherwise it will be nil. - The value can be provided at end of //sys declaration, like - //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA - and is [failretval==0] by default. - -Usage: - mksyscall_windows [flags] [path ...] - -The flags are: - -output - Specify output file name (outputs to console if blank). - -trace - Generate print statement after every syscall. -*/ -package main - -import ( - "bufio" - "bytes" - "errors" - "flag" - "fmt" - "go/format" - "go/parser" - "go/token" - "io" - "io/ioutil" - "log" - "os" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "text/template" -) - -var ( - filename = flag.String("output", "", "output file name (standard output if omitted)") - printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall") - systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory") -) - -func trim(s string) string { - return strings.Trim(s, " \t") -} - -var packageName string - -func packagename() string { - return packageName -} - -func syscalldot() string { - if packageName == "syscall" { - return "" - } - return "syscall." -} - -// Param is function parameter -type Param struct { - Name string - Type string - fn *Fn - tmpVarIdx int -} - -// tmpVar returns temp variable name that will be used to represent p during syscall. -func (p *Param) tmpVar() string { - if p.tmpVarIdx < 0 { - p.tmpVarIdx = p.fn.curTmpVarIdx - p.fn.curTmpVarIdx++ - } - return fmt.Sprintf("_p%d", p.tmpVarIdx) -} - -// BoolTmpVarCode returns source code for bool temp variable. -func (p *Param) BoolTmpVarCode() string { - const code = `var %s uint32 - if %s { - %s = 1 - } else { - %s = 0 - }` - tmp := p.tmpVar() - return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) -} - -// SliceTmpVarCode returns source code for slice temp variable. -func (p *Param) SliceTmpVarCode() string { - const code = `var %s *%s - if len(%s) > 0 { - %s = &%s[0] - }` - tmp := p.tmpVar() - return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) -} - -// StringTmpVarCode returns source code for string temp variable. -func (p *Param) StringTmpVarCode() string { - errvar := p.fn.Rets.ErrorVarName() - if errvar == "" { - errvar = "_" - } - tmp := p.tmpVar() - const code = `var %s %s - %s, %s = %s(%s)` - s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) - if errvar == "-" { - return s - } - const morecode = ` - if %s != nil { - return - }` - return s + fmt.Sprintf(morecode, errvar) -} - -// TmpVarCode returns source code for temp variable. -func (p *Param) TmpVarCode() string { - switch { - case p.Type == "bool": - return p.BoolTmpVarCode() - case strings.HasPrefix(p.Type, "[]"): - return p.SliceTmpVarCode() - default: - return "" - } -} - -// TmpVarHelperCode returns source code for helper's temp variable. -func (p *Param) TmpVarHelperCode() string { - if p.Type != "string" { - return "" - } - return p.StringTmpVarCode() -} - -// SyscallArgList returns source code fragments representing p parameter -// in syscall. Slices are translated into 2 syscall parameters: pointer to -// the first element and length. -func (p *Param) SyscallArgList() []string { - t := p.HelperType() - var s string - switch { - case t[0] == '*': - s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name) - case t == "bool": - s = p.tmpVar() - case strings.HasPrefix(t, "[]"): - return []string{ - fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()), - fmt.Sprintf("uintptr(len(%s))", p.Name), - } - default: - s = p.Name - } - return []string{fmt.Sprintf("uintptr(%s)", s)} -} - -// IsError determines if p parameter is used to return error. -func (p *Param) IsError() bool { - return p.Name == "err" && p.Type == "error" -} - -// HelperType returns type of parameter p used in helper function. -func (p *Param) HelperType() string { - if p.Type == "string" { - return p.fn.StrconvType() - } - return p.Type -} - -// join concatenates parameters ps into a string with sep separator. -// Each parameter is converted into string by applying fn to it -// before conversion. -func join(ps []*Param, fn func(*Param) string, sep string) string { - if len(ps) == 0 { - return "" - } - a := make([]string, 0) - for _, p := range ps { - a = append(a, fn(p)) - } - return strings.Join(a, sep) -} - -// Rets describes function return parameters. -type Rets struct { - Name string - Type string - ReturnsError bool - FailCond string -} - -// ErrorVarName returns error variable name for r. -func (r *Rets) ErrorVarName() string { - if r.ReturnsError { - return "err" - } - if r.Type == "error" { - return r.Name - } - return "" -} - -// ToParams converts r into slice of *Param. -func (r *Rets) ToParams() []*Param { - ps := make([]*Param, 0) - if len(r.Name) > 0 { - ps = append(ps, &Param{Name: r.Name, Type: r.Type}) - } - if r.ReturnsError { - ps = append(ps, &Param{Name: "err", Type: "error"}) - } - return ps -} - -// List returns source code of syscall return parameters. -func (r *Rets) List() string { - s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ") - if len(s) > 0 { - s = "(" + s + ")" - } - return s -} - -// PrintList returns source code of trace printing part correspondent -// to syscall return values. -func (r *Rets) PrintList() string { - return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) -} - -// SetReturnValuesCode returns source code that accepts syscall return values. -func (r *Rets) SetReturnValuesCode() string { - if r.Name == "" && !r.ReturnsError { - return "" - } - retvar := "r0" - if r.Name == "" { - retvar = "r1" - } - errvar := "_" - if r.ReturnsError { - errvar = "e1" - } - return fmt.Sprintf("%s, _, %s := ", retvar, errvar) -} - -func (r *Rets) useLongHandleErrorCode(retvar string) string { - const code = `if %s { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = %sEINVAL - } - }` - cond := retvar + " == 0" - if r.FailCond != "" { - cond = strings.Replace(r.FailCond, "failretval", retvar, 1) - } - return fmt.Sprintf(code, cond, syscalldot()) -} - -// SetErrorCode returns source code that sets return parameters. -func (r *Rets) SetErrorCode() string { - const code = `if r0 != 0 { - %s = %sErrno(r0) - }` - const hrCode = `if int32(r0) < 0 { - %s = %sErrno(win32FromHresult(r0)) - }` - if r.Name == "" && !r.ReturnsError { - return "" - } - if r.Name == "" { - return r.useLongHandleErrorCode("r1") - } - if r.Type == "error" { - if r.Name == "hr" { - return fmt.Sprintf(hrCode, r.Name, syscalldot()) - } else { - return fmt.Sprintf(code, r.Name, syscalldot()) - } - } - s := "" - switch { - case r.Type[0] == '*': - s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type) - case r.Type == "bool": - s = fmt.Sprintf("%s = r0 != 0", r.Name) - default: - s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type) - } - if !r.ReturnsError { - return s - } - return s + "\n\t" + r.useLongHandleErrorCode(r.Name) -} - -// Fn describes syscall function. -type Fn struct { - Name string - Params []*Param - Rets *Rets - PrintTrace bool - confirmproc bool - dllname string - dllfuncname string - src string - // TODO: get rid of this field and just use parameter index instead - curTmpVarIdx int // insure tmp variables have uniq names -} - -// extractParams parses s to extract function parameters. -func extractParams(s string, f *Fn) ([]*Param, error) { - s = trim(s) - if s == "" { - return nil, nil - } - a := strings.Split(s, ",") - ps := make([]*Param, len(a)) - for i := range ps { - s2 := trim(a[i]) - b := strings.Split(s2, " ") - if len(b) != 2 { - b = strings.Split(s2, "\t") - if len(b) != 2 { - return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"") - } - } - ps[i] = &Param{ - Name: trim(b[0]), - Type: trim(b[1]), - fn: f, - tmpVarIdx: -1, - } - } - return ps, nil -} - -// extractSection extracts text out of string s starting after start -// and ending just before end. found return value will indicate success, -// and prefix, body and suffix will contain correspondent parts of string s. -func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) { - s = trim(s) - if strings.HasPrefix(s, string(start)) { - // no prefix - body = s[1:] - } else { - a := strings.SplitN(s, string(start), 2) - if len(a) != 2 { - return "", "", s, false - } - prefix = a[0] - body = a[1] - } - a := strings.SplitN(body, string(end), 2) - if len(a) != 2 { - return "", "", "", false - } - return prefix, a[0], a[1], true -} - -// newFn parses string s and return created function Fn. -func newFn(s string) (*Fn, error) { - s = trim(s) - f := &Fn{ - Rets: &Rets{}, - src: s, - PrintTrace: *printTraceFlag, - } - // function name and args - prefix, body, s, found := extractSection(s, '(', ')') - if !found || prefix == "" { - return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"") - } - f.Name = prefix - var err error - f.Params, err = extractParams(body, f) - if err != nil { - return nil, err - } - // return values - _, body, s, found = extractSection(s, '(', ')') - if found { - r, err := extractParams(body, f) - if err != nil { - return nil, err - } - switch len(r) { - case 0: - case 1: - if r[0].IsError() { - f.Rets.ReturnsError = true - } else { - f.Rets.Name = r[0].Name - f.Rets.Type = r[0].Type - } - case 2: - if !r[1].IsError() { - return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"") - } - f.Rets.ReturnsError = true - f.Rets.Name = r[0].Name - f.Rets.Type = r[0].Type - default: - return nil, errors.New("Too many return values in \"" + f.src + "\"") - } - } - // fail condition - _, body, s, found = extractSection(s, '[', ']') - if found { - f.Rets.FailCond = body - } - // dll and dll function names - s = trim(s) - if s == "" { - return f, nil - } - if !strings.HasPrefix(s, "=") { - return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") - } - s = trim(s[1:]) - a := strings.Split(s, ".") - switch len(a) { - case 1: - f.dllfuncname = a[0] - case 2: - f.dllname = a[0] - f.dllfuncname = a[1] - default: - return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") - } - if f.dllfuncname[len(f.dllfuncname)-1] == '?' { - f.confirmproc = true - f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] - } - return f, nil -} - -// DLLName returns DLL name for function f. -func (f *Fn) DLLName() string { - if f.dllname == "" { - return "kernel32" - } - return f.dllname -} - -// DLLName returns DLL function name for function f. -func (f *Fn) DLLFuncName() string { - if f.dllfuncname == "" { - return f.Name - } - return f.dllfuncname -} - -func (f *Fn) ConfirmProc() bool { - return f.confirmproc -} - -// ParamList returns source code for function f parameters. -func (f *Fn) ParamList() string { - return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ") -} - -// HelperParamList returns source code for helper function f parameters. -func (f *Fn) HelperParamList() string { - return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ") -} - -// ParamPrintList returns source code of trace printing part correspondent -// to syscall input parameters. -func (f *Fn) ParamPrintList() string { - return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) -} - -// ParamCount return number of syscall parameters for function f. -func (f *Fn) ParamCount() int { - n := 0 - for _, p := range f.Params { - n += len(p.SyscallArgList()) - } - return n -} - -// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... -// to use. It returns parameter count for correspondent SyscallX function. -func (f *Fn) SyscallParamCount() int { - n := f.ParamCount() - switch { - case n <= 3: - return 3 - case n <= 6: - return 6 - case n <= 9: - return 9 - case n <= 12: - return 12 - case n <= 15: - return 15 - default: - panic("too many arguments to system call") - } -} - -// Syscall determines which SyscallX function to use for function f. -func (f *Fn) Syscall() string { - c := f.SyscallParamCount() - if c == 3 { - return syscalldot() + "Syscall" - } - return syscalldot() + "Syscall" + strconv.Itoa(c) -} - -// SyscallParamList returns source code for SyscallX parameters for function f. -func (f *Fn) SyscallParamList() string { - a := make([]string, 0) - for _, p := range f.Params { - a = append(a, p.SyscallArgList()...) - } - for len(a) < f.SyscallParamCount() { - a = append(a, "0") - } - return strings.Join(a, ", ") -} - -// HelperCallParamList returns source code of call into function f helper. -func (f *Fn) HelperCallParamList() string { - a := make([]string, 0, len(f.Params)) - for _, p := range f.Params { - s := p.Name - if p.Type == "string" { - s = p.tmpVar() - } - a = append(a, s) - } - return strings.Join(a, ", ") -} - -// IsUTF16 is true, if f is W (utf16) function. It is false -// for all A (ascii) functions. -func (_ *Fn) IsUTF16() bool { - return true -} - -// StrconvFunc returns name of Go string to OS string function for f. -func (f *Fn) StrconvFunc() string { - if f.IsUTF16() { - return syscalldot() + "UTF16PtrFromString" - } - return syscalldot() + "BytePtrFromString" -} - -// StrconvType returns Go type name used for OS string for f. -func (f *Fn) StrconvType() string { - if f.IsUTF16() { - return "*uint16" - } - return "*byte" -} - -// HasStringParam is true, if f has at least one string parameter. -// Otherwise it is false. -func (f *Fn) HasStringParam() bool { - for _, p := range f.Params { - if p.Type == "string" { - return true - } - } - return false -} - -var uniqDllFuncName = make(map[string]bool) - -// IsNotDuplicate is true if f is not a duplicated function -func (f *Fn) IsNotDuplicate() bool { - funcName := f.DLLFuncName() - if uniqDllFuncName[funcName] == false { - uniqDllFuncName[funcName] = true - return true - } - return false -} - -// HelperName returns name of function f helper. -func (f *Fn) HelperName() string { - if !f.HasStringParam() { - return f.Name - } - return "_" + f.Name -} - -// Source files and functions. -type Source struct { - Funcs []*Fn - Files []string - StdLibImports []string - ExternalImports []string -} - -func (src *Source) Import(pkg string) { - src.StdLibImports = append(src.StdLibImports, pkg) - sort.Strings(src.StdLibImports) -} - -func (src *Source) ExternalImport(pkg string) { - src.ExternalImports = append(src.ExternalImports, pkg) - sort.Strings(src.ExternalImports) -} - -// ParseFiles parses files listed in fs and extracts all syscall -// functions listed in sys comments. It returns source files -// and functions collection *Source if successful. -func ParseFiles(fs []string) (*Source, error) { - src := &Source{ - Funcs: make([]*Fn, 0), - Files: make([]string, 0), - StdLibImports: []string{ - "unsafe", - }, - ExternalImports: make([]string, 0), - } - for _, file := range fs { - if err := src.ParseFile(file); err != nil { - return nil, err - } - } - return src, nil -} - -// DLLs return dll names for a source set src. -func (src *Source) DLLs() []string { - uniq := make(map[string]bool) - r := make([]string, 0) - for _, f := range src.Funcs { - name := f.DLLName() - if _, found := uniq[name]; !found { - uniq[name] = true - r = append(r, name) - } - } - return r -} - -// ParseFile adds additional file path to a source set src. -func (src *Source) ParseFile(path string) error { - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() - - s := bufio.NewScanner(file) - for s.Scan() { - t := trim(s.Text()) - if len(t) < 7 { - continue - } - if !strings.HasPrefix(t, "//sys") { - continue - } - t = t[5:] - if !(t[0] == ' ' || t[0] == '\t') { - continue - } - f, err := newFn(t[1:]) - if err != nil { - return err - } - src.Funcs = append(src.Funcs, f) - } - if err := s.Err(); err != nil { - return err - } - src.Files = append(src.Files, path) - - // get package name - fset := token.NewFileSet() - _, err = file.Seek(0, 0) - if err != nil { - return err - } - pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) - if err != nil { - return err - } - packageName = pkg.Name.Name - - return nil -} - -// IsStdRepo returns true if src is part of standard library. -func (src *Source) IsStdRepo() (bool, error) { - if len(src.Files) == 0 { - return false, errors.New("no input files provided") - } - abspath, err := filepath.Abs(src.Files[0]) - if err != nil { - return false, err - } - goroot := runtime.GOROOT() - if runtime.GOOS == "windows" { - abspath = strings.ToLower(abspath) - goroot = strings.ToLower(goroot) - } - sep := string(os.PathSeparator) - if !strings.HasSuffix(goroot, sep) { - goroot += sep - } - return strings.HasPrefix(abspath, goroot), nil -} - -// Generate output source file from a source set src. -func (src *Source) Generate(w io.Writer) error { - const ( - pkgStd = iota // any package in std library - pkgXSysWindows // x/sys/windows package - pkgOther - ) - isStdRepo, err := src.IsStdRepo() - if err != nil { - return err - } - var pkgtype int - switch { - case isStdRepo: - pkgtype = pkgStd - case packageName == "windows": - // TODO: this needs better logic than just using package name - pkgtype = pkgXSysWindows - default: - pkgtype = pkgOther - } - if *systemDLL { - switch pkgtype { - case pkgStd: - src.Import("internal/syscall/windows/sysdll") - case pkgXSysWindows: - default: - src.ExternalImport("golang.org/x/sys/windows") - } - } - src.ExternalImport("github.com/Microsoft/go-winio") - if packageName != "syscall" { - src.Import("syscall") - } - funcMap := template.FuncMap{ - "packagename": packagename, - "syscalldot": syscalldot, - "newlazydll": func(dll string) string { - arg := "\"" + dll + ".dll\"" - if !*systemDLL { - return syscalldot() + "NewLazyDLL(" + arg + ")" - } - switch pkgtype { - case pkgStd: - return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))" - case pkgXSysWindows: - return "NewLazySystemDLL(" + arg + ")" - default: - return "windows.NewLazySystemDLL(" + arg + ")" - } - }, - } - t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate)) - err = t.Execute(w, src) - if err != nil { - return errors.New("Failed to execute template: " + err.Error()) - } - return nil -} - -func usage() { - fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") - flag.PrintDefaults() - os.Exit(1) -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - src, err := ParseFiles(flag.Args()) - if err != nil { - log.Fatal(err) - } - - var buf bytes.Buffer - if err := src.Generate(&buf); err != nil { - log.Fatal(err) - } - - data, err := format.Source(buf.Bytes()) - if err != nil { - log.Fatal(err) - } - if *filename == "" { - _, err = os.Stdout.Write(data) - } else { - err = ioutil.WriteFile(*filename, data, 0644) - } - if err != nil { - log.Fatal(err) - } -} - -// TODO: use println instead to print in the following template -const srcTemplate = ` - -{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT - -package {{packagename}} - -import ( -{{range .StdLibImports}}"{{.}}" -{{end}} - -{{range .ExternalImports}}"{{.}}" -{{end}} -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING) -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e {{syscalldot}}Errno) error { - switch e { - case 0: - return nil - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( -{{template "dlls" .}} -{{template "funcnames" .}}) -{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}} -{{end}} - -{{/* help functions */}} - -{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}} -{{end}}{{end}} - -{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}} -{{end}}{{end}} - -{{define "helperbody"}} -func {{.Name}}({{.ParamList}}) {{template "results" .}}{ -{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}}) -} -{{end}} - -{{define "funcbody"}} -func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{ -{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}} -{{template "seterror" .}}{{template "printtrace" .}} return -} -{{end}} - -{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}} -{{end}}{{end}}{{end}} - -{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}} -{{end}}{{end}}{{end}} - -{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}} - -{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}} - -{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil { - return -} -{{end}}{{end}} - - -{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}} -{{end}}{{end}} - -{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n") -{{end}}{{end}} - -` diff --git a/vendor/github.com/Microsoft/hcsshim/nametoguid.go b/vendor/github.com/Microsoft/hcsshim/nametoguid.go deleted file mode 100644 index b7c6d020c6..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/nametoguid.go +++ /dev/null @@ -1,20 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// NameToGuid converts the given string into a GUID using the algorithm in the -// Host Compute Service, ensuring GUIDs generated with the same string are common -// across all clients. -func NameToGuid(name string) (id GUID, err error) { - title := "hcsshim::NameToGuid " - logrus.Debugf(title+"Name %s", name) - - err = nameToGuid(name, &id) - if err != nil { - err = makeErrorf(err, title, "name=%s", name) - logrus.Error(err) - return - } - - return -} diff --git a/vendor/github.com/Microsoft/hcsshim/preparelayer.go b/vendor/github.com/Microsoft/hcsshim/preparelayer.go deleted file mode 100644 index 5c5b618411..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/preparelayer.go +++ /dev/null @@ -1,46 +0,0 @@ -package hcsshim - -import ( - "sync" - - "github.com/sirupsen/logrus" -) - -var prepareLayerLock sync.Mutex - -// PrepareLayer finds a mounted read-write layer matching layerId and enables the -// the filesystem filter for use on that layer. This requires the paths to all -// parent layers, and is necessary in order to view or interact with the layer -// as an actual filesystem (reading and writing files, creating directories, etc). -// Disabling the filter must be done via UnprepareLayer. -func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error { - title := "hcsshim::PrepareLayer " - logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) - - // Generate layer descriptors - layers, err := layerPathsToDescriptors(parentLayerPaths) - if err != nil { - return err - } - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - // This lock is a temporary workaround for a Windows bug. Only allowing one - // call to prepareLayer at a time vastly reduces the chance of a timeout. - prepareLayerLock.Lock() - defer prepareLayerLock.Unlock() - err = prepareLayer(&infop, layerId, layers) - if err != nil { - err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour=%d layerId=%s", info.Flavour, layerId) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/process.go b/vendor/github.com/Microsoft/hcsshim/process.go deleted file mode 100644 index faee2cfeeb..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/process.go +++ /dev/null @@ -1,384 +0,0 @@ -package hcsshim - -import ( - "encoding/json" - "io" - "sync" - "syscall" - "time" - - "github.com/sirupsen/logrus" -) - -// ContainerError is an error encountered in HCS -type process struct { - handleLock sync.RWMutex - handle hcsProcess - processID int - container *container - cachedPipes *cachedPipes - callbackNumber uintptr -} - -type cachedPipes struct { - stdIn syscall.Handle - stdOut syscall.Handle - stdErr syscall.Handle -} - -type processModifyRequest struct { - Operation string - ConsoleSize *consoleSize `json:",omitempty"` - CloseHandle *closeHandle `json:",omitempty"` -} - -type consoleSize struct { - Height uint16 - Width uint16 -} - -type closeHandle struct { - Handle string -} - -type processStatus struct { - ProcessID uint32 - Exited bool - ExitCode uint32 - LastWaitResult int32 -} - -const ( - stdIn string = "StdIn" - stdOut string = "StdOut" - stdErr string = "StdErr" -) - -const ( - modifyConsoleSize string = "ConsoleSize" - modifyCloseHandle string = "CloseHandle" -) - -// Pid returns the process ID of the process within the container. -func (process *process) Pid() int { - return process.processID -} - -// Kill signals the process to terminate but does not wait for it to finish terminating. -func (process *process) Kill() error { - process.handleLock.RLock() - defer process.handleLock.RUnlock() - operation := "Kill" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) - } - - var resultp *uint16 - err := hcsTerminateProcess(process.handle, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -// Wait waits for the process to exit. -func (process *process) Wait() error { - operation := "Wait" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) - if err != nil { - return makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -// WaitTimeout waits for the process to exit or the duration to elapse. It returns -// false if timeout occurs. -func (process *process) WaitTimeout(timeout time.Duration) error { - operation := "WaitTimeout" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) - if err != nil { - return makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -// ExitCode returns the exit code of the process. The process must have -// already terminated. -func (process *process) ExitCode() (int, error) { - process.handleLock.RLock() - defer process.handleLock.RUnlock() - operation := "ExitCode" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - if process.handle == 0 { - return 0, makeProcessError(process, operation, "", ErrAlreadyClosed) - } - - properties, err := process.properties() - if err != nil { - return 0, makeProcessError(process, operation, "", err) - } - - if properties.Exited == false { - return 0, makeProcessError(process, operation, "", ErrInvalidProcessState) - } - - if properties.LastWaitResult != 0 { - return 0, makeProcessError(process, operation, "", syscall.Errno(properties.LastWaitResult)) - } - - logrus.Debugf(title+" succeeded processid=%d exitCode=%d", process.processID, properties.ExitCode) - return int(properties.ExitCode), nil -} - -// ResizeConsole resizes the console of the process. -func (process *process) ResizeConsole(width, height uint16) error { - process.handleLock.RLock() - defer process.handleLock.RUnlock() - operation := "ResizeConsole" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) - } - - modifyRequest := processModifyRequest{ - Operation: modifyConsoleSize, - ConsoleSize: &consoleSize{ - Height: height, - Width: width, - }, - } - - modifyRequestb, err := json.Marshal(modifyRequest) - if err != nil { - return err - } - - modifyRequestStr := string(modifyRequestb) - - var resultp *uint16 - err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -func (process *process) properties() (*processStatus, error) { - operation := "properties" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - var ( - resultp *uint16 - propertiesp *uint16 - ) - err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, err - } - - if propertiesp == nil { - return nil, ErrUnexpectedValue - } - propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp) - - properties := &processStatus{} - if err := json.Unmarshal(propertiesRaw, properties); err != nil { - return nil, err - } - - logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw) - return properties, nil -} - -// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing -// these pipes does not close the underlying pipes; it should be possible to -// call this multiple times to get multiple interfaces. -func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { - process.handleLock.RLock() - defer process.handleLock.RUnlock() - operation := "Stdio" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - if process.handle == 0 { - return nil, nil, nil, makeProcessError(process, operation, "", ErrAlreadyClosed) - } - - var stdIn, stdOut, stdErr syscall.Handle - - if process.cachedPipes == nil { - var ( - processInfo hcsProcessInformation - resultp *uint16 - ) - err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return nil, nil, nil, makeProcessError(process, operation, "", err) - } - - stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError - } else { - // Use cached pipes - stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr - - // Invalidate the cache - process.cachedPipes = nil - } - - pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) - if err != nil { - return nil, nil, nil, makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return pipes[0], pipes[1], pipes[2], nil -} - -// CloseStdin closes the write side of the stdin pipe so that the process is -// notified on the read side that there is no more data in stdin. -func (process *process) CloseStdin() error { - process.handleLock.RLock() - defer process.handleLock.RUnlock() - operation := "CloseStdin" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) - } - - modifyRequest := processModifyRequest{ - Operation: modifyCloseHandle, - CloseHandle: &closeHandle{ - Handle: stdIn, - }, - } - - modifyRequestb, err := json.Marshal(modifyRequest) - if err != nil { - return err - } - - modifyRequestStr := string(modifyRequestb) - - var resultp *uint16 - err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) - err = processHcsResult(err, resultp) - if err != nil { - return makeProcessError(process, operation, "", err) - } - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -// Close cleans up any state associated with the process but does not kill -// or wait on it. -func (process *process) Close() error { - process.handleLock.Lock() - defer process.handleLock.Unlock() - operation := "Close" - title := "HCSShim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) - - // Don't double free this - if process.handle == 0 { - return nil - } - - if err := process.unregisterCallback(); err != nil { - return makeProcessError(process, operation, "", err) - } - - if err := hcsCloseProcess(process.handle); err != nil { - return makeProcessError(process, operation, "", err) - } - - process.handle = 0 - - logrus.Debugf(title+" succeeded processid=%d", process.processID) - return nil -} - -func (process *process) registerCallback() error { - context := ¬ifcationWatcherContext{ - channels: newChannels(), - } - - callbackMapLock.Lock() - callbackNumber := nextCallback - nextCallback++ - callbackMap[callbackNumber] = context - callbackMapLock.Unlock() - - var callbackHandle hcsCallback - err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) - if err != nil { - return err - } - context.handle = callbackHandle - process.callbackNumber = callbackNumber - - return nil -} - -func (process *process) unregisterCallback() error { - callbackNumber := process.callbackNumber - - callbackMapLock.RLock() - context := callbackMap[callbackNumber] - callbackMapLock.RUnlock() - - if context == nil { - return nil - } - - handle := context.handle - - if handle == 0 { - return nil - } - - // hcsUnregisterProcessCallback has its own syncronization - // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. - err := hcsUnregisterProcessCallback(handle) - if err != nil { - return err - } - - closeChannels(context.channels) - - callbackMapLock.Lock() - callbackMap[callbackNumber] = nil - callbackMapLock.Unlock() - - handle = 0 - - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/processimage.go b/vendor/github.com/Microsoft/hcsshim/processimage.go deleted file mode 100644 index fadb1b92c5..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/processimage.go +++ /dev/null @@ -1,23 +0,0 @@ -package hcsshim - -import "os" - -// ProcessBaseLayer post-processes a base layer that has had its files extracted. -// The files should have been extracted to \Files. -func ProcessBaseLayer(path string) error { - err := processBaseImage(path) - if err != nil { - return &os.PathError{Op: "ProcessBaseLayer", Path: path, Err: err} - } - return nil -} - -// ProcessUtilityVMImage post-processes a utility VM image that has had its files extracted. -// The files should have been extracted to \Files. -func ProcessUtilityVMImage(path string) error { - err := processUtilityImage(path) - if err != nil { - return &os.PathError{Op: "ProcessUtilityVMImage", Path: path, Err: err} - } - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go b/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go deleted file mode 100644 index e8a3b507bf..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go +++ /dev/null @@ -1,27 +0,0 @@ -package hcsshim - -import "github.com/sirupsen/logrus" - -// UnprepareLayer disables the filesystem filter for the read-write layer with -// the given id. -func UnprepareLayer(info DriverInfo, layerId string) error { - title := "hcsshim::UnprepareLayer " - logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) - - // Convert info to API calling convention - infop, err := convertDriverInfo(info) - if err != nil { - logrus.Error(err) - return err - } - - err = unprepareLayer(&infop, layerId) - if err != nil { - err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) - logrus.Error(err) - return err - } - - logrus.Debugf(title+"succeeded flavour %d layerId=%s", info.Flavour, layerId) - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/utils.go b/vendor/github.com/Microsoft/hcsshim/utils.go deleted file mode 100644 index bd6e2d94ab..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/utils.go +++ /dev/null @@ -1,33 +0,0 @@ -package hcsshim - -import ( - "io" - "syscall" - - "github.com/Microsoft/go-winio" -) - -// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles -// if there is an error. -func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) { - fs := make([]io.ReadWriteCloser, len(hs)) - for i, h := range hs { - if h != syscall.Handle(0) { - if err == nil { - fs[i], err = winio.MakeOpenFile(h) - } - if err != nil { - syscall.Close(h) - } - } - } - if err != nil { - for _, f := range fs { - if f != nil { - f.Close() - } - } - return nil, err - } - return fs, nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/version.go b/vendor/github.com/Microsoft/hcsshim/version.go deleted file mode 100644 index ae10c23d42..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/version.go +++ /dev/null @@ -1,7 +0,0 @@ -package hcsshim - -// IsTP4 returns whether the currently running Windows build is at least TP4. -func IsTP4() bool { - // HNSCall was not present in TP4 - return procHNSCall.Find() != nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/waithelper.go b/vendor/github.com/Microsoft/hcsshim/waithelper.go deleted file mode 100644 index b7be20ea0c..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/waithelper.go +++ /dev/null @@ -1,63 +0,0 @@ -package hcsshim - -import ( - "time" - - "github.com/sirupsen/logrus" -) - -func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { - err = processHcsResult(err, resultp) - if IsPending(err) { - return waitForNotification(callbackNumber, expectedNotification, timeout) - } - - return err -} - -func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { - callbackMapLock.RLock() - channels := callbackMap[callbackNumber].channels - callbackMapLock.RUnlock() - - expectedChannel := channels[expectedNotification] - if expectedChannel == nil { - logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification) - return ErrInvalidNotificationType - } - - var c <-chan time.Time - if timeout != nil { - timer := time.NewTimer(*timeout) - c = timer.C - defer timer.Stop() - } - - select { - case err, ok := <-expectedChannel: - if !ok { - return ErrHandleClose - } - return err - case err, ok := <-channels[hcsNotificationSystemExited]: - if !ok { - return ErrHandleClose - } - // If the expected notification is hcsNotificationSystemExited which of the two selects - // chosen is random. Return the raw error if hcsNotificationSystemExited is expected - if channels[hcsNotificationSystemExited] == expectedChannel { - return err - } - return ErrUnexpectedContainerExit - case _, ok := <-channels[hcsNotificationServiceDisconnect]: - if !ok { - return ErrHandleClose - } - // hcsNotificationServiceDisconnect should never be an expected notification - // it does not need the same handling as hcsNotificationSystemExited - return ErrUnexpectedProcessAbort - case <-c: - return ErrTimeout - } - return nil -} diff --git a/vendor/github.com/Microsoft/hcsshim/zhcsshim.go b/vendor/github.com/Microsoft/hcsshim/zhcsshim.go deleted file mode 100644 index 5d1a851ae8..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/zhcsshim.go +++ /dev/null @@ -1,1042 +0,0 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT - -package hcsshim - -import ( - "syscall" - "unsafe" - - "github.com/Microsoft/go-winio" - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return nil - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( - modole32 = windows.NewLazySystemDLL("ole32.dll") - modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") - modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") - - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") - procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId") - procActivateLayer = modvmcompute.NewProc("ActivateLayer") - procCopyLayer = modvmcompute.NewProc("CopyLayer") - procCreateLayer = modvmcompute.NewProc("CreateLayer") - procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer") - procExpandSandboxSize = modvmcompute.NewProc("ExpandSandboxSize") - procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer") - procDestroyLayer = modvmcompute.NewProc("DestroyLayer") - procExportLayer = modvmcompute.NewProc("ExportLayer") - procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath") - procGetBaseImages = modvmcompute.NewProc("GetBaseImages") - procImportLayer = modvmcompute.NewProc("ImportLayer") - procLayerExists = modvmcompute.NewProc("LayerExists") - procNameToGuid = modvmcompute.NewProc("NameToGuid") - procPrepareLayer = modvmcompute.NewProc("PrepareLayer") - procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer") - procProcessBaseImage = modvmcompute.NewProc("ProcessBaseImage") - procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage") - procImportLayerBegin = modvmcompute.NewProc("ImportLayerBegin") - procImportLayerNext = modvmcompute.NewProc("ImportLayerNext") - procImportLayerWrite = modvmcompute.NewProc("ImportLayerWrite") - procImportLayerEnd = modvmcompute.NewProc("ImportLayerEnd") - procExportLayerBegin = modvmcompute.NewProc("ExportLayerBegin") - procExportLayerNext = modvmcompute.NewProc("ExportLayerNext") - procExportLayerRead = modvmcompute.NewProc("ExportLayerRead") - procExportLayerEnd = modvmcompute.NewProc("ExportLayerEnd") - procHcsEnumerateComputeSystems = modvmcompute.NewProc("HcsEnumerateComputeSystems") - procHcsCreateComputeSystem = modvmcompute.NewProc("HcsCreateComputeSystem") - procHcsOpenComputeSystem = modvmcompute.NewProc("HcsOpenComputeSystem") - procHcsCloseComputeSystem = modvmcompute.NewProc("HcsCloseComputeSystem") - procHcsStartComputeSystem = modvmcompute.NewProc("HcsStartComputeSystem") - procHcsShutdownComputeSystem = modvmcompute.NewProc("HcsShutdownComputeSystem") - procHcsTerminateComputeSystem = modvmcompute.NewProc("HcsTerminateComputeSystem") - procHcsPauseComputeSystem = modvmcompute.NewProc("HcsPauseComputeSystem") - procHcsResumeComputeSystem = modvmcompute.NewProc("HcsResumeComputeSystem") - procHcsGetComputeSystemProperties = modvmcompute.NewProc("HcsGetComputeSystemProperties") - procHcsModifyComputeSystem = modvmcompute.NewProc("HcsModifyComputeSystem") - procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback") - procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback") - procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess") - procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess") - procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess") - procHcsTerminateProcess = modvmcompute.NewProc("HcsTerminateProcess") - procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo") - procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties") - procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess") - procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties") - procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback") - procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback") - procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings") - procHNSCall = modvmcompute.NewProc("HNSCall") -) - -func coTaskMemFree(buffer unsafe.Pointer) { - syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0) - return -} - -func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) { - r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func activateLayer(info *driverInfo, id string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _activateLayer(info, _p0) -} - -func _activateLayer(info *driverInfo, id *uint16) (hr error) { - if hr = procActivateLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(srcId) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(dstId) - if hr != nil { - return - } - return _copyLayer(info, _p0, _p1, descriptors) -} - -func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p2 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p2 = &descriptors[0] - } - if hr = procCopyLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func createLayer(info *driverInfo, id string, parent string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(parent) - if hr != nil { - return - } - return _createLayer(info, _p0, _p1) -} - -func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) { - if hr = procCreateLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(parent) - if hr != nil { - return - } - return _createSandboxLayer(info, _p0, _p1, descriptors) -} - -func _createSandboxLayer(info *driverInfo, id *uint16, parent *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p2 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p2 = &descriptors[0] - } - if hr = procCreateSandboxLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _expandSandboxSize(info, _p0, size) -} - -func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) { - if hr = procExpandSandboxSize.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size)) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func deactivateLayer(info *driverInfo, id string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _deactivateLayer(info, _p0) -} - -func _deactivateLayer(info *driverInfo, id *uint16) (hr error) { - if hr = procDeactivateLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func destroyLayer(info *driverInfo, id string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _destroyLayer(info, _p0) -} - -func _destroyLayer(info *driverInfo, id *uint16) (hr error) { - if hr = procDestroyLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(path) - if hr != nil { - return - } - return _exportLayer(info, _p0, _p1, descriptors) -} - -func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p2 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p2 = &descriptors[0] - } - if hr = procExportLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _getLayerMountPath(info, _p0, length, buffer) -} - -func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) { - if hr = procGetLayerMountPath.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func getBaseImages(buffer **uint16) (hr error) { - if hr = procGetBaseImages.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(path) - if hr != nil { - return - } - return _importLayer(info, _p0, _p1, descriptors) -} - -func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p2 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p2 = &descriptors[0] - } - if hr = procImportLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func layerExists(info *driverInfo, id string, exists *uint32) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _layerExists(info, _p0, exists) -} - -func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) { - if hr = procLayerExists.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func nameToGuid(name string, guid *GUID) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(name) - if hr != nil { - return - } - return _nameToGuid(_p0, guid) -} - -func _nameToGuid(name *uint16, guid *GUID) (hr error) { - if hr = procNameToGuid.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _prepareLayer(info, _p0, descriptors) -} - -func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { - var _p1 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p1 = &descriptors[0] - } - if hr = procPrepareLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func unprepareLayer(info *driverInfo, id string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _unprepareLayer(info, _p0) -} - -func _unprepareLayer(info *driverInfo, id *uint16) (hr error) { - if hr = procUnprepareLayer.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func processBaseImage(path string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(path) - if hr != nil { - return - } - return _processBaseImage(_p0) -} - -func _processBaseImage(path *uint16) (hr error) { - if hr = procProcessBaseImage.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func processUtilityImage(path string) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(path) - if hr != nil { - return - } - return _processUtilityImage(_p0) -} - -func _processUtilityImage(path *uint16) (hr error) { - if hr = procProcessUtilityImage.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _importLayerBegin(info, _p0, descriptors, context) -} - -func _importLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p1 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p1 = &descriptors[0] - } - if hr = procImportLayerBegin.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procImportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(fileName) - if hr != nil { - return - } - return _importLayerNext(context, _p0, fileInfo) -} - -func _importLayerNext(context uintptr, fileName *uint16, fileInfo *winio.FileBasicInfo) (hr error) { - if hr = procImportLayerNext.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerNext.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func importLayerWrite(context uintptr, buffer []byte) (hr error) { - var _p0 *byte - if len(buffer) > 0 { - _p0 = &buffer[0] - } - if hr = procImportLayerWrite.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerWrite.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func importLayerEnd(context uintptr) (hr error) { - if hr = procImportLayerEnd.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerEnd.Addr(), 1, uintptr(context), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _exportLayerBegin(info, _p0, descriptors, context) -} - -func _exportLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p1 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p1 = &descriptors[0] - } - if hr = procExportLayerBegin.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) { - if hr = procExportLayerNext.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerNext.Addr(), 5, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo)), uintptr(unsafe.Pointer(fileSize)), uintptr(unsafe.Pointer(deleted)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) { - var _p0 *byte - if len(buffer) > 0 { - _p0 = &buffer[0] - } - if hr = procExportLayerRead.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerRead.Addr(), 4, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer)), uintptr(unsafe.Pointer(bytesRead)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func exportLayerEnd(context uintptr) (hr error) { - if hr = procExportLayerEnd.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procExportLayerEnd.Addr(), 1, uintptr(context), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(query) - if hr != nil { - return - } - return _hcsEnumerateComputeSystems(_p0, computeSystems, result) -} - -func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result **uint16) (hr error) { - if hr = procHcsEnumerateComputeSystems.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(configuration) - if hr != nil { - return - } - return _hcsCreateComputeSystem(_p0, _p1, identity, computeSystem, result) -} - -func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { - if hr = procHcsCreateComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _hcsOpenComputeSystem(_p0, computeSystem, result) -} - -func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16) (hr error) { - if hr = procHcsOpenComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) { - if hr = procHcsCloseComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(options) - if hr != nil { - return - } - return _hcsStartComputeSystem(computeSystem, _p0, result) -} - -func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { - if hr = procHcsStartComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(options) - if hr != nil { - return - } - return _hcsShutdownComputeSystem(computeSystem, _p0, result) -} - -func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { - if hr = procHcsShutdownComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(options) - if hr != nil { - return - } - return _hcsTerminateComputeSystem(computeSystem, _p0, result) -} - -func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { - if hr = procHcsTerminateComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(options) - if hr != nil { - return - } - return _hcsPauseComputeSystem(computeSystem, _p0, result) -} - -func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { - if hr = procHcsPauseComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(options) - if hr != nil { - return - } - return _hcsResumeComputeSystem(computeSystem, _p0, result) -} - -func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { - if hr = procHcsResumeComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(propertyQuery) - if hr != nil { - return - } - return _hcsGetComputeSystemProperties(computeSystem, _p0, properties, result) -} - -func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { - if hr = procHcsGetComputeSystemProperties.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(configuration) - if hr != nil { - return - } - return _hcsModifyComputeSystem(computeSystem, _p0, result) -} - -func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, result **uint16) (hr error) { - if hr = procHcsModifyComputeSystem.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { - if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) { - if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(processParameters) - if hr != nil { - return - } - return _hcsCreateProcess(computeSystem, _p0, processInformation, process, result) -} - -func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { - if hr = procHcsCreateProcess.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) { - if hr = procHcsOpenProcess.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsCloseProcess(process hcsProcess) (hr error) { - if hr = procHcsCloseProcess.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) { - if hr = procHcsTerminateProcess.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) { - if hr = procHcsGetProcessInfo.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) { - if hr = procHcsGetProcessProperties.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(settings) - if hr != nil { - return - } - return _hcsModifyProcess(process, _p0, result) -} - -func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (hr error) { - if hr = procHcsModifyProcess.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(propertyQuery) - if hr != nil { - return - } - return _hcsGetServiceProperties(_p0, properties, result) -} - -func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { - if hr = procHcsGetServiceProperties.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result))) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { - if hr = procHcsRegisterProcessCallback.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) { - if hr = procHcsUnregisterProcessCallback.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func hcsModifyServiceSettings(settings string, result **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(settings) - if hr != nil { - return - } - return _hcsModifyServiceSettings(_p0, result) -} - -func _hcsModifyServiceSettings(settings *uint16, result **uint16) (hr error) { - if hr = procHcsModifyServiceSettings.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procHcsModifyServiceSettings.Addr(), 2, uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} - -func _hnsCall(method string, path string, object string, response **uint16) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(method) - if hr != nil { - return - } - var _p1 *uint16 - _p1, hr = syscall.UTF16PtrFromString(path) - if hr != nil { - return - } - var _p2 *uint16 - _p2, hr = syscall.UTF16PtrFromString(object) - if hr != nil { - return - } - return __hnsCall(_p0, _p1, _p2, response) -} - -func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) { - if hr = procHNSCall.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - return -} diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE deleted file mode 100644 index 339177be66..0000000000 --- a/vendor/github.com/beorn7/perks/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013 Blake Mizerany - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go deleted file mode 100644 index d7d14f8eb6..0000000000 --- a/vendor/github.com/beorn7/perks/quantile/stream.go +++ /dev/null @@ -1,316 +0,0 @@ -// Package quantile computes approximate quantiles over an unbounded data -// stream within low memory and CPU bounds. -// -// A small amount of accuracy is traded to achieve the above properties. -// -// Multiple streams can be merged before calling Query to generate a single set -// of results. This is meaningful when the streams represent the same type of -// data. See Merge and Samples. -// -// For more detailed information about the algorithm used, see: -// -// Effective Computation of Biased Quantiles over Data Streams -// -// http://www.cs.rutgers.edu/~muthu/bquant.pdf -package quantile - -import ( - "math" - "sort" -) - -// Sample holds an observed value and meta information for compression. JSON -// tags have been added for convenience. -type Sample struct { - Value float64 `json:",string"` - Width float64 `json:",string"` - Delta float64 `json:",string"` -} - -// Samples represents a slice of samples. It implements sort.Interface. -type Samples []Sample - -func (a Samples) Len() int { return len(a) } -func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value } -func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -type invariant func(s *stream, r float64) float64 - -// NewLowBiased returns an initialized Stream for low-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the lower ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within (1±Epsilon)*Quantile. -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewLowBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * r - } - return newStream(ƒ) -} - -// NewHighBiased returns an initialized Stream for high-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the higher ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewHighBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * (s.n - r) - } - return newStream(ƒ) -} - -// NewTargeted returns an initialized Stream concerned with a particular set of -// quantile values that are supplied a priori. Knowing these a priori reduces -// space and computation time. The targets map maps the desired quantiles to -// their absolute errors, i.e. the true quantile of a value returned by a query -// is guaranteed to be within (Quantile±Epsilon). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. -func NewTargeted(targetMap map[float64]float64) *Stream { - // Convert map to slice to avoid slow iterations on a map. - // ƒ is called on the hot path, so converting the map to a slice - // beforehand results in significant CPU savings. - targets := targetMapToSlice(targetMap) - - ƒ := func(s *stream, r float64) float64 { - var m = math.MaxFloat64 - var f float64 - for _, t := range targets { - if t.quantile*s.n <= r { - f = (2 * t.epsilon * r) / t.quantile - } else { - f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile) - } - if f < m { - m = f - } - } - return m - } - return newStream(ƒ) -} - -type target struct { - quantile float64 - epsilon float64 -} - -func targetMapToSlice(targetMap map[float64]float64) []target { - targets := make([]target, 0, len(targetMap)) - - for quantile, epsilon := range targetMap { - t := target{ - quantile: quantile, - epsilon: epsilon, - } - targets = append(targets, t) - } - - return targets -} - -// Stream computes quantiles for a stream of float64s. It is not thread-safe by -// design. Take care when using across multiple goroutines. -type Stream struct { - *stream - b Samples - sorted bool -} - -func newStream(ƒ invariant) *Stream { - x := &stream{ƒ: ƒ} - return &Stream{x, make(Samples, 0, 500), true} -} - -// Insert inserts v into the stream. -func (s *Stream) Insert(v float64) { - s.insert(Sample{Value: v, Width: 1}) -} - -func (s *Stream) insert(sample Sample) { - s.b = append(s.b, sample) - s.sorted = false - if len(s.b) == cap(s.b) { - s.flush() - } -} - -// Query returns the computed qth percentiles value. If s was created with -// NewTargeted, and q is not in the set of quantiles provided a priori, Query -// will return an unspecified result. -func (s *Stream) Query(q float64) float64 { - if !s.flushed() { - // Fast path when there hasn't been enough data for a flush; - // this also yields better accuracy for small sets of data. - l := len(s.b) - if l == 0 { - return 0 - } - i := int(math.Ceil(float64(l) * q)) - if i > 0 { - i -= 1 - } - s.maybeSort() - return s.b[i].Value - } - s.flush() - return s.stream.query(q) -} - -// Merge merges samples into the underlying streams samples. This is handy when -// merging multiple streams from separate threads, database shards, etc. -// -// ATTENTION: This method is broken and does not yield correct results. The -// underlying algorithm is not capable of merging streams correctly. -func (s *Stream) Merge(samples Samples) { - sort.Sort(samples) - s.stream.merge(samples) -} - -// Reset reinitializes and clears the list reusing the samples buffer memory. -func (s *Stream) Reset() { - s.stream.reset() - s.b = s.b[:0] -} - -// Samples returns stream samples held by s. -func (s *Stream) Samples() Samples { - if !s.flushed() { - return s.b - } - s.flush() - return s.stream.samples() -} - -// Count returns the total number of samples observed in the stream -// since initialization. -func (s *Stream) Count() int { - return len(s.b) + s.stream.count() -} - -func (s *Stream) flush() { - s.maybeSort() - s.stream.merge(s.b) - s.b = s.b[:0] -} - -func (s *Stream) maybeSort() { - if !s.sorted { - s.sorted = true - sort.Sort(s.b) - } -} - -func (s *Stream) flushed() bool { - return len(s.stream.l) > 0 -} - -type stream struct { - n float64 - l []Sample - ƒ invariant -} - -func (s *stream) reset() { - s.l = s.l[:0] - s.n = 0 -} - -func (s *stream) insert(v float64) { - s.merge(Samples{{v, 1, 0}}) -} - -func (s *stream) merge(samples Samples) { - // TODO(beorn7): This tries to merge not only individual samples, but - // whole summaries. The paper doesn't mention merging summaries at - // all. Unittests show that the merging is inaccurate. Find out how to - // do merges properly. - var r float64 - i := 0 - for _, sample := range samples { - for ; i < len(s.l); i++ { - c := s.l[i] - if c.Value > sample.Value { - // Insert at position i. - s.l = append(s.l, Sample{}) - copy(s.l[i+1:], s.l[i:]) - s.l[i] = Sample{ - sample.Value, - sample.Width, - math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1), - // TODO(beorn7): How to calculate delta correctly? - } - i++ - goto inserted - } - r += c.Width - } - s.l = append(s.l, Sample{sample.Value, sample.Width, 0}) - i++ - inserted: - s.n += sample.Width - r += sample.Width - } - s.compress() -} - -func (s *stream) count() int { - return int(s.n) -} - -func (s *stream) query(q float64) float64 { - t := math.Ceil(q * s.n) - t += math.Ceil(s.ƒ(s, t) / 2) - p := s.l[0] - var r float64 - for _, c := range s.l[1:] { - r += p.Width - if r+c.Width+c.Delta > t { - return p.Value - } - p = c - } - return p.Value -} - -func (s *stream) compress() { - if len(s.l) < 2 { - return - } - x := s.l[len(s.l)-1] - xi := len(s.l) - 1 - r := s.n - 1 - x.Width - - for i := len(s.l) - 2; i >= 0; i-- { - c := s.l[i] - if c.Width+x.Width+x.Delta <= s.ƒ(s, r) { - x.Width += c.Width - s.l[xi] = x - // Remove element at i. - copy(s.l[i:], s.l[i+1:]) - s.l = s.l[:len(s.l)-1] - xi -= 1 - } else { - x = c - xi = i - } - r -= c.Width - } -} - -func (s *stream) samples() Samples { - samples := make(Samples, len(s.l)) - copy(samples, s.l) - return samples -} diff --git a/vendor/github.com/containers/image/LICENSE b/vendor/github.com/containers/image/LICENSE deleted file mode 100644 index 9535635306..0000000000 --- a/vendor/github.com/containers/image/LICENSE +++ /dev/null @@ -1,189 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go deleted file mode 100644 index 29065e031d..0000000000 --- a/vendor/github.com/containers/image/copy/copy.go +++ /dev/null @@ -1,718 +0,0 @@ -package copy - -import ( - "bytes" - "compress/gzip" - "context" - "fmt" - "io" - "io/ioutil" - "reflect" - "runtime" - "strings" - "time" - - "github.com/containers/image/image" - "github.com/containers/image/pkg/compression" - "github.com/containers/image/signature" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - pb "gopkg.in/cheggaaa/pb.v1" -) - -type digestingReader struct { - source io.Reader - digester digest.Digester - expectedDigest digest.Digest - validationFailed bool -} - -// newDigestingReader returns an io.Reader implementation with contents of source, which will eventually return a non-EOF error -// and set validationFailed to true if the source stream does not match expectedDigest. -func newDigestingReader(source io.Reader, expectedDigest digest.Digest) (*digestingReader, error) { - if err := expectedDigest.Validate(); err != nil { - return nil, errors.Errorf("Invalid digest specification %s", expectedDigest) - } - digestAlgorithm := expectedDigest.Algorithm() - if !digestAlgorithm.Available() { - return nil, errors.Errorf("Invalid digest specification %s: unsupported digest algorithm %s", expectedDigest, digestAlgorithm) - } - return &digestingReader{ - source: source, - digester: digestAlgorithm.Digester(), - expectedDigest: expectedDigest, - validationFailed: false, - }, nil -} - -func (d *digestingReader) Read(p []byte) (int, error) { - n, err := d.source.Read(p) - if n > 0 { - if n2, err := d.digester.Hash().Write(p[:n]); n2 != n || err != nil { - // Coverage: This should not happen, the hash.Hash interface requires - // d.digest.Write to never return an error, and the io.Writer interface - // requires n2 == len(input) if no error is returned. - return 0, errors.Wrapf(err, "Error updating digest during verification: %d vs. %d", n2, n) - } - } - if err == io.EOF { - actualDigest := d.digester.Digest() - if actualDigest != d.expectedDigest { - d.validationFailed = true - return 0, errors.Errorf("Digest did not match, expected %s, got %s", d.expectedDigest, actualDigest) - } - } - return n, err -} - -// copier allows us to keep track of diffID values for blobs, and other -// data shared across one or more images in a possible manifest list. -type copier struct { - copiedBlobs map[digest.Digest]digest.Digest - cachedDiffIDs map[digest.Digest]digest.Digest - dest types.ImageDestination - rawSource types.ImageSource - reportWriter io.Writer - progressInterval time.Duration - progress chan types.ProgressProperties -} - -// imageCopier tracks state specific to a single image (possibly an item of a manifest list) -type imageCopier struct { - c *copier - manifestUpdates *types.ManifestUpdateOptions - src types.Image - diffIDsAreNeeded bool - canModifyManifest bool -} - -// Options allows supplying non-default configuration modifying the behavior of CopyImage. -type Options struct { - RemoveSignatures bool // Remove any pre-existing signatures. SignBy will still add a new signature. - SignBy string // If non-empty, asks for a signature to be added during the copy, and specifies a key ID, as accepted by signature.NewGPGSigningMechanism().SignDockerManifest(), - ReportWriter io.Writer - SourceCtx *types.SystemContext - DestinationCtx *types.SystemContext - ProgressInterval time.Duration // time to wait between reports to signal the progress channel - Progress chan types.ProgressProperties // Reported to when ProgressInterval has arrived for a single artifact+offset. - // manifest MIME type of image set by user. "" is default and means use the autodetection to the the manifest MIME type - ForceManifestMIMEType string -} - -// Image copies image from srcRef to destRef, using policyContext to validate -// source image admissibility. -func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (retErr error) { - // NOTE this function uses an output parameter for the error return value. - // Setting this and returning is the ideal way to return an error. - // - // the defers in this routine will wrap the error return with its own errors - // which can be valuable context in the middle of a multi-streamed copy. - if options == nil { - options = &Options{} - } - - reportWriter := ioutil.Discard - - if options.ReportWriter != nil { - reportWriter = options.ReportWriter - } - - dest, err := destRef.NewImageDestination(options.DestinationCtx) - if err != nil { - return errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef)) - } - defer func() { - if err := dest.Close(); err != nil { - retErr = errors.Wrapf(retErr, " (dest: %v)", err) - } - }() - - rawSource, err := srcRef.NewImageSource(options.SourceCtx) - if err != nil { - return errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef)) - } - defer func() { - if err := rawSource.Close(); err != nil { - retErr = errors.Wrapf(retErr, " (src: %v)", err) - } - }() - - c := &copier{ - copiedBlobs: make(map[digest.Digest]digest.Digest), - cachedDiffIDs: make(map[digest.Digest]digest.Digest), - dest: dest, - rawSource: rawSource, - reportWriter: reportWriter, - progressInterval: options.ProgressInterval, - progress: options.Progress, - } - - unparsedToplevel := image.UnparsedInstance(rawSource, nil) - multiImage, err := isMultiImage(unparsedToplevel) - if err != nil { - return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(srcRef)) - } - - if !multiImage { - // The simple case: Just copy a single image. - if err := c.copyOneImage(policyContext, options, unparsedToplevel); err != nil { - return err - } - } else { - // This is a manifest list. Choose a single image and copy it. - // FIXME: Copy to destinations which support manifest lists, one image at a time. - instanceDigest, err := image.ChooseManifestInstanceFromManifestList(options.SourceCtx, unparsedToplevel) - if err != nil { - return errors.Wrapf(err, "Error choosing an image from manifest list %s", transports.ImageName(srcRef)) - } - logrus.Debugf("Source is a manifest list; copying (only) instance %s", instanceDigest) - unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest) - - if err := c.copyOneImage(policyContext, options, unparsedInstance); err != nil { - return err - } - } - - if err := c.dest.Commit(); err != nil { - return errors.Wrap(err, "Error committing the finished image") - } - - return nil -} - -// Image copies a single (on-manifest-list) image unparsedImage, using policyContext to validate -// source image admissibility. -func (c *copier) copyOneImage(policyContext *signature.PolicyContext, options *Options, unparsedImage *image.UnparsedImage) (retErr error) { - // The caller is handling manifest lists; this could happen only if a manifest list contains a manifest list. - // Make sure we fail cleanly in such cases. - multiImage, err := isMultiImage(unparsedImage) - if err != nil { - // FIXME FIXME: How to name a reference for the sub-image? - return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference())) - } - if multiImage { - return fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image") - } - - // Please keep this policy check BEFORE reading any other information about the image. - // (the multiImage check above only matches the MIME type, which we have received anyway. - // Actual parsing of anything should be deferred.) - if allowed, err := policyContext.IsRunningImageAllowed(unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so. - return errors.Wrap(err, "Source image rejected") - } - src, err := image.FromUnparsedImage(options.SourceCtx, unparsedImage) - if err != nil { - return errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference())) - } - - if err := checkImageDestinationForCurrentRuntimeOS(options.DestinationCtx, src, c.dest); err != nil { - return err - } - - var sigs [][]byte - if options.RemoveSignatures { - sigs = [][]byte{} - } else { - c.Printf("Getting image source signatures\n") - s, err := src.Signatures(context.TODO()) - if err != nil { - return errors.Wrap(err, "Error reading signatures") - } - sigs = s - } - if len(sigs) != 0 { - c.Printf("Checking if image destination supports signatures\n") - if err := c.dest.SupportsSignatures(); err != nil { - return errors.Wrap(err, "Can not copy signatures") - } - } - - ic := imageCopier{ - c: c, - manifestUpdates: &types.ManifestUpdateOptions{InformationOnly: types.ManifestUpdateInformation{Destination: c.dest}}, - src: src, - // diffIDsAreNeeded is computed later - canModifyManifest: len(sigs) == 0, - } - - if err := ic.updateEmbeddedDockerReference(); err != nil { - return err - } - - // We compute preferredManifestMIMEType only to show it in error messages. - // Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed. - preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := ic.determineManifestConversion(c.dest.SupportedManifestMIMETypes(), options.ForceManifestMIMEType) - if err != nil { - return err - } - - // If src.UpdatedImageNeedsLayerDiffIDs(ic.manifestUpdates) will be true, it needs to be true by the time we get here. - ic.diffIDsAreNeeded = src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates) - - if err := ic.copyLayers(); err != nil { - return err - } - - // With docker/distribution registries we do not know whether the registry accepts schema2 or schema1 only; - // and at least with the OpenShift registry "acceptschema2" option, there is no way to detect the support - // without actually trying to upload something and getting a types.ManifestTypeRejectedError. - // So, try the preferred manifest MIME type. If the process succeeds, fine… - manifest, err := ic.copyUpdatedConfigAndManifest() - if err != nil { - logrus.Debugf("Writing manifest using preferred type %s failed: %v", preferredManifestMIMEType, err) - // … if it fails, _and_ the failure is because the manifest is rejected, we may have other options. - if _, isManifestRejected := errors.Cause(err).(types.ManifestTypeRejectedError); !isManifestRejected || len(otherManifestMIMETypeCandidates) == 0 { - // We don’t have other options. - // In principle the code below would handle this as well, but the resulting error message is fairly ugly. - // Don’t bother the user with MIME types if we have no choice. - return err - } - // If the original MIME type is acceptable, determineManifestConversion always uses it as preferredManifestMIMEType. - // So if we are here, we will definitely be trying to convert the manifest. - // With !ic.canModifyManifest, that would just be a string of repeated failures for the same reason, - // so let’s bail out early and with a better error message. - if !ic.canModifyManifest { - return errors.Wrap(err, "Writing manifest failed (and converting it is not possible)") - } - - // errs is a list of errors when trying various manifest types. Also serves as an "upload succeeded" flag when set to nil. - errs := []string{fmt.Sprintf("%s(%v)", preferredManifestMIMEType, err)} - for _, manifestMIMEType := range otherManifestMIMETypeCandidates { - logrus.Debugf("Trying to use manifest type %s…", manifestMIMEType) - ic.manifestUpdates.ManifestMIMEType = manifestMIMEType - attemptedManifest, err := ic.copyUpdatedConfigAndManifest() - if err != nil { - logrus.Debugf("Upload of manifest type %s failed: %v", manifestMIMEType, err) - errs = append(errs, fmt.Sprintf("%s(%v)", manifestMIMEType, err)) - continue - } - - // We have successfully uploaded a manifest. - manifest = attemptedManifest - errs = nil // Mark this as a success so that we don't abort below. - break - } - if errs != nil { - return fmt.Errorf("Uploading manifest failed, attempted the following formats: %s", strings.Join(errs, ", ")) - } - } - - if options.SignBy != "" { - newSig, err := c.createSignature(manifest, options.SignBy) - if err != nil { - return err - } - sigs = append(sigs, newSig) - } - - c.Printf("Storing signatures\n") - if err := c.dest.PutSignatures(sigs); err != nil { - return errors.Wrap(err, "Error writing signatures") - } - - return nil -} - -// Printf writes a formatted string to c.reportWriter. -// Note that the method name Printf is not entirely arbitrary: (go tool vet) -// has a built-in list of functions/methods (whatever object they are for) -// which have their format strings checked; for other names we would have -// to pass a parameter to every (go tool vet) invocation. -func (c *copier) Printf(format string, a ...interface{}) { - fmt.Fprintf(c.reportWriter, format, a...) -} - -func checkImageDestinationForCurrentRuntimeOS(ctx *types.SystemContext, src types.Image, dest types.ImageDestination) error { - if dest.MustMatchRuntimeOS() { - wantedOS := runtime.GOOS - if ctx != nil && ctx.OSChoice != "" { - wantedOS = ctx.OSChoice - } - c, err := src.OCIConfig() - if err != nil { - return errors.Wrapf(err, "Error parsing image configuration") - } - osErr := fmt.Errorf("image operating system %q cannot be used on %q", c.OS, wantedOS) - if wantedOS == "windows" && c.OS == "linux" { - return osErr - } else if wantedOS != "windows" && c.OS == "windows" { - return osErr - } - } - return nil -} - -// updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests. -func (ic *imageCopier) updateEmbeddedDockerReference() error { - destRef := ic.c.dest.Reference().DockerReference() - if destRef == nil { - return nil // Destination does not care about Docker references - } - if !ic.src.EmbeddedDockerReferenceConflicts(destRef) { - return nil // No reference embedded in the manifest, or it matches destRef already. - } - - if !ic.canModifyManifest { - return errors.Errorf("Copying a schema1 image with an embedded Docker reference to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway", - transports.ImageName(ic.c.dest.Reference()), destRef.String()) - } - ic.manifestUpdates.EmbeddedDockerReference = destRef - return nil -} - -// copyLayers copies layers from ic.src/ic.c.rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.canModifyManifest. -func (ic *imageCopier) copyLayers() error { - srcInfos := ic.src.LayerInfos() - destInfos := []types.BlobInfo{} - diffIDs := []digest.Digest{} - updatedSrcInfos := ic.src.LayerInfosForCopy() - srcInfosUpdated := false - if updatedSrcInfos != nil && !reflect.DeepEqual(srcInfos, updatedSrcInfos) { - if !ic.canModifyManifest { - return errors.Errorf("Internal error: copyLayers() needs to use an updated manifest but that was known to be forbidden") - } - srcInfos = updatedSrcInfos - srcInfosUpdated = true - } - for _, srcLayer := range srcInfos { - var ( - destInfo types.BlobInfo - diffID digest.Digest - err error - ) - if ic.c.dest.AcceptsForeignLayerURLs() && len(srcLayer.URLs) != 0 { - // DiffIDs are, currently, needed only when converting from schema1. - // In which case src.LayerInfos will not have URLs because schema1 - // does not support them. - if ic.diffIDsAreNeeded { - return errors.New("getting DiffID for foreign layers is unimplemented") - } - destInfo = srcLayer - ic.c.Printf("Skipping foreign layer %q copy to %s\n", destInfo.Digest, ic.c.dest.Reference().Transport().Name()) - } else { - destInfo, diffID, err = ic.copyLayer(srcLayer) - if err != nil { - return err - } - } - destInfos = append(destInfos, destInfo) - diffIDs = append(diffIDs, diffID) - } - ic.manifestUpdates.InformationOnly.LayerInfos = destInfos - if ic.diffIDsAreNeeded { - ic.manifestUpdates.InformationOnly.LayerDiffIDs = diffIDs - } - if srcInfosUpdated || layerDigestsDiffer(srcInfos, destInfos) { - ic.manifestUpdates.LayerInfos = destInfos - } - return nil -} - -// layerDigestsDiffer return true iff the digests in a and b differ (ignoring sizes and possible other fields) -func layerDigestsDiffer(a, b []types.BlobInfo) bool { - if len(a) != len(b) { - return true - } - for i := range a { - if a[i].Digest != b[i].Digest { - return true - } - } - return false -} - -// copyUpdatedConfigAndManifest updates the image per ic.manifestUpdates, if necessary, -// stores the resulting config and manifest to the destination, and returns the stored manifest. -func (ic *imageCopier) copyUpdatedConfigAndManifest() ([]byte, error) { - pendingImage := ic.src - if !reflect.DeepEqual(*ic.manifestUpdates, types.ManifestUpdateOptions{InformationOnly: ic.manifestUpdates.InformationOnly}) { - if !ic.canModifyManifest { - return nil, errors.Errorf("Internal error: copy needs an updated manifest but that was known to be forbidden") - } - if !ic.diffIDsAreNeeded && ic.src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates) { - // We have set ic.diffIDsAreNeeded based on the preferred MIME type returned by determineManifestConversion. - // So, this can only happen if we are trying to upload using one of the other MIME type candidates. - // Because UpdatedImageNeedsLayerDiffIDs is true only when converting from s1 to s2, this case should only arise - // when ic.c.dest.SupportedManifestMIMETypes() includes both s1 and s2, the upload using s1 failed, and we are now trying s2. - // Supposedly s2-only registries do not exist or are extremely rare, so failing with this error message is good enough for now. - // If handling such registries turns out to be necessary, we could compute ic.diffIDsAreNeeded based on the full list of manifest MIME type candidates. - return nil, errors.Errorf("Can not convert image to %s, preparing DiffIDs for this case is not supported", ic.manifestUpdates.ManifestMIMEType) - } - pi, err := ic.src.UpdatedImage(*ic.manifestUpdates) - if err != nil { - return nil, errors.Wrap(err, "Error creating an updated image manifest") - } - pendingImage = pi - } - manifest, _, err := pendingImage.Manifest() - if err != nil { - return nil, errors.Wrap(err, "Error reading manifest") - } - - if err := ic.c.copyConfig(pendingImage); err != nil { - return nil, err - } - - ic.c.Printf("Writing manifest to image destination\n") - if err := ic.c.dest.PutManifest(manifest); err != nil { - return nil, errors.Wrap(err, "Error writing manifest") - } - return manifest, nil -} - -// copyConfig copies config.json, if any, from src to dest. -func (c *copier) copyConfig(src types.Image) error { - srcInfo := src.ConfigInfo() - if srcInfo.Digest != "" { - c.Printf("Copying config %s\n", srcInfo.Digest) - configBlob, err := src.ConfigBlob() - if err != nil { - return errors.Wrapf(err, "Error reading config blob %s", srcInfo.Digest) - } - destInfo, err := c.copyBlobFromStream(bytes.NewReader(configBlob), srcInfo, nil, false) - if err != nil { - return err - } - if destInfo.Digest != srcInfo.Digest { - return errors.Errorf("Internal error: copying uncompressed config blob %s changed digest to %s", srcInfo.Digest, destInfo.Digest) - } - } - return nil -} - -// diffIDResult contains both a digest value and an error from diffIDComputationGoroutine. -// We could also send the error through the pipeReader, but this more cleanly separates the copying of the layer and the DiffID computation. -type diffIDResult struct { - digest digest.Digest - err error -} - -// copyLayer copies a layer with srcInfo (with known Digest and possibly known Size) in src to dest, perhaps compressing it if canCompress, -// and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded -func (ic *imageCopier) copyLayer(srcInfo types.BlobInfo) (types.BlobInfo, digest.Digest, error) { - // Check if we already have a blob with this digest - haveBlob, extantBlobSize, err := ic.c.dest.HasBlob(srcInfo) - if err != nil { - return types.BlobInfo{}, "", errors.Wrapf(err, "Error checking for blob %s at destination", srcInfo.Digest) - } - // If we already have a cached diffID for this blob, we don't need to compute it - diffIDIsNeeded := ic.diffIDsAreNeeded && (ic.c.cachedDiffIDs[srcInfo.Digest] == "") - // If we already have the blob, and we don't need to recompute the diffID, then we might be able to avoid reading it again - if haveBlob && !diffIDIsNeeded { - // Check the blob sizes match, if we were given a size this time - if srcInfo.Size != -1 && srcInfo.Size != extantBlobSize { - return types.BlobInfo{}, "", errors.Errorf("Error: blob %s is already present, but with size %d instead of %d", srcInfo.Digest, extantBlobSize, srcInfo.Size) - } - srcInfo.Size = extantBlobSize - // Tell the image destination that this blob's delta is being applied again. For some image destinations, this can be faster than using GetBlob/PutBlob - blobinfo, err := ic.c.dest.ReapplyBlob(srcInfo) - if err != nil { - return types.BlobInfo{}, "", errors.Wrapf(err, "Error reapplying blob %s at destination", srcInfo.Digest) - } - ic.c.Printf("Skipping fetch of repeat blob %s\n", srcInfo.Digest) - return blobinfo, ic.c.cachedDiffIDs[srcInfo.Digest], err - } - - // Fallback: copy the layer, computing the diffID if we need to do so - ic.c.Printf("Copying blob %s\n", srcInfo.Digest) - srcStream, srcBlobSize, err := ic.c.rawSource.GetBlob(srcInfo) - if err != nil { - return types.BlobInfo{}, "", errors.Wrapf(err, "Error reading blob %s", srcInfo.Digest) - } - defer srcStream.Close() - - blobInfo, diffIDChan, err := ic.copyLayerFromStream(srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize}, - diffIDIsNeeded) - if err != nil { - return types.BlobInfo{}, "", err - } - var diffIDResult diffIDResult // = {digest:""} - if diffIDIsNeeded { - diffIDResult = <-diffIDChan - if diffIDResult.err != nil { - return types.BlobInfo{}, "", errors.Wrap(diffIDResult.err, "Error computing layer DiffID") - } - logrus.Debugf("Computed DiffID %s for layer %s", diffIDResult.digest, srcInfo.Digest) - ic.c.cachedDiffIDs[srcInfo.Digest] = diffIDResult.digest - } - return blobInfo, diffIDResult.digest, nil -} - -// copyLayerFromStream is an implementation detail of copyLayer; mostly providing a separate “defer” scope. -// it copies a blob with srcInfo (with known Digest and possibly known Size) from srcStream to dest, -// perhaps compressing the stream if canCompress, -// and returns a complete blobInfo of the copied blob and perhaps a <-chan diffIDResult if diffIDIsNeeded, to be read by the caller. -func (ic *imageCopier) copyLayerFromStream(srcStream io.Reader, srcInfo types.BlobInfo, - diffIDIsNeeded bool) (types.BlobInfo, <-chan diffIDResult, error) { - var getDiffIDRecorder func(compression.DecompressorFunc) io.Writer // = nil - var diffIDChan chan diffIDResult - - err := errors.New("Internal error: unexpected panic in copyLayer") // For pipeWriter.CloseWithError below - if diffIDIsNeeded { - diffIDChan = make(chan diffIDResult, 1) // Buffered, so that sending a value after this or our caller has failed and exited does not block. - pipeReader, pipeWriter := io.Pipe() - defer func() { // Note that this is not the same as {defer pipeWriter.CloseWithError(err)}; we need err to be evaluated lazily. - pipeWriter.CloseWithError(err) // CloseWithError(nil) is equivalent to Close() - }() - - getDiffIDRecorder = func(decompressor compression.DecompressorFunc) io.Writer { - // If this fails, e.g. because we have exited and due to pipeWriter.CloseWithError() above further - // reading from the pipe has failed, we don’t really care. - // We only read from diffIDChan if the rest of the flow has succeeded, and when we do read from it, - // the return value includes an error indication, which we do check. - // - // If this gets never called, pipeReader will not be used anywhere, but pipeWriter will only be - // closed above, so we are happy enough with both pipeReader and pipeWriter to just get collected by GC. - go diffIDComputationGoroutine(diffIDChan, pipeReader, decompressor) // Closes pipeReader - return pipeWriter - } - } - blobInfo, err := ic.c.copyBlobFromStream(srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest) // Sets err to nil on success - return blobInfo, diffIDChan, err - // We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan -} - -// diffIDComputationGoroutine reads all input from layerStream, uncompresses using decompressor if necessary, and sends its digest, and status, if any, to dest. -func diffIDComputationGoroutine(dest chan<- diffIDResult, layerStream io.ReadCloser, decompressor compression.DecompressorFunc) { - result := diffIDResult{ - digest: "", - err: errors.New("Internal error: unexpected panic in diffIDComputationGoroutine"), - } - defer func() { dest <- result }() - defer layerStream.Close() // We do not care to bother the other end of the pipe with other failures; we send them to dest instead. - - result.digest, result.err = computeDiffID(layerStream, decompressor) -} - -// computeDiffID reads all input from layerStream, uncompresses it using decompressor if necessary, and returns its digest. -func computeDiffID(stream io.Reader, decompressor compression.DecompressorFunc) (digest.Digest, error) { - if decompressor != nil { - s, err := decompressor(stream) - if err != nil { - return "", err - } - stream = s - } - - return digest.Canonical.FromReader(stream) -} - -// copyBlobFromStream copies a blob with srcInfo (with known Digest and possibly known Size) from srcStream to dest, -// perhaps sending a copy to an io.Writer if getOriginalLayerCopyWriter != nil, -// perhaps compressing it if canCompress, -// and returns a complete blobInfo of the copied blob. -func (c *copier) copyBlobFromStream(srcStream io.Reader, srcInfo types.BlobInfo, - getOriginalLayerCopyWriter func(decompressor compression.DecompressorFunc) io.Writer, - canCompress bool) (types.BlobInfo, error) { - // The copying happens through a pipeline of connected io.Readers. - // === Input: srcStream - - // === Process input through digestingReader to validate against the expected digest. - // Be paranoid; in case PutBlob somehow managed to ignore an error from digestingReader, - // use a separate validation failure indicator. - // Note that we don't use a stronger "validationSucceeded" indicator, because - // dest.PutBlob may detect that the layer already exists, in which case we don't - // read stream to the end, and validation does not happen. - digestingReader, err := newDigestingReader(srcStream, srcInfo.Digest) - if err != nil { - return types.BlobInfo{}, errors.Wrapf(err, "Error preparing to verify blob %s", srcInfo.Digest) - } - var destStream io.Reader = digestingReader - - // === Detect compression of the input stream. - // This requires us to “peek ahead” into the stream to read the initial part, which requires us to chain through another io.Reader returned by DetectCompression. - decompressor, destStream, err := compression.DetectCompression(destStream) // We could skip this in some cases, but let's keep the code path uniform - if err != nil { - return types.BlobInfo{}, errors.Wrapf(err, "Error reading blob %s", srcInfo.Digest) - } - isCompressed := decompressor != nil - - // === Report progress using a pb.Reader. - bar := pb.New(int(srcInfo.Size)).SetUnits(pb.U_BYTES) - bar.Output = c.reportWriter - bar.SetMaxWidth(80) - bar.ShowTimeLeft = false - bar.ShowPercent = false - bar.Start() - destStream = bar.NewProxyReader(destStream) - defer bar.Finish() - - // === Send a copy of the original, uncompressed, stream, to a separate path if necessary. - var originalLayerReader io.Reader // DO NOT USE this other than to drain the input if no other consumer in the pipeline has done so. - if getOriginalLayerCopyWriter != nil { - destStream = io.TeeReader(destStream, getOriginalLayerCopyWriter(decompressor)) - originalLayerReader = destStream - } - - // === Compress the layer if it is uncompressed and compression is desired - var inputInfo types.BlobInfo - if !canCompress || isCompressed || !c.dest.ShouldCompressLayers() { - logrus.Debugf("Using original blob without modification") - inputInfo = srcInfo - } else { - logrus.Debugf("Compressing blob on the fly") - pipeReader, pipeWriter := io.Pipe() - defer pipeReader.Close() - - // If this fails while writing data, it will do pipeWriter.CloseWithError(); if it fails otherwise, - // e.g. because we have exited and due to pipeReader.Close() above further writing to the pipe has failed, - // we don’t care. - go compressGoroutine(pipeWriter, destStream) // Closes pipeWriter - destStream = pipeReader - inputInfo.Digest = "" - inputInfo.Size = -1 - } - - // === Report progress using the c.progress channel, if required. - if c.progress != nil && c.progressInterval > 0 { - destStream = &progressReader{ - source: destStream, - channel: c.progress, - interval: c.progressInterval, - artifact: srcInfo, - lastTime: time.Now(), - } - } - - // === Finally, send the layer stream to dest. - uploadedInfo, err := c.dest.PutBlob(destStream, inputInfo) - if err != nil { - return types.BlobInfo{}, errors.Wrap(err, "Error writing blob") - } - - // This is fairly horrible: the writer from getOriginalLayerCopyWriter wants to consumer - // all of the input (to compute DiffIDs), even if dest.PutBlob does not need it. - // So, read everything from originalLayerReader, which will cause the rest to be - // sent there if we are not already at EOF. - if getOriginalLayerCopyWriter != nil { - logrus.Debugf("Consuming rest of the original blob to satisfy getOriginalLayerCopyWriter") - _, err := io.Copy(ioutil.Discard, originalLayerReader) - if err != nil { - return types.BlobInfo{}, errors.Wrapf(err, "Error reading input blob %s", srcInfo.Digest) - } - } - - if digestingReader.validationFailed { // Coverage: This should never happen. - return types.BlobInfo{}, errors.Errorf("Internal error writing blob %s, digest verification failed but was ignored", srcInfo.Digest) - } - if inputInfo.Digest != "" && uploadedInfo.Digest != inputInfo.Digest { - return types.BlobInfo{}, errors.Errorf("Internal error writing blob %s, blob with digest %s saved with digest %s", srcInfo.Digest, inputInfo.Digest, uploadedInfo.Digest) - } - return uploadedInfo, nil -} - -// compressGoroutine reads all input from src and writes its compressed equivalent to dest. -func compressGoroutine(dest *io.PipeWriter, src io.Reader) { - err := errors.New("Internal error: unexpected panic in compressGoroutine") - defer func() { // Note that this is not the same as {defer dest.CloseWithError(err)}; we need err to be evaluated lazily. - dest.CloseWithError(err) // CloseWithError(nil) is equivalent to Close() - }() - - zipper := gzip.NewWriter(dest) - defer zipper.Close() - - _, err = io.Copy(zipper, src) // Sets err to nil, i.e. causes dest.Close() -} diff --git a/vendor/github.com/containers/image/copy/fixtures/Hello.bz2 b/vendor/github.com/containers/image/copy/fixtures/Hello.bz2 deleted file mode 120000 index fc28d6c9ac..0000000000 --- a/vendor/github.com/containers/image/copy/fixtures/Hello.bz2 +++ /dev/null @@ -1 +0,0 @@ -../../pkg/compression/fixtures/Hello.bz2 \ No newline at end of file diff --git a/vendor/github.com/containers/image/copy/fixtures/Hello.gz b/vendor/github.com/containers/image/copy/fixtures/Hello.gz deleted file mode 120000 index 08aa805fcc..0000000000 --- a/vendor/github.com/containers/image/copy/fixtures/Hello.gz +++ /dev/null @@ -1 +0,0 @@ -../../pkg/compression/fixtures/Hello.gz \ No newline at end of file diff --git a/vendor/github.com/containers/image/copy/fixtures/Hello.uncompressed b/vendor/github.com/containers/image/copy/fixtures/Hello.uncompressed deleted file mode 120000 index 49b46625d8..0000000000 --- a/vendor/github.com/containers/image/copy/fixtures/Hello.uncompressed +++ /dev/null @@ -1 +0,0 @@ -../../pkg/compression/fixtures/Hello.uncompressed \ No newline at end of file diff --git a/vendor/github.com/containers/image/copy/fixtures/Hello.xz b/vendor/github.com/containers/image/copy/fixtures/Hello.xz deleted file mode 120000 index 77bcd85587..0000000000 --- a/vendor/github.com/containers/image/copy/fixtures/Hello.xz +++ /dev/null @@ -1 +0,0 @@ -../../pkg/compression/fixtures/Hello.xz \ No newline at end of file diff --git a/vendor/github.com/containers/image/copy/manifest.go b/vendor/github.com/containers/image/copy/manifest.go deleted file mode 100644 index 7e4cd10ef8..0000000000 --- a/vendor/github.com/containers/image/copy/manifest.go +++ /dev/null @@ -1,115 +0,0 @@ -package copy - -import ( - "strings" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// preferredManifestMIMETypes lists manifest MIME types in order of our preference, if we can't use the original manifest and need to convert. -// Prefer v2s2 to v2s1 because v2s2 does not need to be changed when uploading to a different location. -// Include v2s1 signed but not v2s1 unsigned, because docker/distribution requires a signature even if the unsigned MIME type is used. -var preferredManifestMIMETypes = []string{manifest.DockerV2Schema2MediaType, manifest.DockerV2Schema1SignedMediaType} - -// orderedSet is a list of strings (MIME types in our case), with each string appearing at most once. -type orderedSet struct { - list []string - included map[string]struct{} -} - -// newOrderedSet creates a correctly initialized orderedSet. -// [Sometimes it would be really nice if Golang had constructors…] -func newOrderedSet() *orderedSet { - return &orderedSet{ - list: []string{}, - included: map[string]struct{}{}, - } -} - -// append adds s to the end of os, only if it is not included already. -func (os *orderedSet) append(s string) { - if _, ok := os.included[s]; !ok { - os.list = append(os.list, s) - os.included[s] = struct{}{} - } -} - -// determineManifestConversion updates ic.manifestUpdates to convert manifest to a supported MIME type, if necessary and ic.canModifyManifest. -// Note that the conversion will only happen later, through ic.src.UpdatedImage -// Returns the preferred manifest MIME type (whether we are converting to it or using it unmodified), -// and a list of other possible alternatives, in order. -func (ic *imageCopier) determineManifestConversion(destSupportedManifestMIMETypes []string, forceManifestMIMEType string) (string, []string, error) { - _, srcType, err := ic.src.Manifest() - if err != nil { // This should have been cached?! - return "", nil, errors.Wrap(err, "Error reading manifest") - } - - if forceManifestMIMEType != "" { - destSupportedManifestMIMETypes = []string{forceManifestMIMEType} - } - - if len(destSupportedManifestMIMETypes) == 0 { - return srcType, []string{}, nil // Anything goes; just use the original as is, do not try any conversions. - } - supportedByDest := map[string]struct{}{} - for _, t := range destSupportedManifestMIMETypes { - supportedByDest[t] = struct{}{} - } - - // destSupportedManifestMIMETypes is a static guess; a particular registry may still only support a subset of the types. - // So, build a list of types to try in order of decreasing preference. - // FIXME? This treats manifest.DockerV2Schema1SignedMediaType and manifest.DockerV2Schema1MediaType as distinct, - // although we are not really making any conversion, and it is very unlikely that a destination would support one but not the other. - // In practice, schema1 is probably the lowest common denominator, so we would expect to try the first one of the MIME types - // and never attempt the other one. - prioritizedTypes := newOrderedSet() - - // First of all, prefer to keep the original manifest unmodified. - if _, ok := supportedByDest[srcType]; ok { - prioritizedTypes.append(srcType) - } - if !ic.canModifyManifest { - // We could also drop the !ic.canModifyManifest check and have the caller - // make the choice; it is already doing that to an extent, to improve error - // messages. But it is nice to hide the “if !ic.canModifyManifest, do no conversion” - // special case in here; the caller can then worry (or not) only about a good UI. - logrus.Debugf("We can't modify the manifest, hoping for the best...") - return srcType, []string{}, nil // Take our chances - FIXME? Or should we fail without trying? - } - - // Then use our list of preferred types. - for _, t := range preferredManifestMIMETypes { - if _, ok := supportedByDest[t]; ok { - prioritizedTypes.append(t) - } - } - - // Finally, try anything else the destination supports. - for _, t := range destSupportedManifestMIMETypes { - prioritizedTypes.append(t) - } - - logrus.Debugf("Manifest has MIME type %s, ordered candidate list [%s]", srcType, strings.Join(prioritizedTypes.list, ", ")) - if len(prioritizedTypes.list) == 0 { // Coverage: destSupportedManifestMIMETypes is not empty (or we would have exited in the “Anything goes” case above), so this should never happen. - return "", nil, errors.New("Internal error: no candidate MIME types") - } - preferredType := prioritizedTypes.list[0] - if preferredType != srcType { - ic.manifestUpdates.ManifestMIMEType = preferredType - } else { - logrus.Debugf("... will first try using the original manifest unmodified") - } - return preferredType, prioritizedTypes.list[1:], nil -} - -// isMultiImage returns true if img is a list of images -func isMultiImage(img types.UnparsedImage) (bool, error) { - _, mt, err := img.Manifest() - if err != nil { - return false, err - } - return manifest.MIMETypeIsMultiImage(mt), nil -} diff --git a/vendor/github.com/containers/image/copy/progress_reader.go b/vendor/github.com/containers/image/copy/progress_reader.go deleted file mode 100644 index b670ee59f1..0000000000 --- a/vendor/github.com/containers/image/copy/progress_reader.go +++ /dev/null @@ -1,28 +0,0 @@ -package copy - -import ( - "io" - "time" - - "github.com/containers/image/types" -) - -// progressReader is a reader that reports its progress on an interval. -type progressReader struct { - source io.Reader - channel chan types.ProgressProperties - interval time.Duration - artifact types.BlobInfo - lastTime time.Time - offset uint64 -} - -func (r *progressReader) Read(p []byte) (int, error) { - n, err := r.source.Read(p) - r.offset += uint64(n) - if time.Since(r.lastTime) > r.interval { - r.channel <- types.ProgressProperties{Artifact: r.artifact, Offset: r.offset} - r.lastTime = time.Now() - } - return n, err -} diff --git a/vendor/github.com/containers/image/copy/sign.go b/vendor/github.com/containers/image/copy/sign.go deleted file mode 100644 index 91394d2b0f..0000000000 --- a/vendor/github.com/containers/image/copy/sign.go +++ /dev/null @@ -1,31 +0,0 @@ -package copy - -import ( - "github.com/containers/image/signature" - "github.com/containers/image/transports" - "github.com/pkg/errors" -) - -// createSignature creates a new signature of manifest using keyIdentity. -func (c *copier) createSignature(manifest []byte, keyIdentity string) ([]byte, error) { - mech, err := signature.NewGPGSigningMechanism() - if err != nil { - return nil, errors.Wrap(err, "Error initializing GPG") - } - defer mech.Close() - if err := mech.SupportsSigning(); err != nil { - return nil, errors.Wrap(err, "Signing not supported") - } - - dockerReference := c.dest.Reference().DockerReference() - if dockerReference == nil { - return nil, errors.Errorf("Cannot determine canonical Docker reference for destination %s", transports.ImageName(c.dest.Reference())) - } - - c.Printf("Signing manifest\n") - newSig, err := signature.SignDockerManifest(manifest, dockerReference.String(), mech, keyIdentity) - if err != nil { - return nil, errors.Wrap(err, "Error creating signature") - } - return newSig, nil -} diff --git a/vendor/github.com/containers/image/directory/directory_dest.go b/vendor/github.com/containers/image/directory/directory_dest.go deleted file mode 100644 index 5f7443fa0f..0000000000 --- a/vendor/github.com/containers/image/directory/directory_dest.go +++ /dev/null @@ -1,243 +0,0 @@ -package directory - -import ( - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -const version = "Directory Transport Version: 1.0\n" - -// ErrNotContainerImageDir indicates that the directory doesn't match the expected contents of a directory created -// using the 'dir' transport -var ErrNotContainerImageDir = errors.New("not a containers image directory, don't want to overwrite important data") - -type dirImageDestination struct { - ref dirReference - compress bool -} - -// newImageDestination returns an ImageDestination for writing to a directory. -func newImageDestination(ref dirReference, compress bool) (types.ImageDestination, error) { - d := &dirImageDestination{ref: ref, compress: compress} - - // If directory exists check if it is empty - // if not empty, check whether the contents match that of a container image directory and overwrite the contents - // if the contents don't match throw an error - dirExists, err := pathExists(d.ref.resolvedPath) - if err != nil { - return nil, errors.Wrapf(err, "error checking for path %q", d.ref.resolvedPath) - } - if dirExists { - isEmpty, err := isDirEmpty(d.ref.resolvedPath) - if err != nil { - return nil, err - } - - if !isEmpty { - versionExists, err := pathExists(d.ref.versionPath()) - if err != nil { - return nil, errors.Wrapf(err, "error checking if path exists %q", d.ref.versionPath()) - } - if versionExists { - contents, err := ioutil.ReadFile(d.ref.versionPath()) - if err != nil { - return nil, err - } - // check if contents of version file is what we expect it to be - if string(contents) != version { - return nil, ErrNotContainerImageDir - } - } else { - return nil, ErrNotContainerImageDir - } - // delete directory contents so that only one image is in the directory at a time - if err = removeDirContents(d.ref.resolvedPath); err != nil { - return nil, errors.Wrapf(err, "error erasing contents in %q", d.ref.resolvedPath) - } - logrus.Debugf("overwriting existing container image directory %q", d.ref.resolvedPath) - } - } else { - // create directory if it doesn't exist - if err := os.MkdirAll(d.ref.resolvedPath, 0755); err != nil { - return nil, errors.Wrapf(err, "unable to create directory %q", d.ref.resolvedPath) - } - } - // create version file - err = ioutil.WriteFile(d.ref.versionPath(), []byte(version), 0644) - if err != nil { - return nil, errors.Wrapf(err, "error creating version file %q", d.ref.versionPath()) - } - return d, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *dirImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *dirImageDestination) Close() error { - return nil -} - -func (d *dirImageDestination) SupportedManifestMIMETypes() []string { - return nil -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *dirImageDestination) SupportsSignatures() error { - return nil -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *dirImageDestination) ShouldCompressLayers() bool { - return d.compress -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *dirImageDestination) AcceptsForeignLayerURLs() bool { - return false -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *dirImageDestination) MustMatchRuntimeOS() bool { - return false -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available -// to any other readers for download using the supplied digest. -// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. -func (d *dirImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - blobFile, err := ioutil.TempFile(d.ref.path, "dir-put-blob") - if err != nil { - return types.BlobInfo{}, err - } - succeeded := false - defer func() { - blobFile.Close() - if !succeeded { - os.Remove(blobFile.Name()) - } - }() - - digester := digest.Canonical.Digester() - tee := io.TeeReader(stream, digester.Hash()) - - size, err := io.Copy(blobFile, tee) - if err != nil { - return types.BlobInfo{}, err - } - computedDigest := digester.Digest() - if inputInfo.Size != -1 && size != inputInfo.Size { - return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size) - } - if err := blobFile.Sync(); err != nil { - return types.BlobInfo{}, err - } - if err := blobFile.Chmod(0644); err != nil { - return types.BlobInfo{}, err - } - blobPath := d.ref.layerPath(computedDigest) - if err := os.Rename(blobFile.Name(), blobPath); err != nil { - return types.BlobInfo{}, err - } - succeeded = true - return types.BlobInfo{Digest: computedDigest, Size: size}, nil -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob. -// Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. -// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); -// it returns a non-nil error only on an unexpected failure. -func (d *dirImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - if info.Digest == "" { - return false, -1, errors.Errorf(`"Can not check for a blob with unknown digest`) - } - blobPath := d.ref.layerPath(info.Digest) - finfo, err := os.Stat(blobPath) - if err != nil && os.IsNotExist(err) { - return false, -1, nil - } - if err != nil { - return false, -1, err - } - return true, finfo.Size(), nil -} - -func (d *dirImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return info, nil -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *dirImageDestination) PutManifest(manifest []byte) error { - return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644) -} - -func (d *dirImageDestination) PutSignatures(signatures [][]byte) error { - for i, sig := range signatures { - if err := ioutil.WriteFile(d.ref.signaturePath(i), sig, 0644); err != nil { - return err - } - } - return nil -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *dirImageDestination) Commit() error { - return nil -} - -// returns true if path exists -func pathExists(path string) (bool, error) { - _, err := os.Stat(path) - if err == nil { - return true, nil - } - if err != nil && os.IsNotExist(err) { - return false, nil - } - return false, err -} - -// returns true if directory is empty -func isDirEmpty(path string) (bool, error) { - files, err := ioutil.ReadDir(path) - if err != nil { - return false, err - } - return len(files) == 0, nil -} - -// deletes the contents of a directory -func removeDirContents(path string) error { - files, err := ioutil.ReadDir(path) - if err != nil { - return err - } - - for _, file := range files { - if err := os.RemoveAll(filepath.Join(path, file.Name())); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/containers/image/directory/directory_src.go b/vendor/github.com/containers/image/directory/directory_src.go deleted file mode 100644 index 0a8acf6bf9..0000000000 --- a/vendor/github.com/containers/image/directory/directory_src.go +++ /dev/null @@ -1,89 +0,0 @@ -package directory - -import ( - "context" - "io" - "io/ioutil" - "os" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -type dirImageSource struct { - ref dirReference -} - -// newImageSource returns an ImageSource reading from an existing directory. -// The caller must call .Close() on the returned ImageSource. -func newImageSource(ref dirReference) types.ImageSource { - return &dirImageSource{ref} -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (s *dirImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *dirImageSource) Close() error { - return nil -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *dirImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if instanceDigest != nil { - return nil, "", errors.Errorf(`Getting target manifest not supported by "dir:"`) - } - m, err := ioutil.ReadFile(s.ref.manifestPath()) - if err != nil { - return nil, "", err - } - return m, manifest.GuessMIMEType(m), err -} - -// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). -func (s *dirImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - r, err := os.Open(s.ref.layerPath(info.Digest)) - if err != nil { - return nil, 0, nil - } - fi, err := r.Stat() - if err != nil { - return nil, 0, nil - } - return r, fi.Size(), nil -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - if instanceDigest != nil { - return nil, errors.Errorf(`Manifests lists are not supported by "dir:"`) - } - signatures := [][]byte{} - for i := 0; ; i++ { - signature, err := ioutil.ReadFile(s.ref.signaturePath(i)) - if err != nil { - if os.IsNotExist(err) { - break - } - return nil, err - } - signatures = append(signatures, signature) - } - return signatures, nil -} - -// LayerInfosForCopy() returns updated layer info that should be used when copying, in preference to values in the manifest, if specified. -func (s *dirImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/directory/directory_transport.go b/vendor/github.com/containers/image/directory/directory_transport.go deleted file mode 100644 index c38753087e..0000000000 --- a/vendor/github.com/containers/image/directory/directory_transport.go +++ /dev/null @@ -1,187 +0,0 @@ -package directory - -import ( - "fmt" - "path/filepath" - "strings" - - "github.com/pkg/errors" - - "github.com/containers/image/directory/explicitfilepath" - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for directory paths. -var Transport = dirTransport{} - -type dirTransport struct{} - -func (t dirTransport) Name() string { - return "dir" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t dirTransport) ParseReference(reference string) (types.ImageReference, error) { - return NewReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t dirTransport) ValidatePolicyConfigurationScope(scope string) error { - if !strings.HasPrefix(scope, "/") { - return errors.Errorf("Invalid scope %s: Must be an absolute path", scope) - } - // Refuse also "/", otherwise "/" and "" would have the same semantics, - // and "" could be unexpectedly shadowed by the "/" entry. - if scope == "/" { - return errors.New(`Invalid scope "/": Use the generic default scope ""`) - } - cleaned := filepath.Clean(scope) - if cleaned != scope { - return errors.Errorf(`Invalid scope %s: Uses non-canonical format, perhaps try %s`, scope, cleaned) - } - return nil -} - -// dirReference is an ImageReference for directory paths. -type dirReference struct { - // Note that the interpretation of paths below depends on the underlying filesystem state, which may change under us at any time! - // Either of the paths may point to a different, or no, inode over time. resolvedPath may contain symbolic links, and so on. - - // Generally we follow the intent of the user, and use the "path" member for filesystem operations (e.g. the user can use a relative path to avoid - // being exposed to symlinks and renames in the parent directories to the working directory). - // (But in general, we make no attempt to be completely safe against concurrent hostile filesystem modifications.) - path string // As specified by the user. May be relative, contain symlinks, etc. - resolvedPath string // Absolute path with no symlinks, at least at the time of its creation. Primarily used for policy namespaces. -} - -// There is no directory.ParseReference because it is rather pointless. -// Callers who need a transport-independent interface will go through -// dirTransport.ParseReference; callers who intentionally deal with directories -// can use directory.NewReference. - -// NewReference returns a directory reference for a specified path. -// -// We do not expose an API supplying the resolvedPath; we could, but recomputing it -// is generally cheap enough that we prefer being confident about the properties of resolvedPath. -func NewReference(path string) (types.ImageReference, error) { - resolved, err := explicitfilepath.ResolvePathToFullyExplicit(path) - if err != nil { - return nil, err - } - return dirReference{path: path, resolvedPath: resolved}, nil -} - -func (ref dirReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref dirReference) StringWithinTransport() string { - return ref.path -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref dirReference) DockerReference() reference.Named { - return nil -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref dirReference) PolicyConfigurationIdentity() string { - return ref.resolvedPath -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref dirReference) PolicyConfigurationNamespaces() []string { - res := []string{} - path := ref.resolvedPath - for { - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 || lastSlash == 0 { - break - } - path = path[:lastSlash] - res = append(res, path) - } - // Note that we do not include "/"; it is redundant with the default "" global default, - // and rejected by dirTransport.ValidatePolicyConfigurationScope above. - return res -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref dirReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src := newImageSource(ref) - return image.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref dirReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ref), nil -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref dirReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - compress := false - if ctx != nil { - compress = ctx.DirForceCompress - } - return newImageDestination(ref, compress) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref dirReference) DeleteImage(ctx *types.SystemContext) error { - return errors.Errorf("Deleting images not implemented for dir: images") -} - -// manifestPath returns a path for the manifest within a directory using our conventions. -func (ref dirReference) manifestPath() string { - return filepath.Join(ref.path, "manifest.json") -} - -// layerPath returns a path for a layer tarball within a directory using our conventions. -func (ref dirReference) layerPath(digest digest.Digest) string { - // FIXME: Should we keep the digest identification? - return filepath.Join(ref.path, digest.Hex()+".tar") -} - -// signaturePath returns a path for a signature within a directory using our conventions. -func (ref dirReference) signaturePath(index int) string { - return filepath.Join(ref.path, fmt.Sprintf("signature-%d", index+1)) -} - -// versionPath returns a path for the version file within a directory using our conventions. -func (ref dirReference) versionPath() string { - return filepath.Join(ref.path, "version") -} diff --git a/vendor/github.com/containers/image/directory/explicitfilepath/path.go b/vendor/github.com/containers/image/directory/explicitfilepath/path.go deleted file mode 100644 index 71136b8808..0000000000 --- a/vendor/github.com/containers/image/directory/explicitfilepath/path.go +++ /dev/null @@ -1,56 +0,0 @@ -package explicitfilepath - -import ( - "os" - "path/filepath" - - "github.com/pkg/errors" -) - -// ResolvePathToFullyExplicit returns the input path converted to an absolute, no-symlinks, cleaned up path. -// To do so, all elements of the input path must exist; as a special case, the final component may be -// a non-existent name (but not a symlink pointing to a non-existent name) -// This is intended as a a helper for implementations of types.ImageReference.PolicyConfigurationIdentity etc. -func ResolvePathToFullyExplicit(path string) (string, error) { - switch _, err := os.Lstat(path); { - case err == nil: - return resolveExistingPathToFullyExplicit(path) - case os.IsNotExist(err): - parent, file := filepath.Split(path) - resolvedParent, err := resolveExistingPathToFullyExplicit(parent) - if err != nil { - return "", err - } - if file == "." || file == ".." { - // Coverage: This can happen, but very rarely: if we have successfully resolved the parent, both "." and ".." in it should have been resolved as well. - // This can still happen if there is a filesystem race condition, causing the Lstat() above to fail but the later resolution to succeed. - // We do not care to promise anything if such filesystem race conditions can happen, but we definitely don't want to return "."/".." components - // in the resulting path, and especially not at the end. - return "", errors.Errorf("Unexpectedly missing special filename component in %s", path) - } - resolvedPath := filepath.Join(resolvedParent, file) - // As a sanity check, ensure that there are no "." or ".." components. - cleanedResolvedPath := filepath.Clean(resolvedPath) - if cleanedResolvedPath != resolvedPath { - // Coverage: This should never happen. - return "", errors.Errorf("Internal inconsistency: Path %s resolved to %s still cleaned up to %s", path, resolvedPath, cleanedResolvedPath) - } - return resolvedPath, nil - default: // err != nil, unrecognized - return "", err - } -} - -// resolveExistingPathToFullyExplicit is the same as ResolvePathToFullyExplicit, -// but without the special case for missing final component. -func resolveExistingPathToFullyExplicit(path string) (string, error) { - resolved, err := filepath.Abs(path) - if err != nil { - return "", err // Coverage: This can fail only if os.Getwd() fails. - } - resolved, err = filepath.EvalSymlinks(resolved) - if err != nil { - return "", err - } - return filepath.Clean(resolved), nil -} diff --git a/vendor/github.com/containers/image/docker/archive/dest.go b/vendor/github.com/containers/image/docker/archive/dest.go deleted file mode 100644 index 9fc85bd85b..0000000000 --- a/vendor/github.com/containers/image/docker/archive/dest.go +++ /dev/null @@ -1,66 +0,0 @@ -package archive - -import ( - "io" - "os" - - "github.com/containers/image/docker/tarfile" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -type archiveImageDestination struct { - *tarfile.Destination // Implements most of types.ImageDestination - ref archiveReference - writer io.Closer -} - -func newImageDestination(ctx *types.SystemContext, ref archiveReference) (types.ImageDestination, error) { - if ref.destinationRef == nil { - return nil, errors.Errorf("docker-archive: destination reference not supplied (must be of form :)") - } - - // ref.path can be either a pipe or a regular file - // in the case of a pipe, we require that we can open it for write - // in the case of a regular file, we don't want to overwrite any pre-existing file - // so we check for Size() == 0 below (This is racy, but using O_EXCL would also be racy, - // only in a different way. Either way, it’s up to the user to not have two writers to the same path.) - fh, err := os.OpenFile(ref.path, os.O_WRONLY|os.O_CREATE, 0644) - if err != nil { - return nil, errors.Wrapf(err, "error opening file %q", ref.path) - } - - fhStat, err := fh.Stat() - if err != nil { - return nil, errors.Wrapf(err, "error statting file %q", ref.path) - } - - if fhStat.Mode().IsRegular() && fhStat.Size() != 0 { - return nil, errors.New("docker-archive doesn't support modifying existing images") - } - - return &archiveImageDestination{ - Destination: tarfile.NewDestination(fh, ref.destinationRef), - ref: ref, - writer: fh, - }, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *archiveImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *archiveImageDestination) Close() error { - return d.writer.Close() -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *archiveImageDestination) Commit() error { - return d.Destination.Commit() -} diff --git a/vendor/github.com/containers/image/docker/archive/src.go b/vendor/github.com/containers/image/docker/archive/src.go deleted file mode 100644 index b2ffd965df..0000000000 --- a/vendor/github.com/containers/image/docker/archive/src.go +++ /dev/null @@ -1,41 +0,0 @@ -package archive - -import ( - "github.com/containers/image/docker/tarfile" - "github.com/containers/image/types" - "github.com/sirupsen/logrus" -) - -type archiveImageSource struct { - *tarfile.Source // Implements most of types.ImageSource - ref archiveReference -} - -// newImageSource returns a types.ImageSource for the specified image reference. -// The caller must call .Close() on the returned ImageSource. -func newImageSource(ctx *types.SystemContext, ref archiveReference) types.ImageSource { - if ref.destinationRef != nil { - logrus.Warnf("docker-archive: references are not supported for sources (ignoring)") - } - src := tarfile.NewSource(ref.path) - return &archiveImageSource{ - Source: src, - ref: ref, - } -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (s *archiveImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *archiveImageSource) Close() error { - return nil -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *archiveImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/docker/archive/transport.go b/vendor/github.com/containers/image/docker/archive/transport.go deleted file mode 100644 index 047df73db9..0000000000 --- a/vendor/github.com/containers/image/docker/archive/transport.go +++ /dev/null @@ -1,154 +0,0 @@ -package archive - -import ( - "fmt" - "strings" - - "github.com/containers/image/docker/reference" - ctrImage "github.com/containers/image/image" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for local Docker archives. -var Transport = archiveTransport{} - -type archiveTransport struct{} - -func (t archiveTransport) Name() string { - return "docker-archive" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t archiveTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t archiveTransport) ValidatePolicyConfigurationScope(scope string) error { - // See the explanation in archiveReference.PolicyConfigurationIdentity. - return errors.New(`docker-archive: does not support any scopes except the default "" one`) -} - -// archiveReference is an ImageReference for Docker images. -type archiveReference struct { - destinationRef reference.NamedTagged // only used for destinations - path string -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an Docker ImageReference. -func ParseReference(refString string) (types.ImageReference, error) { - if refString == "" { - return nil, errors.Errorf("docker-archive reference %s isn't of the form [:]", refString) - } - - parts := strings.SplitN(refString, ":", 2) - path := parts[0] - var destinationRef reference.NamedTagged - - // A :tag was specified, which is only necessary for destinations. - if len(parts) == 2 { - ref, err := reference.ParseNormalizedNamed(parts[1]) - if err != nil { - return nil, errors.Wrapf(err, "docker-archive parsing reference") - } - ref = reference.TagNameOnly(ref) - - if _, isDigest := ref.(reference.Canonical); isDigest { - return nil, errors.Errorf("docker-archive doesn't support digest references: %s", refString) - } - - refTagged, isTagged := ref.(reference.NamedTagged) - if !isTagged { - // Really shouldn't be hit... - return nil, errors.Errorf("internal error: reference is not tagged even after reference.TagNameOnly: %s", refString) - } - destinationRef = refTagged - } - - return archiveReference{ - destinationRef: destinationRef, - path: path, - }, nil -} - -func (ref archiveReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref archiveReference) StringWithinTransport() string { - if ref.destinationRef == nil { - return ref.path - } - return fmt.Sprintf("%s:%s", ref.path, ref.destinationRef.String()) -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref archiveReference) DockerReference() reference.Named { - return ref.destinationRef -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref archiveReference) PolicyConfigurationIdentity() string { - // Punt, the justification is similar to dockerReference.PolicyConfigurationIdentity. - return "" -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref archiveReference) PolicyConfigurationNamespaces() []string { - // TODO - return []string{} -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref archiveReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src := newImageSource(ctx, ref) - return ctrImage.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref archiveReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref), nil -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref archiveReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref archiveReference) DeleteImage(ctx *types.SystemContext) error { - // Not really supported, for safety reasons. - return errors.New("Deleting images not implemented for docker-archive: images") -} diff --git a/vendor/github.com/containers/image/docker/daemon/client.go b/vendor/github.com/containers/image/docker/daemon/client.go deleted file mode 100644 index 82fab4b19a..0000000000 --- a/vendor/github.com/containers/image/docker/daemon/client.go +++ /dev/null @@ -1,69 +0,0 @@ -package daemon - -import ( - "net/http" - "path/filepath" - - "github.com/containers/image/types" - dockerclient "github.com/docker/docker/client" - "github.com/docker/go-connections/tlsconfig" -) - -const ( - // The default API version to be used in case none is explicitly specified - defaultAPIVersion = "1.22" -) - -// NewDockerClient initializes a new API client based on the passed SystemContext. -func newDockerClient(ctx *types.SystemContext) (*dockerclient.Client, error) { - host := dockerclient.DefaultDockerHost - if ctx != nil && ctx.DockerDaemonHost != "" { - host = ctx.DockerDaemonHost - } - - // Sadly, unix:// sockets don't work transparently with dockerclient.NewClient. - // They work fine with a nil httpClient; with a non-nil httpClient, the transport’s - // TLSClientConfig must be nil (or the client will try using HTTPS over the PF_UNIX socket - // regardless of the values in the *tls.Config), and we would have to call sockets.ConfigureTransport. - // - // We don't really want to configure anything for unix:// sockets, so just pass a nil *http.Client. - proto, _, _, err := dockerclient.ParseHost(host) - if err != nil { - return nil, err - } - var httpClient *http.Client - if proto != "unix" { - hc, err := tlsConfig(ctx) - if err != nil { - return nil, err - } - httpClient = hc - } - - return dockerclient.NewClient(host, defaultAPIVersion, httpClient, nil) -} - -func tlsConfig(ctx *types.SystemContext) (*http.Client, error) { - options := tlsconfig.Options{} - if ctx != nil && ctx.DockerDaemonInsecureSkipTLSVerify { - options.InsecureSkipVerify = true - } - - if ctx != nil && ctx.DockerDaemonCertPath != "" { - options.CAFile = filepath.Join(ctx.DockerDaemonCertPath, "ca.pem") - options.CertFile = filepath.Join(ctx.DockerDaemonCertPath, "cert.pem") - options.KeyFile = filepath.Join(ctx.DockerDaemonCertPath, "key.pem") - } - - tlsc, err := tlsconfig.Client(options) - if err != nil { - return nil, err - } - - return &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsc, - }, - CheckRedirect: dockerclient.CheckRedirect, - }, nil -} diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_dest.go b/vendor/github.com/containers/image/docker/daemon/daemon_dest.go deleted file mode 100644 index f73ac23392..0000000000 --- a/vendor/github.com/containers/image/docker/daemon/daemon_dest.go +++ /dev/null @@ -1,135 +0,0 @@ -package daemon - -import ( - "io" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/docker/tarfile" - "github.com/containers/image/types" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -type daemonImageDestination struct { - ref daemonReference - mustMatchRuntimeOS bool - *tarfile.Destination // Implements most of types.ImageDestination - // For talking to imageLoadGoroutine - goroutineCancel context.CancelFunc - statusChannel <-chan error - writer *io.PipeWriter - // Other state - committed bool // writer has been closed -} - -// newImageDestination returns a types.ImageDestination for the specified image reference. -func newImageDestination(ctx *types.SystemContext, ref daemonReference) (types.ImageDestination, error) { - if ref.ref == nil { - return nil, errors.Errorf("Invalid destination docker-daemon:%s: a destination must be a name:tag", ref.StringWithinTransport()) - } - namedTaggedRef, ok := ref.ref.(reference.NamedTagged) - if !ok { - return nil, errors.Errorf("Invalid destination docker-daemon:%s: a destination must be a name:tag", ref.StringWithinTransport()) - } - - var mustMatchRuntimeOS = true - if ctx != nil && ctx.DockerDaemonHost != client.DefaultDockerHost { - mustMatchRuntimeOS = false - } - - c, err := newDockerClient(ctx) - if err != nil { - return nil, errors.Wrap(err, "Error initializing docker engine client") - } - - reader, writer := io.Pipe() - // Commit() may never be called, so we may never read from this channel; so, make this buffered to allow imageLoadGoroutine to write status and terminate even if we never read it. - statusChannel := make(chan error, 1) - - goroutineContext, goroutineCancel := context.WithCancel(context.Background()) - go imageLoadGoroutine(goroutineContext, c, reader, statusChannel) - - return &daemonImageDestination{ - ref: ref, - mustMatchRuntimeOS: mustMatchRuntimeOS, - Destination: tarfile.NewDestination(writer, namedTaggedRef), - goroutineCancel: goroutineCancel, - statusChannel: statusChannel, - writer: writer, - committed: false, - }, nil -} - -// imageLoadGoroutine accepts tar stream on reader, sends it to c, and reports error or success by writing to statusChannel -func imageLoadGoroutine(ctx context.Context, c *client.Client, reader *io.PipeReader, statusChannel chan<- error) { - err := errors.New("Internal error: unexpected panic in imageLoadGoroutine") - defer func() { - logrus.Debugf("docker-daemon: sending done, status %v", err) - statusChannel <- err - }() - defer func() { - if err == nil { - reader.Close() - } else { - reader.CloseWithError(err) - } - }() - - resp, err := c.ImageLoad(ctx, reader, true) - if err != nil { - err = errors.Wrap(err, "Error saving image to docker engine") - return - } - defer resp.Body.Close() -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *daemonImageDestination) MustMatchRuntimeOS() bool { - return d.mustMatchRuntimeOS -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *daemonImageDestination) Close() error { - if !d.committed { - logrus.Debugf("docker-daemon: Closing tar stream to abort loading") - // In principle, goroutineCancel() should abort the HTTP request and stop the process from continuing. - // In practice, though, various HTTP implementations used by client.Client.ImageLoad() (including - // https://github.com/golang/net/blob/master/context/ctxhttp/ctxhttp_pre17.go and the - // net/http version with native Context support in Go 1.7) do not always actually immediately cancel - // the operation: they may process the HTTP request, or a part of it, to completion in a goroutine, and - // return early if the context is canceled without terminating the goroutine at all. - // So we need this CloseWithError to terminate sending the HTTP request Body - // immediately, and hopefully, through terminating the sending which uses "Transfer-Encoding: chunked"" without sending - // the terminating zero-length chunk, prevent the docker daemon from processing the tar stream at all. - // Whether that works or not, closing the PipeWriter seems desirable in any case. - d.writer.CloseWithError(errors.New("Aborting upload, daemonImageDestination closed without a previous .Commit()")) - } - d.goroutineCancel() - - return nil -} - -func (d *daemonImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *daemonImageDestination) Commit() error { - logrus.Debugf("docker-daemon: Closing tar stream") - if err := d.Destination.Commit(); err != nil { - return err - } - if err := d.writer.Close(); err != nil { - return err - } - d.committed = true // We may still fail, but we are done sending to imageLoadGoroutine. - - logrus.Debugf("docker-daemon: Waiting for status") - err := <-d.statusChannel - return err -} diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_src.go b/vendor/github.com/containers/image/docker/daemon/daemon_src.go deleted file mode 100644 index 5cf7679b1c..0000000000 --- a/vendor/github.com/containers/image/docker/daemon/daemon_src.go +++ /dev/null @@ -1,88 +0,0 @@ -package daemon - -import ( - "io" - "io/ioutil" - "os" - - "github.com/containers/image/docker/tarfile" - "github.com/containers/image/internal/tmpdir" - "github.com/containers/image/types" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -type daemonImageSource struct { - ref daemonReference - *tarfile.Source // Implements most of types.ImageSource - tarCopyPath string -} - -type layerInfo struct { - path string - size int64 -} - -// newImageSource returns a types.ImageSource for the specified image reference. -// The caller must call .Close() on the returned ImageSource. -// -// It would be great if we were able to stream the input tar as it is being -// sent; but Docker sends the top-level manifest, which determines which paths -// to look for, at the end, so in we will need to seek back and re-read, several times. -// (We could, perhaps, expect an exact sequence, assume that the first plaintext file -// is the config, and that the following len(RootFS) files are the layers, but that feels -// way too brittle.) -func newImageSource(ctx *types.SystemContext, ref daemonReference) (types.ImageSource, error) { - c, err := newDockerClient(ctx) - if err != nil { - return nil, errors.Wrap(err, "Error initializing docker engine client") - } - // Per NewReference(), ref.StringWithinTransport() is either an image ID (config digest), or a !reference.NameOnly() reference. - // Either way ImageSave should create a tarball with exactly one image. - inputStream, err := c.ImageSave(context.TODO(), []string{ref.StringWithinTransport()}) - if err != nil { - return nil, errors.Wrap(err, "Error loading image from docker engine") - } - defer inputStream.Close() - - // FIXME: use SystemContext here. - tarCopyFile, err := ioutil.TempFile(tmpdir.TemporaryDirectoryForBigFiles(), "docker-daemon-tar") - if err != nil { - return nil, err - } - defer tarCopyFile.Close() - - succeeded := false - defer func() { - if !succeeded { - os.Remove(tarCopyFile.Name()) - } - }() - - if _, err := io.Copy(tarCopyFile, inputStream); err != nil { - return nil, err - } - - succeeded = true - return &daemonImageSource{ - ref: ref, - Source: tarfile.NewSource(tarCopyFile.Name()), - tarCopyPath: tarCopyFile.Name(), - }, nil -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (s *daemonImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *daemonImageSource) Close() error { - return os.Remove(s.tarCopyPath) -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *daemonImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_transport.go b/vendor/github.com/containers/image/docker/daemon/daemon_transport.go deleted file mode 100644 index 8ad6b521ff..0000000000 --- a/vendor/github.com/containers/image/docker/daemon/daemon_transport.go +++ /dev/null @@ -1,185 +0,0 @@ -package daemon - -import ( - "github.com/pkg/errors" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for images managed by a local Docker daemon. -var Transport = daemonTransport{} - -type daemonTransport struct{} - -// Name returns the name of the transport, which must be unique among other transports. -func (t daemonTransport) Name() string { - return "docker-daemon" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t daemonTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t daemonTransport) ValidatePolicyConfigurationScope(scope string) error { - // See the explanation in daemonReference.PolicyConfigurationIdentity. - return errors.New(`docker-daemon: does not support any scopes except the default "" one`) -} - -// daemonReference is an ImageReference for images managed by a local Docker daemon -// Exactly one of id and ref can be set. -// For daemonImageSource, both id and ref are acceptable, ref must not be a NameOnly (interpreted as all tags in that repository by the daemon) -// For daemonImageDestination, it must be a ref, which is NamedTagged. -// (We could, in principle, also allow storing images without tagging them, and the user would have to refer to them using the docker image ID = config digest. -// Using the config digest requires the caller to parse the manifest themselves, which is very cumbersome; so, for now, we don’t bother.) -type daemonReference struct { - id digest.Digest - ref reference.Named // !reference.IsNameOnly -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func ParseReference(refString string) (types.ImageReference, error) { - // This is intended to be compatible with reference.ParseAnyReference, but more strict about refusing some of the ambiguous cases. - // In particular, this rejects unprefixed digest values (64 hex chars), and sha256 digest prefixes (sha256:fewer-than-64-hex-chars). - - // digest:hexstring is structurally the same as a reponame:tag (meaning docker.io/library/reponame:tag). - // reference.ParseAnyReference interprets such strings as digests. - if dgst, err := digest.Parse(refString); err == nil { - // The daemon explicitly refuses to tag images with a reponame equal to digest.Canonical - but _only_ this digest name. - // Other digest references are ambiguous, so refuse them. - if dgst.Algorithm() != digest.Canonical { - return nil, errors.Errorf("Invalid docker-daemon: reference %s: only digest algorithm %s accepted", refString, digest.Canonical) - } - return NewReference(dgst, nil) - } - - ref, err := reference.ParseNormalizedNamed(refString) // This also rejects unprefixed digest values - if err != nil { - return nil, err - } - if reference.FamiliarName(ref) == digest.Canonical.String() { - return nil, errors.Errorf("Invalid docker-daemon: reference %s: The %s repository name is reserved for (non-shortened) digest references", refString, digest.Canonical) - } - return NewReference("", ref) -} - -// NewReference returns a docker-daemon reference for either the supplied image ID (config digest) or the supplied reference (which must satisfy !reference.IsNameOnly) -func NewReference(id digest.Digest, ref reference.Named) (types.ImageReference, error) { - if id != "" && ref != nil { - return nil, errors.New("docker-daemon: reference must not have an image ID and a reference string specified at the same time") - } - if ref != nil { - if reference.IsNameOnly(ref) { - return nil, errors.Errorf("docker-daemon: reference %s has neither a tag nor a digest", reference.FamiliarString(ref)) - } - // A github.com/distribution/reference value can have a tag and a digest at the same time! - // Most versions of docker/reference do not handle that (ignoring the tag), so reject such input. - // This MAY be accepted in the future. - _, isTagged := ref.(reference.NamedTagged) - _, isDigested := ref.(reference.Canonical) - if isTagged && isDigested { - return nil, errors.Errorf("docker-daemon: references with both a tag and digest are currently not supported") - } - } - return daemonReference{ - id: id, - ref: ref, - }, nil -} - -func (ref daemonReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix; -// instead, see transports.ImageName(). -func (ref daemonReference) StringWithinTransport() string { - switch { - case ref.id != "": - return ref.id.String() - case ref.ref != nil: - return reference.FamiliarString(ref.ref) - default: // Coverage: Should never happen, NewReference above should refuse such values. - panic("Internal inconsistency: daemonReference has empty id and nil ref") - } -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref daemonReference) DockerReference() reference.Named { - return ref.ref // May be nil -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref daemonReference) PolicyConfigurationIdentity() string { - // We must allow referring to images in the daemon by image ID, otherwise untagged images would not be accessible. - // But the existence of image IDs means that we can’t truly well namespace the input; the untagged images would have to fall into the default policy, - // which can be unexpected. So, punt. - return "" // This still allows using the default "" scope to define a policy for this transport. -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref daemonReference) PolicyConfigurationNamespaces() []string { - // See the explanation in daemonReference.PolicyConfigurationIdentity. - return []string{} -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref daemonReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src, err := newImageSource(ctx, ref) - if err != nil { - return nil, err - } - return image.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref daemonReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref daemonReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref daemonReference) DeleteImage(ctx *types.SystemContext) error { - // Should this just untag the image? Should this stop running containers? - // The semantics is not quite as clear as for remote repositories. - // The user can run (docker rmi) directly anyway, so, for now(?), punt instead of trying to guess what the user meant. - return errors.Errorf("Deleting images not implemented for docker-daemon: images") -} diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go deleted file mode 100644 index 91006e8d24..0000000000 --- a/vendor/github.com/containers/image/docker/docker_client.go +++ /dev/null @@ -1,439 +0,0 @@ -package docker - -import ( - "context" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "path/filepath" - "strings" - "time" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/pkg/docker/config" - "github.com/containers/image/pkg/tlsclientconfig" - "github.com/containers/image/types" - "github.com/docker/distribution/registry/client" - "github.com/docker/go-connections/tlsconfig" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -const ( - dockerHostname = "docker.io" - dockerRegistry = "registry-1.docker.io" - - systemPerHostCertDirPath = "/etc/docker/certs.d" - - resolvedPingV2URL = "%s://%s/v2/" - resolvedPingV1URL = "%s://%s/v1/_ping" - tagsPath = "/v2/%s/tags/list" - manifestPath = "/v2/%s/manifests/%s" - blobsPath = "/v2/%s/blobs/%s" - blobUploadPath = "/v2/%s/blobs/uploads/" - extensionsSignaturePath = "/extensions/v2/%s/signatures/%s" - - minimumTokenLifetimeSeconds = 60 - - extensionSignatureSchemaVersion = 2 // extensionSignature.Version - extensionSignatureTypeAtomic = "atomic" // extensionSignature.Type -) - -var ( - // ErrV1NotSupported is returned when we're trying to talk to a - // docker V1 registry. - ErrV1NotSupported = errors.New("can't talk to a V1 docker registry") - // ErrUnauthorizedForCredentials is returned when the status code returned is 401 - ErrUnauthorizedForCredentials = errors.New("unable to retrieve auth token: invalid username/password") -) - -// extensionSignature and extensionSignatureList come from github.com/openshift/origin/pkg/dockerregistry/server/signaturedispatcher.go: -// signature represents a Docker image signature. -type extensionSignature struct { - Version int `json:"schemaVersion"` // Version specifies the schema version - Name string `json:"name"` // Name must be in "sha256:@signatureName" format - Type string `json:"type"` // Type is optional, of not set it will be defaulted to "AtomicImageV1" - Content []byte `json:"content"` // Content contains the signature -} - -// signatureList represents list of Docker image signatures. -type extensionSignatureList struct { - Signatures []extensionSignature `json:"signatures"` -} - -type bearerToken struct { - Token string `json:"token"` - AccessToken string `json:"access_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` -} - -// dockerClient is configuration for dealing with a single Docker registry. -type dockerClient struct { - // The following members are set by newDockerClient and do not change afterwards. - ctx *types.SystemContext - registry string - username string - password string - client *http.Client - signatureBase signatureStorageBase - scope authScope - // The following members are detected registry properties: - // They are set after a successful detectProperties(), and never change afterwards. - scheme string // Empty value also used to indicate detectProperties() has not yet succeeded. - challenges []challenge - supportsSignatures bool - // The following members are private state for setupRequestAuth, both are valid if token != nil. - token *bearerToken - tokenExpiration time.Time -} - -type authScope struct { - remoteName string - actions string -} - -func newBearerTokenFromJSONBlob(blob []byte) (*bearerToken, error) { - token := new(bearerToken) - if err := json.Unmarshal(blob, &token); err != nil { - return nil, err - } - if token.Token == "" { - token.Token = token.AccessToken - } - if token.ExpiresIn < minimumTokenLifetimeSeconds { - token.ExpiresIn = minimumTokenLifetimeSeconds - logrus.Debugf("Increasing token expiration to: %d seconds", token.ExpiresIn) - } - if token.IssuedAt.IsZero() { - token.IssuedAt = time.Now().UTC() - } - return token, nil -} - -// this is cloned from docker/go-connections because upstream docker has changed -// it and make deps here fails otherwise. -// We'll drop this once we upgrade to docker 1.13.x deps. -func serverDefault() *tls.Config { - return &tls.Config{ - // Avoid fallback to SSL protocols < TLS1.0 - MinVersion: tls.VersionTLS10, - PreferServerCipherSuites: true, - CipherSuites: tlsconfig.DefaultServerAcceptedCiphers, - } -} - -// dockerCertDir returns a path to a directory to be consumed by tlsclientconfig.SetupCertificates() depending on ctx and hostPort. -func dockerCertDir(ctx *types.SystemContext, hostPort string) string { - if ctx != nil && ctx.DockerCertPath != "" { - return ctx.DockerCertPath - } - var hostCertDir string - if ctx != nil && ctx.DockerPerHostCertDirPath != "" { - hostCertDir = ctx.DockerPerHostCertDirPath - } else if ctx != nil && ctx.RootForImplicitAbsolutePaths != "" { - hostCertDir = filepath.Join(ctx.RootForImplicitAbsolutePaths, systemPerHostCertDirPath) - } else { - hostCertDir = systemPerHostCertDirPath - } - return filepath.Join(hostCertDir, hostPort) -} - -// newDockerClientFromRef returns a new dockerClient instance for refHostname (a host a specified in the Docker image reference, not canonicalized to dockerRegistry) -// “write” specifies whether the client will be used for "write" access (in particular passed to lookaside.go:toplevelFromSection) -func newDockerClientFromRef(ctx *types.SystemContext, ref dockerReference, write bool, actions string) (*dockerClient, error) { - registry := reference.Domain(ref.ref) - username, password, err := config.GetAuthentication(ctx, reference.Domain(ref.ref)) - if err != nil { - return nil, errors.Wrapf(err, "error getting username and password") - } - sigBase, err := configuredSignatureStorageBase(ctx, ref, write) - if err != nil { - return nil, err - } - remoteName := reference.Path(ref.ref) - - return newDockerClientWithDetails(ctx, registry, username, password, actions, sigBase, remoteName) -} - -// newDockerClientWithDetails returns a new dockerClient instance for the given parameters -func newDockerClientWithDetails(ctx *types.SystemContext, registry, username, password, actions string, sigBase signatureStorageBase, remoteName string) (*dockerClient, error) { - hostName := registry - if registry == dockerHostname { - registry = dockerRegistry - } - tr := tlsclientconfig.NewTransport() - tr.TLSClientConfig = serverDefault() - - // It is undefined whether the host[:port] string for dockerHostname should be dockerHostname or dockerRegistry, - // because docker/docker does not read the certs.d subdirectory at all in that case. We use the user-visible - // dockerHostname here, because it is more symmetrical to read the configuration in that case as well, and because - // generally the UI hides the existence of the different dockerRegistry. But note that this behavior is - // undocumented and may change if docker/docker changes. - certDir := dockerCertDir(ctx, hostName) - if err := tlsclientconfig.SetupCertificates(certDir, tr.TLSClientConfig); err != nil { - return nil, err - } - - if ctx != nil && ctx.DockerInsecureSkipTLSVerify { - tr.TLSClientConfig.InsecureSkipVerify = true - } - - return &dockerClient{ - ctx: ctx, - registry: registry, - username: username, - password: password, - client: &http.Client{Transport: tr}, - signatureBase: sigBase, - scope: authScope{ - actions: actions, - remoteName: remoteName, - }, - }, nil -} - -// CheckAuth validates the credentials by attempting to log into the registry -// returns an error if an error occcured while making the http request or the status code received was 401 -func CheckAuth(ctx context.Context, sCtx *types.SystemContext, username, password, registry string) error { - newLoginClient, err := newDockerClientWithDetails(sCtx, registry, username, password, "", nil, "") - if err != nil { - return errors.Wrapf(err, "error creating new docker client") - } - - resp, err := newLoginClient.makeRequest(ctx, "GET", "/v2/", nil, nil) - if err != nil { - return err - } - defer resp.Body.Close() - - switch resp.StatusCode { - case http.StatusOK: - return nil - case http.StatusUnauthorized: - return ErrUnauthorizedForCredentials - default: - return errors.Errorf("error occured with status code %q", resp.StatusCode) - } -} - -// makeRequest creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client. -// The host name and schema is taken from the client or autodetected, and the path is relative to it, i.e. the path usually starts with /v2/. -func (c *dockerClient) makeRequest(ctx context.Context, method, path string, headers map[string][]string, stream io.Reader) (*http.Response, error) { - if err := c.detectProperties(ctx); err != nil { - return nil, err - } - - url := fmt.Sprintf("%s://%s%s", c.scheme, c.registry, path) - return c.makeRequestToResolvedURL(ctx, method, url, headers, stream, -1, true) -} - -// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client. -// streamLen, if not -1, specifies the length of the data expected on stream. -// makeRequest should generally be preferred. -// TODO(runcom): too many arguments here, use a struct -func (c *dockerClient) makeRequestToResolvedURL(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, sendAuth bool) (*http.Response, error) { - req, err := http.NewRequest(method, url, stream) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if streamLen != -1 { // Do not blindly overwrite if streamLen == -1, http.NewRequest above can figure out the length of bytes.Reader and similar objects without us having to compute it. - req.ContentLength = streamLen - } - req.Header.Set("Docker-Distribution-API-Version", "registry/2.0") - for n, h := range headers { - for _, hh := range h { - req.Header.Add(n, hh) - } - } - if c.ctx != nil && c.ctx.DockerRegistryUserAgent != "" { - req.Header.Add("User-Agent", c.ctx.DockerRegistryUserAgent) - } - if sendAuth { - if err := c.setupRequestAuth(req); err != nil { - return nil, err - } - } - logrus.Debugf("%s %s", method, url) - res, err := c.client.Do(req) - if err != nil { - return nil, err - } - return res, nil -} - -// we're using the challenges from the /v2/ ping response and not the one from the destination -// URL in this request because: -// -// 1) docker does that as well -// 2) gcr.io is sending 401 without a WWW-Authenticate header in the real request -// -// debugging: https://github.com/containers/image/pull/211#issuecomment-273426236 and follows up -func (c *dockerClient) setupRequestAuth(req *http.Request) error { - if len(c.challenges) == 0 { - return nil - } - schemeNames := make([]string, 0, len(c.challenges)) - for _, challenge := range c.challenges { - schemeNames = append(schemeNames, challenge.Scheme) - switch challenge.Scheme { - case "basic": - req.SetBasicAuth(c.username, c.password) - return nil - case "bearer": - if c.token == nil || time.Now().After(c.tokenExpiration) { - realm, ok := challenge.Parameters["realm"] - if !ok { - return errors.Errorf("missing realm in bearer auth challenge") - } - service, _ := challenge.Parameters["service"] // Will be "" if not present - var scope string - if c.scope.remoteName != "" && c.scope.actions != "" { - scope = fmt.Sprintf("repository:%s:%s", c.scope.remoteName, c.scope.actions) - } - token, err := c.getBearerToken(req.Context(), realm, service, scope) - if err != nil { - return err - } - c.token = token - c.tokenExpiration = token.IssuedAt.Add(time.Duration(token.ExpiresIn) * time.Second) - } - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.token.Token)) - return nil - default: - logrus.Debugf("no handler for %s authentication", challenge.Scheme) - } - } - logrus.Infof("None of the challenges sent by server (%s) are supported, trying an unauthenticated request anyway", strings.Join(schemeNames, ", ")) - return nil -} - -func (c *dockerClient) getBearerToken(ctx context.Context, realm, service, scope string) (*bearerToken, error) { - authReq, err := http.NewRequest("GET", realm, nil) - if err != nil { - return nil, err - } - authReq = authReq.WithContext(ctx) - getParams := authReq.URL.Query() - if service != "" { - getParams.Add("service", service) - } - if scope != "" { - getParams.Add("scope", scope) - } - authReq.URL.RawQuery = getParams.Encode() - if c.username != "" && c.password != "" { - authReq.SetBasicAuth(c.username, c.password) - } - tr := tlsclientconfig.NewTransport() - // TODO(runcom): insecure for now to contact the external token service - tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - client := &http.Client{Transport: tr} - res, err := client.Do(authReq) - if err != nil { - return nil, err - } - defer res.Body.Close() - switch res.StatusCode { - case http.StatusUnauthorized: - return nil, ErrUnauthorizedForCredentials - case http.StatusOK: - break - default: - return nil, errors.Errorf("unexpected http code: %d, URL: %s", res.StatusCode, authReq.URL) - } - tokenBlob, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - - return newBearerTokenFromJSONBlob(tokenBlob) -} - -// detectProperties detects various properties of the registry. -// See the dockerClient documentation for members which are affected by this. -func (c *dockerClient) detectProperties(ctx context.Context) error { - if c.scheme != "" { - return nil - } - - ping := func(scheme string) error { - url := fmt.Sprintf(resolvedPingV2URL, scheme, c.registry) - resp, err := c.makeRequestToResolvedURL(ctx, "GET", url, nil, nil, -1, true) - logrus.Debugf("Ping %s err %#v", url, err) - if err != nil { - return err - } - defer resp.Body.Close() - logrus.Debugf("Ping %s status %d", url, resp.StatusCode) - if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized { - return errors.Errorf("error pinging repository, response code %d", resp.StatusCode) - } - c.challenges = parseAuthHeader(resp.Header) - c.scheme = scheme - c.supportsSignatures = resp.Header.Get("X-Registry-Supports-Signatures") == "1" - return nil - } - err := ping("https") - if err != nil && c.ctx != nil && c.ctx.DockerInsecureSkipTLSVerify { - err = ping("http") - } - if err != nil { - err = errors.Wrap(err, "pinging docker registry returned") - if c.ctx != nil && c.ctx.DockerDisableV1Ping { - return err - } - // best effort to understand if we're talking to a V1 registry - pingV1 := func(scheme string) bool { - url := fmt.Sprintf(resolvedPingV1URL, scheme, c.registry) - resp, err := c.makeRequestToResolvedURL(ctx, "GET", url, nil, nil, -1, true) - logrus.Debugf("Ping %s err %#v", url, err) - if err != nil { - return false - } - defer resp.Body.Close() - logrus.Debugf("Ping %s status %d", url, resp.StatusCode) - if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized { - return false - } - return true - } - isV1 := pingV1("https") - if !isV1 && c.ctx != nil && c.ctx.DockerInsecureSkipTLSVerify { - isV1 = pingV1("http") - } - if isV1 { - err = ErrV1NotSupported - } - } - return err -} - -// getExtensionsSignatures returns signatures from the X-Registry-Supports-Signatures API extension, -// using the original data structures. -func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerReference, manifestDigest digest.Digest) (*extensionSignatureList, error) { - path := fmt.Sprintf(extensionsSignaturePath, reference.Path(ref.ref), manifestDigest) - res, err := c.makeRequest(ctx, "GET", path, nil, nil) - if err != nil { - return nil, err - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, client.HandleErrorResponse(res) - } - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - - var parsedBody extensionSignatureList - if err := json.Unmarshal(body, &parsedBody); err != nil { - return nil, errors.Wrapf(err, "Error decoding signature list") - } - return &parsedBody, nil -} diff --git a/vendor/github.com/containers/image/docker/docker_image.go b/vendor/github.com/containers/image/docker/docker_image.go deleted file mode 100644 index 2148ed8bab..0000000000 --- a/vendor/github.com/containers/image/docker/docker_image.go +++ /dev/null @@ -1,63 +0,0 @@ -package docker - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -// Image is a Docker-specific implementation of types.ImageCloser with a few extra methods -// which are specific to Docker. -type Image struct { - types.ImageCloser - src *dockerImageSource -} - -// newImage returns a new Image interface type after setting up -// a client to the registry hosting the given image. -// The caller must call .Close() on the returned Image. -func newImage(ctx *types.SystemContext, ref dockerReference) (types.ImageCloser, error) { - s, err := newImageSource(ctx, ref) - if err != nil { - return nil, err - } - img, err := image.FromSource(ctx, s) - if err != nil { - return nil, err - } - return &Image{ImageCloser: img, src: s}, nil -} - -// SourceRefFullName returns a fully expanded name for the repository this image is in. -func (i *Image) SourceRefFullName() string { - return i.src.ref.ref.Name() -} - -// GetRepositoryTags list all tags available in the repository. Note that this has no connection with the tag(s) used for this specific image, if any. -func (i *Image) GetRepositoryTags() ([]string, error) { - path := fmt.Sprintf(tagsPath, reference.Path(i.src.ref.ref)) - // FIXME: Pass the context.Context - res, err := i.src.c.makeRequest(context.TODO(), "GET", path, nil, nil) - if err != nil { - return nil, err - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - // print url also - return nil, errors.Errorf("Invalid status code returned when fetching tags list %d", res.StatusCode) - } - type tagsRes struct { - Tags []string - } - tags := &tagsRes{} - if err := json.NewDecoder(res.Body).Decode(tags); err != nil { - return nil, err - } - return tags.Tags, nil -} diff --git a/vendor/github.com/containers/image/docker/docker_image_dest.go b/vendor/github.com/containers/image/docker/docker_image_dest.go deleted file mode 100644 index 9a6c351378..0000000000 --- a/vendor/github.com/containers/image/docker/docker_image_dest.go +++ /dev/null @@ -1,463 +0,0 @@ -package docker - -import ( - "bytes" - "context" - "crypto/rand" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "path/filepath" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" - "github.com/docker/distribution/registry/client" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -type dockerImageDestination struct { - ref dockerReference - c *dockerClient - // State - manifestDigest digest.Digest // or "" if not yet known. -} - -// newImageDestination creates a new ImageDestination for the specified image reference. -func newImageDestination(ctx *types.SystemContext, ref dockerReference) (types.ImageDestination, error) { - c, err := newDockerClientFromRef(ctx, ref, true, "pull,push") - if err != nil { - return nil, err - } - return &dockerImageDestination{ - ref: ref, - c: c, - }, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *dockerImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *dockerImageDestination) Close() error { - return nil -} - -func (d *dockerImageDestination) SupportedManifestMIMETypes() []string { - return []string{ - imgspecv1.MediaTypeImageManifest, - manifest.DockerV2Schema2MediaType, - manifest.DockerV2Schema1SignedMediaType, - manifest.DockerV2Schema1MediaType, - } -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *dockerImageDestination) SupportsSignatures() error { - if err := d.c.detectProperties(context.TODO()); err != nil { - return err - } - switch { - case d.c.signatureBase != nil: - return nil - case d.c.supportsSignatures: - return nil - default: - return errors.Errorf("X-Registry-Supports-Signatures extension not supported, and lookaside is not configured") - } -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *dockerImageDestination) ShouldCompressLayers() bool { - return true -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *dockerImageDestination) AcceptsForeignLayerURLs() bool { - return true -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *dockerImageDestination) MustMatchRuntimeOS() bool { - return false -} - -// sizeCounter is an io.Writer which only counts the total size of its input. -type sizeCounter struct{ size int64 } - -func (c *sizeCounter) Write(p []byte) (n int, err error) { - c.size += int64(len(p)) - return len(p), nil -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available -// to any other readers for download using the supplied digest. -// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. -func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - if inputInfo.Digest.String() != "" { - haveBlob, size, err := d.HasBlob(inputInfo) - if err != nil { - return types.BlobInfo{}, err - } - if haveBlob { - return types.BlobInfo{Digest: inputInfo.Digest, Size: size}, nil - } - } - - // FIXME? Chunked upload, progress reporting, etc. - uploadPath := fmt.Sprintf(blobUploadPath, reference.Path(d.ref.ref)) - logrus.Debugf("Uploading %s", uploadPath) - res, err := d.c.makeRequest(context.TODO(), "POST", uploadPath, nil, nil) - if err != nil { - return types.BlobInfo{}, err - } - defer res.Body.Close() - if res.StatusCode != http.StatusAccepted { - logrus.Debugf("Error initiating layer upload, response %#v", *res) - return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error initiating layer upload to %s", uploadPath) - } - uploadLocation, err := res.Location() - if err != nil { - return types.BlobInfo{}, errors.Wrap(err, "Error determining upload URL") - } - - digester := digest.Canonical.Digester() - sizeCounter := &sizeCounter{} - tee := io.TeeReader(stream, io.MultiWriter(digester.Hash(), sizeCounter)) - res, err = d.c.makeRequestToResolvedURL(context.TODO(), "PATCH", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, tee, inputInfo.Size, true) - if err != nil { - logrus.Debugf("Error uploading layer chunked, response %#v", res) - return types.BlobInfo{}, err - } - defer res.Body.Close() - computedDigest := digester.Digest() - - uploadLocation, err = res.Location() - if err != nil { - return types.BlobInfo{}, errors.Wrap(err, "Error determining upload URL") - } - - // FIXME: DELETE uploadLocation on failure - - locationQuery := uploadLocation.Query() - // TODO: check inputInfo.Digest == computedDigest https://github.com/containers/image/pull/70#discussion_r77646717 - locationQuery.Set("digest", computedDigest.String()) - uploadLocation.RawQuery = locationQuery.Encode() - res, err = d.c.makeRequestToResolvedURL(context.TODO(), "PUT", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, nil, -1, true) - if err != nil { - return types.BlobInfo{}, err - } - defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - logrus.Debugf("Error uploading layer, response %#v", *res) - return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error uploading layer to %s", uploadLocation) - } - - logrus.Debugf("Upload of layer %s complete", computedDigest) - return types.BlobInfo{Digest: computedDigest, Size: sizeCounter.size}, nil -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob. -// Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. -// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); -// it returns a non-nil error only on an unexpected failure. -func (d *dockerImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - if info.Digest == "" { - return false, -1, errors.Errorf(`"Can not check for a blob with unknown digest`) - } - checkPath := fmt.Sprintf(blobsPath, reference.Path(d.ref.ref), info.Digest.String()) - - logrus.Debugf("Checking %s", checkPath) - res, err := d.c.makeRequest(context.TODO(), "HEAD", checkPath, nil, nil) - if err != nil { - return false, -1, err - } - defer res.Body.Close() - switch res.StatusCode { - case http.StatusOK: - logrus.Debugf("... already exists") - return true, getBlobSize(res), nil - case http.StatusUnauthorized: - logrus.Debugf("... not authorized") - return false, -1, errors.Errorf("not authorized to read from destination repository %s", reference.Path(d.ref.ref)) - case http.StatusNotFound: - logrus.Debugf("... not present") - return false, -1, nil - default: - return false, -1, errors.Errorf("failed to read from destination repository %s: %v", reference.Path(d.ref.ref), http.StatusText(res.StatusCode)) - } -} - -func (d *dockerImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return info, nil -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *dockerImageDestination) PutManifest(m []byte) error { - digest, err := manifest.Digest(m) - if err != nil { - return err - } - d.manifestDigest = digest - - refTail, err := d.ref.tagOrDigest() - if err != nil { - return err - } - path := fmt.Sprintf(manifestPath, reference.Path(d.ref.ref), refTail) - - headers := map[string][]string{} - mimeType := manifest.GuessMIMEType(m) - if mimeType != "" { - headers["Content-Type"] = []string{mimeType} - } - res, err := d.c.makeRequest(context.TODO(), "PUT", path, headers, bytes.NewReader(m)) - if err != nil { - return err - } - defer res.Body.Close() - if !successStatus(res.StatusCode) { - err = errors.Wrapf(client.HandleErrorResponse(res), "Error uploading manifest to %s", path) - if isManifestInvalidError(errors.Cause(err)) { - err = types.ManifestTypeRejectedError{Err: err} - } - return err - } - return nil -} - -// successStatus returns true if the argument is a successful HTTP response -// code (in the range 200 - 399 inclusive). -func successStatus(status int) bool { - return status >= 200 && status <= 399 -} - -// isManifestInvalidError returns true iff err from client.HandleErrorReponse is a “manifest invalid” error. -func isManifestInvalidError(err error) bool { - errors, ok := err.(errcode.Errors) - if !ok || len(errors) == 0 { - return false - } - ec, ok := errors[0].(errcode.ErrorCoder) - if !ok { - return false - } - // ErrorCodeManifestInvalid is returned by OpenShift with acceptschema2=false. - // ErrorCodeTagInvalid is returned by docker/distribution (at least as of commit ec87e9b6971d831f0eff752ddb54fb64693e51cd) - // when uploading to a tag (because it can’t find a matching tag inside the manifest) - return ec.ErrorCode() == v2.ErrorCodeManifestInvalid || ec.ErrorCode() == v2.ErrorCodeTagInvalid -} - -func (d *dockerImageDestination) PutSignatures(signatures [][]byte) error { - // Do not fail if we don’t really need to support signatures. - if len(signatures) == 0 { - return nil - } - if err := d.c.detectProperties(context.TODO()); err != nil { - return err - } - switch { - case d.c.signatureBase != nil: - return d.putSignaturesToLookaside(signatures) - case d.c.supportsSignatures: - return d.putSignaturesToAPIExtension(signatures) - default: - return errors.Errorf("X-Registry-Supports-Signatures extension not supported, and lookaside is not configured") - } -} - -// putSignaturesToLookaside implements PutSignatures() from the lookaside location configured in s.c.signatureBase, -// which is not nil. -func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte) error { - // FIXME? This overwrites files one at a time, definitely not atomic. - // A failure when updating signatures with a reordered copy could lose some of them. - - // Skip dealing with the manifest digest if not necessary. - if len(signatures) == 0 { - return nil - } - - if d.manifestDigest.String() == "" { - // This shouldn’t happen, ImageDestination users are required to call PutManifest before PutSignatures - return errors.Errorf("Unknown manifest digest, can't add signatures") - } - - // NOTE: Keep this in sync with docs/signature-protocols.md! - for i, signature := range signatures { - url := signatureStorageURL(d.c.signatureBase, d.manifestDigest, i) - if url == nil { - return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") - } - err := d.putOneSignature(url, signature) - if err != nil { - return err - } - } - // Remove any other signatures, if present. - // We stop at the first missing signature; if a previous deleting loop aborted - // prematurely, this may not clean up all of them, but one missing signature - // is enough for dockerImageSource to stop looking for other signatures, so that - // is sufficient. - for i := len(signatures); ; i++ { - url := signatureStorageURL(d.c.signatureBase, d.manifestDigest, i) - if url == nil { - return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") - } - missing, err := d.c.deleteOneSignature(url) - if err != nil { - return err - } - if missing { - break - } - } - - return nil -} - -// putOneSignature stores one signature to url. -// NOTE: Keep this in sync with docs/signature-protocols.md! -func (d *dockerImageDestination) putOneSignature(url *url.URL, signature []byte) error { - switch url.Scheme { - case "file": - logrus.Debugf("Writing to %s", url.Path) - err := os.MkdirAll(filepath.Dir(url.Path), 0755) - if err != nil { - return err - } - err = ioutil.WriteFile(url.Path, signature, 0644) - if err != nil { - return err - } - return nil - - case "http", "https": - return errors.Errorf("Writing directly to a %s sigstore %s is not supported. Configure a sigstore-staging: location", url.Scheme, url.String()) - default: - return errors.Errorf("Unsupported scheme when writing signature to %s", url.String()) - } -} - -// deleteOneSignature deletes a signature from url, if it exists. -// If it successfully determines that the signature does not exist, returns (true, nil) -// NOTE: Keep this in sync with docs/signature-protocols.md! -func (c *dockerClient) deleteOneSignature(url *url.URL) (missing bool, err error) { - switch url.Scheme { - case "file": - logrus.Debugf("Deleting %s", url.Path) - err := os.Remove(url.Path) - if err != nil && os.IsNotExist(err) { - return true, nil - } - return false, err - - case "http", "https": - return false, errors.Errorf("Writing directly to a %s sigstore %s is not supported. Configure a sigstore-staging: location", url.Scheme, url.String()) - default: - return false, errors.Errorf("Unsupported scheme when deleting signature from %s", url.String()) - } -} - -// putSignaturesToAPIExtension implements PutSignatures() using the X-Registry-Supports-Signatures API extension. -func (d *dockerImageDestination) putSignaturesToAPIExtension(signatures [][]byte) error { - // Skip dealing with the manifest digest, or reading the old state, if not necessary. - if len(signatures) == 0 { - return nil - } - - if d.manifestDigest.String() == "" { - // This shouldn’t happen, ImageDestination users are required to call PutManifest before PutSignatures - return errors.Errorf("Unknown manifest digest, can't add signatures") - } - - // Because image signatures are a shared resource in Atomic Registry, the default upload - // always adds signatures. Eventually we should also allow removing signatures, - // but the X-Registry-Supports-Signatures API extension does not support that yet. - - existingSignatures, err := d.c.getExtensionsSignatures(context.TODO(), d.ref, d.manifestDigest) - if err != nil { - return err - } - existingSigNames := map[string]struct{}{} - for _, sig := range existingSignatures.Signatures { - existingSigNames[sig.Name] = struct{}{} - } - -sigExists: - for _, newSig := range signatures { - for _, existingSig := range existingSignatures.Signatures { - if existingSig.Version == extensionSignatureSchemaVersion && existingSig.Type == extensionSignatureTypeAtomic && bytes.Equal(existingSig.Content, newSig) { - continue sigExists - } - } - - // The API expect us to invent a new unique name. This is racy, but hopefully good enough. - var signatureName string - for { - randBytes := make([]byte, 16) - n, err := rand.Read(randBytes) - if err != nil || n != 16 { - return errors.Wrapf(err, "Error generating random signature len %d", n) - } - signatureName = fmt.Sprintf("%s@%032x", d.manifestDigest.String(), randBytes) - if _, ok := existingSigNames[signatureName]; !ok { - break - } - } - sig := extensionSignature{ - Version: extensionSignatureSchemaVersion, - Name: signatureName, - Type: extensionSignatureTypeAtomic, - Content: newSig, - } - body, err := json.Marshal(sig) - if err != nil { - return err - } - - path := fmt.Sprintf(extensionsSignaturePath, reference.Path(d.ref.ref), d.manifestDigest.String()) - res, err := d.c.makeRequest(context.TODO(), "PUT", path, nil, bytes.NewReader(body)) - if err != nil { - return err - } - defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - body, err := ioutil.ReadAll(res.Body) - if err == nil { - logrus.Debugf("Error body %s", string(body)) - } - logrus.Debugf("Error uploading signature, status %d, %#v", res.StatusCode, res) - return errors.Wrapf(client.HandleErrorResponse(res), "Error uploading signature to %s", path) - } - } - - return nil -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *dockerImageDestination) Commit() error { - return nil -} diff --git a/vendor/github.com/containers/image/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go deleted file mode 100644 index 63bfe8aa43..0000000000 --- a/vendor/github.com/containers/image/docker/docker_image_src.go +++ /dev/null @@ -1,386 +0,0 @@ -package docker - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "mime" - "net/http" - "net/url" - "os" - "strconv" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/docker/distribution/registry/client" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -type dockerImageSource struct { - ref dockerReference - c *dockerClient - // State - cachedManifest []byte // nil if not loaded yet - cachedManifestMIMEType string // Only valid if cachedManifest != nil -} - -// newImageSource creates a new ImageSource for the specified image reference. -// The caller must call .Close() on the returned ImageSource. -func newImageSource(ctx *types.SystemContext, ref dockerReference) (*dockerImageSource, error) { - c, err := newDockerClientFromRef(ctx, ref, false, "pull") - if err != nil { - return nil, err - } - return &dockerImageSource{ - ref: ref, - c: c, - }, nil -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (s *dockerImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *dockerImageSource) Close() error { - return nil -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *dockerImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} - -// simplifyContentType drops parameters from a HTTP media type (see https://tools.ietf.org/html/rfc7231#section-3.1.1.1) -// Alternatively, an empty string is returned unchanged, and invalid values are "simplified" to an empty string. -func simplifyContentType(contentType string) string { - if contentType == "" { - return contentType - } - mimeType, _, err := mime.ParseMediaType(contentType) - if err != nil { - return "" - } - return mimeType -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *dockerImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if instanceDigest != nil { - return s.fetchManifest(context.TODO(), instanceDigest.String()) - } - err := s.ensureManifestIsLoaded(context.TODO()) - if err != nil { - return nil, "", err - } - return s.cachedManifest, s.cachedManifestMIMEType, nil -} - -func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest string) ([]byte, string, error) { - path := fmt.Sprintf(manifestPath, reference.Path(s.ref.ref), tagOrDigest) - headers := make(map[string][]string) - headers["Accept"] = manifest.DefaultRequestedManifestMIMETypes - res, err := s.c.makeRequest(ctx, "GET", path, headers, nil) - if err != nil { - return nil, "", err - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, "", client.HandleErrorResponse(res) - } - manblob, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, "", err - } - return manblob, simplifyContentType(res.Header.Get("Content-Type")), nil -} - -// ensureManifestIsLoaded sets s.cachedManifest and s.cachedManifestMIMEType -// -// ImageSource implementations are not required or expected to do any caching, -// but because our signatures are “attached” to the manifest digest, -// we need to ensure that the digest of the manifest returned by GetManifest(nil) -// and used by GetSignatures(ctx, nil) are consistent, otherwise we would get spurious -// signature verification failures when pulling while a tag is being updated. -func (s *dockerImageSource) ensureManifestIsLoaded(ctx context.Context) error { - if s.cachedManifest != nil { - return nil - } - - reference, err := s.ref.tagOrDigest() - if err != nil { - return err - } - - manblob, mt, err := s.fetchManifest(ctx, reference) - if err != nil { - return err - } - // We might validate manblob against the Docker-Content-Digest header here to protect against transport errors. - s.cachedManifest = manblob - s.cachedManifestMIMEType = mt - return nil -} - -func (s *dockerImageSource) getExternalBlob(urls []string) (io.ReadCloser, int64, error) { - var ( - resp *http.Response - err error - ) - for _, url := range urls { - resp, err = s.c.makeRequestToResolvedURL(context.TODO(), "GET", url, nil, nil, -1, false) - if err == nil { - if resp.StatusCode != http.StatusOK { - err = errors.Errorf("error fetching external blob from %q: %d", url, resp.StatusCode) - logrus.Debug(err) - continue - } - break - } - } - if resp.Body != nil && err == nil { - return resp.Body, getBlobSize(resp), nil - } - return nil, 0, err -} - -func getBlobSize(resp *http.Response) int64 { - size, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) - if err != nil { - size = -1 - } - return size -} - -// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). -func (s *dockerImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - if len(info.URLs) != 0 { - return s.getExternalBlob(info.URLs) - } - - path := fmt.Sprintf(blobsPath, reference.Path(s.ref.ref), info.Digest.String()) - logrus.Debugf("Downloading %s", path) - res, err := s.c.makeRequest(context.TODO(), "GET", path, nil, nil) - if err != nil { - return nil, 0, err - } - if res.StatusCode != http.StatusOK { - // print url also - return nil, 0, errors.Errorf("Invalid status code returned when fetching blob %d", res.StatusCode) - } - return res.Body, getBlobSize(res), nil -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *dockerImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - if err := s.c.detectProperties(ctx); err != nil { - return nil, err - } - switch { - case s.c.signatureBase != nil: - return s.getSignaturesFromLookaside(ctx, instanceDigest) - case s.c.supportsSignatures: - return s.getSignaturesFromAPIExtension(ctx, instanceDigest) - default: - return [][]byte{}, nil - } -} - -// manifestDigest returns a digest of the manifest, from instanceDigest if non-nil; or from the supplied reference, -// or finally, from a fetched manifest. -func (s *dockerImageSource) manifestDigest(ctx context.Context, instanceDigest *digest.Digest) (digest.Digest, error) { - if instanceDigest != nil { - return *instanceDigest, nil - } - if digested, ok := s.ref.ref.(reference.Digested); ok { - d := digested.Digest() - if d.Algorithm() == digest.Canonical { - return d, nil - } - } - if err := s.ensureManifestIsLoaded(ctx); err != nil { - return "", err - } - return manifest.Digest(s.cachedManifest) -} - -// getSignaturesFromLookaside implements GetSignatures() from the lookaside location configured in s.c.signatureBase, -// which is not nil. -func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - manifestDigest, err := s.manifestDigest(ctx, instanceDigest) - if err != nil { - return nil, err - } - - // NOTE: Keep this in sync with docs/signature-protocols.md! - signatures := [][]byte{} - for i := 0; ; i++ { - url := signatureStorageURL(s.c.signatureBase, manifestDigest, i) - if url == nil { - return nil, errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") - } - signature, missing, err := s.getOneSignature(ctx, url) - if err != nil { - return nil, err - } - if missing { - break - } - signatures = append(signatures, signature) - } - return signatures, nil -} - -// getOneSignature downloads one signature from url. -// If it successfully determines that the signature does not exist, returns with missing set to true and error set to nil. -// NOTE: Keep this in sync with docs/signature-protocols.md! -func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (signature []byte, missing bool, err error) { - switch url.Scheme { - case "file": - logrus.Debugf("Reading %s", url.Path) - sig, err := ioutil.ReadFile(url.Path) - if err != nil { - if os.IsNotExist(err) { - return nil, true, nil - } - return nil, false, err - } - return sig, false, nil - - case "http", "https": - logrus.Debugf("GET %s", url) - req, err := http.NewRequest("GET", url.String(), nil) - if err != nil { - return nil, false, err - } - req = req.WithContext(ctx) - res, err := s.c.client.Do(req) - if err != nil { - return nil, false, err - } - defer res.Body.Close() - if res.StatusCode == http.StatusNotFound { - return nil, true, nil - } else if res.StatusCode != http.StatusOK { - return nil, false, errors.Errorf("Error reading signature from %s: status %d", url.String(), res.StatusCode) - } - sig, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, false, err - } - return sig, false, nil - - default: - return nil, false, errors.Errorf("Unsupported scheme when reading signature from %s", url.String()) - } -} - -// getSignaturesFromAPIExtension implements GetSignatures() using the X-Registry-Supports-Signatures API extension. -func (s *dockerImageSource) getSignaturesFromAPIExtension(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - manifestDigest, err := s.manifestDigest(ctx, instanceDigest) - if err != nil { - return nil, err - } - - parsedBody, err := s.c.getExtensionsSignatures(ctx, s.ref, manifestDigest) - if err != nil { - return nil, err - } - - var sigs [][]byte - for _, sig := range parsedBody.Signatures { - if sig.Version == extensionSignatureSchemaVersion && sig.Type == extensionSignatureTypeAtomic { - sigs = append(sigs, sig.Content) - } - } - return sigs, nil -} - -// deleteImage deletes the named image from the registry, if supported. -func deleteImage(ctx *types.SystemContext, ref dockerReference) error { - c, err := newDockerClientFromRef(ctx, ref, true, "push") - if err != nil { - return err - } - - // When retrieving the digest from a registry >= 2.3 use the following header: - // "Accept": "application/vnd.docker.distribution.manifest.v2+json" - headers := make(map[string][]string) - headers["Accept"] = []string{manifest.DockerV2Schema2MediaType} - - refTail, err := ref.tagOrDigest() - if err != nil { - return err - } - getPath := fmt.Sprintf(manifestPath, reference.Path(ref.ref), refTail) - get, err := c.makeRequest(context.TODO(), "GET", getPath, headers, nil) - if err != nil { - return err - } - defer get.Body.Close() - manifestBody, err := ioutil.ReadAll(get.Body) - if err != nil { - return err - } - switch get.StatusCode { - case http.StatusOK: - case http.StatusNotFound: - return errors.Errorf("Unable to delete %v. Image may not exist or is not stored with a v2 Schema in a v2 registry", ref.ref) - default: - return errors.Errorf("Failed to delete %v: %s (%v)", ref.ref, manifestBody, get.Status) - } - - digest := get.Header.Get("Docker-Content-Digest") - deletePath := fmt.Sprintf(manifestPath, reference.Path(ref.ref), digest) - - // When retrieving the digest from a registry >= 2.3 use the following header: - // "Accept": "application/vnd.docker.distribution.manifest.v2+json" - delete, err := c.makeRequest(context.TODO(), "DELETE", deletePath, headers, nil) - if err != nil { - return err - } - defer delete.Body.Close() - - body, err := ioutil.ReadAll(delete.Body) - if err != nil { - return err - } - if delete.StatusCode != http.StatusAccepted { - return errors.Errorf("Failed to delete %v: %s (%v)", deletePath, string(body), delete.Status) - } - - if c.signatureBase != nil { - manifestDigest, err := manifest.Digest(manifestBody) - if err != nil { - return err - } - - for i := 0; ; i++ { - url := signatureStorageURL(c.signatureBase, manifestDigest, i) - if url == nil { - return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") - } - missing, err := c.deleteOneSignature(url) - if err != nil { - return err - } - if missing { - break - } - } - } - - return nil -} diff --git a/vendor/github.com/containers/image/docker/docker_transport.go b/vendor/github.com/containers/image/docker/docker_transport.go deleted file mode 100644 index cc0aa298ae..0000000000 --- a/vendor/github.com/containers/image/docker/docker_transport.go +++ /dev/null @@ -1,161 +0,0 @@ -package docker - -import ( - "fmt" - "strings" - - "github.com/containers/image/docker/policyconfiguration" - "github.com/containers/image/docker/reference" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for Docker registry-hosted images. -var Transport = dockerTransport{} - -type dockerTransport struct{} - -func (t dockerTransport) Name() string { - return "docker" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t dockerTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t dockerTransport) ValidatePolicyConfigurationScope(scope string) error { - // FIXME? We could be verifying the various character set and length restrictions - // from docker/distribution/reference.regexp.go, but other than that there - // are few semantically invalid strings. - return nil -} - -// dockerReference is an ImageReference for Docker images. -type dockerReference struct { - ref reference.Named // By construction we know that !reference.IsNameOnly(ref) -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an Docker ImageReference. -func ParseReference(refString string) (types.ImageReference, error) { - if !strings.HasPrefix(refString, "//") { - return nil, errors.Errorf("docker: image reference %s does not start with //", refString) - } - ref, err := reference.ParseNormalizedNamed(strings.TrimPrefix(refString, "//")) - if err != nil { - return nil, err - } - ref = reference.TagNameOnly(ref) - return NewReference(ref) -} - -// NewReference returns a Docker reference for a named reference. The reference must satisfy !reference.IsNameOnly(). -func NewReference(ref reference.Named) (types.ImageReference, error) { - if reference.IsNameOnly(ref) { - return nil, errors.Errorf("Docker reference %s has neither a tag nor a digest", reference.FamiliarString(ref)) - } - // A github.com/distribution/reference value can have a tag and a digest at the same time! - // The docker/distribution API does not really support that (we can’t ask for an image with a specific - // tag and digest), so fail. This MAY be accepted in the future. - // (Even if it were supported, the semantics of policy namespaces are unclear - should we drop - // the tag or the digest first?) - _, isTagged := ref.(reference.NamedTagged) - _, isDigested := ref.(reference.Canonical) - if isTagged && isDigested { - return nil, errors.Errorf("Docker references with both a tag and digest are currently not supported") - } - return dockerReference{ - ref: ref, - }, nil -} - -func (ref dockerReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref dockerReference) StringWithinTransport() string { - return "//" + reference.FamiliarString(ref.ref) -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref dockerReference) DockerReference() reference.Named { - return ref.ref -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref dockerReference) PolicyConfigurationIdentity() string { - res, err := policyconfiguration.DockerReferenceIdentity(ref.ref) - if res == "" || err != nil { // Coverage: Should never happen, NewReference above should refuse values which could cause a failure. - panic(fmt.Sprintf("Internal inconsistency: policyconfiguration.DockerReferenceIdentity returned %#v, %v", res, err)) - } - return res -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref dockerReference) PolicyConfigurationNamespaces() []string { - return policyconfiguration.DockerReferenceNamespaces(ref.ref) -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref dockerReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - return newImage(ctx, ref) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref dockerReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref dockerReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref dockerReference) DeleteImage(ctx *types.SystemContext) error { - return deleteImage(ctx, ref) -} - -// tagOrDigest returns a tag or digest from the reference. -func (ref dockerReference) tagOrDigest() (string, error) { - if ref, ok := ref.ref.(reference.Canonical); ok { - return ref.Digest().String(), nil - } - if ref, ok := ref.ref.(reference.NamedTagged); ok { - return ref.Tag(), nil - } - // This should not happen, NewReference above refuses reference.IsNameOnly values. - return "", errors.Errorf("Internal inconsistency: Reference %s unexpectedly has neither a digest nor a tag", reference.FamiliarString(ref.ref)) -} diff --git a/vendor/github.com/containers/image/docker/lookaside.go b/vendor/github.com/containers/image/docker/lookaside.go deleted file mode 100644 index 18e7733b93..0000000000 --- a/vendor/github.com/containers/image/docker/lookaside.go +++ /dev/null @@ -1,202 +0,0 @@ -package docker - -import ( - "fmt" - "io/ioutil" - "net/url" - "os" - "path" - "path/filepath" - "strings" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/types" - "github.com/ghodss/yaml" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// systemRegistriesDirPath is the path to registries.d, used for locating lookaside Docker signature storage. -// You can override this at build time with -// -ldflags '-X github.com/containers/image/docker.systemRegistriesDirPath=$your_path' -var systemRegistriesDirPath = builtinRegistriesDirPath - -// builtinRegistriesDirPath is the path to registries.d. -// DO NOT change this, instead see systemRegistriesDirPath above. -const builtinRegistriesDirPath = "/etc/containers/registries.d" - -// registryConfiguration is one of the files in registriesDirPath configuring lookaside locations, or the result of merging them all. -// NOTE: Keep this in sync with docs/registries.d.md! -type registryConfiguration struct { - DefaultDocker *registryNamespace `json:"default-docker"` - // The key is a namespace, using fully-expanded Docker reference format or parent namespaces (per dockerReference.PolicyConfiguration*), - Docker map[string]registryNamespace `json:"docker"` -} - -// registryNamespace defines lookaside locations for a single namespace. -type registryNamespace struct { - SigStore string `json:"sigstore"` // For reading, and if SigStoreStaging is not present, for writing. - SigStoreStaging string `json:"sigstore-staging"` // For writing only. -} - -// signatureStorageBase is an "opaque" type representing a lookaside Docker signature storage. -// Users outside of this file should use configuredSignatureStorageBase and signatureStorageURL below. -type signatureStorageBase *url.URL // The only documented value is nil, meaning storage is not supported. - -// configuredSignatureStorageBase reads configuration to find an appropriate signature storage URL for ref, for write access if “write”. -func configuredSignatureStorageBase(ctx *types.SystemContext, ref dockerReference, write bool) (signatureStorageBase, error) { - // FIXME? Loading and parsing the config could be cached across calls. - dirPath := registriesDirPath(ctx) - logrus.Debugf(`Using registries.d directory %s for sigstore configuration`, dirPath) - config, err := loadAndMergeConfig(dirPath) - if err != nil { - return nil, err - } - - topLevel := config.signatureTopLevel(ref, write) - if topLevel == "" { - return nil, nil - } - - url, err := url.Parse(topLevel) - if err != nil { - return nil, errors.Wrapf(err, "Invalid signature storage URL %s", topLevel) - } - // NOTE: Keep this in sync with docs/signature-protocols.md! - // FIXME? Restrict to explicitly supported schemes? - repo := reference.Path(ref.ref) // Note that this is without a tag or digest. - if path.Clean(repo) != repo { // Coverage: This should not be reachable because /./ and /../ components are not valid in docker references - return nil, errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", ref.ref.String()) - } - url.Path = url.Path + "/" + repo - return url, nil -} - -// registriesDirPath returns a path to registries.d -func registriesDirPath(ctx *types.SystemContext) string { - if ctx != nil { - if ctx.RegistriesDirPath != "" { - return ctx.RegistriesDirPath - } - if ctx.RootForImplicitAbsolutePaths != "" { - return filepath.Join(ctx.RootForImplicitAbsolutePaths, systemRegistriesDirPath) - } - } - return systemRegistriesDirPath -} - -// loadAndMergeConfig loads configuration files in dirPath -func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) { - mergedConfig := registryConfiguration{Docker: map[string]registryNamespace{}} - dockerDefaultMergedFrom := "" - nsMergedFrom := map[string]string{} - - dir, err := os.Open(dirPath) - if err != nil { - if os.IsNotExist(err) { - return &mergedConfig, nil - } - return nil, err - } - configNames, err := dir.Readdirnames(0) - if err != nil { - return nil, err - } - for _, configName := range configNames { - if !strings.HasSuffix(configName, ".yaml") { - continue - } - configPath := filepath.Join(dirPath, configName) - configBytes, err := ioutil.ReadFile(configPath) - if err != nil { - return nil, err - } - - var config registryConfiguration - err = yaml.Unmarshal(configBytes, &config) - if err != nil { - return nil, errors.Wrapf(err, "Error parsing %s", configPath) - } - - if config.DefaultDocker != nil { - if mergedConfig.DefaultDocker != nil { - return nil, errors.Errorf(`Error parsing signature storage configuration: "default-docker" defined both in "%s" and "%s"`, - dockerDefaultMergedFrom, configPath) - } - mergedConfig.DefaultDocker = config.DefaultDocker - dockerDefaultMergedFrom = configPath - } - - for nsName, nsConfig := range config.Docker { // includes config.Docker == nil - if _, ok := mergedConfig.Docker[nsName]; ok { - return nil, errors.Errorf(`Error parsing signature storage configuration: "docker" namespace "%s" defined both in "%s" and "%s"`, - nsName, nsMergedFrom[nsName], configPath) - } - mergedConfig.Docker[nsName] = nsConfig - nsMergedFrom[nsName] = configPath - } - } - - return &mergedConfig, nil -} - -// config.signatureTopLevel returns an URL string configured in config for ref, for write access if “write”. -// (the top level of the storage, namespaced by repo.FullName etc.), or "" if no signature storage should be used. -func (config *registryConfiguration) signatureTopLevel(ref dockerReference, write bool) string { - if config.Docker != nil { - // Look for a full match. - identity := ref.PolicyConfigurationIdentity() - if ns, ok := config.Docker[identity]; ok { - logrus.Debugf(` Using "docker" namespace %s`, identity) - if url := ns.signatureTopLevel(write); url != "" { - return url - } - } - - // Look for a match of the possible parent namespaces. - for _, name := range ref.PolicyConfigurationNamespaces() { - if ns, ok := config.Docker[name]; ok { - logrus.Debugf(` Using "docker" namespace %s`, name) - if url := ns.signatureTopLevel(write); url != "" { - return url - } - } - } - } - // Look for a default location - if config.DefaultDocker != nil { - logrus.Debugf(` Using "default-docker" configuration`) - if url := config.DefaultDocker.signatureTopLevel(write); url != "" { - return url - } - } - logrus.Debugf(" No signature storage configuration found for %s", ref.PolicyConfigurationIdentity()) - return "" -} - -// ns.signatureTopLevel returns an URL string configured in ns for ref, for write access if “write”. -// or "" if nothing has been configured. -func (ns registryNamespace) signatureTopLevel(write bool) string { - if write && ns.SigStoreStaging != "" { - logrus.Debugf(` Using %s`, ns.SigStoreStaging) - return ns.SigStoreStaging - } - if ns.SigStore != "" { - logrus.Debugf(` Using %s`, ns.SigStore) - return ns.SigStore - } - return "" -} - -// signatureStorageURL returns an URL usable for acessing signature index in base with known manifestDigest, or nil if not applicable. -// Returns nil iff base == nil. -// NOTE: Keep this in sync with docs/signature-protocols.md! -func signatureStorageURL(base signatureStorageBase, manifestDigest digest.Digest, index int) *url.URL { - if base == nil { - return nil - } - url := *base - url.Path = fmt.Sprintf("%s@%s=%s/signature-%d", url.Path, manifestDigest.Algorithm(), manifestDigest.Hex(), index+1) - return &url -} diff --git a/vendor/github.com/containers/image/docker/policyconfiguration/naming.go b/vendor/github.com/containers/image/docker/policyconfiguration/naming.go deleted file mode 100644 index 31bbb544c6..0000000000 --- a/vendor/github.com/containers/image/docker/policyconfiguration/naming.go +++ /dev/null @@ -1,56 +0,0 @@ -package policyconfiguration - -import ( - "strings" - - "github.com/containers/image/docker/reference" - "github.com/pkg/errors" -) - -// DockerReferenceIdentity returns a string representation of the reference, suitable for policy lookup, -// as a backend for ImageReference.PolicyConfigurationIdentity. -// The reference must satisfy !reference.IsNameOnly(). -func DockerReferenceIdentity(ref reference.Named) (string, error) { - res := ref.Name() - tagged, isTagged := ref.(reference.NamedTagged) - digested, isDigested := ref.(reference.Canonical) - switch { - case isTagged && isDigested: // Note that this CAN actually happen. - return "", errors.Errorf("Unexpected Docker reference %s with both a name and a digest", reference.FamiliarString(ref)) - case !isTagged && !isDigested: // This should not happen, the caller is expected to ensure !reference.IsNameOnly() - return "", errors.Errorf("Internal inconsistency: Docker reference %s with neither a tag nor a digest", reference.FamiliarString(ref)) - case isTagged: - res = res + ":" + tagged.Tag() - case isDigested: - res = res + "@" + digested.Digest().String() - default: // Coverage: The above was supposed to be exhaustive. - return "", errors.New("Internal inconsistency, unexpected default branch") - } - return res, nil -} - -// DockerReferenceNamespaces returns a list of other policy configuration namespaces to search, -// as a backend for ImageReference.PolicyConfigurationIdentity. -// The reference must satisfy !reference.IsNameOnly(). -func DockerReferenceNamespaces(ref reference.Named) []string { - // Look for a match of the repository, and then of the possible parent - // namespaces. Note that this only happens on the expanded host names - // and repository names, i.e. "busybox" is looked up as "docker.io/library/busybox", - // then in its parent "docker.io/library"; in none of "busybox", - // un-namespaced "library" nor in "" supposedly implicitly representing "library/". - // - // ref.FullName() == ref.Hostname() + "/" + ref.RemoteName(), so the last - // iteration matches the host name (for any namespace). - res := []string{} - name := ref.Name() - for { - res = append(res, name) - - lastSlash := strings.LastIndex(name, "/") - if lastSlash == -1 { - break - } - name = name[:lastSlash] - } - return res -} diff --git a/vendor/github.com/containers/image/docker/reference/helpers.go b/vendor/github.com/containers/image/docker/reference/helpers.go deleted file mode 100644 index 978df7eabb..0000000000 --- a/vendor/github.com/containers/image/docker/reference/helpers.go +++ /dev/null @@ -1,42 +0,0 @@ -package reference - -import "path" - -// IsNameOnly returns true if reference only contains a repo name. -func IsNameOnly(ref Named) bool { - if _, ok := ref.(NamedTagged); ok { - return false - } - if _, ok := ref.(Canonical); ok { - return false - } - return true -} - -// FamiliarName returns the familiar name string -// for the given named, familiarizing if needed. -func FamiliarName(ref Named) string { - if nn, ok := ref.(normalizedNamed); ok { - return nn.Familiar().Name() - } - return ref.Name() -} - -// FamiliarString returns the familiar string representation -// for the given reference, familiarizing if needed. -func FamiliarString(ref Reference) string { - if nn, ok := ref.(normalizedNamed); ok { - return nn.Familiar().String() - } - return ref.String() -} - -// FamiliarMatch reports whether ref matches the specified pattern. -// See https://godoc.org/path#Match for supported patterns. -func FamiliarMatch(pattern string, ref Reference) (bool, error) { - matched, err := path.Match(pattern, FamiliarString(ref)) - if namedRef, isNamed := ref.(Named); isNamed && !matched { - matched, _ = path.Match(pattern, FamiliarName(namedRef)) - } - return matched, err -} diff --git a/vendor/github.com/containers/image/docker/reference/normalize.go b/vendor/github.com/containers/image/docker/reference/normalize.go deleted file mode 100644 index fcc436a395..0000000000 --- a/vendor/github.com/containers/image/docker/reference/normalize.go +++ /dev/null @@ -1,152 +0,0 @@ -package reference - -import ( - "errors" - "fmt" - "strings" - - "github.com/opencontainers/go-digest" -) - -var ( - legacyDefaultDomain = "index.docker.io" - defaultDomain = "docker.io" - officialRepoName = "library" - defaultTag = "latest" -) - -// normalizedNamed represents a name which has been -// normalized and has a familiar form. A familiar name -// is what is used in Docker UI. An example normalized -// name is "docker.io/library/ubuntu" and corresponding -// familiar name of "ubuntu". -type normalizedNamed interface { - Named - Familiar() Named -} - -// ParseNormalizedNamed parses a string into a named reference -// transforming a familiar name from Docker UI to a fully -// qualified reference. If the value may be an identifier -// use ParseAnyReference. -func ParseNormalizedNamed(s string) (Named, error) { - if ok := anchoredIdentifierRegexp.MatchString(s); ok { - return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s) - } - domain, remainder := splitDockerDomain(s) - var remoteName string - if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 { - remoteName = remainder[:tagSep] - } else { - remoteName = remainder - } - if strings.ToLower(remoteName) != remoteName { - return nil, errors.New("invalid reference format: repository name must be lowercase") - } - - ref, err := Parse(domain + "/" + remainder) - if err != nil { - return nil, err - } - named, isNamed := ref.(Named) - if !isNamed { - return nil, fmt.Errorf("reference %s has no name", ref.String()) - } - return named, nil -} - -// splitDockerDomain splits a repository name to domain and remotename string. -// If no valid domain is found, the default domain is used. Repository name -// needs to be already validated before. -func splitDockerDomain(name string) (domain, remainder string) { - i := strings.IndexRune(name, '/') - if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") { - domain, remainder = defaultDomain, name - } else { - domain, remainder = name[:i], name[i+1:] - } - if domain == legacyDefaultDomain { - domain = defaultDomain - } - if domain == defaultDomain && !strings.ContainsRune(remainder, '/') { - remainder = officialRepoName + "/" + remainder - } - return -} - -// familiarizeName returns a shortened version of the name familiar -// to to the Docker UI. Familiar names have the default domain -// "docker.io" and "library/" repository prefix removed. -// For example, "docker.io/library/redis" will have the familiar -// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp". -// Returns a familiarized named only reference. -func familiarizeName(named namedRepository) repository { - repo := repository{ - domain: named.Domain(), - path: named.Path(), - } - - if repo.domain == defaultDomain { - repo.domain = "" - // Handle official repositories which have the pattern "library/" - if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName { - repo.path = split[1] - } - } - return repo -} - -func (r reference) Familiar() Named { - return reference{ - namedRepository: familiarizeName(r.namedRepository), - tag: r.tag, - digest: r.digest, - } -} - -func (r repository) Familiar() Named { - return familiarizeName(r) -} - -func (t taggedReference) Familiar() Named { - return taggedReference{ - namedRepository: familiarizeName(t.namedRepository), - tag: t.tag, - } -} - -func (c canonicalReference) Familiar() Named { - return canonicalReference{ - namedRepository: familiarizeName(c.namedRepository), - digest: c.digest, - } -} - -// TagNameOnly adds the default tag "latest" to a reference if it only has -// a repo name. -func TagNameOnly(ref Named) Named { - if IsNameOnly(ref) { - namedTagged, err := WithTag(ref, defaultTag) - if err != nil { - // Default tag must be valid, to create a NamedTagged - // type with non-validated input the WithTag function - // should be used instead - panic(err) - } - return namedTagged - } - return ref -} - -// ParseAnyReference parses a reference string as a possible identifier, -// full digest, or familiar name. -func ParseAnyReference(ref string) (Reference, error) { - if ok := anchoredIdentifierRegexp.MatchString(ref); ok { - return digestReference("sha256:" + ref), nil - } - if dgst, err := digest.Parse(ref); err == nil { - return digestReference(dgst), nil - } - - return ParseNormalizedNamed(ref) -} diff --git a/vendor/github.com/containers/image/docker/reference/reference.go b/vendor/github.com/containers/image/docker/reference/reference.go deleted file mode 100644 index fd3510e9ee..0000000000 --- a/vendor/github.com/containers/image/docker/reference/reference.go +++ /dev/null @@ -1,433 +0,0 @@ -// Package reference provides a general type to represent any way of referencing images within the registry. -// Its main purpose is to abstract tags and digests (content-addressable hash). -// -// Grammar -// -// reference := name [ ":" tag ] [ "@" digest ] -// name := [domain '/'] path-component ['/' path-component]* -// domain := domain-component ['.' domain-component]* [':' port-number] -// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/ -// port-number := /[0-9]+/ -// path-component := alpha-numeric [separator alpha-numeric]* -// alpha-numeric := /[a-z0-9]+/ -// separator := /[_.]|__|[-]*/ -// -// tag := /[\w][\w.-]{0,127}/ -// -// digest := digest-algorithm ":" digest-hex -// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ] -// digest-algorithm-separator := /[+.-_]/ -// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/ -// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value -// -// identifier := /[a-f0-9]{64}/ -// short-identifier := /[a-f0-9]{6,64}/ -package reference - -import ( - "errors" - "fmt" - "strings" - - "github.com/opencontainers/go-digest" -) - -const ( - // NameTotalLengthMax is the maximum total number of characters in a repository name. - NameTotalLengthMax = 255 -) - -var ( - // ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference. - ErrReferenceInvalidFormat = errors.New("invalid reference format") - - // ErrTagInvalidFormat represents an error while trying to parse a string as a tag. - ErrTagInvalidFormat = errors.New("invalid tag format") - - // ErrDigestInvalidFormat represents an error while trying to parse a string as a tag. - ErrDigestInvalidFormat = errors.New("invalid digest format") - - // ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters. - ErrNameContainsUppercase = errors.New("repository name must be lowercase") - - // ErrNameEmpty is returned for empty, invalid repository names. - ErrNameEmpty = errors.New("repository name must have at least one component") - - // ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax. - ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax) - - // ErrNameNotCanonical is returned when a name is not canonical. - ErrNameNotCanonical = errors.New("repository name must be canonical") -) - -// Reference is an opaque object reference identifier that may include -// modifiers such as a hostname, name, tag, and digest. -type Reference interface { - // String returns the full reference - String() string -} - -// Field provides a wrapper type for resolving correct reference types when -// working with encoding. -type Field struct { - reference Reference -} - -// AsField wraps a reference in a Field for encoding. -func AsField(reference Reference) Field { - return Field{reference} -} - -// Reference unwraps the reference type from the field to -// return the Reference object. This object should be -// of the appropriate type to further check for different -// reference types. -func (f Field) Reference() Reference { - return f.reference -} - -// MarshalText serializes the field to byte text which -// is the string of the reference. -func (f Field) MarshalText() (p []byte, err error) { - return []byte(f.reference.String()), nil -} - -// UnmarshalText parses text bytes by invoking the -// reference parser to ensure the appropriately -// typed reference object is wrapped by field. -func (f *Field) UnmarshalText(p []byte) error { - r, err := Parse(string(p)) - if err != nil { - return err - } - - f.reference = r - return nil -} - -// Named is an object with a full name -type Named interface { - Reference - Name() string -} - -// Tagged is an object which has a tag -type Tagged interface { - Reference - Tag() string -} - -// NamedTagged is an object including a name and tag. -type NamedTagged interface { - Named - Tag() string -} - -// Digested is an object which has a digest -// in which it can be referenced by -type Digested interface { - Reference - Digest() digest.Digest -} - -// Canonical reference is an object with a fully unique -// name including a name with domain and digest -type Canonical interface { - Named - Digest() digest.Digest -} - -// namedRepository is a reference to a repository with a name. -// A namedRepository has both domain and path components. -type namedRepository interface { - Named - Domain() string - Path() string -} - -// Domain returns the domain part of the Named reference -func Domain(named Named) string { - if r, ok := named.(namedRepository); ok { - return r.Domain() - } - domain, _ := splitDomain(named.Name()) - return domain -} - -// Path returns the name without the domain part of the Named reference -func Path(named Named) (name string) { - if r, ok := named.(namedRepository); ok { - return r.Path() - } - _, path := splitDomain(named.Name()) - return path -} - -func splitDomain(name string) (string, string) { - match := anchoredNameRegexp.FindStringSubmatch(name) - if len(match) != 3 { - return "", name - } - return match[1], match[2] -} - -// SplitHostname splits a named reference into a -// hostname and name string. If no valid hostname is -// found, the hostname is empty and the full value -// is returned as name -// DEPRECATED: Use Domain or Path -func SplitHostname(named Named) (string, string) { - if r, ok := named.(namedRepository); ok { - return r.Domain(), r.Path() - } - return splitDomain(named.Name()) -} - -// Parse parses s and returns a syntactically valid Reference. -// If an error was encountered it is returned, along with a nil Reference. -// NOTE: Parse will not handle short digests. -func Parse(s string) (Reference, error) { - matches := ReferenceRegexp.FindStringSubmatch(s) - if matches == nil { - if s == "" { - return nil, ErrNameEmpty - } - if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil { - return nil, ErrNameContainsUppercase - } - return nil, ErrReferenceInvalidFormat - } - - if len(matches[1]) > NameTotalLengthMax { - return nil, ErrNameTooLong - } - - var repo repository - - nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1]) - if nameMatch != nil && len(nameMatch) == 3 { - repo.domain = nameMatch[1] - repo.path = nameMatch[2] - } else { - repo.domain = "" - repo.path = matches[1] - } - - ref := reference{ - namedRepository: repo, - tag: matches[2], - } - if matches[3] != "" { - var err error - ref.digest, err = digest.Parse(matches[3]) - if err != nil { - return nil, err - } - } - - r := getBestReferenceType(ref) - if r == nil { - return nil, ErrNameEmpty - } - - return r, nil -} - -// ParseNamed parses s and returns a syntactically valid reference implementing -// the Named interface. The reference must have a name and be in the canonical -// form, otherwise an error is returned. -// If an error was encountered it is returned, along with a nil Reference. -// NOTE: ParseNamed will not handle short digests. -func ParseNamed(s string) (Named, error) { - named, err := ParseNormalizedNamed(s) - if err != nil { - return nil, err - } - if named.String() != s { - return nil, ErrNameNotCanonical - } - return named, nil -} - -// WithName returns a named object representing the given string. If the input -// is invalid ErrReferenceInvalidFormat will be returned. -func WithName(name string) (Named, error) { - if len(name) > NameTotalLengthMax { - return nil, ErrNameTooLong - } - - match := anchoredNameRegexp.FindStringSubmatch(name) - if match == nil || len(match) != 3 { - return nil, ErrReferenceInvalidFormat - } - return repository{ - domain: match[1], - path: match[2], - }, nil -} - -// WithTag combines the name from "name" and the tag from "tag" to form a -// reference incorporating both the name and the tag. -func WithTag(name Named, tag string) (NamedTagged, error) { - if !anchoredTagRegexp.MatchString(tag) { - return nil, ErrTagInvalidFormat - } - var repo repository - if r, ok := name.(namedRepository); ok { - repo.domain = r.Domain() - repo.path = r.Path() - } else { - repo.path = name.Name() - } - if canonical, ok := name.(Canonical); ok { - return reference{ - namedRepository: repo, - tag: tag, - digest: canonical.Digest(), - }, nil - } - return taggedReference{ - namedRepository: repo, - tag: tag, - }, nil -} - -// WithDigest combines the name from "name" and the digest from "digest" to form -// a reference incorporating both the name and the digest. -func WithDigest(name Named, digest digest.Digest) (Canonical, error) { - if !anchoredDigestRegexp.MatchString(digest.String()) { - return nil, ErrDigestInvalidFormat - } - var repo repository - if r, ok := name.(namedRepository); ok { - repo.domain = r.Domain() - repo.path = r.Path() - } else { - repo.path = name.Name() - } - if tagged, ok := name.(Tagged); ok { - return reference{ - namedRepository: repo, - tag: tagged.Tag(), - digest: digest, - }, nil - } - return canonicalReference{ - namedRepository: repo, - digest: digest, - }, nil -} - -// TrimNamed removes any tag or digest from the named reference. -func TrimNamed(ref Named) Named { - domain, path := SplitHostname(ref) - return repository{ - domain: domain, - path: path, - } -} - -func getBestReferenceType(ref reference) Reference { - if ref.Name() == "" { - // Allow digest only references - if ref.digest != "" { - return digestReference(ref.digest) - } - return nil - } - if ref.tag == "" { - if ref.digest != "" { - return canonicalReference{ - namedRepository: ref.namedRepository, - digest: ref.digest, - } - } - return ref.namedRepository - } - if ref.digest == "" { - return taggedReference{ - namedRepository: ref.namedRepository, - tag: ref.tag, - } - } - - return ref -} - -type reference struct { - namedRepository - tag string - digest digest.Digest -} - -func (r reference) String() string { - return r.Name() + ":" + r.tag + "@" + r.digest.String() -} - -func (r reference) Tag() string { - return r.tag -} - -func (r reference) Digest() digest.Digest { - return r.digest -} - -type repository struct { - domain string - path string -} - -func (r repository) String() string { - return r.Name() -} - -func (r repository) Name() string { - if r.domain == "" { - return r.path - } - return r.domain + "/" + r.path -} - -func (r repository) Domain() string { - return r.domain -} - -func (r repository) Path() string { - return r.path -} - -type digestReference digest.Digest - -func (d digestReference) String() string { - return digest.Digest(d).String() -} - -func (d digestReference) Digest() digest.Digest { - return digest.Digest(d) -} - -type taggedReference struct { - namedRepository - tag string -} - -func (t taggedReference) String() string { - return t.Name() + ":" + t.tag -} - -func (t taggedReference) Tag() string { - return t.tag -} - -type canonicalReference struct { - namedRepository - digest digest.Digest -} - -func (c canonicalReference) String() string { - return c.Name() + "@" + c.digest.String() -} - -func (c canonicalReference) Digest() digest.Digest { - return c.digest -} diff --git a/vendor/github.com/containers/image/docker/reference/regexp.go b/vendor/github.com/containers/image/docker/reference/regexp.go deleted file mode 100644 index 405e995db9..0000000000 --- a/vendor/github.com/containers/image/docker/reference/regexp.go +++ /dev/null @@ -1,143 +0,0 @@ -package reference - -import "regexp" - -var ( - // alphaNumericRegexp defines the alpha numeric atom, typically a - // component of names. This only allows lower case characters and digits. - alphaNumericRegexp = match(`[a-z0-9]+`) - - // separatorRegexp defines the separators allowed to be embedded in name - // components. This allow one period, one or two underscore and multiple - // dashes. - separatorRegexp = match(`(?:[._]|__|[-]*)`) - - // nameComponentRegexp restricts registry path component names to start - // with at least one letter or number, with following parts able to be - // separated by one period, one or two underscore and multiple dashes. - nameComponentRegexp = expression( - alphaNumericRegexp, - optional(repeated(separatorRegexp, alphaNumericRegexp))) - - // domainComponentRegexp restricts the registry domain component of a - // repository name to start with a component as defined by domainRegexp - // and followed by an optional port. - domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`) - - // domainRegexp defines the structure of potential domain components - // that may be part of image names. This is purposely a subset of what is - // allowed by DNS to ensure backwards compatibility with Docker image - // names. - domainRegexp = expression( - domainComponentRegexp, - optional(repeated(literal(`.`), domainComponentRegexp)), - optional(literal(`:`), match(`[0-9]+`))) - - // TagRegexp matches valid tag names. From docker/docker:graph/tags.go. - TagRegexp = match(`[\w][\w.-]{0,127}`) - - // anchoredTagRegexp matches valid tag names, anchored at the start and - // end of the matched string. - anchoredTagRegexp = anchored(TagRegexp) - - // DigestRegexp matches valid digests. - DigestRegexp = match(`[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`) - - // anchoredDigestRegexp matches valid digests, anchored at the start and - // end of the matched string. - anchoredDigestRegexp = anchored(DigestRegexp) - - // NameRegexp is the format for the name component of references. The - // regexp has capturing groups for the domain and name part omitting - // the separating forward slash from either. - NameRegexp = expression( - optional(domainRegexp, literal(`/`)), - nameComponentRegexp, - optional(repeated(literal(`/`), nameComponentRegexp))) - - // anchoredNameRegexp is used to parse a name value, capturing the - // domain and trailing components. - anchoredNameRegexp = anchored( - optional(capture(domainRegexp), literal(`/`)), - capture(nameComponentRegexp, - optional(repeated(literal(`/`), nameComponentRegexp)))) - - // ReferenceRegexp is the full supported format of a reference. The regexp - // is anchored and has capturing groups for name, tag, and digest - // components. - ReferenceRegexp = anchored(capture(NameRegexp), - optional(literal(":"), capture(TagRegexp)), - optional(literal("@"), capture(DigestRegexp))) - - // IdentifierRegexp is the format for string identifier used as a - // content addressable identifier using sha256. These identifiers - // are like digests without the algorithm, since sha256 is used. - IdentifierRegexp = match(`([a-f0-9]{64})`) - - // ShortIdentifierRegexp is the format used to represent a prefix - // of an identifier. A prefix may be used to match a sha256 identifier - // within a list of trusted identifiers. - ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`) - - // anchoredIdentifierRegexp is used to check or match an - // identifier value, anchored at start and end of string. - anchoredIdentifierRegexp = anchored(IdentifierRegexp) - - // anchoredShortIdentifierRegexp is used to check if a value - // is a possible identifier prefix, anchored at start and end - // of string. - anchoredShortIdentifierRegexp = anchored(ShortIdentifierRegexp) -) - -// match compiles the string to a regular expression. -var match = regexp.MustCompile - -// literal compiles s into a literal regular expression, escaping any regexp -// reserved characters. -func literal(s string) *regexp.Regexp { - re := match(regexp.QuoteMeta(s)) - - if _, complete := re.LiteralPrefix(); !complete { - panic("must be a literal") - } - - return re -} - -// expression defines a full expression, where each regular expression must -// follow the previous. -func expression(res ...*regexp.Regexp) *regexp.Regexp { - var s string - for _, re := range res { - s += re.String() - } - - return match(s) -} - -// optional wraps the expression in a non-capturing group and makes the -// production optional. -func optional(res ...*regexp.Regexp) *regexp.Regexp { - return match(group(expression(res...)).String() + `?`) -} - -// repeated wraps the regexp in a non-capturing group to get one or more -// matches. -func repeated(res ...*regexp.Regexp) *regexp.Regexp { - return match(group(expression(res...)).String() + `+`) -} - -// group wraps the regexp in a non-capturing group. -func group(res ...*regexp.Regexp) *regexp.Regexp { - return match(`(?:` + expression(res...).String() + `)`) -} - -// capture wraps the expression in a capturing group. -func capture(res ...*regexp.Regexp) *regexp.Regexp { - return match(`(` + expression(res...).String() + `)`) -} - -// anchored anchors the regular expression by adding start and end delimiters. -func anchored(res ...*regexp.Regexp) *regexp.Regexp { - return match(`^` + expression(res...).String() + `$`) -} diff --git a/vendor/github.com/containers/image/docker/tarfile/dest.go b/vendor/github.com/containers/image/docker/tarfile/dest.go deleted file mode 100644 index eb11ca8668..0000000000 --- a/vendor/github.com/containers/image/docker/tarfile/dest.go +++ /dev/null @@ -1,257 +0,0 @@ -package tarfile - -import ( - "archive/tar" - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "time" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/internal/tmpdir" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// Destination is a partial implementation of types.ImageDestination for writing to an io.Writer. -type Destination struct { - writer io.Writer - tar *tar.Writer - repoTag string - // Other state. - blobs map[digest.Digest]types.BlobInfo // list of already-sent blobs -} - -// NewDestination returns a tarfile.Destination for the specified io.Writer. -func NewDestination(dest io.Writer, ref reference.NamedTagged) *Destination { - // For github.com/docker/docker consumers, this works just as well as - // refString := ref.String() - // because when reading the RepoTags strings, github.com/docker/docker/reference - // normalizes both of them to the same value. - // - // Doing it this way to include the normalized-out `docker.io[/library]` does make - // a difference for github.com/projectatomic/docker consumers, with the - // “Add --add-registry and --block-registry options to docker daemon” patch. - // These consumers treat reference strings which include a hostname and reference - // strings without a hostname differently. - // - // Using the host name here is more explicit about the intent, and it has the same - // effect as (docker pull) in projectatomic/docker, which tags the result using - // a hostname-qualified reference. - // See https://github.com/containers/image/issues/72 for a more detailed - // analysis and explanation. - refString := fmt.Sprintf("%s:%s", ref.Name(), ref.Tag()) - return &Destination{ - writer: dest, - tar: tar.NewWriter(dest), - repoTag: refString, - blobs: make(map[digest.Digest]types.BlobInfo), - } -} - -// SupportedManifestMIMETypes tells which manifest mime types the destination supports -// If an empty slice or nil it's returned, then any mime type can be tried to upload -func (d *Destination) SupportedManifestMIMETypes() []string { - return []string{ - manifest.DockerV2Schema2MediaType, // We rely on the types.Image.UpdatedImage schema conversion capabilities. - } -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *Destination) SupportsSignatures() error { - return errors.Errorf("Storing signatures for docker tar files is not supported") -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *Destination) ShouldCompressLayers() bool { - return false -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *Destination) AcceptsForeignLayerURLs() bool { - return false -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *Destination) MustMatchRuntimeOS() bool { - return false -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available -// to any other readers for download using the supplied digest. -// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. -func (d *Destination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - if inputInfo.Digest.String() == "" { - return types.BlobInfo{}, errors.Errorf("Can not stream a blob with unknown digest to docker tarfile") - } - - ok, size, err := d.HasBlob(inputInfo) - if err != nil { - return types.BlobInfo{}, err - } - if ok { - return types.BlobInfo{Digest: inputInfo.Digest, Size: size}, nil - } - - if inputInfo.Size == -1 { // Ouch, we need to stream the blob into a temporary file just to determine the size. - logrus.Debugf("docker tarfile: input with unknown size, streaming to disk first ...") - streamCopy, err := ioutil.TempFile(tmpdir.TemporaryDirectoryForBigFiles(), "docker-tarfile-blob") - if err != nil { - return types.BlobInfo{}, err - } - defer os.Remove(streamCopy.Name()) - defer streamCopy.Close() - - size, err := io.Copy(streamCopy, stream) - if err != nil { - return types.BlobInfo{}, err - } - _, err = streamCopy.Seek(0, os.SEEK_SET) - if err != nil { - return types.BlobInfo{}, err - } - inputInfo.Size = size // inputInfo is a struct, so we are only modifying our copy. - stream = streamCopy - logrus.Debugf("... streaming done") - } - - digester := digest.Canonical.Digester() - tee := io.TeeReader(stream, digester.Hash()) - if err := d.sendFile(inputInfo.Digest.String(), inputInfo.Size, tee); err != nil { - return types.BlobInfo{}, err - } - d.blobs[inputInfo.Digest] = types.BlobInfo{Digest: digester.Digest(), Size: inputInfo.Size} - return types.BlobInfo{Digest: digester.Digest(), Size: inputInfo.Size}, nil -} - -// HasBlob returns true iff the image destination already contains a blob with -// the matching digest which can be reapplied using ReapplyBlob. Unlike -// PutBlob, the digest can not be empty. If HasBlob returns true, the size of -// the blob must also be returned. If the destination does not contain the -// blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); it -// returns a non-nil error only on an unexpected failure. -func (d *Destination) HasBlob(info types.BlobInfo) (bool, int64, error) { - if info.Digest == "" { - return false, -1, errors.Errorf("Can not check for a blob with unknown digest") - } - if blob, ok := d.blobs[info.Digest]; ok { - return true, blob.Size, nil - } - return false, -1, nil -} - -// ReapplyBlob informs the image destination that a blob for which HasBlob -// previously returned true would have been passed to PutBlob if it had -// returned false. Like HasBlob and unlike PutBlob, the digest can not be -// empty. If the blob is a filesystem layer, this signifies that the changes -// it describes need to be applied again when composing a filesystem tree. -func (d *Destination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return info, nil -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *Destination) PutManifest(m []byte) error { - // We do not bother with types.ManifestTypeRejectedError; our .SupportedManifestMIMETypes() above is already providing only one alternative, - // so the caller trying a different manifest kind would be pointless. - var man manifest.Schema2 - if err := json.Unmarshal(m, &man); err != nil { - return errors.Wrap(err, "Error parsing manifest") - } - if man.SchemaVersion != 2 || man.MediaType != manifest.DockerV2Schema2MediaType { - return errors.Errorf("Unsupported manifest type, need a Docker schema 2 manifest") - } - - layerPaths := []string{} - for _, l := range man.LayersDescriptors { - layerPaths = append(layerPaths, l.Digest.String()) - } - - items := []ManifestItem{{ - Config: man.ConfigDescriptor.Digest.String(), - RepoTags: []string{d.repoTag}, - Layers: layerPaths, - Parent: "", - LayerSources: nil, - }} - itemsBytes, err := json.Marshal(&items) - if err != nil { - return err - } - - // FIXME? Do we also need to support the legacy format? - return d.sendFile(manifestFileName, int64(len(itemsBytes)), bytes.NewReader(itemsBytes)) -} - -type tarFI struct { - path string - size int64 -} - -func (t *tarFI) Name() string { - return t.path -} -func (t *tarFI) Size() int64 { - return t.size -} -func (t *tarFI) Mode() os.FileMode { - return 0444 -} -func (t *tarFI) ModTime() time.Time { - return time.Unix(0, 0) -} -func (t *tarFI) IsDir() bool { - return false -} -func (t *tarFI) Sys() interface{} { - return nil -} - -// sendFile sends a file into the tar stream. -func (d *Destination) sendFile(path string, expectedSize int64, stream io.Reader) error { - hdr, err := tar.FileInfoHeader(&tarFI{path: path, size: expectedSize}, "") - if err != nil { - return nil - } - logrus.Debugf("Sending as tar file %s", path) - if err := d.tar.WriteHeader(hdr); err != nil { - return err - } - size, err := io.Copy(d.tar, stream) - if err != nil { - return err - } - if size != expectedSize { - return errors.Errorf("Size mismatch when copying %s, expected %d, got %d", path, expectedSize, size) - } - return nil -} - -// PutSignatures adds the given signatures to the docker tarfile (currently not -// supported). MUST be called after PutManifest (signatures reference manifest -// contents) -func (d *Destination) PutSignatures(signatures [][]byte) error { - if len(signatures) != 0 { - return errors.Errorf("Storing signatures for docker tar files is not supported") - } - return nil -} - -// Commit finishes writing data to the underlying io.Writer. -// It is the caller's responsibility to close it, if necessary. -func (d *Destination) Commit() error { - return d.tar.Close() -} diff --git a/vendor/github.com/containers/image/docker/tarfile/doc.go b/vendor/github.com/containers/image/docker/tarfile/doc.go deleted file mode 100644 index 4ea5369c05..0000000000 --- a/vendor/github.com/containers/image/docker/tarfile/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package tarfile is an internal implementation detail of some transports. -// Do not use outside of the github.com/containers/image repo! -package tarfile diff --git a/vendor/github.com/containers/image/docker/tarfile/src.go b/vendor/github.com/containers/image/docker/tarfile/src.go deleted file mode 100644 index a18e210585..0000000000 --- a/vendor/github.com/containers/image/docker/tarfile/src.go +++ /dev/null @@ -1,366 +0,0 @@ -package tarfile - -import ( - "archive/tar" - "bytes" - "context" - "encoding/json" - "io" - "io/ioutil" - "os" - "path" - - "github.com/containers/image/manifest" - "github.com/containers/image/pkg/compression" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// Source is a partial implementation of types.ImageSource for reading from tarPath. -type Source struct { - tarPath string - // The following data is only available after ensureCachedDataIsPresent() succeeds - tarManifest *ManifestItem // nil if not available yet. - configBytes []byte - configDigest digest.Digest - orderedDiffIDList []digest.Digest - knownLayers map[digest.Digest]*layerInfo - // Other state - generatedManifest []byte // Private cache for GetManifest(), nil if not set yet. -} - -type layerInfo struct { - path string - size int64 -} - -// NewSource returns a tarfile.Source for the specified path. -func NewSource(path string) *Source { - // TODO: We could add support for multiple images in a single archive, so - // that people could use docker-archive:opensuse.tar:opensuse:leap as - // the source of an image. - return &Source{ - tarPath: path, - } -} - -// tarReadCloser is a way to close the backing file of a tar.Reader when the user no longer needs the tar component. -type tarReadCloser struct { - *tar.Reader - backingFile *os.File -} - -func (t *tarReadCloser) Close() error { - return t.backingFile.Close() -} - -// openTarComponent returns a ReadCloser for the specific file within the archive. -// This is linear scan; we assume that the tar file will have a fairly small amount of files (~layers), -// and that filesystem caching will make the repeated seeking over the (uncompressed) tarPath cheap enough. -// The caller should call .Close() on the returned stream. -func (s *Source) openTarComponent(componentPath string) (io.ReadCloser, error) { - f, err := os.Open(s.tarPath) - if err != nil { - return nil, err - } - succeeded := false - defer func() { - if !succeeded { - f.Close() - } - }() - - tarReader, header, err := findTarComponent(f, componentPath) - if err != nil { - return nil, err - } - if header == nil { - return nil, os.ErrNotExist - } - if header.FileInfo().Mode()&os.ModeType == os.ModeSymlink { // FIXME: untested - // We follow only one symlink; so no loops are possible. - if _, err := f.Seek(0, os.SEEK_SET); err != nil { - return nil, err - } - // The new path could easily point "outside" the archive, but we only compare it to existing tar headers without extracting the archive, - // so we don't care. - tarReader, header, err = findTarComponent(f, path.Join(path.Dir(componentPath), header.Linkname)) - if err != nil { - return nil, err - } - if header == nil { - return nil, os.ErrNotExist - } - } - - if !header.FileInfo().Mode().IsRegular() { - return nil, errors.Errorf("Error reading tar archive component %s: not a regular file", header.Name) - } - succeeded = true - return &tarReadCloser{Reader: tarReader, backingFile: f}, nil -} - -// findTarComponent returns a header and a reader matching path within inputFile, -// or (nil, nil, nil) if not found. -func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Header, error) { - t := tar.NewReader(inputFile) - for { - h, err := t.Next() - if err == io.EOF { - break - } - if err != nil { - return nil, nil, err - } - if h.Name == path { - return t, h, nil - } - } - return nil, nil, nil -} - -// readTarComponent returns full contents of componentPath. -func (s *Source) readTarComponent(path string) ([]byte, error) { - file, err := s.openTarComponent(path) - if err != nil { - return nil, errors.Wrapf(err, "Error loading tar component %s", path) - } - defer file.Close() - bytes, err := ioutil.ReadAll(file) - if err != nil { - return nil, err - } - return bytes, nil -} - -// ensureCachedDataIsPresent loads data necessary for any of the public accessors. -func (s *Source) ensureCachedDataIsPresent() error { - if s.tarManifest != nil { - return nil - } - - // Read and parse manifest.json - tarManifest, err := s.loadTarManifest() - if err != nil { - return err - } - - // Check to make sure length is 1 - if len(tarManifest) != 1 { - return errors.Errorf("Unexpected tar manifest.json: expected 1 item, got %d", len(tarManifest)) - } - - // Read and parse config. - configBytes, err := s.readTarComponent(tarManifest[0].Config) - if err != nil { - return err - } - var parsedConfig manifest.Schema2Image // There's a lot of info there, but we only really care about layer DiffIDs. - if err := json.Unmarshal(configBytes, &parsedConfig); err != nil { - return errors.Wrapf(err, "Error decoding tar config %s", tarManifest[0].Config) - } - - knownLayers, err := s.prepareLayerData(&tarManifest[0], &parsedConfig) - if err != nil { - return err - } - - // Success; commit. - s.tarManifest = &tarManifest[0] - s.configBytes = configBytes - s.configDigest = digest.FromBytes(configBytes) - s.orderedDiffIDList = parsedConfig.RootFS.DiffIDs - s.knownLayers = knownLayers - return nil -} - -// loadTarManifest loads and decodes the manifest.json. -func (s *Source) loadTarManifest() ([]ManifestItem, error) { - // FIXME? Do we need to deal with the legacy format? - bytes, err := s.readTarComponent(manifestFileName) - if err != nil { - return nil, err - } - var items []ManifestItem - if err := json.Unmarshal(bytes, &items); err != nil { - return nil, errors.Wrap(err, "Error decoding tar manifest.json") - } - return items, nil -} - -// LoadTarManifest loads and decodes the manifest.json -func (s *Source) LoadTarManifest() ([]ManifestItem, error) { - return s.loadTarManifest() -} - -func (s *Source) prepareLayerData(tarManifest *ManifestItem, parsedConfig *manifest.Schema2Image) (map[digest.Digest]*layerInfo, error) { - // Collect layer data available in manifest and config. - if len(tarManifest.Layers) != len(parsedConfig.RootFS.DiffIDs) { - return nil, errors.Errorf("Inconsistent layer count: %d in manifest, %d in config", len(tarManifest.Layers), len(parsedConfig.RootFS.DiffIDs)) - } - knownLayers := map[digest.Digest]*layerInfo{} - unknownLayerSizes := map[string]*layerInfo{} // Points into knownLayers, a "to do list" of items with unknown sizes. - for i, diffID := range parsedConfig.RootFS.DiffIDs { - if _, ok := knownLayers[diffID]; ok { - // Apparently it really can happen that a single image contains the same layer diff more than once. - // In that case, the diffID validation ensures that both layers truly are the same, and it should not matter - // which of the tarManifest.Layers paths is used; (docker save) actually makes the duplicates symlinks to the original. - continue - } - layerPath := tarManifest.Layers[i] - if _, ok := unknownLayerSizes[layerPath]; ok { - return nil, errors.Errorf("Layer tarfile %s used for two different DiffID values", layerPath) - } - li := &layerInfo{ // A new element in each iteration - path: layerPath, - size: -1, - } - knownLayers[diffID] = li - unknownLayerSizes[layerPath] = li - } - - // Scan the tar file to collect layer sizes. - file, err := os.Open(s.tarPath) - if err != nil { - return nil, err - } - defer file.Close() - t := tar.NewReader(file) - for { - h, err := t.Next() - if err == io.EOF { - break - } - if err != nil { - return nil, err - } - if li, ok := unknownLayerSizes[h.Name]; ok { - li.size = h.Size - delete(unknownLayerSizes, h.Name) - } - } - if len(unknownLayerSizes) != 0 { - return nil, errors.Errorf("Some layer tarfiles are missing in the tarball") // This could do with a better error reporting, if this ever happened in practice. - } - - return knownLayers, nil -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *Source) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if instanceDigest != nil { - // How did we even get here? GetManifest(nil) has returned a manifest.DockerV2Schema2MediaType. - return nil, "", errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`) - } - if s.generatedManifest == nil { - if err := s.ensureCachedDataIsPresent(); err != nil { - return nil, "", err - } - m := manifest.Schema2{ - SchemaVersion: 2, - MediaType: manifest.DockerV2Schema2MediaType, - ConfigDescriptor: manifest.Schema2Descriptor{ - MediaType: manifest.DockerV2Schema2ConfigMediaType, - Size: int64(len(s.configBytes)), - Digest: s.configDigest, - }, - LayersDescriptors: []manifest.Schema2Descriptor{}, - } - for _, diffID := range s.orderedDiffIDList { - li, ok := s.knownLayers[diffID] - if !ok { - return nil, "", errors.Errorf("Internal inconsistency: Information about layer %s missing", diffID) - } - m.LayersDescriptors = append(m.LayersDescriptors, manifest.Schema2Descriptor{ - Digest: diffID, // diffID is a digest of the uncompressed tarball - MediaType: manifest.DockerV2Schema2LayerMediaType, - Size: li.size, - }) - } - manifestBytes, err := json.Marshal(&m) - if err != nil { - return nil, "", err - } - s.generatedManifest = manifestBytes - } - return s.generatedManifest, manifest.DockerV2Schema2MediaType, nil -} - -type readCloseWrapper struct { - io.Reader - closeFunc func() error -} - -func (r readCloseWrapper) Close() error { - if r.closeFunc != nil { - return r.closeFunc() - } - return nil -} - -// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). -func (s *Source) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - if err := s.ensureCachedDataIsPresent(); err != nil { - return nil, 0, err - } - - if info.Digest == s.configDigest { // FIXME? Implement a more general algorithm matching instead of assuming sha256. - return ioutil.NopCloser(bytes.NewReader(s.configBytes)), int64(len(s.configBytes)), nil - } - - if li, ok := s.knownLayers[info.Digest]; ok { // diffID is a digest of the uncompressed tarball, - stream, err := s.openTarComponent(li.path) - if err != nil { - return nil, 0, err - } - - // In order to handle the fact that digests != diffIDs (and thus that a - // caller which is trying to verify the blob will run into problems), - // we need to decompress blobs. This is a bit ugly, but it's a - // consequence of making everything addressable by their DiffID rather - // than by their digest... - // - // In particular, because the v2s2 manifest being generated uses - // DiffIDs, any caller of GetBlob is going to be asking for DiffIDs of - // layers not their _actual_ digest. The result is that copy/... will - // be verifing a "digest" which is not the actual layer's digest (but - // is instead the DiffID). - - decompressFunc, reader, err := compression.DetectCompression(stream) - if err != nil { - return nil, 0, errors.Wrapf(err, "Detecting compression in blob %s", info.Digest) - } - - if decompressFunc != nil { - reader, err = decompressFunc(reader) - if err != nil { - return nil, 0, errors.Wrapf(err, "Decompressing blob %s stream", info.Digest) - } - } - - newStream := readCloseWrapper{ - Reader: reader, - closeFunc: stream.Close, - } - - return newStream, li.size, nil - } - - return nil, 0, errors.Errorf("Unknown blob %s", info.Digest) -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *Source) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - if instanceDigest != nil { - // How did we even get here? GetManifest(nil) has returned a manifest.DockerV2Schema2MediaType. - return nil, errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`) - } - return [][]byte{}, nil -} diff --git a/vendor/github.com/containers/image/docker/tarfile/types.go b/vendor/github.com/containers/image/docker/tarfile/types.go deleted file mode 100644 index 2aa5675457..0000000000 --- a/vendor/github.com/containers/image/docker/tarfile/types.go +++ /dev/null @@ -1,28 +0,0 @@ -package tarfile - -import ( - "github.com/containers/image/manifest" - "github.com/opencontainers/go-digest" -) - -// Various data structures. - -// Based on github.com/docker/docker/image/tarexport/tarexport.go -const ( - manifestFileName = "manifest.json" - // legacyLayerFileName = "layer.tar" - // legacyConfigFileName = "json" - // legacyVersionFileName = "VERSION" - // legacyRepositoriesFileName = "repositories" -) - -// ManifestItem is an element of the array stored in the top-level manifest.json file. -type ManifestItem struct { - Config string - RepoTags []string - Layers []string - Parent imageID `json:",omitempty"` - LayerSources map[digest.Digest]manifest.Schema2Descriptor `json:",omitempty"` -} - -type imageID string diff --git a/vendor/github.com/containers/image/docker/wwwauthenticate.go b/vendor/github.com/containers/image/docker/wwwauthenticate.go deleted file mode 100644 index 23664a74a5..0000000000 --- a/vendor/github.com/containers/image/docker/wwwauthenticate.go +++ /dev/null @@ -1,159 +0,0 @@ -package docker - -// Based on github.com/docker/distribution/registry/client/auth/authchallenge.go, primarily stripping unnecessary dependencies. - -import ( - "net/http" - "strings" -) - -// challenge carries information from a WWW-Authenticate response header. -// See RFC 7235. -type challenge struct { - // Scheme is the auth-scheme according to RFC 7235 - Scheme string - - // Parameters are the auth-params according to RFC 7235 - Parameters map[string]string -} - -// Octet types from RFC 7230. -type octetType byte - -var octetTypes [256]octetType - -const ( - isToken octetType = 1 << iota - isSpace -) - -func init() { - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t octetType - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { - t |= isSpace - } - if isChar && !isCtl && !isSeparator { - t |= isToken - } - octetTypes[c] = t - } -} - -func parseAuthHeader(header http.Header) []challenge { - challenges := []challenge{} - for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] { - v, p := parseValueAndParams(h) - if v != "" { - challenges = append(challenges, challenge{Scheme: v, Parameters: p}) - } - } - return challenges -} - -// NOTE: This is not a fully compliant parser per RFC 7235: -// Most notably it does not support more than one challenge within a single header -// Some of the whitespace parsing also seems noncompliant. -// But it is clearly better than what we used to have… -func parseValueAndParams(header string) (value string, params map[string]string) { - params = make(map[string]string) - value, s := expectToken(header) - if value == "" { - return - } - value = strings.ToLower(value) - s = "," + skipSpace(s) - for strings.HasPrefix(s, ",") { - var pkey string - pkey, s = expectToken(skipSpace(s[1:])) - if pkey == "" { - return - } - if !strings.HasPrefix(s, "=") { - return - } - var pvalue string - pvalue, s = expectTokenOrQuoted(s[1:]) - if pvalue == "" { - return - } - pkey = strings.ToLower(pkey) - params[pkey] = pvalue - s = skipSpace(s) - } - return -} - -func skipSpace(s string) (rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpace == 0 { - break - } - } - return s[i:] -} - -func expectToken(s string) (token, rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isToken == 0 { - break - } - } - return s[:i], s[i:] -} - -func expectTokenOrQuoted(s string) (value string, rest string) { - if !strings.HasPrefix(s, "\"") { - return expectToken(s) - } - s = s[1:] - for i := 0; i < len(s); i++ { - switch s[i] { - case '"': - return s[:i], s[i+1:] - case '\\': - p := make([]byte, len(s)-1) - j := copy(p, s[:i]) - escape := true - for i = i + 1; i < len(s); i++ { - b := s[i] - switch { - case escape: - escape = false - p[j] = b - j++ - case b == '\\': - escape = true - case b == '"': - return string(p[:j]), s[i+1:] - default: - p[j] = b - j++ - } - } - return "", "" - } - } - return "", "" -} diff --git a/vendor/github.com/containers/image/image/docker_list.go b/vendor/github.com/containers/image/image/docker_list.go deleted file mode 100644 index 412261ddbb..0000000000 --- a/vendor/github.com/containers/image/image/docker_list.go +++ /dev/null @@ -1,93 +0,0 @@ -package image - -import ( - "encoding/json" - "fmt" - "runtime" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -type platformSpec struct { - Architecture string `json:"architecture"` - OS string `json:"os"` - OSVersion string `json:"os.version,omitempty"` - OSFeatures []string `json:"os.features,omitempty"` - Variant string `json:"variant,omitempty"` - Features []string `json:"features,omitempty"` // removed in OCI -} - -// A manifestDescriptor references a platform-specific manifest. -type manifestDescriptor struct { - manifest.Schema2Descriptor - Platform platformSpec `json:"platform"` -} - -type manifestList struct { - SchemaVersion int `json:"schemaVersion"` - MediaType string `json:"mediaType"` - Manifests []manifestDescriptor `json:"manifests"` -} - -// chooseDigestFromManifestList parses blob as a schema2 manifest list, -// and returns the digest of the image appropriate for the current environment. -func chooseDigestFromManifestList(ctx *types.SystemContext, blob []byte) (digest.Digest, error) { - wantedArch := runtime.GOARCH - if ctx != nil && ctx.ArchitectureChoice != "" { - wantedArch = ctx.ArchitectureChoice - } - wantedOS := runtime.GOOS - if ctx != nil && ctx.OSChoice != "" { - wantedOS = ctx.OSChoice - } - - list := manifestList{} - if err := json.Unmarshal(blob, &list); err != nil { - return "", err - } - for _, d := range list.Manifests { - if d.Platform.Architecture == wantedArch && d.Platform.OS == wantedOS { - return d.Digest, nil - } - } - return "", fmt.Errorf("no image found in manifest list for architecture %s, OS %s", wantedArch, wantedOS) -} - -func manifestSchema2FromManifestList(ctx *types.SystemContext, src types.ImageSource, manblob []byte) (genericManifest, error) { - targetManifestDigest, err := chooseDigestFromManifestList(ctx, manblob) - if err != nil { - return nil, err - } - manblob, mt, err := src.GetManifest(&targetManifestDigest) - if err != nil { - return nil, err - } - - matches, err := manifest.MatchesDigest(manblob, targetManifestDigest) - if err != nil { - return nil, errors.Wrap(err, "Error computing manifest digest") - } - if !matches { - return nil, errors.Errorf("Manifest image does not match selected manifest digest %s", targetManifestDigest) - } - - return manifestInstanceFromBlob(ctx, src, manblob, mt) -} - -// ChooseManifestInstanceFromManifestList returns a digest of a manifest appropriate -// for the current system from the manifest available from src. -func ChooseManifestInstanceFromManifestList(ctx *types.SystemContext, src types.UnparsedImage) (digest.Digest, error) { - // For now this only handles manifest.DockerV2ListMediaType; we can generalize it later, - // probably along with manifest list editing. - blob, mt, err := src.Manifest() - if err != nil { - return "", err - } - if mt != manifest.DockerV2ListMediaType { - return "", fmt.Errorf("Internal error: Trying to select an image from a non-manifest-list manifest type %s", mt) - } - return chooseDigestFromManifestList(ctx, blob) -} diff --git a/vendor/github.com/containers/image/image/docker_schema1.go b/vendor/github.com/containers/image/image/docker_schema1.go deleted file mode 100644 index c6a6989dee..0000000000 --- a/vendor/github.com/containers/image/image/docker_schema1.go +++ /dev/null @@ -1,201 +0,0 @@ -package image - -import ( - "encoding/json" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -type manifestSchema1 struct { - m *manifest.Schema1 -} - -func manifestSchema1FromManifest(manifestBlob []byte) (genericManifest, error) { - m, err := manifest.Schema1FromManifest(manifestBlob) - if err != nil { - return nil, err - } - return &manifestSchema1{m: m}, nil -} - -// manifestSchema1FromComponents builds a new manifestSchema1 from the supplied data. -func manifestSchema1FromComponents(ref reference.Named, fsLayers []manifest.Schema1FSLayers, history []manifest.Schema1History, architecture string) genericManifest { - return &manifestSchema1{m: manifest.Schema1FromComponents(ref, fsLayers, history, architecture)} -} - -func (m *manifestSchema1) serialize() ([]byte, error) { - return m.m.Serialize() -} - -func (m *manifestSchema1) manifestMIMEType() string { - return manifest.DockerV2Schema1SignedMediaType -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below. -func (m *manifestSchema1) ConfigInfo() types.BlobInfo { - return m.m.ConfigInfo() -} - -// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise. -// The result is cached; it is OK to call this however often you need. -func (m *manifestSchema1) ConfigBlob() ([]byte, error) { - return nil, nil -} - -// OCIConfig returns the image configuration as per OCI v1 image-spec. Information about -// layers in the resulting configuration isn't guaranteed to be returned to due how -// old image manifests work (docker v2s1 especially). -func (m *manifestSchema1) OCIConfig() (*imgspecv1.Image, error) { - v2s2, err := m.convertToManifestSchema2(nil, nil) - if err != nil { - return nil, err - } - return v2s2.OCIConfig() -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *manifestSchema1) LayerInfos() []types.BlobInfo { - return m.m.LayerInfos() -} - -// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. -// It returns false if the manifest does not embed a Docker reference. -// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) -func (m *manifestSchema1) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { - // This is a bit convoluted: We can’t just have a "get embedded docker reference" method - // and have the “does it conflict” logic in the generic copy code, because the manifest does not actually - // embed a full docker/distribution reference, but only the repo name and tag (without the host name). - // So we would have to provide a “return repo without host name, and tag” getter for the generic code, - // which would be very awkward. Instead, we do the matching here in schema1-specific code, and all the - // generic copy code needs to know about is reference.Named and that a manifest may need updating - // for some destinations. - name := reference.Path(ref) - var tag string - if tagged, isTagged := ref.(reference.NamedTagged); isTagged { - tag = tagged.Tag() - } else { - tag = "" - } - return m.m.Name != name || m.m.Tag != tag -} - -func (m *manifestSchema1) imageInspectInfo() (*types.ImageInspectInfo, error) { - return m.m.Inspect(nil) -} - -// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. -// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute -// (most importantly it forces us to download the full layers even if they are already present at the destination). -func (m *manifestSchema1) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool { - return options.ManifestMIMEType == manifest.DockerV2Schema2MediaType -} - -// UpdatedImage returns a types.Image modified according to options. -// This does not change the state of the original Image object. -func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) { - copy := manifestSchema1{m: manifest.Schema1Clone(m.m)} - if options.LayerInfos != nil { - if err := copy.m.UpdateLayerInfos(options.LayerInfos); err != nil { - return nil, err - } - } - if options.EmbeddedDockerReference != nil { - copy.m.Name = reference.Path(options.EmbeddedDockerReference) - if tagged, isTagged := options.EmbeddedDockerReference.(reference.NamedTagged); isTagged { - copy.m.Tag = tagged.Tag() - } else { - copy.m.Tag = "" - } - } - - switch options.ManifestMIMEType { - case "": // No conversion, OK - case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType: - // We have 2 MIME types for schema 1, which are basically equivalent (even the un-"Signed" MIME type will be rejected if there isn’t a signature; so, - // handle conversions between them by doing nothing. - case manifest.DockerV2Schema2MediaType: - m2, err := copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs) - if err != nil { - return nil, err - } - return memoryImageFromManifest(m2), nil - case imgspecv1.MediaTypeImageManifest: - // We can't directly convert to OCI, but we can transitively convert via a Docker V2.2 Distribution manifest - m2, err := copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs) - if err != nil { - return nil, err - } - return m2.UpdatedImage(types.ManifestUpdateOptions{ - ManifestMIMEType: imgspecv1.MediaTypeImageManifest, - InformationOnly: options.InformationOnly, - }) - default: - return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema1SignedMediaType, options.ManifestMIMEType) - } - - return memoryImageFromManifest(©), nil -} - -// Based on github.com/docker/docker/distribution/pull_v2.go -func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.BlobInfo, layerDiffIDs []digest.Digest) (genericManifest, error) { - if len(m.m.History) == 0 { - // What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing. - return nil, errors.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema2MediaType) - } - if len(m.m.History) != len(m.m.FSLayers) { - return nil, errors.Errorf("Inconsistent schema 1 manifest: %d history entries, %d fsLayers entries", len(m.m.History), len(m.m.FSLayers)) - } - if uploadedLayerInfos != nil && len(uploadedLayerInfos) != len(m.m.FSLayers) { - return nil, errors.Errorf("Internal error: uploaded %d blobs, but schema1 manifest has %d fsLayers", len(uploadedLayerInfos), len(m.m.FSLayers)) - } - if layerDiffIDs != nil && len(layerDiffIDs) != len(m.m.FSLayers) { - return nil, errors.Errorf("Internal error: collected %d DiffID values, but schema1 manifest has %d fsLayers", len(layerDiffIDs), len(m.m.FSLayers)) - } - - // Build a list of the diffIDs for the non-empty layers. - diffIDs := []digest.Digest{} - var layers []manifest.Schema2Descriptor - for v1Index := len(m.m.History) - 1; v1Index >= 0; v1Index-- { - v2Index := (len(m.m.History) - 1) - v1Index - - var v1compat manifest.Schema1V1Compatibility - if err := json.Unmarshal([]byte(m.m.History[v1Index].V1Compatibility), &v1compat); err != nil { - return nil, errors.Wrapf(err, "Error decoding history entry %d", v1Index) - } - if !v1compat.ThrowAway { - var size int64 - if uploadedLayerInfos != nil { - size = uploadedLayerInfos[v2Index].Size - } - var d digest.Digest - if layerDiffIDs != nil { - d = layerDiffIDs[v2Index] - } - layers = append(layers, manifest.Schema2Descriptor{ - MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", - Size: size, - Digest: m.m.FSLayers[v1Index].BlobSum, - }) - diffIDs = append(diffIDs, d) - } - } - configJSON, err := m.m.ToSchema2(diffIDs) - if err != nil { - return nil, err - } - configDescriptor := manifest.Schema2Descriptor{ - MediaType: "application/vnd.docker.container.image.v1+json", - Size: int64(len(configJSON)), - Digest: digest.FromBytes(configJSON), - } - - return manifestSchema2FromComponents(configDescriptor, nil, configJSON, layers), nil -} diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go deleted file mode 100644 index b43bc17cfd..0000000000 --- a/vendor/github.com/containers/image/image/docker_schema2.go +++ /dev/null @@ -1,347 +0,0 @@ -package image - -import ( - "bytes" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "io/ioutil" - "strings" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// gzippedEmptyLayer is a gzip-compressed version of an empty tar file (1024 NULL bytes) -// This comes from github.com/docker/distribution/manifest/schema1/config_builder.go; there is -// a non-zero embedded timestamp; we could zero that, but that would just waste storage space -// in registries, so let’s use the same values. -var gzippedEmptyLayer = []byte{ - 31, 139, 8, 0, 0, 9, 110, 136, 0, 255, 98, 24, 5, 163, 96, 20, 140, 88, - 0, 8, 0, 0, 255, 255, 46, 175, 181, 239, 0, 4, 0, 0, -} - -// gzippedEmptyLayerDigest is a digest of gzippedEmptyLayer -const gzippedEmptyLayerDigest = digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4") - -type manifestSchema2 struct { - src types.ImageSource // May be nil if configBlob is not nil - configBlob []byte // If set, corresponds to contents of ConfigDescriptor. - m *manifest.Schema2 -} - -func manifestSchema2FromManifest(src types.ImageSource, manifestBlob []byte) (genericManifest, error) { - m, err := manifest.Schema2FromManifest(manifestBlob) - if err != nil { - return nil, err - } - return &manifestSchema2{ - src: src, - m: m, - }, nil -} - -// manifestSchema2FromComponents builds a new manifestSchema2 from the supplied data: -func manifestSchema2FromComponents(config manifest.Schema2Descriptor, src types.ImageSource, configBlob []byte, layers []manifest.Schema2Descriptor) genericManifest { - return &manifestSchema2{ - src: src, - configBlob: configBlob, - m: manifest.Schema2FromComponents(config, layers), - } -} - -func (m *manifestSchema2) serialize() ([]byte, error) { - return m.m.Serialize() -} - -func (m *manifestSchema2) manifestMIMEType() string { - return m.m.MediaType -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below. -func (m *manifestSchema2) ConfigInfo() types.BlobInfo { - return m.m.ConfigInfo() -} - -// OCIConfig returns the image configuration as per OCI v1 image-spec. Information about -// layers in the resulting configuration isn't guaranteed to be returned to due how -// old image manifests work (docker v2s1 especially). -func (m *manifestSchema2) OCIConfig() (*imgspecv1.Image, error) { - configBlob, err := m.ConfigBlob() - if err != nil { - return nil, err - } - // docker v2s2 and OCI v1 are mostly compatible but v2s2 contains more fields - // than OCI v1. This unmarshal makes sure we drop docker v2s2 - // fields that aren't needed in OCI v1. - configOCI := &imgspecv1.Image{} - if err := json.Unmarshal(configBlob, configOCI); err != nil { - return nil, err - } - return configOCI, nil -} - -// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise. -// The result is cached; it is OK to call this however often you need. -func (m *manifestSchema2) ConfigBlob() ([]byte, error) { - if m.configBlob == nil { - if m.src == nil { - return nil, errors.Errorf("Internal error: neither src nor configBlob set in manifestSchema2") - } - stream, _, err := m.src.GetBlob(types.BlobInfo{ - Digest: m.m.ConfigDescriptor.Digest, - Size: m.m.ConfigDescriptor.Size, - URLs: m.m.ConfigDescriptor.URLs, - }) - if err != nil { - return nil, err - } - defer stream.Close() - blob, err := ioutil.ReadAll(stream) - if err != nil { - return nil, err - } - computedDigest := digest.FromBytes(blob) - if computedDigest != m.m.ConfigDescriptor.Digest { - return nil, errors.Errorf("Download config.json digest %s does not match expected %s", computedDigest, m.m.ConfigDescriptor.Digest) - } - m.configBlob = blob - } - return m.configBlob, nil -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *manifestSchema2) LayerInfos() []types.BlobInfo { - return m.m.LayerInfos() -} - -// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. -// It returns false if the manifest does not embed a Docker reference. -// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) -func (m *manifestSchema2) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { - return false -} - -func (m *manifestSchema2) imageInspectInfo() (*types.ImageInspectInfo, error) { - getter := func(info types.BlobInfo) ([]byte, error) { - if info.Digest != m.ConfigInfo().Digest { - // Shouldn't ever happen - return nil, errors.New("asked for a different config blob") - } - config, err := m.ConfigBlob() - if err != nil { - return nil, err - } - return config, nil - } - return m.m.Inspect(getter) -} - -// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. -// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute -// (most importantly it forces us to download the full layers even if they are already present at the destination). -func (m *manifestSchema2) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool { - return false -} - -// UpdatedImage returns a types.Image modified according to options. -// This does not change the state of the original Image object. -func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) { - copy := manifestSchema2{ // NOTE: This is not a deep copy, it still shares slices etc. - src: m.src, - configBlob: m.configBlob, - m: manifest.Schema2Clone(m.m), - } - if options.LayerInfos != nil { - if err := copy.m.UpdateLayerInfos(options.LayerInfos); err != nil { - return nil, err - } - } - // Ignore options.EmbeddedDockerReference: it may be set when converting from schema1 to schema2, but we really don't care. - - switch options.ManifestMIMEType { - case "": // No conversion, OK - case manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType: - return copy.convertToManifestSchema1(options.InformationOnly.Destination) - case imgspecv1.MediaTypeImageManifest: - return copy.convertToManifestOCI1() - default: - return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema2MediaType, options.ManifestMIMEType) - } - - return memoryImageFromManifest(©), nil -} - -func oci1DescriptorFromSchema2Descriptor(d manifest.Schema2Descriptor) imgspecv1.Descriptor { - return imgspecv1.Descriptor{ - MediaType: d.MediaType, - Size: d.Size, - Digest: d.Digest, - URLs: d.URLs, - } -} - -func (m *manifestSchema2) convertToManifestOCI1() (types.Image, error) { - configOCI, err := m.OCIConfig() - if err != nil { - return nil, err - } - configOCIBytes, err := json.Marshal(configOCI) - if err != nil { - return nil, err - } - - config := imgspecv1.Descriptor{ - MediaType: imgspecv1.MediaTypeImageConfig, - Size: int64(len(configOCIBytes)), - Digest: digest.FromBytes(configOCIBytes), - } - - layers := make([]imgspecv1.Descriptor, len(m.m.LayersDescriptors)) - for idx := range layers { - layers[idx] = oci1DescriptorFromSchema2Descriptor(m.m.LayersDescriptors[idx]) - if m.m.LayersDescriptors[idx].MediaType == manifest.DockerV2Schema2ForeignLayerMediaType { - layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable - } else { - // we assume layers are gzip'ed because docker v2s2 only deals with - // gzip'ed layers. However, OCI has non-gzip'ed layers as well. - layers[idx].MediaType = imgspecv1.MediaTypeImageLayerGzip - } - } - - m1 := manifestOCI1FromComponents(config, m.src, configOCIBytes, layers) - return memoryImageFromManifest(m1), nil -} - -// Based on docker/distribution/manifest/schema1/config_builder.go -func (m *manifestSchema2) convertToManifestSchema1(dest types.ImageDestination) (types.Image, error) { - configBytes, err := m.ConfigBlob() - if err != nil { - return nil, err - } - imageConfig := &manifest.Schema2Image{} - if err := json.Unmarshal(configBytes, imageConfig); err != nil { - return nil, err - } - - // Build fsLayers and History, discarding all configs. We will patch the top-level config in later. - fsLayers := make([]manifest.Schema1FSLayers, len(imageConfig.History)) - history := make([]manifest.Schema1History, len(imageConfig.History)) - nonemptyLayerIndex := 0 - var parentV1ID string // Set in the loop - v1ID := "" - haveGzippedEmptyLayer := false - if len(imageConfig.History) == 0 { - // What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing. - return nil, errors.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema1SignedMediaType) - } - for v2Index, historyEntry := range imageConfig.History { - parentV1ID = v1ID - v1Index := len(imageConfig.History) - 1 - v2Index - - var blobDigest digest.Digest - if historyEntry.EmptyLayer { - if !haveGzippedEmptyLayer { - logrus.Debugf("Uploading empty layer during conversion to schema 1") - info, err := dest.PutBlob(bytes.NewReader(gzippedEmptyLayer), types.BlobInfo{Digest: gzippedEmptyLayerDigest, Size: int64(len(gzippedEmptyLayer))}) - if err != nil { - return nil, errors.Wrap(err, "Error uploading empty layer") - } - if info.Digest != gzippedEmptyLayerDigest { - return nil, errors.Errorf("Internal error: Uploaded empty layer has digest %#v instead of %s", info.Digest, gzippedEmptyLayerDigest) - } - haveGzippedEmptyLayer = true - } - blobDigest = gzippedEmptyLayerDigest - } else { - if nonemptyLayerIndex >= len(m.m.LayersDescriptors) { - return nil, errors.Errorf("Invalid image configuration, needs more than the %d distributed layers", len(m.m.LayersDescriptors)) - } - blobDigest = m.m.LayersDescriptors[nonemptyLayerIndex].Digest - nonemptyLayerIndex++ - } - - // AFAICT pull ignores these ID values, at least nowadays, so we could use anything unique, including a simple counter. Use what Docker uses for cargo-cult consistency. - v, err := v1IDFromBlobDigestAndComponents(blobDigest, parentV1ID) - if err != nil { - return nil, err - } - v1ID = v - - fakeImage := manifest.Schema1V1Compatibility{ - ID: v1ID, - Parent: parentV1ID, - Comment: historyEntry.Comment, - Created: historyEntry.Created, - Author: historyEntry.Author, - ThrowAway: historyEntry.EmptyLayer, - } - fakeImage.ContainerConfig.Cmd = []string{historyEntry.CreatedBy} - v1CompatibilityBytes, err := json.Marshal(&fakeImage) - if err != nil { - return nil, errors.Errorf("Internal error: Error creating v1compatibility for %#v", fakeImage) - } - - fsLayers[v1Index] = manifest.Schema1FSLayers{BlobSum: blobDigest} - history[v1Index] = manifest.Schema1History{V1Compatibility: string(v1CompatibilityBytes)} - // Note that parentV1ID of the top layer is preserved when exiting this loop - } - - // Now patch in real configuration for the top layer (v1Index == 0) - v1ID, err = v1IDFromBlobDigestAndComponents(fsLayers[0].BlobSum, parentV1ID, string(configBytes)) // See above WRT v1ID value generation and cargo-cult consistency. - if err != nil { - return nil, err - } - v1Config, err := v1ConfigFromConfigJSON(configBytes, v1ID, parentV1ID, imageConfig.History[len(imageConfig.History)-1].EmptyLayer) - if err != nil { - return nil, err - } - history[0].V1Compatibility = string(v1Config) - - m1 := manifestSchema1FromComponents(dest.Reference().DockerReference(), fsLayers, history, imageConfig.Architecture) - return memoryImageFromManifest(m1), nil -} - -func v1IDFromBlobDigestAndComponents(blobDigest digest.Digest, others ...string) (string, error) { - if err := blobDigest.Validate(); err != nil { - return "", err - } - parts := append([]string{blobDigest.Hex()}, others...) - v1IDHash := sha256.Sum256([]byte(strings.Join(parts, " "))) - return hex.EncodeToString(v1IDHash[:]), nil -} - -func v1ConfigFromConfigJSON(configJSON []byte, v1ID, parentV1ID string, throwaway bool) ([]byte, error) { - // Preserve everything we don't specifically know about. - // (This must be a *json.RawMessage, even though *[]byte is fairly redundant, because only *RawMessage implements json.Marshaler.) - rawContents := map[string]*json.RawMessage{} - if err := json.Unmarshal(configJSON, &rawContents); err != nil { // We have already unmarshaled it before, using a more detailed schema?! - return nil, err - } - delete(rawContents, "rootfs") - delete(rawContents, "history") - - updates := map[string]interface{}{"id": v1ID} - if parentV1ID != "" { - updates["parent"] = parentV1ID - } - if throwaway { - updates["throwaway"] = throwaway - } - for field, value := range updates { - encoded, err := json.Marshal(value) - if err != nil { - return nil, err - } - rawContents[field] = (*json.RawMessage)(&encoded) - } - return json.Marshal(rawContents) -} diff --git a/vendor/github.com/containers/image/image/manifest.go b/vendor/github.com/containers/image/image/manifest.go deleted file mode 100644 index cdd4233f70..0000000000 --- a/vendor/github.com/containers/image/image/manifest.go +++ /dev/null @@ -1,67 +0,0 @@ -package image - -import ( - "fmt" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -// genericManifest is an interface for parsing, modifying image manifests and related data. -// Note that the public methods are intended to be a subset of types.Image -// so that embedding a genericManifest into structs works. -// will support v1 one day... -type genericManifest interface { - serialize() ([]byte, error) - manifestMIMEType() string - // ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. - // Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below. - ConfigInfo() types.BlobInfo - // ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise. - // The result is cached; it is OK to call this however often you need. - ConfigBlob() ([]byte, error) - // OCIConfig returns the image configuration as per OCI v1 image-spec. Information about - // layers in the resulting configuration isn't guaranteed to be returned to due how - // old image manifests work (docker v2s1 especially). - OCIConfig() (*imgspecv1.Image, error) - // LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). - // The Digest field is guaranteed to be provided; Size may be -1. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfos() []types.BlobInfo - // EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. - // It returns false if the manifest does not embed a Docker reference. - // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) - EmbeddedDockerReferenceConflicts(ref reference.Named) bool - imageInspectInfo() (*types.ImageInspectInfo, error) // To be called by inspectManifest - // UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. - // This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute - // (most importantly it forces us to download the full layers even if they are already present at the destination). - UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool - // UpdatedImage returns a types.Image modified according to options. - // This does not change the state of the original Image object. - UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) -} - -// manifestInstanceFromBlob returns a genericManifest implementation for (manblob, mt) in src. -// If manblob is a manifest list, it implicitly chooses an appropriate image from the list. -func manifestInstanceFromBlob(ctx *types.SystemContext, src types.ImageSource, manblob []byte, mt string) (genericManifest, error) { - switch manifest.NormalizedMIMEType(mt) { - case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType: - return manifestSchema1FromManifest(manblob) - case imgspecv1.MediaTypeImageManifest: - return manifestOCI1FromManifest(src, manblob) - case manifest.DockerV2Schema2MediaType: - return manifestSchema2FromManifest(src, manblob) - case manifest.DockerV2ListMediaType: - return manifestSchema2FromManifestList(ctx, src, manblob) - default: // Note that this may not be reachable, manifest.NormalizedMIMEType has a default for unknown values. - return nil, fmt.Errorf("Unimplemented manifest MIME type %s", mt) - } -} - -// inspectManifest is an implementation of types.Image.Inspect -func inspectManifest(m genericManifest) (*types.ImageInspectInfo, error) { - return m.imageInspectInfo() -} diff --git a/vendor/github.com/containers/image/image/memory.go b/vendor/github.com/containers/image/image/memory.go deleted file mode 100644 index 4639c49a32..0000000000 --- a/vendor/github.com/containers/image/image/memory.go +++ /dev/null @@ -1,70 +0,0 @@ -package image - -import ( - "context" - - "github.com/pkg/errors" - - "github.com/containers/image/types" -) - -// memoryImage is a mostly-implementation of types.Image assembled from data -// created in memory, used primarily as a return value of types.Image.UpdatedImage -// as a way to carry various structured information in a type-safe and easy-to-use way. -// Note that this _only_ carries the immediate metadata; it is _not_ a stand-alone -// collection of all related information, e.g. there is no way to get layer blobs -// from a memoryImage. -type memoryImage struct { - genericManifest - serializedManifest []byte // A private cache for Manifest() -} - -func memoryImageFromManifest(m genericManifest) types.Image { - return &memoryImage{ - genericManifest: m, - serializedManifest: nil, - } -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (i *memoryImage) Reference() types.ImageReference { - // It would really be inappropriate to return the ImageReference of the image this was based on. - return nil -} - -// Size returns the size of the image as stored, if known, or -1 if not. -func (i *memoryImage) Size() (int64, error) { - return -1, nil -} - -// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need. -func (i *memoryImage) Manifest() ([]byte, string, error) { - if i.serializedManifest == nil { - m, err := i.genericManifest.serialize() - if err != nil { - return nil, "", err - } - i.serializedManifest = m - } - return i.serializedManifest, i.genericManifest.manifestMIMEType(), nil -} - -// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. -func (i *memoryImage) Signatures(ctx context.Context) ([][]byte, error) { - // Modifying an image invalidates signatures; a caller asking the updated image for signatures - // is probably confused. - return nil, errors.New("Internal error: Image.Signatures() is not supported for images modified in memory") -} - -// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. -func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) { - return inspectManifest(i.genericManifest) -} - -// LayerInfosForCopy returns an updated set of layer blob information which may not match the manifest. -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (i *memoryImage) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/image/oci.go b/vendor/github.com/containers/image/image/oci.go deleted file mode 100644 index e7780c5a6f..0000000000 --- a/vendor/github.com/containers/image/image/oci.go +++ /dev/null @@ -1,199 +0,0 @@ -package image - -import ( - "encoding/json" - "io/ioutil" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -type manifestOCI1 struct { - src types.ImageSource // May be nil if configBlob is not nil - configBlob []byte // If set, corresponds to contents of m.Config. - m *manifest.OCI1 -} - -func manifestOCI1FromManifest(src types.ImageSource, manifestBlob []byte) (genericManifest, error) { - m, err := manifest.OCI1FromManifest(manifestBlob) - if err != nil { - return nil, err - } - return &manifestOCI1{ - src: src, - m: m, - }, nil -} - -// manifestOCI1FromComponents builds a new manifestOCI1 from the supplied data: -func manifestOCI1FromComponents(config imgspecv1.Descriptor, src types.ImageSource, configBlob []byte, layers []imgspecv1.Descriptor) genericManifest { - return &manifestOCI1{ - src: src, - configBlob: configBlob, - m: manifest.OCI1FromComponents(config, layers), - } -} - -func (m *manifestOCI1) serialize() ([]byte, error) { - return m.m.Serialize() -} - -func (m *manifestOCI1) manifestMIMEType() string { - return imgspecv1.MediaTypeImageManifest -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below. -func (m *manifestOCI1) ConfigInfo() types.BlobInfo { - return m.m.ConfigInfo() -} - -// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise. -// The result is cached; it is OK to call this however often you need. -func (m *manifestOCI1) ConfigBlob() ([]byte, error) { - if m.configBlob == nil { - if m.src == nil { - return nil, errors.Errorf("Internal error: neither src nor configBlob set in manifestOCI1") - } - stream, _, err := m.src.GetBlob(types.BlobInfo{ - Digest: m.m.Config.Digest, - Size: m.m.Config.Size, - URLs: m.m.Config.URLs, - }) - if err != nil { - return nil, err - } - defer stream.Close() - blob, err := ioutil.ReadAll(stream) - if err != nil { - return nil, err - } - computedDigest := digest.FromBytes(blob) - if computedDigest != m.m.Config.Digest { - return nil, errors.Errorf("Download config.json digest %s does not match expected %s", computedDigest, m.m.Config.Digest) - } - m.configBlob = blob - } - return m.configBlob, nil -} - -// OCIConfig returns the image configuration as per OCI v1 image-spec. Information about -// layers in the resulting configuration isn't guaranteed to be returned to due how -// old image manifests work (docker v2s1 especially). -func (m *manifestOCI1) OCIConfig() (*imgspecv1.Image, error) { - cb, err := m.ConfigBlob() - if err != nil { - return nil, err - } - configOCI := &imgspecv1.Image{} - if err := json.Unmarshal(cb, configOCI); err != nil { - return nil, err - } - return configOCI, nil -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *manifestOCI1) LayerInfos() []types.BlobInfo { - return m.m.LayerInfos() -} - -// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. -// It returns false if the manifest does not embed a Docker reference. -// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) -func (m *manifestOCI1) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { - return false -} - -func (m *manifestOCI1) imageInspectInfo() (*types.ImageInspectInfo, error) { - getter := func(info types.BlobInfo) ([]byte, error) { - if info.Digest != m.ConfigInfo().Digest { - // Shouldn't ever happen - return nil, errors.New("asked for a different config blob") - } - config, err := m.ConfigBlob() - if err != nil { - return nil, err - } - return config, nil - } - return m.m.Inspect(getter) -} - -// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. -// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute -// (most importantly it forces us to download the full layers even if they are already present at the destination). -func (m *manifestOCI1) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool { - return false -} - -// UpdatedImage returns a types.Image modified according to options. -// This does not change the state of the original Image object. -func (m *manifestOCI1) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) { - copy := manifestOCI1{ // NOTE: This is not a deep copy, it still shares slices etc. - src: m.src, - configBlob: m.configBlob, - m: manifest.OCI1Clone(m.m), - } - if options.LayerInfos != nil { - if err := copy.m.UpdateLayerInfos(options.LayerInfos); err != nil { - return nil, err - } - } - // Ignore options.EmbeddedDockerReference: it may be set when converting from schema1, but we really don't care. - - switch options.ManifestMIMEType { - case "": // No conversion, OK - case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType: - // We can't directly convert to V1, but we can transitively convert via a V2 image - m2, err := copy.convertToManifestSchema2() - if err != nil { - return nil, err - } - return m2.UpdatedImage(types.ManifestUpdateOptions{ - ManifestMIMEType: options.ManifestMIMEType, - InformationOnly: options.InformationOnly, - }) - case manifest.DockerV2Schema2MediaType: - return copy.convertToManifestSchema2() - default: - return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", imgspecv1.MediaTypeImageManifest, options.ManifestMIMEType) - } - - return memoryImageFromManifest(©), nil -} - -func schema2DescriptorFromOCI1Descriptor(d imgspecv1.Descriptor) manifest.Schema2Descriptor { - return manifest.Schema2Descriptor{ - MediaType: d.MediaType, - Size: d.Size, - Digest: d.Digest, - URLs: d.URLs, - } -} - -func (m *manifestOCI1) convertToManifestSchema2() (types.Image, error) { - // Create a copy of the descriptor. - config := schema2DescriptorFromOCI1Descriptor(m.m.Config) - - // The only difference between OCI and DockerSchema2 is the mediatypes. The - // media type of the manifest is handled by manifestSchema2FromComponents. - config.MediaType = manifest.DockerV2Schema2ConfigMediaType - - layers := make([]manifest.Schema2Descriptor, len(m.m.Layers)) - for idx := range layers { - layers[idx] = schema2DescriptorFromOCI1Descriptor(m.m.Layers[idx]) - layers[idx].MediaType = manifest.DockerV2Schema2LayerMediaType - } - - // Rather than copying the ConfigBlob now, we just pass m.src to the - // translated manifest, since the only difference is the mediatype of - // descriptors there is no change to any blob stored in m.src. - m1 := manifestSchema2FromComponents(config, m.src, nil, layers) - return memoryImageFromManifest(m1), nil -} diff --git a/vendor/github.com/containers/image/image/sourced.go b/vendor/github.com/containers/image/image/sourced.go deleted file mode 100644 index 3477f341ea..0000000000 --- a/vendor/github.com/containers/image/image/sourced.go +++ /dev/null @@ -1,106 +0,0 @@ -// Package image consolidates knowledge about various container image formats -// (as opposed to image storage mechanisms, which are handled by types.ImageSource) -// and exposes all of them using an unified interface. -package image - -import ( - "github.com/containers/image/types" -) - -// imageCloser implements types.ImageCloser, perhaps allowing simple users -// to use a single object without having keep a reference to a types.ImageSource -// only to call types.ImageSource.Close(). -type imageCloser struct { - types.Image - src types.ImageSource -} - -// FromSource returns a types.ImageCloser implementation for the default instance of source. -// If source is a manifest list, .Manifest() still returns the manifest list, -// but other methods transparently return data from an appropriate image instance. -// -// The caller must call .Close() on the returned ImageCloser. -// -// FromSource “takes ownership” of the input ImageSource and will call src.Close() -// when the image is closed. (This does not prevent callers from using both the -// Image and ImageSource objects simultaneously, but it means that they only need to -// the Image.) -// -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function. -func FromSource(ctx *types.SystemContext, src types.ImageSource) (types.ImageCloser, error) { - img, err := FromUnparsedImage(ctx, UnparsedInstance(src, nil)) - if err != nil { - return nil, err - } - return &imageCloser{ - Image: img, - src: src, - }, nil -} - -func (ic *imageCloser) Close() error { - return ic.src.Close() -} - -// sourcedImage is a general set of utilities for working with container images, -// whatever is their underlying location (i.e. dockerImageSource-independent). -// Note the existence of skopeo/docker.Image: some instances of a `types.Image` -// may not be a `sourcedImage` directly. However, most users of `types.Image` -// do not care, and those who care about `skopeo/docker.Image` know they do. -type sourcedImage struct { - *UnparsedImage - manifestBlob []byte - manifestMIMEType string - // genericManifest contains data corresponding to manifestBlob. - // NOTE: The manifest may have been modified in the process; DO NOT reserialize and store genericManifest - // if you want to preserve the original manifest; use manifestBlob directly. - genericManifest -} - -// FromUnparsedImage returns a types.Image implementation for unparsed. -// If unparsed represents a manifest list, .Manifest() still returns the manifest list, -// but other methods transparently return data from an appropriate single image. -// -// The Image must not be used after the underlying ImageSource is Close()d. -func FromUnparsedImage(ctx *types.SystemContext, unparsed *UnparsedImage) (types.Image, error) { - // Note that the input parameter above is specifically *image.UnparsedImage, not types.UnparsedImage: - // we want to be able to use unparsed.src. We could make that an explicit interface, but, well, - // this is the only UnparsedImage implementation around, anyway. - - // NOTE: It is essential for signature verification that all parsing done in this object happens on the same manifest which is returned by unparsed.Manifest(). - manifestBlob, manifestMIMEType, err := unparsed.Manifest() - if err != nil { - return nil, err - } - - parsedManifest, err := manifestInstanceFromBlob(ctx, unparsed.src, manifestBlob, manifestMIMEType) - if err != nil { - return nil, err - } - - return &sourcedImage{ - UnparsedImage: unparsed, - manifestBlob: manifestBlob, - manifestMIMEType: manifestMIMEType, - genericManifest: parsedManifest, - }, nil -} - -// Size returns the size of the image as stored, if it's known, or -1 if it isn't. -func (i *sourcedImage) Size() (int64, error) { - return -1, nil -} - -// Manifest overrides the UnparsedImage.Manifest to always use the fields which we have already fetched. -func (i *sourcedImage) Manifest() ([]byte, string, error) { - return i.manifestBlob, i.manifestMIMEType, nil -} - -func (i *sourcedImage) Inspect() (*types.ImageInspectInfo, error) { - return inspectManifest(i.genericManifest) -} - -func (i *sourcedImage) LayerInfosForCopy() []types.BlobInfo { - return i.UnparsedImage.LayerInfosForCopy() -} diff --git a/vendor/github.com/containers/image/image/unparsed.go b/vendor/github.com/containers/image/image/unparsed.go deleted file mode 100644 index aff06d8ada..0000000000 --- a/vendor/github.com/containers/image/image/unparsed.go +++ /dev/null @@ -1,102 +0,0 @@ -package image - -import ( - "context" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// UnparsedImage implements types.UnparsedImage . -// An UnparsedImage is a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance. -type UnparsedImage struct { - src types.ImageSource - instanceDigest *digest.Digest - cachedManifest []byte // A private cache for Manifest(); nil if not yet known. - // A private cache for Manifest(), may be the empty string if guessing failed. - // Valid iff cachedManifest is not nil. - cachedManifestMIMEType string - cachedSignatures [][]byte // A private cache for Signatures(); nil if not yet known. -} - -// UnparsedInstance returns a types.UnparsedImage implementation for (source, instanceDigest). -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list). -// -// The UnparsedImage must not be used after the underlying ImageSource is Close()d. -func UnparsedInstance(src types.ImageSource, instanceDigest *digest.Digest) *UnparsedImage { - return &UnparsedImage{ - src: src, - instanceDigest: instanceDigest, - } -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (i *UnparsedImage) Reference() types.ImageReference { - // Note that this does not depend on instanceDigest; e.g. all instances within a manifest list need to be signed with the manifest list identity. - return i.src.Reference() -} - -// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need. -func (i *UnparsedImage) Manifest() ([]byte, string, error) { - if i.cachedManifest == nil { - m, mt, err := i.src.GetManifest(i.instanceDigest) - if err != nil { - return nil, "", err - } - - // ImageSource.GetManifest does not do digest verification, but we do; - // this immediately protects also any user of types.Image. - if digest, haveDigest := i.expectedManifestDigest(); haveDigest { - matches, err := manifest.MatchesDigest(m, digest) - if err != nil { - return nil, "", errors.Wrap(err, "Error computing manifest digest") - } - if !matches { - return nil, "", errors.Errorf("Manifest does not match provided manifest digest %s", digest) - } - } - - i.cachedManifest = m - i.cachedManifestMIMEType = mt - } - return i.cachedManifest, i.cachedManifestMIMEType, nil -} - -// expectedManifestDigest returns a the expected value of the manifest digest, and an indicator whether it is known. -// The bool return value seems redundant with digest != ""; it is used explicitly -// to refuse (unexpected) situations when the digest exists but is "". -func (i *UnparsedImage) expectedManifestDigest() (digest.Digest, bool) { - if i.instanceDigest != nil { - return *i.instanceDigest, true - } - ref := i.Reference().DockerReference() - if ref != nil { - if canonical, ok := ref.(reference.Canonical); ok { - return canonical.Digest(), true - } - } - return "", false -} - -// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. -func (i *UnparsedImage) Signatures(ctx context.Context) ([][]byte, error) { - if i.cachedSignatures == nil { - sigs, err := i.src.GetSignatures(ctx, i.instanceDigest) - if err != nil { - return nil, err - } - i.cachedSignatures = sigs - } - return i.cachedSignatures, nil -} - -// LayerInfosForCopy returns an updated set of layer blob information which may not match the manifest. -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (i *UnparsedImage) LayerInfosForCopy() []types.BlobInfo { - return i.src.LayerInfosForCopy() -} diff --git a/vendor/github.com/containers/image/internal/tmpdir/tmpdir.go b/vendor/github.com/containers/image/internal/tmpdir/tmpdir.go deleted file mode 100644 index a28020edcc..0000000000 --- a/vendor/github.com/containers/image/internal/tmpdir/tmpdir.go +++ /dev/null @@ -1,19 +0,0 @@ -package tmpdir - -import ( - "os" - "runtime" -) - -// TemporaryDirectoryForBigFiles returns a directory for temporary (big) files. -// On non Windows systems it avoids the use of os.TempDir(), because the default temporary directory usually falls under /tmp -// which on systemd based systems could be the unsuitable tmpfs filesystem. -func TemporaryDirectoryForBigFiles() string { - var temporaryDirectoryForBigFiles string - if runtime.GOOS == "windows" { - temporaryDirectoryForBigFiles = os.TempDir() - } else { - temporaryDirectoryForBigFiles = "/var/tmp" - } - return temporaryDirectoryForBigFiles -} diff --git a/vendor/github.com/containers/image/manifest/docker_schema1.go b/vendor/github.com/containers/image/manifest/docker_schema1.go deleted file mode 100644 index b1c1cfe9ff..0000000000 --- a/vendor/github.com/containers/image/manifest/docker_schema1.go +++ /dev/null @@ -1,310 +0,0 @@ -package manifest - -import ( - "encoding/json" - "regexp" - "strings" - "time" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/types" - "github.com/docker/docker/api/types/versions" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// Schema1FSLayers is an entry of the "fsLayers" array in docker/distribution schema 1. -type Schema1FSLayers struct { - BlobSum digest.Digest `json:"blobSum"` -} - -// Schema1History is an entry of the "history" array in docker/distribution schema 1. -type Schema1History struct { - V1Compatibility string `json:"v1Compatibility"` -} - -// Schema1 is a manifest in docker/distribution schema 1. -type Schema1 struct { - Name string `json:"name"` - Tag string `json:"tag"` - Architecture string `json:"architecture"` - FSLayers []Schema1FSLayers `json:"fsLayers"` - History []Schema1History `json:"history"` - SchemaVersion int `json:"schemaVersion"` -} - -// Schema1V1Compatibility is a v1Compatibility in docker/distribution schema 1. -type Schema1V1Compatibility struct { - ID string `json:"id"` - Parent string `json:"parent,omitempty"` - Comment string `json:"comment,omitempty"` - Created time.Time `json:"created"` - ContainerConfig struct { - Cmd []string - } `json:"container_config,omitempty"` - Author string `json:"author,omitempty"` - ThrowAway bool `json:"throwaway,omitempty"` -} - -// Schema1FromManifest creates a Schema1 manifest instance from a manifest blob. -// (NOTE: The instance is not necessary a literal representation of the original blob, -// layers with duplicate IDs are eliminated.) -func Schema1FromManifest(manifest []byte) (*Schema1, error) { - s1 := Schema1{} - if err := json.Unmarshal(manifest, &s1); err != nil { - return nil, err - } - if s1.SchemaVersion != 1 { - return nil, errors.Errorf("unsupported schema version %d", s1.SchemaVersion) - } - if len(s1.FSLayers) != len(s1.History) { - return nil, errors.New("length of history not equal to number of layers") - } - if len(s1.FSLayers) == 0 { - return nil, errors.New("no FSLayers in manifest") - } - if err := s1.fixManifestLayers(); err != nil { - return nil, err - } - return &s1, nil -} - -// Schema1FromComponents creates an Schema1 manifest instance from the supplied data. -func Schema1FromComponents(ref reference.Named, fsLayers []Schema1FSLayers, history []Schema1History, architecture string) *Schema1 { - var name, tag string - if ref != nil { // Well, what to do if it _is_ nil? Most consumers actually don't use these fields nowadays, so we might as well try not supplying them. - name = reference.Path(ref) - if tagged, ok := ref.(reference.NamedTagged); ok { - tag = tagged.Tag() - } - } - return &Schema1{ - Name: name, - Tag: tag, - Architecture: architecture, - FSLayers: fsLayers, - History: history, - SchemaVersion: 1, - } -} - -// Schema1Clone creates a copy of the supplied Schema1 manifest. -func Schema1Clone(src *Schema1) *Schema1 { - copy := *src - return © -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -func (m *Schema1) ConfigInfo() types.BlobInfo { - return types.BlobInfo{} -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *Schema1) LayerInfos() []types.BlobInfo { - layers := make([]types.BlobInfo, len(m.FSLayers)) - for i, layer := range m.FSLayers { // NOTE: This includes empty layers (where m.History.V1Compatibility->ThrowAway) - layers[(len(m.FSLayers)-1)-i] = types.BlobInfo{Digest: layer.BlobSum, Size: -1} - } - return layers -} - -// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers) -func (m *Schema1) UpdateLayerInfos(layerInfos []types.BlobInfo) error { - // Our LayerInfos includes empty layers (where m.History.V1Compatibility->ThrowAway), so expect them to be included here as well. - if len(m.FSLayers) != len(layerInfos) { - return errors.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(m.FSLayers), len(layerInfos)) - } - for i, info := range layerInfos { - // (docker push) sets up m.History.V1Compatibility->{Id,Parent} based on values of info.Digest, - // but (docker pull) ignores them in favor of computing DiffIDs from uncompressed data, except verifying the child->parent links and uniqueness. - // So, we don't bother recomputing the IDs in m.History.V1Compatibility. - m.FSLayers[(len(layerInfos)-1)-i].BlobSum = info.Digest - } - return nil -} - -// Serialize returns the manifest in a blob format. -// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made! -func (m *Schema1) Serialize() ([]byte, error) { - // docker/distribution requires a signature even if the incoming data uses the nominally unsigned DockerV2Schema1MediaType. - unsigned, err := json.Marshal(*m) - if err != nil { - return nil, err - } - return AddDummyV2S1Signature(unsigned) -} - -// fixManifestLayers, after validating the supplied manifest -// (to use correctly-formatted IDs, and to not have non-consecutive ID collisions in m.History), -// modifies manifest to only have one entry for each layer ID in m.History (deleting the older duplicates, -// both from m.History and m.FSLayers). -// Note that even after this succeeds, m.FSLayers may contain duplicate entries -// (for Dockerfile operations which change the configuration but not the filesystem). -func (m *Schema1) fixManifestLayers() error { - type imageV1 struct { - ID string - Parent string - } - // Per the specification, we can assume that len(m.FSLayers) == len(m.History) - imgs := make([]*imageV1, len(m.FSLayers)) - for i := range m.FSLayers { - img := &imageV1{} - - if err := json.Unmarshal([]byte(m.History[i].V1Compatibility), img); err != nil { - return err - } - - imgs[i] = img - if err := validateV1ID(img.ID); err != nil { - return err - } - } - if imgs[len(imgs)-1].Parent != "" { - return errors.New("Invalid parent ID in the base layer of the image") - } - // check general duplicates to error instead of a deadlock - idmap := make(map[string]struct{}) - var lastID string - for _, img := range imgs { - // skip IDs that appear after each other, we handle those later - if _, exists := idmap[img.ID]; img.ID != lastID && exists { - return errors.Errorf("ID %+v appears multiple times in manifest", img.ID) - } - lastID = img.ID - idmap[lastID] = struct{}{} - } - // backwards loop so that we keep the remaining indexes after removing items - for i := len(imgs) - 2; i >= 0; i-- { - if imgs[i].ID == imgs[i+1].ID { // repeated ID. remove and continue - m.FSLayers = append(m.FSLayers[:i], m.FSLayers[i+1:]...) - m.History = append(m.History[:i], m.History[i+1:]...) - } else if imgs[i].Parent != imgs[i+1].ID { - return errors.Errorf("Invalid parent ID. Expected %v, got %v", imgs[i+1].ID, imgs[i].Parent) - } - } - return nil -} - -var validHex = regexp.MustCompile(`^([a-f0-9]{64})$`) - -func validateV1ID(id string) error { - if ok := validHex.MatchString(id); !ok { - return errors.Errorf("image ID %q is invalid", id) - } - return nil -} - -// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. -func (m *Schema1) Inspect(_ func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) { - s1 := &Schema2V1Image{} - if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), s1); err != nil { - return nil, err - } - return &types.ImageInspectInfo{ - Tag: m.Tag, - Created: s1.Created, - DockerVersion: s1.DockerVersion, - Labels: make(map[string]string), - Architecture: s1.Architecture, - Os: s1.OS, - Layers: LayerInfosToStrings(m.LayerInfos()), - }, nil -} - -// ToSchema2 builds a schema2-style configuration blob using the supplied diffIDs. -func (m *Schema1) ToSchema2(diffIDs []digest.Digest) ([]byte, error) { - // Convert the schema 1 compat info into a schema 2 config, constructing some of the fields - // that aren't directly comparable using info from the manifest. - if len(m.History) == 0 { - return nil, errors.New("image has no layers") - } - s2 := struct { - Schema2Image - ID string `json:"id,omitempty"` - Parent string `json:"parent,omitempty"` - ParentID string `json:"parent_id,omitempty"` - LayerID string `json:"layer_id,omitempty"` - ThrowAway bool `json:"throwaway,omitempty"` - Size int64 `json:",omitempty"` - }{} - config := []byte(m.History[0].V1Compatibility) - err := json.Unmarshal(config, &s2) - if err != nil { - return nil, errors.Wrapf(err, "error decoding configuration") - } - // Images created with versions prior to 1.8.3 require us to re-encode the encoded object, - // adding some fields that aren't "omitempty". - if s2.DockerVersion != "" && versions.LessThan(s2.DockerVersion, "1.8.3") { - config, err = json.Marshal(&s2) - if err != nil { - return nil, errors.Wrapf(err, "error re-encoding compat image config %#v", s2) - } - } - // Build the history. - convertedHistory := []Schema2History{} - for _, h := range m.History { - compat := Schema1V1Compatibility{} - if err := json.Unmarshal([]byte(h.V1Compatibility), &compat); err != nil { - return nil, errors.Wrapf(err, "error decoding history information") - } - hitem := Schema2History{ - Created: compat.Created, - CreatedBy: strings.Join(compat.ContainerConfig.Cmd, " "), - Author: compat.Author, - Comment: compat.Comment, - EmptyLayer: compat.ThrowAway, - } - convertedHistory = append([]Schema2History{hitem}, convertedHistory...) - } - // Build the rootfs information. We need the decompressed sums that we've been - // calculating to fill in the DiffIDs. It's expected (but not enforced by us) - // that the number of diffIDs corresponds to the number of non-EmptyLayer - // entries in the history. - rootFS := &Schema2RootFS{ - Type: "layers", - DiffIDs: diffIDs, - } - // And now for some raw manipulation. - raw := make(map[string]*json.RawMessage) - err = json.Unmarshal(config, &raw) - if err != nil { - return nil, errors.Wrapf(err, "error re-decoding compat image config %#v: %v", s2) - } - // Drop some fields. - delete(raw, "id") - delete(raw, "parent") - delete(raw, "parent_id") - delete(raw, "layer_id") - delete(raw, "throwaway") - delete(raw, "Size") - // Add the history and rootfs information. - rootfs, err := json.Marshal(rootFS) - if err != nil { - return nil, errors.Errorf("error encoding rootfs information %#v: %v", rootFS, err) - } - rawRootfs := json.RawMessage(rootfs) - raw["rootfs"] = &rawRootfs - history, err := json.Marshal(convertedHistory) - if err != nil { - return nil, errors.Errorf("error encoding history information %#v: %v", convertedHistory, err) - } - rawHistory := json.RawMessage(history) - raw["history"] = &rawHistory - // Encode the result. - config, err = json.Marshal(raw) - if err != nil { - return nil, errors.Errorf("error re-encoding compat image config %#v: %v", s2, err) - } - return config, nil -} - -// ImageID computes an ID which can uniquely identify this image by its contents. -func (m *Schema1) ImageID(diffIDs []digest.Digest) (string, error) { - image, err := m.ToSchema2(diffIDs) - if err != nil { - return "", err - } - return digest.FromBytes(image).Hex(), nil -} diff --git a/vendor/github.com/containers/image/manifest/docker_schema2.go b/vendor/github.com/containers/image/manifest/docker_schema2.go deleted file mode 100644 index ef82ffc246..0000000000 --- a/vendor/github.com/containers/image/manifest/docker_schema2.go +++ /dev/null @@ -1,251 +0,0 @@ -package manifest - -import ( - "encoding/json" - "time" - - "github.com/containers/image/pkg/strslice" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// Schema2Descriptor is a “descriptor” in docker/distribution schema 2. -type Schema2Descriptor struct { - MediaType string `json:"mediaType"` - Size int64 `json:"size"` - Digest digest.Digest `json:"digest"` - URLs []string `json:"urls,omitempty"` -} - -// Schema2 is a manifest in docker/distribution schema 2. -type Schema2 struct { - SchemaVersion int `json:"schemaVersion"` - MediaType string `json:"mediaType"` - ConfigDescriptor Schema2Descriptor `json:"config"` - LayersDescriptors []Schema2Descriptor `json:"layers"` -} - -// Schema2Port is a Port, a string containing port number and protocol in the -// format "80/tcp", from docker/go-connections/nat. -type Schema2Port string - -// Schema2PortSet is a PortSet, a collection of structs indexed by Port, from -// docker/go-connections/nat. -type Schema2PortSet map[Schema2Port]struct{} - -// Schema2HealthConfig is a HealthConfig, which holds configuration settings -// for the HEALTHCHECK feature, from docker/docker/api/types/container. -type Schema2HealthConfig struct { - // Test is the test to perform to check that the container is healthy. - // An empty slice means to inherit the default. - // The options are: - // {} : inherit healthcheck - // {"NONE"} : disable healthcheck - // {"CMD", args...} : exec arguments directly - // {"CMD-SHELL", command} : run command with system's default shell - Test []string `json:",omitempty"` - - // Zero means to inherit. Durations are expressed as integer nanoseconds. - Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks. - Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung. - - // Retries is the number of consecutive failures needed to consider a container as unhealthy. - // Zero means inherit. - Retries int `json:",omitempty"` -} - -// Schema2Config is a Config in docker/docker/api/types/container. -type Schema2Config struct { - Hostname string // Hostname - Domainname string // Domainname - User string // User that will run the command(s) inside the container, also support user:group - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStdout bool // Attach the standard output - AttachStderr bool // Attach the standard error - ExposedPorts Schema2PortSet `json:",omitempty"` // List of exposed ports - Tty bool // Attach standard streams to a tty, including stdin if it is not closed. - OpenStdin bool // Open stdin - StdinOnce bool // If true, close stdin after the 1 attached client disconnects. - Env []string // List of environment variable to set in the container - Cmd strslice.StrSlice // Command to run when starting the container - Healthcheck *Schema2HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy - ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific) - Image string // Name of the image as it was passed by the operator (e.g. could be symbolic) - Volumes map[string]struct{} // List of volumes (mounts) used for the container - WorkingDir string // Current directory (PWD) in the command will be launched - Entrypoint strslice.StrSlice // Entrypoint to run when starting the container - NetworkDisabled bool `json:",omitempty"` // Is network disabled - MacAddress string `json:",omitempty"` // Mac Address of the container - OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile - Labels map[string]string // List of labels set to this container - StopSignal string `json:",omitempty"` // Signal to stop a container - StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container - Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT -} - -// Schema2V1Image is a V1Image in docker/docker/image. -type Schema2V1Image struct { - // ID is a unique 64 character identifier of the image - ID string `json:"id,omitempty"` - // Parent is the ID of the parent image - Parent string `json:"parent,omitempty"` - // Comment is the commit message that was set when committing the image - Comment string `json:"comment,omitempty"` - // Created is the timestamp at which the image was created - Created time.Time `json:"created"` - // Container is the id of the container used to commit - Container string `json:"container,omitempty"` - // ContainerConfig is the configuration of the container that is committed into the image - ContainerConfig Schema2Config `json:"container_config,omitempty"` - // DockerVersion specifies the version of Docker that was used to build the image - DockerVersion string `json:"docker_version,omitempty"` - // Author is the name of the author that was specified when committing the image - Author string `json:"author,omitempty"` - // Config is the configuration of the container received from the client - Config *Schema2Config `json:"config,omitempty"` - // Architecture is the hardware that the image is build and runs on - Architecture string `json:"architecture,omitempty"` - // OS is the operating system used to build and run the image - OS string `json:"os,omitempty"` - // Size is the total size of the image including all layers it is composed of - Size int64 `json:",omitempty"` -} - -// Schema2RootFS is a description of how to build up an image's root filesystem, from docker/docker/image. -type Schema2RootFS struct { - Type string `json:"type"` - DiffIDs []digest.Digest `json:"diff_ids,omitempty"` -} - -// Schema2History stores build commands that were used to create an image, from docker/docker/image. -type Schema2History struct { - // Created is the timestamp at which the image was created - Created time.Time `json:"created"` - // Author is the name of the author that was specified when committing the image - Author string `json:"author,omitempty"` - // CreatedBy keeps the Dockerfile command used while building the image - CreatedBy string `json:"created_by,omitempty"` - // Comment is the commit message that was set when committing the image - Comment string `json:"comment,omitempty"` - // EmptyLayer is set to true if this history item did not generate a - // layer. Otherwise, the history item is associated with the next - // layer in the RootFS section. - EmptyLayer bool `json:"empty_layer,omitempty"` -} - -// Schema2Image is an Image in docker/docker/image. -type Schema2Image struct { - Schema2V1Image - Parent digest.Digest `json:"parent,omitempty"` - RootFS *Schema2RootFS `json:"rootfs,omitempty"` - History []Schema2History `json:"history,omitempty"` - OSVersion string `json:"os.version,omitempty"` - OSFeatures []string `json:"os.features,omitempty"` - - // rawJSON caches the immutable JSON associated with this image. - rawJSON []byte - - // computedID is the ID computed from the hash of the image config. - // Not to be confused with the legacy V1 ID in V1Image. - computedID digest.Digest -} - -// Schema2FromManifest creates a Schema2 manifest instance from a manifest blob. -func Schema2FromManifest(manifest []byte) (*Schema2, error) { - s2 := Schema2{} - if err := json.Unmarshal(manifest, &s2); err != nil { - return nil, err - } - return &s2, nil -} - -// Schema2FromComponents creates an Schema2 manifest instance from the supplied data. -func Schema2FromComponents(config Schema2Descriptor, layers []Schema2Descriptor) *Schema2 { - return &Schema2{ - SchemaVersion: 2, - MediaType: DockerV2Schema2MediaType, - ConfigDescriptor: config, - LayersDescriptors: layers, - } -} - -// Schema2Clone creates a copy of the supplied Schema2 manifest. -func Schema2Clone(src *Schema2) *Schema2 { - copy := *src - return © -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -func (m *Schema2) ConfigInfo() types.BlobInfo { - return types.BlobInfo{Digest: m.ConfigDescriptor.Digest, Size: m.ConfigDescriptor.Size} -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *Schema2) LayerInfos() []types.BlobInfo { - blobs := []types.BlobInfo{} - for _, layer := range m.LayersDescriptors { - blobs = append(blobs, types.BlobInfo{ - Digest: layer.Digest, - Size: layer.Size, - URLs: layer.URLs, - }) - } - return blobs -} - -// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers) -func (m *Schema2) UpdateLayerInfos(layerInfos []types.BlobInfo) error { - if len(m.LayersDescriptors) != len(layerInfos) { - return errors.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(m.LayersDescriptors), len(layerInfos)) - } - original := m.LayersDescriptors - m.LayersDescriptors = make([]Schema2Descriptor, len(layerInfos)) - for i, info := range layerInfos { - m.LayersDescriptors[i].MediaType = original[i].MediaType - m.LayersDescriptors[i].Digest = info.Digest - m.LayersDescriptors[i].Size = info.Size - m.LayersDescriptors[i].URLs = info.URLs - } - return nil -} - -// Serialize returns the manifest in a blob format. -// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made! -func (m *Schema2) Serialize() ([]byte, error) { - return json.Marshal(*m) -} - -// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. -func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) { - config, err := configGetter(m.ConfigInfo()) - if err != nil { - return nil, err - } - s2 := &Schema2Image{} - if err := json.Unmarshal(config, s2); err != nil { - return nil, err - } - i := &types.ImageInspectInfo{ - Tag: "", - Created: s2.Created, - DockerVersion: s2.DockerVersion, - Architecture: s2.Architecture, - Os: s2.OS, - Layers: LayerInfosToStrings(m.LayerInfos()), - } - if s2.Config != nil { - i.Labels = s2.Config.Labels - } - return i, nil -} - -// ImageID computes an ID which can uniquely identify this image by its contents. -func (m *Schema2) ImageID([]digest.Digest) (string, error) { - if err := m.ConfigDescriptor.Digest.Validate(); err != nil { - return "", err - } - return m.ConfigDescriptor.Digest.Hex(), nil -} diff --git a/vendor/github.com/containers/image/manifest/manifest.go b/vendor/github.com/containers/image/manifest/manifest.go deleted file mode 100644 index 2bc801d815..0000000000 --- a/vendor/github.com/containers/image/manifest/manifest.go +++ /dev/null @@ -1,238 +0,0 @@ -package manifest - -import ( - "encoding/json" - "fmt" - - "github.com/containers/image/types" - "github.com/docker/libtrust" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -// FIXME: Should we just use docker/distribution and docker/docker implementations directly? - -// FIXME(runcom, mitr): should we havea mediatype pkg?? -const ( - // DockerV2Schema1MediaType MIME type represents Docker manifest schema 1 - DockerV2Schema1MediaType = "application/vnd.docker.distribution.manifest.v1+json" - // DockerV2Schema1MediaType MIME type represents Docker manifest schema 1 with a JWS signature - DockerV2Schema1SignedMediaType = "application/vnd.docker.distribution.manifest.v1+prettyjws" - // DockerV2Schema2MediaType MIME type represents Docker manifest schema 2 - DockerV2Schema2MediaType = "application/vnd.docker.distribution.manifest.v2+json" - // DockerV2Schema2ConfigMediaType is the MIME type used for schema 2 config blobs. - DockerV2Schema2ConfigMediaType = "application/vnd.docker.container.image.v1+json" - // DockerV2Schema2LayerMediaType is the MIME type used for schema 2 layers. - DockerV2Schema2LayerMediaType = "application/vnd.docker.image.rootfs.diff.tar.gzip" - // DockerV2ListMediaType MIME type represents Docker manifest schema 2 list - DockerV2ListMediaType = "application/vnd.docker.distribution.manifest.list.v2+json" - // DockerV2Schema2ForeignLayerMediaType is the MIME type used for schema 2 foreign layers. - DockerV2Schema2ForeignLayerMediaType = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" -) - -// DefaultRequestedManifestMIMETypes is a list of MIME types a types.ImageSource -// should request from the backend unless directed otherwise. -var DefaultRequestedManifestMIMETypes = []string{ - imgspecv1.MediaTypeImageManifest, - DockerV2Schema2MediaType, - DockerV2Schema1SignedMediaType, - DockerV2Schema1MediaType, - DockerV2ListMediaType, -} - -// Manifest is an interface for parsing, modifying image manifests in isolation. -// Callers can either use this abstract interface without understanding the details of the formats, -// or instantiate a specific implementation (e.g. manifest.OCI1) and access the public members -// directly. -// -// See types.Image for functionality not limited to manifests, including format conversions and config parsing. -// This interface is similar to, but not strictly equivalent to, the equivalent methods in types.Image. -type Manifest interface { - // ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. - ConfigInfo() types.BlobInfo - // LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). - // The Digest field is guaranteed to be provided; Size may be -1. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfos() []types.BlobInfo - // UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers) - UpdateLayerInfos(layerInfos []types.BlobInfo) error - - // ImageID computes an ID which can uniquely identify this image by its contents, irrespective - // of which (of possibly more than one simultaneously valid) reference was used to locate the - // image, and unchanged by whether or how the layers are compressed. The result takes the form - // of the hexadecimal portion of a digest.Digest. - ImageID(diffIDs []digest.Digest) (string, error) - - // Inspect returns various information for (skopeo inspect) parsed from the manifest, - // incorporating information from a configuration blob returned by configGetter, if - // the underlying image format is expected to include a configuration blob. - Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) - - // Serialize returns the manifest in a blob format. - // NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made! - Serialize() ([]byte, error) -} - -// GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized. -// FIXME? We should, in general, prefer out-of-band MIME type instead of blindly parsing the manifest, -// but we may not have such metadata available (e.g. when the manifest is a local file). -func GuessMIMEType(manifest []byte) string { - // A subset of manifest fields; the rest is silently ignored by json.Unmarshal. - // Also docker/distribution/manifest.Versioned. - meta := struct { - MediaType string `json:"mediaType"` - SchemaVersion int `json:"schemaVersion"` - Signatures interface{} `json:"signatures"` - }{} - if err := json.Unmarshal(manifest, &meta); err != nil { - return "" - } - - switch meta.MediaType { - case DockerV2Schema2MediaType, DockerV2ListMediaType: // A recognized type. - return meta.MediaType - } - // this is the only way the function can return DockerV2Schema1MediaType, and recognizing that is essential for stripping the JWS signatures = computing the correct manifest digest. - switch meta.SchemaVersion { - case 1: - if meta.Signatures != nil { - return DockerV2Schema1SignedMediaType - } - return DockerV2Schema1MediaType - case 2: - // best effort to understand if this is an OCI image since mediaType - // isn't in the manifest for OCI anymore - // for docker v2s2 meta.MediaType should have been set. But given the data, this is our best guess. - ociMan := struct { - Config struct { - MediaType string `json:"mediaType"` - } `json:"config"` - Layers []imgspecv1.Descriptor `json:"layers"` - }{} - if err := json.Unmarshal(manifest, &ociMan); err != nil { - return "" - } - if ociMan.Config.MediaType == imgspecv1.MediaTypeImageConfig && len(ociMan.Layers) != 0 { - return imgspecv1.MediaTypeImageManifest - } - ociIndex := struct { - Manifests []imgspecv1.Descriptor `json:"manifests"` - }{} - if err := json.Unmarshal(manifest, &ociIndex); err != nil { - return "" - } - if len(ociIndex.Manifests) != 0 && ociIndex.Manifests[0].MediaType == imgspecv1.MediaTypeImageManifest { - return imgspecv1.MediaTypeImageIndex - } - return DockerV2Schema2MediaType - } - return "" -} - -// Digest returns the a digest of a docker manifest, with any necessary implied transformations like stripping v1s1 signatures. -func Digest(manifest []byte) (digest.Digest, error) { - if GuessMIMEType(manifest) == DockerV2Schema1SignedMediaType { - sig, err := libtrust.ParsePrettySignature(manifest, "signatures") - if err != nil { - return "", err - } - manifest, err = sig.Payload() - if err != nil { - // Coverage: This should never happen, libtrust's Payload() can fail only if joseBase64UrlDecode() fails, on a string - // that libtrust itself has josebase64UrlEncode()d - return "", err - } - } - - return digest.FromBytes(manifest), nil -} - -// MatchesDigest returns true iff the manifest matches expectedDigest. -// Error may be set if this returns false. -// Note that this is not doing ConstantTimeCompare; by the time we get here, the cryptographic signature must already have been verified, -// or we are not using a cryptographic channel and the attacker can modify the digest along with the manifest blob. -func MatchesDigest(manifest []byte, expectedDigest digest.Digest) (bool, error) { - // This should eventually support various digest types. - actualDigest, err := Digest(manifest) - if err != nil { - return false, err - } - return expectedDigest == actualDigest, nil -} - -// AddDummyV2S1Signature adds an JWS signature with a temporary key (i.e. useless) to a v2s1 manifest. -// This is useful to make the manifest acceptable to a Docker Registry (even though nothing needs or wants the JWS signature). -func AddDummyV2S1Signature(manifest []byte) ([]byte, error) { - key, err := libtrust.GenerateECP256PrivateKey() - if err != nil { - return nil, err // Coverage: This can fail only if rand.Reader fails. - } - - js, err := libtrust.NewJSONSignature(manifest) - if err != nil { - return nil, err - } - if err := js.Sign(key); err != nil { // Coverage: This can fail basically only if rand.Reader fails. - return nil, err - } - return js.PrettySignature("signatures") -} - -// MIMETypeIsMultiImage returns true if mimeType is a list of images -func MIMETypeIsMultiImage(mimeType string) bool { - return mimeType == DockerV2ListMediaType -} - -// NormalizedMIMEType returns the effective MIME type of a manifest MIME type returned by a server, -// centralizing various workarounds. -func NormalizedMIMEType(input string) string { - switch input { - // "application/json" is a valid v2s1 value per https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md . - // This works for now, when nothing else seems to return "application/json"; if that were not true, the mapping/detection might - // need to happen within the ImageSource. - case "application/json": - return DockerV2Schema1SignedMediaType - case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType, - imgspecv1.MediaTypeImageManifest, - DockerV2Schema2MediaType, - DockerV2ListMediaType: - return input - default: - // If it's not a recognized manifest media type, or we have failed determining the type, we'll try one last time - // to deserialize using v2s1 as per https://github.com/docker/distribution/blob/master/manifests.go#L108 - // and https://github.com/docker/distribution/blob/master/manifest/schema1/manifest.go#L50 - // - // Crane registries can also return "text/plain", or pretty much anything else depending on a file extension “recognized” in the tag. - // This makes no real sense, but it happens - // because requests for manifests are - // redirected to a content distribution - // network which is configured that way. See https://bugzilla.redhat.com/show_bug.cgi?id=1389442 - return DockerV2Schema1SignedMediaType - } -} - -// FromBlob returns a Manifest instance for the specified manifest blob and the corresponding MIME type -func FromBlob(manblob []byte, mt string) (Manifest, error) { - switch NormalizedMIMEType(mt) { - case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType: - return Schema1FromManifest(manblob) - case imgspecv1.MediaTypeImageManifest: - return OCI1FromManifest(manblob) - case DockerV2Schema2MediaType: - return Schema2FromManifest(manblob) - case DockerV2ListMediaType: - return nil, fmt.Errorf("Treating manifest lists as individual manifests is not implemented") - default: // Note that this may not be reachable, NormalizedMIMEType has a default for unknown values. - return nil, fmt.Errorf("Unimplemented manifest MIME type %s", mt) - } -} - -// LayerInfosToStrings converts a list of layer infos, presumably obtained from a Manifest.LayerInfos() -// method call, into a format suitable for inclusion in a types.ImageInspectInfo structure. -func LayerInfosToStrings(infos []types.BlobInfo) []string { - layers := make([]string, len(infos)) - for i, info := range infos { - layers[i] = info.Digest.String() - } - return layers -} diff --git a/vendor/github.com/containers/image/manifest/oci.go b/vendor/github.com/containers/image/manifest/oci.go deleted file mode 100644 index 0ffb35b746..0000000000 --- a/vendor/github.com/containers/image/manifest/oci.go +++ /dev/null @@ -1,120 +0,0 @@ -package manifest - -import ( - "encoding/json" - "time" - - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -// OCI1 is a manifest.Manifest implementation for OCI images. -// The underlying data from imgspecv1.Manifest is also available. -type OCI1 struct { - imgspecv1.Manifest -} - -// OCI1FromManifest creates an OCI1 manifest instance from a manifest blob. -func OCI1FromManifest(manifest []byte) (*OCI1, error) { - oci1 := OCI1{} - if err := json.Unmarshal(manifest, &oci1); err != nil { - return nil, err - } - return &oci1, nil -} - -// OCI1FromComponents creates an OCI1 manifest instance from the supplied data. -func OCI1FromComponents(config imgspecv1.Descriptor, layers []imgspecv1.Descriptor) *OCI1 { - return &OCI1{ - imgspecv1.Manifest{ - Versioned: specs.Versioned{SchemaVersion: 2}, - Config: config, - Layers: layers, - }, - } -} - -// OCI1Clone creates a copy of the supplied OCI1 manifest. -func OCI1Clone(src *OCI1) *OCI1 { - return &OCI1{ - Manifest: src.Manifest, - } -} - -// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. -func (m *OCI1) ConfigInfo() types.BlobInfo { - return types.BlobInfo{Digest: m.Config.Digest, Size: m.Config.Size, Annotations: m.Config.Annotations} -} - -// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (m *OCI1) LayerInfos() []types.BlobInfo { - blobs := []types.BlobInfo{} - for _, layer := range m.Layers { - blobs = append(blobs, types.BlobInfo{Digest: layer.Digest, Size: layer.Size, Annotations: layer.Annotations, URLs: layer.URLs, MediaType: layer.MediaType}) - } - return blobs -} - -// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers) -func (m *OCI1) UpdateLayerInfos(layerInfos []types.BlobInfo) error { - if len(m.Layers) != len(layerInfos) { - return errors.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(m.Layers), len(layerInfos)) - } - original := m.Layers - m.Layers = make([]imgspecv1.Descriptor, len(layerInfos)) - for i, info := range layerInfos { - m.Layers[i].MediaType = original[i].MediaType - m.Layers[i].Digest = info.Digest - m.Layers[i].Size = info.Size - m.Layers[i].Annotations = info.Annotations - m.Layers[i].URLs = info.URLs - } - return nil -} - -// Serialize returns the manifest in a blob format. -// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made! -func (m *OCI1) Serialize() ([]byte, error) { - return json.Marshal(*m) -} - -// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. -func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) { - config, err := configGetter(m.ConfigInfo()) - if err != nil { - return nil, err - } - v1 := &imgspecv1.Image{} - if err := json.Unmarshal(config, v1); err != nil { - return nil, err - } - d1 := &Schema2V1Image{} - json.Unmarshal(config, d1) - created := time.Time{} - if v1.Created != nil { - created = *v1.Created - } - i := &types.ImageInspectInfo{ - Tag: "", - Created: created, - DockerVersion: d1.DockerVersion, - Labels: v1.Config.Labels, - Architecture: v1.Architecture, - Os: v1.OS, - Layers: LayerInfosToStrings(m.LayerInfos()), - } - return i, nil -} - -// ImageID computes an ID which can uniquely identify this image by its contents. -func (m *OCI1) ImageID([]digest.Digest) (string, error) { - if err := m.Config.Digest.Validate(); err != nil { - return "", err - } - return m.Config.Digest.Hex(), nil -} diff --git a/vendor/github.com/containers/image/oci/archive/oci_dest.go b/vendor/github.com/containers/image/oci/archive/oci_dest.go deleted file mode 100644 index 52e99a43dc..0000000000 --- a/vendor/github.com/containers/image/oci/archive/oci_dest.go +++ /dev/null @@ -1,131 +0,0 @@ -package archive - -import ( - "io" - "os" - - "github.com/containers/image/types" - "github.com/containers/storage/pkg/archive" - "github.com/pkg/errors" -) - -type ociArchiveImageDestination struct { - ref ociArchiveReference - unpackedDest types.ImageDestination - tempDirRef tempDirOCIRef -} - -// newImageDestination returns an ImageDestination for writing to an existing directory. -func newImageDestination(ctx *types.SystemContext, ref ociArchiveReference) (types.ImageDestination, error) { - tempDirRef, err := createOCIRef(ref.image) - if err != nil { - return nil, errors.Wrapf(err, "error creating oci reference") - } - unpackedDest, err := tempDirRef.ociRefExtracted.NewImageDestination(ctx) - if err != nil { - if err := tempDirRef.deleteTempDir(); err != nil { - return nil, errors.Wrapf(err, "error deleting temp directory", tempDirRef.tempDirectory) - } - return nil, err - } - return &ociArchiveImageDestination{ref: ref, - unpackedDest: unpackedDest, - tempDirRef: tempDirRef}, nil -} - -// Reference returns the reference used to set up this destination. -func (d *ociArchiveImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any -// Close deletes the temp directory of the oci-archive image -func (d *ociArchiveImageDestination) Close() error { - defer d.tempDirRef.deleteTempDir() - return d.unpackedDest.Close() -} - -func (d *ociArchiveImageDestination) SupportedManifestMIMETypes() []string { - return d.unpackedDest.SupportedManifestMIMETypes() -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures -func (d *ociArchiveImageDestination) SupportsSignatures() error { - return d.unpackedDest.SupportsSignatures() -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination -func (d *ociArchiveImageDestination) ShouldCompressLayers() bool { - return d.unpackedDest.ShouldCompressLayers() -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *ociArchiveImageDestination) AcceptsForeignLayerURLs() bool { - return d.unpackedDest.AcceptsForeignLayerURLs() -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise -func (d *ociArchiveImageDestination) MustMatchRuntimeOS() bool { - return d.unpackedDest.MustMatchRuntimeOS() -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -func (d *ociArchiveImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - return d.unpackedDest.PutBlob(stream, inputInfo) -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob -func (d *ociArchiveImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - return d.unpackedDest.HasBlob(info) -} - -func (d *ociArchiveImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return d.unpackedDest.ReapplyBlob(info) -} - -// PutManifest writes manifest to the destination -func (d *ociArchiveImageDestination) PutManifest(m []byte) error { - return d.unpackedDest.PutManifest(m) -} - -func (d *ociArchiveImageDestination) PutSignatures(signatures [][]byte) error { - return d.unpackedDest.PutSignatures(signatures) -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted -// after the directory is made, it is tarred up into a file and the directory is deleted -func (d *ociArchiveImageDestination) Commit() error { - if err := d.unpackedDest.Commit(); err != nil { - return errors.Wrapf(err, "error storing image %q", d.ref.image) - } - - // path of directory to tar up - src := d.tempDirRef.tempDirectory - // path to save tarred up file - dst := d.ref.resolvedFile - return tarDirectory(src, dst) -} - -// tar converts the directory at src and saves it to dst -func tarDirectory(src, dst string) error { - // input is a stream of bytes from the archive of the directory at path - input, err := archive.Tar(src, archive.Uncompressed) - if err != nil { - return errors.Wrapf(err, "error retrieving stream of bytes from %q", src) - } - - // creates the tar file - outFile, err := os.Create(dst) - if err != nil { - return errors.Wrapf(err, "error creating tar file %q", dst) - } - defer outFile.Close() - - // copies the contents of the directory to the tar file - _, err = io.Copy(outFile, input) - - return err -} diff --git a/vendor/github.com/containers/image/oci/archive/oci_src.go b/vendor/github.com/containers/image/oci/archive/oci_src.go deleted file mode 100644 index aee5d8d5bf..0000000000 --- a/vendor/github.com/containers/image/oci/archive/oci_src.go +++ /dev/null @@ -1,95 +0,0 @@ -package archive - -import ( - "context" - "io" - - ocilayout "github.com/containers/image/oci/layout" - "github.com/containers/image/types" - digest "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -type ociArchiveImageSource struct { - ref ociArchiveReference - unpackedSrc types.ImageSource - tempDirRef tempDirOCIRef -} - -// newImageSource returns an ImageSource for reading from an existing directory. -// newImageSource untars the file and saves it in a temp directory -func newImageSource(ctx *types.SystemContext, ref ociArchiveReference) (types.ImageSource, error) { - tempDirRef, err := createUntarTempDir(ref) - if err != nil { - return nil, errors.Wrap(err, "error creating temp directory") - } - - unpackedSrc, err := tempDirRef.ociRefExtracted.NewImageSource(ctx) - if err != nil { - if err := tempDirRef.deleteTempDir(); err != nil { - return nil, errors.Wrapf(err, "error deleting temp directory", tempDirRef.tempDirectory) - } - return nil, err - } - return &ociArchiveImageSource{ref: ref, - unpackedSrc: unpackedSrc, - tempDirRef: tempDirRef}, nil -} - -// LoadManifestDescriptor loads the manifest -func LoadManifestDescriptor(imgRef types.ImageReference) (imgspecv1.Descriptor, error) { - ociArchRef, ok := imgRef.(ociArchiveReference) - if !ok { - return imgspecv1.Descriptor{}, errors.Errorf("error typecasting, need type ociArchiveReference") - } - tempDirRef, err := createUntarTempDir(ociArchRef) - if err != nil { - return imgspecv1.Descriptor{}, errors.Wrap(err, "error creating temp directory") - } - defer tempDirRef.deleteTempDir() - - descriptor, err := ocilayout.LoadManifestDescriptor(tempDirRef.ociRefExtracted) - if err != nil { - return imgspecv1.Descriptor{}, errors.Wrap(err, "error loading index") - } - return descriptor, nil -} - -// Reference returns the reference used to set up this source. -func (s *ociArchiveImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -// Close deletes the temporary directory at dst -func (s *ociArchiveImageSource) Close() error { - defer s.tempDirRef.deleteTempDir() - return s.unpackedSrc.Close() -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *ociArchiveImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - return s.unpackedSrc.GetManifest(instanceDigest) -} - -// GetBlob returns a stream for the specified blob, and the blob's size. -func (s *ociArchiveImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - return s.unpackedSrc.GetBlob(info) -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *ociArchiveImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - return s.unpackedSrc.GetSignatures(ctx, instanceDigest) -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *ociArchiveImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/oci/archive/oci_transport.go b/vendor/github.com/containers/image/oci/archive/oci_transport.go deleted file mode 100644 index c4a4fa716e..0000000000 --- a/vendor/github.com/containers/image/oci/archive/oci_transport.go +++ /dev/null @@ -1,190 +0,0 @@ -package archive - -import ( - "fmt" - "io/ioutil" - "os" - "strings" - - "github.com/containers/image/directory/explicitfilepath" - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/internal/tmpdir" - "github.com/containers/image/oci/internal" - ocilayout "github.com/containers/image/oci/layout" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/containers/storage/pkg/archive" - "github.com/pkg/errors" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for OCI archive -// it creates an oci-archive tar file by calling into the OCI transport -// tarring the directory created by oci and deleting the directory -var Transport = ociArchiveTransport{} - -type ociArchiveTransport struct{} - -// ociArchiveReference is an ImageReference for OCI Archive paths -type ociArchiveReference struct { - file string - resolvedFile string - image string -} - -func (t ociArchiveTransport) Name() string { - return "oci-archive" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix -// into an ImageReference. -func (t ociArchiveTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -func (t ociArchiveTransport) ValidatePolicyConfigurationScope(scope string) error { - return internal.ValidateScope(scope) -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OCI ImageReference. -func ParseReference(reference string) (types.ImageReference, error) { - file, image := internal.SplitPathAndImage(reference) - return NewReference(file, image) -} - -// NewReference returns an OCI reference for a file and a image. -func NewReference(file, image string) (types.ImageReference, error) { - resolved, err := explicitfilepath.ResolvePathToFullyExplicit(file) - if err != nil { - return nil, err - } - - if err := internal.ValidateOCIPath(file); err != nil { - return nil, err - } - - if err := internal.ValidateImageName(image); err != nil { - return nil, err - } - - return ociArchiveReference{file: file, resolvedFile: resolved, image: image}, nil -} - -func (ref ociArchiveReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -func (ref ociArchiveReference) StringWithinTransport() string { - return fmt.Sprintf("%s:%s", ref.file, ref.image) -} - -// DockerReference returns a Docker reference associated with this reference -func (ref ociArchiveReference) DockerReference() reference.Named { - return nil -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -func (ref ociArchiveReference) PolicyConfigurationIdentity() string { - // NOTE: ref.image is not a part of the image identity, because "$dir:$someimage" and "$dir:" may mean the - // same image and the two can’t be statically disambiguated. Using at least the repository directory is - // less granular but hopefully still useful. - return fmt.Sprintf("%s", ref.resolvedFile) -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set -func (ref ociArchiveReference) PolicyConfigurationNamespaces() []string { - res := []string{} - path := ref.resolvedFile - for { - lastSlash := strings.LastIndex(path, "/") - // Note that we do not include "/"; it is redundant with the default "" global default, - // and rejected by ociTransport.ValidatePolicyConfigurationScope above. - if lastSlash == -1 || path == "/" { - break - } - res = append(res, path) - path = path[:lastSlash] - } - return res -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref ociArchiveReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src, err := newImageSource(ctx, ref) - if err != nil { - return nil, err - } - return image.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref ociArchiveReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref ociArchiveReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref ociArchiveReference) DeleteImage(ctx *types.SystemContext) error { - return errors.Errorf("Deleting images not implemented for oci: images") -} - -// struct to store the ociReference and temporary directory returned by createOCIRef -type tempDirOCIRef struct { - tempDirectory string - ociRefExtracted types.ImageReference -} - -// deletes the temporary directory created -func (t *tempDirOCIRef) deleteTempDir() error { - return os.RemoveAll(t.tempDirectory) -} - -// createOCIRef creates the oci reference of the image -func createOCIRef(image string) (tempDirOCIRef, error) { - dir, err := ioutil.TempDir(tmpdir.TemporaryDirectoryForBigFiles(), "oci") - if err != nil { - return tempDirOCIRef{}, errors.Wrapf(err, "error creating temp directory") - } - ociRef, err := ocilayout.NewReference(dir, image) - if err != nil { - return tempDirOCIRef{}, err - } - - tempDirRef := tempDirOCIRef{tempDirectory: dir, ociRefExtracted: ociRef} - return tempDirRef, nil -} - -// creates the temporary directory and copies the tarred content to it -func createUntarTempDir(ref ociArchiveReference) (tempDirOCIRef, error) { - tempDirRef, err := createOCIRef(ref.image) - if err != nil { - return tempDirOCIRef{}, errors.Wrap(err, "error creating oci reference") - } - src := ref.resolvedFile - dst := tempDirRef.tempDirectory - if err := archive.UntarPath(src, dst); err != nil { - if err := tempDirRef.deleteTempDir(); err != nil { - return tempDirOCIRef{}, errors.Wrapf(err, "error deleting temp directory %q", tempDirRef.tempDirectory) - } - return tempDirOCIRef{}, errors.Wrapf(err, "error untarring file %q", tempDirRef.tempDirectory) - } - return tempDirRef, nil -} diff --git a/vendor/github.com/containers/image/oci/internal/oci_util.go b/vendor/github.com/containers/image/oci/internal/oci_util.go deleted file mode 100644 index c2012e50e0..0000000000 --- a/vendor/github.com/containers/image/oci/internal/oci_util.go +++ /dev/null @@ -1,126 +0,0 @@ -package internal - -import ( - "github.com/pkg/errors" - "path/filepath" - "regexp" - "runtime" - "strings" -) - -// annotation spex from https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys -const ( - separator = `(?:[-._:@+]|--)` - alphanum = `(?:[A-Za-z0-9]+)` - component = `(?:` + alphanum + `(?:` + separator + alphanum + `)*)` -) - -var refRegexp = regexp.MustCompile(`^` + component + `(?:/` + component + `)*$`) -var windowsRefRegexp = regexp.MustCompile(`^([a-zA-Z]:\\.+?):(.*)$`) - -// ValidateImageName returns nil if the image name is empty or matches the open-containers image name specs. -// In any other case an error is returned. -func ValidateImageName(image string) error { - if len(image) == 0 { - return nil - } - - var err error - if !refRegexp.MatchString(image) { - err = errors.Errorf("Invalid image %s", image) - } - return err -} - -// SplitPathAndImage tries to split the provided OCI reference into the OCI path and image. -// Neither path nor image parts are validated at this stage. -func SplitPathAndImage(reference string) (string, string) { - if runtime.GOOS == "windows" { - return splitPathAndImageWindows(reference) - } - return splitPathAndImageNonWindows(reference) -} - -func splitPathAndImageWindows(reference string) (string, string) { - groups := windowsRefRegexp.FindStringSubmatch(reference) - // nil group means no match - if groups == nil { - return reference, "" - } - - // we expect three elements. First one full match, second the capture group for the path and - // the third the capture group for the image - if len(groups) != 3 { - return reference, "" - } - return groups[1], groups[2] -} - -func splitPathAndImageNonWindows(reference string) (string, string) { - sep := strings.SplitN(reference, ":", 2) - path := sep[0] - - var image string - if len(sep) == 2 { - image = sep[1] - } - return path, image -} - -// ValidateOCIPath takes the OCI path and validates it. -func ValidateOCIPath(path string) error { - if runtime.GOOS == "windows" { - // On Windows we must allow for a ':' as part of the path - if strings.Count(path, ":") > 1 { - return errors.Errorf("Invalid OCI reference: path %s contains more than one colon", path) - } - } else { - if strings.Contains(path, ":") { - return errors.Errorf("Invalid OCI reference: path %s contains a colon", path) - } - } - return nil -} - -// ValidateScope validates a policy configuration scope for an OCI transport. -func ValidateScope(scope string) error { - var err error - if runtime.GOOS == "windows" { - err = validateScopeWindows(scope) - } else { - err = validateScopeNonWindows(scope) - } - if err != nil { - return err - } - - cleaned := filepath.Clean(scope) - if cleaned != scope { - return errors.Errorf(`Invalid scope %s: Uses non-canonical path format, perhaps try with path %s`, scope, cleaned) - } - - return nil -} - -func validateScopeWindows(scope string) error { - matched, _ := regexp.Match(`^[a-zA-Z]:\\`, []byte(scope)) - if !matched { - return errors.Errorf("Invalid scope '%s'. Must be an absolute path", scope) - } - - return nil -} - -func validateScopeNonWindows(scope string) error { - if !strings.HasPrefix(scope, "/") { - return errors.Errorf("Invalid scope %s: must be an absolute path", scope) - } - - // Refuse also "/", otherwise "/" and "" would have the same semantics, - // and "" could be unexpectedly shadowed by the "/" entry. - if scope == "/" { - return errors.New(`Invalid scope "/": Use the generic default scope ""`) - } - - return nil -} diff --git a/vendor/github.com/containers/image/oci/layout/oci_dest.go b/vendor/github.com/containers/image/oci/layout/oci_dest.go deleted file mode 100644 index e95f65167a..0000000000 --- a/vendor/github.com/containers/image/oci/layout/oci_dest.go +++ /dev/null @@ -1,294 +0,0 @@ -package layout - -import ( - "encoding/json" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - - "github.com/pkg/errors" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - imgspec "github.com/opencontainers/image-spec/specs-go" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -type ociImageDestination struct { - ref ociReference - index imgspecv1.Index - sharedBlobDir string -} - -// newImageDestination returns an ImageDestination for writing to an existing directory. -func newImageDestination(ctx *types.SystemContext, ref ociReference) (types.ImageDestination, error) { - if ref.image == "" { - return nil, errors.Errorf("cannot save image with empty image.ref.name") - } - - var index *imgspecv1.Index - if indexExists(ref) { - var err error - index, err = ref.getIndex() - if err != nil { - return nil, err - } - } else { - index = &imgspecv1.Index{ - Versioned: imgspec.Versioned{ - SchemaVersion: 2, - }, - } - } - - d := &ociImageDestination{ref: ref, index: *index} - if ctx != nil { - d.sharedBlobDir = ctx.OCISharedBlobDirPath - } - - if err := ensureDirectoryExists(d.ref.dir); err != nil { - return nil, err - } - // Per the OCI image specification, layouts MUST have a "blobs" subdirectory, - // but it MAY be empty (e.g. if we never end up calling PutBlob) - // https://github.com/opencontainers/image-spec/blame/7c889fafd04a893f5c5f50b7ab9963d5d64e5242/image-layout.md#L19 - if err := ensureDirectoryExists(filepath.Join(d.ref.dir, "blobs")); err != nil { - return nil, err - } - return d, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *ociImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *ociImageDestination) Close() error { - return nil -} - -func (d *ociImageDestination) SupportedManifestMIMETypes() []string { - return []string{ - imgspecv1.MediaTypeImageManifest, - } -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *ociImageDestination) SupportsSignatures() error { - return errors.Errorf("Pushing signatures for OCI images is not supported") -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *ociImageDestination) ShouldCompressLayers() bool { - return true -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *ociImageDestination) AcceptsForeignLayerURLs() bool { - return true -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *ociImageDestination) MustMatchRuntimeOS() bool { - return false -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available -// to any other readers for download using the supplied digest. -// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. -func (d *ociImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - blobFile, err := ioutil.TempFile(d.ref.dir, "oci-put-blob") - if err != nil { - return types.BlobInfo{}, err - } - succeeded := false - explicitClosed := false - defer func() { - if !explicitClosed { - blobFile.Close() - } - if !succeeded { - os.Remove(blobFile.Name()) - } - }() - - digester := digest.Canonical.Digester() - tee := io.TeeReader(stream, digester.Hash()) - - size, err := io.Copy(blobFile, tee) - if err != nil { - return types.BlobInfo{}, err - } - computedDigest := digester.Digest() - if inputInfo.Size != -1 && size != inputInfo.Size { - return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size) - } - if err := blobFile.Sync(); err != nil { - return types.BlobInfo{}, err - } - - // On POSIX systems, blobFile was created with mode 0600, so we need to make it readable. - // On Windows, the “permissions of newly created files” argument to syscall.Open is - // ignored and the file is already readable; besides, blobFile.Chmod, i.e. syscall.Fchmod, - // always fails on Windows. - if runtime.GOOS != "windows" { - if err := blobFile.Chmod(0644); err != nil { - return types.BlobInfo{}, err - } - } - - blobPath, err := d.ref.blobPath(computedDigest, d.sharedBlobDir) - if err != nil { - return types.BlobInfo{}, err - } - if err := ensureParentDirectoryExists(blobPath); err != nil { - return types.BlobInfo{}, err - } - - // need to explicitly close the file, since a rename won't otherwise not work on Windows - blobFile.Close() - explicitClosed = true - if err := os.Rename(blobFile.Name(), blobPath); err != nil { - return types.BlobInfo{}, err - } - succeeded = true - return types.BlobInfo{Digest: computedDigest, Size: size}, nil -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob. -// Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. -// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); -// it returns a non-nil error only on an unexpected failure. -func (d *ociImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - if info.Digest == "" { - return false, -1, errors.Errorf(`"Can not check for a blob with unknown digest`) - } - blobPath, err := d.ref.blobPath(info.Digest, d.sharedBlobDir) - if err != nil { - return false, -1, err - } - finfo, err := os.Stat(blobPath) - if err != nil && os.IsNotExist(err) { - return false, -1, nil - } - if err != nil { - return false, -1, err - } - return true, finfo.Size(), nil -} - -func (d *ociImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return info, nil -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *ociImageDestination) PutManifest(m []byte) error { - digest, err := manifest.Digest(m) - if err != nil { - return err - } - desc := imgspecv1.Descriptor{} - desc.Digest = digest - // TODO(runcom): beaware and add support for OCI manifest list - desc.MediaType = imgspecv1.MediaTypeImageManifest - desc.Size = int64(len(m)) - - blobPath, err := d.ref.blobPath(digest, d.sharedBlobDir) - if err != nil { - return err - } - if err := ensureParentDirectoryExists(blobPath); err != nil { - return err - } - if err := ioutil.WriteFile(blobPath, m, 0644); err != nil { - return err - } - - if d.ref.image == "" { - return errors.Errorf("cannot save image with empyt image.ref.name") - } - - annotations := make(map[string]string) - annotations["org.opencontainers.image.ref.name"] = d.ref.image - desc.Annotations = annotations - desc.Platform = &imgspecv1.Platform{ - Architecture: runtime.GOARCH, - OS: runtime.GOOS, - } - d.addManifest(&desc) - - return nil -} - -func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) { - for i, manifest := range d.index.Manifests { - if manifest.Annotations["org.opencontainers.image.ref.name"] == desc.Annotations["org.opencontainers.image.ref.name"] { - // TODO Should there first be a cleanup based on the descriptor we are going to replace? - d.index.Manifests[i] = *desc - return - } - } - d.index.Manifests = append(d.index.Manifests, *desc) -} - -func (d *ociImageDestination) PutSignatures(signatures [][]byte) error { - if len(signatures) != 0 { - return errors.Errorf("Pushing signatures for OCI images is not supported") - } - return nil -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *ociImageDestination) Commit() error { - if err := ioutil.WriteFile(d.ref.ociLayoutPath(), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0644); err != nil { - return err - } - indexJSON, err := json.Marshal(d.index) - if err != nil { - return err - } - return ioutil.WriteFile(d.ref.indexPath(), indexJSON, 0644) -} - -func ensureDirectoryExists(path string) error { - if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - } - return nil -} - -// ensureParentDirectoryExists ensures the parent of the supplied path exists. -func ensureParentDirectoryExists(path string) error { - return ensureDirectoryExists(filepath.Dir(path)) -} - -// indexExists checks whether the index location specified in the OCI reference exists. -// The implementation is opinionated, since in case of unexpected errors false is returned -func indexExists(ref ociReference) bool { - _, err := os.Stat(ref.indexPath()) - if err == nil { - return true - } - if os.IsNotExist(err) { - return false - } - return true -} diff --git a/vendor/github.com/containers/image/oci/layout/oci_src.go b/vendor/github.com/containers/image/oci/layout/oci_src.go deleted file mode 100644 index 1109f65c6a..0000000000 --- a/vendor/github.com/containers/image/oci/layout/oci_src.go +++ /dev/null @@ -1,157 +0,0 @@ -package layout - -import ( - "context" - "io" - "io/ioutil" - "net/http" - "os" - "strconv" - - "github.com/containers/image/pkg/tlsclientconfig" - "github.com/containers/image/types" - "github.com/docker/go-connections/tlsconfig" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -type ociImageSource struct { - ref ociReference - descriptor imgspecv1.Descriptor - client *http.Client - sharedBlobDir string -} - -// newImageSource returns an ImageSource for reading from an existing directory. -func newImageSource(ctx *types.SystemContext, ref ociReference) (types.ImageSource, error) { - tr := tlsclientconfig.NewTransport() - tr.TLSClientConfig = tlsconfig.ServerDefault() - - if ctx != nil && ctx.OCICertPath != "" { - if err := tlsclientconfig.SetupCertificates(ctx.OCICertPath, tr.TLSClientConfig); err != nil { - return nil, err - } - tr.TLSClientConfig.InsecureSkipVerify = ctx.OCIInsecureSkipTLSVerify - } - - client := &http.Client{} - client.Transport = tr - descriptor, err := ref.getManifestDescriptor() - if err != nil { - return nil, err - } - d := &ociImageSource{ref: ref, descriptor: descriptor, client: client} - if ctx != nil { - // TODO(jonboulle): check dir existence? - d.sharedBlobDir = ctx.OCISharedBlobDirPath - } - return d, nil -} - -// Reference returns the reference used to set up this source. -func (s *ociImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *ociImageSource) Close() error { - return nil -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *ociImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - var dig digest.Digest - var mimeType string - if instanceDigest == nil { - dig = digest.Digest(s.descriptor.Digest) - mimeType = s.descriptor.MediaType - } else { - dig = *instanceDigest - // XXX: instanceDigest means that we don't immediately have the context of what - // mediaType the manifest has. In OCI this means that we don't know - // what reference it came from, so we just *assume* that its - // MediaTypeImageManifest. - // FIXME: We should actually be able to look up the manifest in the index, - // and see the MIME type there. - mimeType = imgspecv1.MediaTypeImageManifest - } - - manifestPath, err := s.ref.blobPath(dig, s.sharedBlobDir) - if err != nil { - return nil, "", err - } - m, err := ioutil.ReadFile(manifestPath) - if err != nil { - return nil, "", err - } - - return m, mimeType, nil -} - -// GetBlob returns a stream for the specified blob, and the blob's size. -func (s *ociImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - if len(info.URLs) != 0 { - return s.getExternalBlob(info.URLs) - } - - path, err := s.ref.blobPath(info.Digest, s.sharedBlobDir) - if err != nil { - return nil, 0, err - } - - r, err := os.Open(path) - if err != nil { - return nil, 0, err - } - fi, err := r.Stat() - if err != nil { - return nil, 0, err - } - return r, fi.Size(), nil -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *ociImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - return [][]byte{}, nil -} - -func (s *ociImageSource) getExternalBlob(urls []string) (io.ReadCloser, int64, error) { - errWrap := errors.New("failed fetching external blob from all urls") - for _, url := range urls { - resp, err := s.client.Get(url) - if err != nil { - errWrap = errors.Wrapf(errWrap, "fetching %s failed %s", url, err.Error()) - continue - } - - if resp.StatusCode != http.StatusOK { - resp.Body.Close() - errWrap = errors.Wrapf(errWrap, "fetching %s failed, response code not 200", url) - continue - } - - return resp.Body, getBlobSize(resp), nil - } - - return nil, 0, errWrap -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *ociImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} - -func getBlobSize(resp *http.Response) int64 { - size, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) - if err != nil { - size = -1 - } - return size -} diff --git a/vendor/github.com/containers/image/oci/layout/oci_transport.go b/vendor/github.com/containers/image/oci/layout/oci_transport.go deleted file mode 100644 index c181c4c77b..0000000000 --- a/vendor/github.com/containers/image/oci/layout/oci_transport.go +++ /dev/null @@ -1,255 +0,0 @@ -package layout - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/containers/image/directory/explicitfilepath" - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/oci/internal" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for OCI directories. -var Transport = ociTransport{} - -type ociTransport struct{} - -func (t ociTransport) Name() string { - return "oci" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t ociTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t ociTransport) ValidatePolicyConfigurationScope(scope string) error { - return internal.ValidateScope(scope) -} - -// ociReference is an ImageReference for OCI directory paths. -type ociReference struct { - // Note that the interpretation of paths below depends on the underlying filesystem state, which may change under us at any time! - // Either of the paths may point to a different, or no, inode over time. resolvedDir may contain symbolic links, and so on. - - // Generally we follow the intent of the user, and use the "dir" member for filesystem operations (e.g. the user can use a relative path to avoid - // being exposed to symlinks and renames in the parent directories to the working directory). - // (But in general, we make no attempt to be completely safe against concurrent hostile filesystem modifications.) - dir string // As specified by the user. May be relative, contain symlinks, etc. - resolvedDir string // Absolute path with no symlinks, at least at the time of its creation. Primarily used for policy namespaces. - image string // If image=="", it means the only image in the index.json is used -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OCI ImageReference. -func ParseReference(reference string) (types.ImageReference, error) { - dir, image := internal.SplitPathAndImage(reference) - return NewReference(dir, image) -} - -// NewReference returns an OCI reference for a directory and a image. -// -// We do not expose an API supplying the resolvedDir; we could, but recomputing it -// is generally cheap enough that we prefer being confident about the properties of resolvedDir. -func NewReference(dir, image string) (types.ImageReference, error) { - resolved, err := explicitfilepath.ResolvePathToFullyExplicit(dir) - if err != nil { - return nil, err - } - - if err := internal.ValidateOCIPath(dir); err != nil { - return nil, err - } - - if err = internal.ValidateImageName(image); err != nil { - return nil, err - } - - return ociReference{dir: dir, resolvedDir: resolved, image: image}, nil -} - -func (ref ociReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref ociReference) StringWithinTransport() string { - return fmt.Sprintf("%s:%s", ref.dir, ref.image) -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref ociReference) DockerReference() reference.Named { - return nil -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref ociReference) PolicyConfigurationIdentity() string { - // NOTE: ref.image is not a part of the image identity, because "$dir:$someimage" and "$dir:" may mean the - // same image and the two can’t be statically disambiguated. Using at least the repository directory is - // less granular but hopefully still useful. - return fmt.Sprintf("%s", ref.resolvedDir) -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref ociReference) PolicyConfigurationNamespaces() []string { - res := []string{} - path := ref.resolvedDir - for { - lastSlash := strings.LastIndex(path, "/") - // Note that we do not include "/"; it is redundant with the default "" global default, - // and rejected by ociTransport.ValidatePolicyConfigurationScope above. - if lastSlash == -1 || path == "/" { - break - } - res = append(res, path) - path = path[:lastSlash] - } - return res -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref ociReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src, err := newImageSource(ctx, ref) - if err != nil { - return nil, err - } - return image.FromSource(ctx, src) -} - -// getIndex returns a pointer to the index references by this ociReference. If an error occurs opening an index nil is returned together -// with an error. -func (ref ociReference) getIndex() (*imgspecv1.Index, error) { - indexJSON, err := os.Open(ref.indexPath()) - if err != nil { - return nil, err - } - defer indexJSON.Close() - - index := &imgspecv1.Index{} - if err := json.NewDecoder(indexJSON).Decode(index); err != nil { - return nil, err - } - return index, nil -} - -func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, error) { - index, err := ref.getIndex() - if err != nil { - return imgspecv1.Descriptor{}, err - } - - var d *imgspecv1.Descriptor - if ref.image == "" { - // return manifest if only one image is in the oci directory - if len(index.Manifests) == 1 { - d = &index.Manifests[0] - } else { - // ask user to choose image when more than one image in the oci directory - return imgspecv1.Descriptor{}, errors.Wrapf(err, "more than one image in oci, choose an image") - } - } else { - // if image specified, look through all manifests for a match - for _, md := range index.Manifests { - if md.MediaType != imgspecv1.MediaTypeImageManifest { - continue - } - refName, ok := md.Annotations["org.opencontainers.image.ref.name"] - if !ok { - continue - } - if refName == ref.image { - d = &md - break - } - } - } - if d == nil { - return imgspecv1.Descriptor{}, fmt.Errorf("no descriptor found for reference %q", ref.image) - } - return *d, nil -} - -// LoadManifestDescriptor loads the manifest descriptor to be used to retrieve the image name -// when pulling an image -func LoadManifestDescriptor(imgRef types.ImageReference) (imgspecv1.Descriptor, error) { - ociRef, ok := imgRef.(ociReference) - if !ok { - return imgspecv1.Descriptor{}, errors.Errorf("error typecasting, need type ociRef") - } - return ociRef.getManifestDescriptor() -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref ociReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref ociReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref ociReference) DeleteImage(ctx *types.SystemContext) error { - return errors.Errorf("Deleting images not implemented for oci: images") -} - -// ociLayoutPath returns a path for the oci-layout within a directory using OCI conventions. -func (ref ociReference) ociLayoutPath() string { - return filepath.Join(ref.dir, "oci-layout") -} - -// indexPath returns a path for the index.json within a directory using OCI conventions. -func (ref ociReference) indexPath() string { - return filepath.Join(ref.dir, "index.json") -} - -// blobPath returns a path for a blob within a directory using OCI image-layout conventions. -func (ref ociReference) blobPath(digest digest.Digest, sharedBlobDir string) (string, error) { - if err := digest.Validate(); err != nil { - return "", errors.Wrapf(err, "unexpected digest reference %s", digest) - } - blobDir := filepath.Join(ref.dir, "blobs") - if sharedBlobDir != "" { - blobDir = sharedBlobDir - } - return filepath.Join(blobDir, digest.Algorithm().String(), digest.Hex()), nil -} diff --git a/vendor/github.com/containers/image/openshift/openshift-copies.go b/vendor/github.com/containers/image/openshift/openshift-copies.go deleted file mode 100644 index 01fe71a243..0000000000 --- a/vendor/github.com/containers/image/openshift/openshift-copies.go +++ /dev/null @@ -1,1174 +0,0 @@ -package openshift - -import ( - "crypto/tls" - "crypto/x509" - "encoding/json" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "reflect" - "strings" - "time" - - "github.com/ghodss/yaml" - "github.com/imdario/mergo" - "github.com/pkg/errors" - "golang.org/x/net/http2" - "k8s.io/client-go/util/homedir" -) - -// restTLSClientConfig is a modified copy of k8s.io/kubernets/pkg/client/restclient.TLSClientConfig. -// restTLSClientConfig contains settings to enable transport layer security -type restTLSClientConfig struct { - // Server requires TLS client certificate authentication - CertFile string - // Server requires TLS client certificate authentication - KeyFile string - // Trusted root certificates for server - CAFile string - - // CertData holds PEM-encoded bytes (typically read from a client certificate file). - // CertData takes precedence over CertFile - CertData []byte - // KeyData holds PEM-encoded bytes (typically read from a client certificate key file). - // KeyData takes precedence over KeyFile - KeyData []byte - // CAData holds PEM-encoded bytes (typically read from a root certificates bundle). - // CAData takes precedence over CAFile - CAData []byte -} - -// restConfig is a modified copy of k8s.io/kubernets/pkg/client/restclient.Config. -// Config holds the common attributes that can be passed to a Kubernetes client on -// initialization. -type restConfig struct { - // Host must be a host string, a host:port pair, or a URL to the base of the apiserver. - // If a URL is given then the (optional) Path of that URL represents a prefix that must - // be appended to all request URIs used to access the apiserver. This allows a frontend - // proxy to easily relocate all of the apiserver endpoints. - Host string - - // Server requires Basic authentication - Username string - Password string - - // Server requires Bearer authentication. This client will not attempt to use - // refresh tokens for an OAuth2 flow. - // TODO: demonstrate an OAuth2 compatible client. - BearerToken string - - // TLSClientConfig contains settings to enable transport layer security - restTLSClientConfig - - // Server should be accessed without verifying the TLS - // certificate. For testing only. - Insecure bool -} - -// ClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfig. -// ClientConfig is used to make it easy to get an api server client -type clientConfig interface { - // ClientConfig returns a complete client config - ClientConfig() (*restConfig, error) -} - -// defaultClientConfig is a modified copy of openshift/origin/pkg/cmd/util/clientcmd.DefaultClientConfig. -func defaultClientConfig() clientConfig { - loadingRules := newOpenShiftClientConfigLoadingRules() - // REMOVED: Allowing command-line overriding of loadingRules - // REMOVED: clientcmd.ConfigOverrides - - clientConfig := newNonInteractiveDeferredLoadingClientConfig(loadingRules) - - return clientConfig -} - -var recommendedHomeFile = path.Join(homedir.HomeDir(), ".kube/config") - -// newOpenShiftClientConfigLoadingRules is a modified copy of openshift/origin/pkg/cmd/cli/config.NewOpenShiftClientConfigLoadingRules. -// NewOpenShiftClientConfigLoadingRules returns file priority loading rules for OpenShift. -// 1. --config value -// 2. if KUBECONFIG env var has a value, use it. Otherwise, ~/.kube/config file -func newOpenShiftClientConfigLoadingRules() *clientConfigLoadingRules { - chain := []string{} - - envVarFile := os.Getenv("KUBECONFIG") - if len(envVarFile) != 0 { - chain = append(chain, filepath.SplitList(envVarFile)...) - } else { - chain = append(chain, recommendedHomeFile) - } - - return &clientConfigLoadingRules{ - Precedence: chain, - // REMOVED: Migration support; run (oc login) to trigger migration - } -} - -// deferredLoadingClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DeferredLoadingClientConfig. -// DeferredLoadingClientConfig is a ClientConfig interface that is backed by a set of loading rules -// It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that -// the most recent rules are used. This is useful in cases where you bind flags to loading rule parameters before -// the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid -// passing extraneous information down a call stack -type deferredLoadingClientConfig struct { - loadingRules *clientConfigLoadingRules - - clientConfig clientConfig -} - -// NewNonInteractiveDeferredLoadingClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.NewNonInteractiveDeferredLoadingClientConfig. -// NewNonInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name -func newNonInteractiveDeferredLoadingClientConfig(loadingRules *clientConfigLoadingRules) clientConfig { - return &deferredLoadingClientConfig{loadingRules: loadingRules} -} - -func (config *deferredLoadingClientConfig) createClientConfig() (clientConfig, error) { - if config.clientConfig == nil { - // REMOVED: Support for concurrent use in multiple threads. - mergedConfig, err := config.loadingRules.Load() - if err != nil { - return nil, err - } - - var mergedClientConfig clientConfig - // REMOVED: Interactive fallback support. - mergedClientConfig = newNonInteractiveClientConfig(*mergedConfig) - - config.clientConfig = mergedClientConfig - } - - return config.clientConfig, nil -} - -// ClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DeferredLoadingClientConfig.ClientConfig. -// ClientConfig implements ClientConfig -func (config *deferredLoadingClientConfig) ClientConfig() (*restConfig, error) { - mergedClientConfig, err := config.createClientConfig() - if err != nil { - return nil, err - } - mergedConfig, err := mergedClientConfig.ClientConfig() - if err != nil { - return nil, err - } - // REMOVED: In-cluster service account configuration use. - - return mergedConfig, nil -} - -var ( - // DefaultCluster is the cluster config used when no other config is specified - // TODO: eventually apiserver should start on 443 and be secure by default - defaultCluster = clientcmdCluster{Server: "http://localhost:8080"} - - // EnvVarCluster allows overriding the DefaultCluster using an envvar for the server name - envVarCluster = clientcmdCluster{Server: os.Getenv("KUBERNETES_MASTER")} -) - -// directClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig. -// DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information -type directClientConfig struct { - config clientcmdConfig -} - -// newNonInteractiveClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.NewNonInteractiveClientConfig. -// NewNonInteractiveClientConfig creates a DirectClientConfig using the passed context name and does not have a fallback reader for auth information -func newNonInteractiveClientConfig(config clientcmdConfig) clientConfig { - return &directClientConfig{config} -} - -// ClientConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.ClientConfig. -// ClientConfig implements ClientConfig -func (config *directClientConfig) ClientConfig() (*restConfig, error) { - if err := config.ConfirmUsable(); err != nil { - return nil, err - } - - configAuthInfo := config.getAuthInfo() - configClusterInfo := config.getCluster() - - clientConfig := &restConfig{} - clientConfig.Host = configClusterInfo.Server - if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 { - u.RawQuery = "" - u.Fragment = "" - clientConfig.Host = u.String() - } - - // only try to read the auth information if we are secure - if isConfigTransportTLS(*clientConfig) { - var err error - - // mergo is a first write wins for map value and a last writing wins for interface values - // NOTE: This behavior changed with https://github.com/imdario/mergo/commit/d304790b2ed594794496464fadd89d2bb266600a. - // Our mergo.Merge version is older than this change. - // REMOVED: Support for interactive fallback. - userAuthPartialConfig, err := getUserIdentificationPartialConfig(configAuthInfo) - if err != nil { - return nil, err - } - mergo.Merge(clientConfig, userAuthPartialConfig) - - serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo) - if err != nil { - return nil, err - } - mergo.Merge(clientConfig, serverAuthPartialConfig) - } - - return clientConfig, nil -} - -// getServerIdentificationPartialConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.getServerIdentificationPartialConfig. -// clientauth.Info object contain both user identification and server identification. We want different precedence orders for -// both, so we have to split the objects and merge them separately -// we want this order of precedence for the server identification -// 1. configClusterInfo (the final result of command line flags and merged .kubeconfig files) -// 2. configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority) -// 3. load the ~/.kubernetes_auth file as a default -func getServerIdentificationPartialConfig(configAuthInfo clientcmdAuthInfo, configClusterInfo clientcmdCluster) (*restConfig, error) { - mergedConfig := &restConfig{} - - // configClusterInfo holds the information identify the server provided by .kubeconfig - configClientConfig := &restConfig{} - configClientConfig.CAFile = configClusterInfo.CertificateAuthority - configClientConfig.CAData = configClusterInfo.CertificateAuthorityData - configClientConfig.Insecure = configClusterInfo.InsecureSkipTLSVerify - mergo.Merge(mergedConfig, configClientConfig) - - return mergedConfig, nil -} - -// getUserIdentificationPartialConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.getUserIdentificationPartialConfig. -// clientauth.Info object contain both user identification and server identification. We want different precedence orders for -// both, so we have to split the objects and merge them separately -// we want this order of precedence for user identifcation -// 1. configAuthInfo minus auth-path (the final result of command line flags and merged .kubeconfig files) -// 2. configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority) -// 3. if there is not enough information to idenfity the user, load try the ~/.kubernetes_auth file -// 4. if there is not enough information to identify the user, prompt if possible -func getUserIdentificationPartialConfig(configAuthInfo clientcmdAuthInfo) (*restConfig, error) { - mergedConfig := &restConfig{} - - // blindly overwrite existing values based on precedence - if len(configAuthInfo.Token) > 0 { - mergedConfig.BearerToken = configAuthInfo.Token - } - if len(configAuthInfo.ClientCertificate) > 0 || len(configAuthInfo.ClientCertificateData) > 0 { - mergedConfig.CertFile = configAuthInfo.ClientCertificate - mergedConfig.CertData = configAuthInfo.ClientCertificateData - mergedConfig.KeyFile = configAuthInfo.ClientKey - mergedConfig.KeyData = configAuthInfo.ClientKeyData - } - if len(configAuthInfo.Username) > 0 || len(configAuthInfo.Password) > 0 { - mergedConfig.Username = configAuthInfo.Username - mergedConfig.Password = configAuthInfo.Password - } - - // REMOVED: prompting for missing information. - return mergedConfig, nil -} - -// canIdentifyUser is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.canIdentifyUser -func canIdentifyUser(config restConfig) bool { - return len(config.Username) > 0 || - (len(config.CertFile) > 0 || len(config.CertData) > 0) || - len(config.BearerToken) > 0 - -} - -// ConfirmUsable is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.ConfirmUsable. -// ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config, -// but no errors in the sections requested or referenced. It does not return early so that it can find as many errors as possible. -func (config *directClientConfig) ConfirmUsable() error { - var validationErrors []error - validationErrors = append(validationErrors, validateAuthInfo(config.getAuthInfoName(), config.getAuthInfo())...) - validationErrors = append(validationErrors, validateClusterInfo(config.getClusterName(), config.getCluster())...) - // when direct client config is specified, and our only error is that no server is defined, we should - // return a standard "no config" error - if len(validationErrors) == 1 && validationErrors[0] == errEmptyCluster { - return newErrConfigurationInvalid([]error{errEmptyConfig}) - } - return newErrConfigurationInvalid(validationErrors) -} - -// getContextName is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getContextName. -func (config *directClientConfig) getContextName() string { - // REMOVED: overrides support - return config.config.CurrentContext -} - -// getAuthInfoName is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getAuthInfoName. -func (config *directClientConfig) getAuthInfoName() string { - // REMOVED: overrides support - return config.getContext().AuthInfo -} - -// getClusterName is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getClusterName. -func (config *directClientConfig) getClusterName() string { - // REMOVED: overrides support - return config.getContext().Cluster -} - -// getContext is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getContext. -func (config *directClientConfig) getContext() clientcmdContext { - contexts := config.config.Contexts - contextName := config.getContextName() - - var mergedContext clientcmdContext - if configContext, exists := contexts[contextName]; exists { - mergo.Merge(&mergedContext, configContext) - } - // REMOVED: overrides support - - return mergedContext -} - -var ( - errEmptyConfig = errors.New("no configuration has been provided") - // message is for consistency with old behavior - errEmptyCluster = errors.New("cluster has no server defined") -) - -// validateClusterInfo is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.validateClusterInfo. -// validateClusterInfo looks for conflicts and errors in the cluster info -func validateClusterInfo(clusterName string, clusterInfo clientcmdCluster) []error { - var validationErrors []error - - if reflect.DeepEqual(clientcmdCluster{}, clusterInfo) { - return []error{errEmptyCluster} - } - - if len(clusterInfo.Server) == 0 { - if len(clusterName) == 0 { - validationErrors = append(validationErrors, errors.Errorf("default cluster has no server defined")) - } else { - validationErrors = append(validationErrors, errors.Errorf("no server found for cluster %q", clusterName)) - } - } - // Make sure CA data and CA file aren't both specified - if len(clusterInfo.CertificateAuthority) != 0 && len(clusterInfo.CertificateAuthorityData) != 0 { - validationErrors = append(validationErrors, errors.Errorf("certificate-authority-data and certificate-authority are both specified for %v. certificate-authority-data will override", clusterName)) - } - if len(clusterInfo.CertificateAuthority) != 0 { - clientCertCA, err := os.Open(clusterInfo.CertificateAuthority) - defer clientCertCA.Close() - if err != nil { - validationErrors = append(validationErrors, errors.Errorf("unable to read certificate-authority %v for %v due to %v", clusterInfo.CertificateAuthority, clusterName, err)) - } - } - - return validationErrors -} - -// validateAuthInfo is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.validateAuthInfo. -// validateAuthInfo looks for conflicts and errors in the auth info -func validateAuthInfo(authInfoName string, authInfo clientcmdAuthInfo) []error { - var validationErrors []error - - usingAuthPath := false - methods := make([]string, 0, 3) - if len(authInfo.Token) != 0 { - methods = append(methods, "token") - } - if len(authInfo.Username) != 0 || len(authInfo.Password) != 0 { - methods = append(methods, "basicAuth") - } - - if len(authInfo.ClientCertificate) != 0 || len(authInfo.ClientCertificateData) != 0 { - // Make sure cert data and file aren't both specified - if len(authInfo.ClientCertificate) != 0 && len(authInfo.ClientCertificateData) != 0 { - validationErrors = append(validationErrors, errors.Errorf("client-cert-data and client-cert are both specified for %v. client-cert-data will override", authInfoName)) - } - // Make sure key data and file aren't both specified - if len(authInfo.ClientKey) != 0 && len(authInfo.ClientKeyData) != 0 { - validationErrors = append(validationErrors, errors.Errorf("client-key-data and client-key are both specified for %v; client-key-data will override", authInfoName)) - } - // Make sure a key is specified - if len(authInfo.ClientKey) == 0 && len(authInfo.ClientKeyData) == 0 { - validationErrors = append(validationErrors, errors.Errorf("client-key-data or client-key must be specified for %v to use the clientCert authentication method", authInfoName)) - } - - if len(authInfo.ClientCertificate) != 0 { - clientCertFile, err := os.Open(authInfo.ClientCertificate) - defer clientCertFile.Close() - if err != nil { - validationErrors = append(validationErrors, errors.Errorf("unable to read client-cert %v for %v due to %v", authInfo.ClientCertificate, authInfoName, err)) - } - } - if len(authInfo.ClientKey) != 0 { - clientKeyFile, err := os.Open(authInfo.ClientKey) - defer clientKeyFile.Close() - if err != nil { - validationErrors = append(validationErrors, errors.Errorf("unable to read client-key %v for %v due to %v", authInfo.ClientKey, authInfoName, err)) - } - } - } - - // authPath also provides information for the client to identify the server, so allow multiple auth methods in that case - if (len(methods) > 1) && (!usingAuthPath) { - validationErrors = append(validationErrors, errors.Errorf("more than one authentication method found for %v; found %v, only one is allowed", authInfoName, methods)) - } - - return validationErrors -} - -// getAuthInfo is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getAuthInfo. -func (config *directClientConfig) getAuthInfo() clientcmdAuthInfo { - authInfos := config.config.AuthInfos - authInfoName := config.getAuthInfoName() - - var mergedAuthInfo clientcmdAuthInfo - if configAuthInfo, exists := authInfos[authInfoName]; exists { - mergo.Merge(&mergedAuthInfo, configAuthInfo) - } - // REMOVED: overrides support - - return mergedAuthInfo -} - -// getCluster is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.DirectClientConfig.getCluster. -func (config *directClientConfig) getCluster() clientcmdCluster { - clusterInfos := config.config.Clusters - clusterInfoName := config.getClusterName() - - var mergedClusterInfo clientcmdCluster - mergo.Merge(&mergedClusterInfo, defaultCluster) - mergo.Merge(&mergedClusterInfo, envVarCluster) - if configClusterInfo, exists := clusterInfos[clusterInfoName]; exists { - mergo.Merge(&mergedClusterInfo, configClusterInfo) - } - // REMOVED: overrides support - - return mergedClusterInfo -} - -// aggregateErr is a modified copy of k8s.io/apimachinery/pkg/util/errors.aggregate. -// This helper implements the error and Errors interfaces. Keeping it private -// prevents people from making an aggregate of 0 errors, which is not -// an error, but does satisfy the error interface. -type aggregateErr []error - -// newAggregate is a modified copy of k8s.io/apimachinery/pkg/util/errors.NewAggregate. -// NewAggregate converts a slice of errors into an Aggregate interface, which -// is itself an implementation of the error interface. If the slice is empty, -// this returns nil. -// It will check if any of the element of input error list is nil, to avoid -// nil pointer panic when call Error(). -func newAggregate(errlist []error) error { - if len(errlist) == 0 { - return nil - } - // In case of input error list contains nil - var errs []error - for _, e := range errlist { - if e != nil { - errs = append(errs, e) - } - } - if len(errs) == 0 { - return nil - } - return aggregateErr(errs) -} - -// Error is a modified copy of k8s.io/apimachinery/pkg/util/errors.aggregate.Error. -// Error is part of the error interface. -func (agg aggregateErr) Error() string { - if len(agg) == 0 { - // This should never happen, really. - return "" - } - if len(agg) == 1 { - return agg[0].Error() - } - result := fmt.Sprintf("[%s", agg[0].Error()) - for i := 1; i < len(agg); i++ { - result += fmt.Sprintf(", %s", agg[i].Error()) - } - result += "]" - return result -} - -// REMOVED: aggregateErr.Errors - -// errConfigurationInvalid is a modified? copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.errConfigurationInvalid. -// errConfigurationInvalid is a set of errors indicating the configuration is invalid. -type errConfigurationInvalid []error - -var _ error = errConfigurationInvalid{} - -// REMOVED: utilerrors.Aggregate implementation for errConfigurationInvalid. - -// newErrConfigurationInvalid is a modified? copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.newErrConfigurationInvalid. -func newErrConfigurationInvalid(errs []error) error { - switch len(errs) { - case 0: - return nil - default: - return errConfigurationInvalid(errs) - } -} - -// Error implements the error interface -func (e errConfigurationInvalid) Error() string { - return fmt.Sprintf("invalid configuration: %v", newAggregate(e).Error()) -} - -// clientConfigLoadingRules is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules -// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config -// Callers can put the chain together however they want, but we'd recommend: -// EnvVarPathFiles if set (a list of files if set) OR the HomeDirectoryPath -// ExplicitPath is special, because if a user specifically requests a certain file be used and error is reported if thie file is not present -type clientConfigLoadingRules struct { - Precedence []string -} - -// Load is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules.Load -// Load starts by running the MigrationRules and then -// takes the loading rules and returns a Config object based on following rules. -// if the ExplicitPath, return the unmerged explicit file -// Otherwise, return a merged config based on the Precedence slice -// A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored. -// Read errors or files with non-deserializable content produce errors. -// The first file to set a particular map key wins and map key's value is never changed. -// BUT, if you set a struct value that is NOT contained inside of map, the value WILL be changed. -// This results in some odd looking logic to merge in one direction, merge in the other, and then merge the two. -// It also means that if two files specify a "red-user", only values from the first file's red-user are used. Even -// non-conflicting entries from the second file's "red-user" are discarded. -// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder -// and only absolute file paths are returned. -func (rules *clientConfigLoadingRules) Load() (*clientcmdConfig, error) { - errlist := []error{} - - kubeConfigFiles := []string{} - - // REMOVED: explicit path support - kubeConfigFiles = append(kubeConfigFiles, rules.Precedence...) - - kubeconfigs := []*clientcmdConfig{} - // read and cache the config files so that we only look at them once - for _, filename := range kubeConfigFiles { - if len(filename) == 0 { - // no work to do - continue - } - - config, err := loadFromFile(filename) - if os.IsNotExist(err) { - // skip missing files - continue - } - if err != nil { - errlist = append(errlist, errors.Wrapf(err, "Error loading config file \"%s\"", filename)) - continue - } - - kubeconfigs = append(kubeconfigs, config) - } - - // first merge all of our maps - mapConfig := clientcmdNewConfig() - for _, kubeconfig := range kubeconfigs { - mergo.Merge(mapConfig, kubeconfig) - } - - // merge all of the struct values in the reverse order so that priority is given correctly - // errors are not added to the list the second time - nonMapConfig := clientcmdNewConfig() - for i := len(kubeconfigs) - 1; i >= 0; i-- { - kubeconfig := kubeconfigs[i] - mergo.Merge(nonMapConfig, kubeconfig) - } - - // since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and - // get the values we expect. - config := clientcmdNewConfig() - mergo.Merge(config, mapConfig) - mergo.Merge(config, nonMapConfig) - - // REMOVED: Possibility to skip this. - if err := resolveLocalPaths(config); err != nil { - errlist = append(errlist, err) - } - - return config, newAggregate(errlist) -} - -// loadFromFile is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.LoadFromFile -// LoadFromFile takes a filename and deserializes the contents into Config object -func loadFromFile(filename string) (*clientcmdConfig, error) { - kubeconfigBytes, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - config, err := load(kubeconfigBytes) - if err != nil { - return nil, err - } - - // set LocationOfOrigin on every Cluster, User, and Context - for key, obj := range config.AuthInfos { - obj.LocationOfOrigin = filename - config.AuthInfos[key] = obj - } - for key, obj := range config.Clusters { - obj.LocationOfOrigin = filename - config.Clusters[key] = obj - } - for key, obj := range config.Contexts { - obj.LocationOfOrigin = filename - config.Contexts[key] = obj - } - - if config.AuthInfos == nil { - config.AuthInfos = map[string]*clientcmdAuthInfo{} - } - if config.Clusters == nil { - config.Clusters = map[string]*clientcmdCluster{} - } - if config.Contexts == nil { - config.Contexts = map[string]*clientcmdContext{} - } - - return config, nil -} - -// load is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.Load -// Load takes a byte slice and deserializes the contents into Config object. -// Encapsulates deserialization without assuming the source is a file. -func load(data []byte) (*clientcmdConfig, error) { - config := clientcmdNewConfig() - // if there's no data in a file, return the default object instead of failing (DecodeInto reject empty input) - if len(data) == 0 { - return config, nil - } - // Note: This does absolutely no kind/version checking or conversions. - data, err := yaml.YAMLToJSON(data) - if err != nil { - return nil, err - } - if err := json.Unmarshal(data, config); err != nil { - return nil, err - } - return config, nil -} - -// resolveLocalPaths is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules.resolveLocalPaths. -// ResolveLocalPaths resolves all relative paths in the config object with respect to the stanza's LocationOfOrigin -// this cannot be done directly inside of LoadFromFile because doing so there would make it impossible to load a file without -// modification of its contents. -func resolveLocalPaths(config *clientcmdConfig) error { - for _, cluster := range config.Clusters { - if len(cluster.LocationOfOrigin) == 0 { - continue - } - base, err := filepath.Abs(filepath.Dir(cluster.LocationOfOrigin)) - if err != nil { - return errors.Wrapf(err, "Could not determine the absolute path of config file %s", cluster.LocationOfOrigin) - } - - if err := resolvePaths(getClusterFileReferences(cluster), base); err != nil { - return err - } - } - for _, authInfo := range config.AuthInfos { - if len(authInfo.LocationOfOrigin) == 0 { - continue - } - base, err := filepath.Abs(filepath.Dir(authInfo.LocationOfOrigin)) - if err != nil { - return errors.Wrapf(err, "Could not determine the absolute path of config file %s", authInfo.LocationOfOrigin) - } - - if err := resolvePaths(getAuthInfoFileReferences(authInfo), base); err != nil { - return err - } - } - - return nil -} - -// getClusterFileReferences is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules.GetClusterFileReferences. -func getClusterFileReferences(cluster *clientcmdCluster) []*string { - return []*string{&cluster.CertificateAuthority} -} - -// getAuthInfoFileReferences is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules.GetAuthInfoFileReferences. -func getAuthInfoFileReferences(authInfo *clientcmdAuthInfo) []*string { - return []*string{&authInfo.ClientCertificate, &authInfo.ClientKey} -} - -// resolvePaths is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd.ClientConfigLoadingRules.resolvePaths. -// ResolvePaths updates the given refs to be absolute paths, relative to the given base directory -func resolvePaths(refs []*string, base string) error { - for _, ref := range refs { - // Don't resolve empty paths - if len(*ref) > 0 { - // Don't resolve absolute paths - if !filepath.IsAbs(*ref) { - *ref = filepath.Join(base, *ref) - } - } - } - return nil -} - -// restClientFor is a modified copy of k8s.io/kubernets/pkg/client/restclient.RESTClientFor. -// RESTClientFor returns a RESTClient that satisfies the requested attributes on a client Config -// object. Note that a RESTClient may require fields that are optional when initializing a Client. -// A RESTClient created by this method is generic - it expects to operate on an API that follows -// the Kubernetes conventions, but may not be the Kubernetes API. -func restClientFor(config *restConfig) (*url.URL, *http.Client, error) { - // REMOVED: Configurable GroupVersion, Codec - // REMOVED: Configurable versionedAPIPath - baseURL, err := defaultServerURLFor(config) - if err != nil { - return nil, nil, err - } - - transport, err := transportFor(config) - if err != nil { - return nil, nil, err - } - - var httpClient *http.Client - if transport != http.DefaultTransport { - httpClient = &http.Client{Transport: transport} - } - - // REMOVED: Configurable QPS, Burst, ContentConfig - // REMOVED: Actually returning a RESTClient object. - return baseURL, httpClient, nil -} - -// defaultServerURL is a modified copy of k8s.io/kubernets/pkg/client/restclient.DefaultServerURL. -// DefaultServerURL converts a host, host:port, or URL string to the default base server API path -// to use with a Client at a given API version following the standard conventions for a -// Kubernetes API. -func defaultServerURL(host string, defaultTLS bool) (*url.URL, error) { - if host == "" { - return nil, errors.Errorf("host must be a URL or a host:port pair") - } - base := host - hostURL, err := url.Parse(base) - if err != nil { - return nil, err - } - if hostURL.Scheme == "" { - scheme := "http://" - if defaultTLS { - scheme = "https://" - } - hostURL, err = url.Parse(scheme + base) - if err != nil { - return nil, err - } - if hostURL.Path != "" && hostURL.Path != "/" { - return nil, errors.Errorf("host must be a URL or a host:port pair: %q", base) - } - } - - // REMOVED: versionedAPIPath computation. - return hostURL, nil -} - -// defaultServerURLFor is a modified copy of k8s.io/kubernets/pkg/client/restclient.defaultServerURLFor. -// defaultServerUrlFor is shared between IsConfigTransportTLS and RESTClientFor. It -// requires Host and Version to be set prior to being called. -func defaultServerURLFor(config *restConfig) (*url.URL, error) { - // TODO: move the default to secure when the apiserver supports TLS by default - // config.Insecure is taken to mean "I want HTTPS but don't bother checking the certs against a CA." - hasCA := len(config.CAFile) != 0 || len(config.CAData) != 0 - hasCert := len(config.CertFile) != 0 || len(config.CertData) != 0 - defaultTLS := hasCA || hasCert || config.Insecure - host := config.Host - if host == "" { - host = "localhost" - } - - // REMOVED: Configurable APIPath, GroupVersion - return defaultServerURL(host, defaultTLS) -} - -// transportFor is a modified copy of k8s.io/kubernets/pkg/client/restclient.transportFor. -// TransportFor returns an http.RoundTripper that will provide the authentication -// or transport level security defined by the provided Config. Will return the -// default http.DefaultTransport if no special case behavior is needed. -func transportFor(config *restConfig) (http.RoundTripper, error) { - // REMOVED: separation between restclient.Config and transport.Config, Transport, WrapTransport support - return transportNew(config) -} - -// isConfigTransportTLS is a modified copy of k8s.io/kubernets/pkg/client/restclient.IsConfigTransportTLS. -// IsConfigTransportTLS returns true if and only if the provided -// config will result in a protected connection to the server when it -// is passed to restclient.RESTClientFor(). Use to determine when to -// send credentials over the wire. -// -// Note: the Insecure flag is ignored when testing for this value, so MITM attacks are -// still possible. -func isConfigTransportTLS(config restConfig) bool { - baseURL, err := defaultServerURLFor(&config) - if err != nil { - return false - } - return baseURL.Scheme == "https" -} - -// transportNew is a modified copy of k8s.io/kubernetes/pkg/client/transport.New. -// New returns an http.RoundTripper that will provide the authentication -// or transport level security defined by the provided Config. -func transportNew(config *restConfig) (http.RoundTripper, error) { - // REMOVED: custom config.Transport support. - // Set transport level security - - var ( - rt http.RoundTripper - err error - ) - - rt, err = tlsCacheGet(config) - if err != nil { - return nil, err - } - - // REMOVED: HTTPWrappersForConfig(config, rt) in favor of the caller setting HTTP headers itself based on restConfig. Only this inlined check remains. - if len(config.Username) != 0 && len(config.BearerToken) != 0 { - return nil, errors.Errorf("username/password or bearer token may be set, but not both") - } - - return rt, nil -} - -// newProxierWithNoProxyCIDR is a modified copy of k8s.io/apimachinery/pkg/util/net.NewProxierWithNoProxyCIDR. -// NewProxierWithNoProxyCIDR constructs a Proxier function that respects CIDRs in NO_PROXY and delegates if -// no matching CIDRs are found -func newProxierWithNoProxyCIDR(delegate func(req *http.Request) (*url.URL, error)) func(req *http.Request) (*url.URL, error) { - // we wrap the default method, so we only need to perform our check if the NO_PROXY envvar has a CIDR in it - noProxyEnv := os.Getenv("NO_PROXY") - noProxyRules := strings.Split(noProxyEnv, ",") - - cidrs := []*net.IPNet{} - for _, noProxyRule := range noProxyRules { - _, cidr, _ := net.ParseCIDR(noProxyRule) - if cidr != nil { - cidrs = append(cidrs, cidr) - } - } - - if len(cidrs) == 0 { - return delegate - } - - return func(req *http.Request) (*url.URL, error) { - host := req.URL.Host - // for some urls, the Host is already the host, not the host:port - if net.ParseIP(host) == nil { - var err error - host, _, err = net.SplitHostPort(req.URL.Host) - if err != nil { - return delegate(req) - } - } - - ip := net.ParseIP(host) - if ip == nil { - return delegate(req) - } - - for _, cidr := range cidrs { - if cidr.Contains(ip) { - return nil, nil - } - } - - return delegate(req) - } -} - -// tlsCacheGet is a modified copy of k8s.io/kubernetes/pkg/client/transport.tlsTransportCache.get. -func tlsCacheGet(config *restConfig) (http.RoundTripper, error) { - // REMOVED: any actual caching - - // Get the TLS options for this client config - tlsConfig, err := tlsConfigFor(config) - if err != nil { - return nil, err - } - // The options didn't require a custom TLS config - if tlsConfig == nil { - return http.DefaultTransport, nil - } - - // REMOVED: Call to k8s.io/apimachinery/pkg/util/net.SetTransportDefaults; instead of the generic machinery and conditionals, hard-coded the result here. - t := &http.Transport{ - // http.ProxyFromEnvironment doesn't respect CIDRs and that makes it impossible to exclude things like pod and service IPs from proxy settings - // ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY - Proxy: newProxierWithNoProxyCIDR(http.ProxyFromEnvironment), - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - } - // Allow clients to disable http2 if needed. - if s := os.Getenv("DISABLE_HTTP2"); len(s) == 0 { - _ = http2.ConfigureTransport(t) - } - return t, nil -} - -// tlsConfigFor is a modified copy of k8s.io/kubernetes/pkg/client/transport.TLSConfigFor. -// TLSConfigFor returns a tls.Config that will provide the transport level security defined -// by the provided Config. Will return nil if no transport level security is requested. -func tlsConfigFor(c *restConfig) (*tls.Config, error) { - if !(c.HasCA() || c.HasCertAuth() || c.Insecure) { - return nil, nil - } - if c.HasCA() && c.Insecure { - return nil, errors.Errorf("specifying a root certificates file with the insecure flag is not allowed") - } - if err := loadTLSFiles(c); err != nil { - return nil, err - } - - tlsConfig := &tls.Config{ - // Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability) - MinVersion: tls.VersionTLS10, - InsecureSkipVerify: c.Insecure, - } - - if c.HasCA() { - tlsConfig.RootCAs = rootCertPool(c.CAData) - } - - if c.HasCertAuth() { - cert, err := tls.X509KeyPair(c.CertData, c.KeyData) - if err != nil { - return nil, err - } - tlsConfig.Certificates = []tls.Certificate{cert} - } - - return tlsConfig, nil -} - -// loadTLSFiles is a modified copy of k8s.io/kubernetes/pkg/client/transport.loadTLSFiles. -// loadTLSFiles copies the data from the CertFile, KeyFile, and CAFile fields into the CertData, -// KeyData, and CAFile fields, or returns an error. If no error is returned, all three fields are -// either populated or were empty to start. -func loadTLSFiles(c *restConfig) error { - var err error - c.CAData, err = dataFromSliceOrFile(c.CAData, c.CAFile) - if err != nil { - return err - } - - c.CertData, err = dataFromSliceOrFile(c.CertData, c.CertFile) - if err != nil { - return err - } - - c.KeyData, err = dataFromSliceOrFile(c.KeyData, c.KeyFile) - if err != nil { - return err - } - return nil -} - -// dataFromSliceOrFile is a modified copy of k8s.io/kubernetes/pkg/client/transport.dataFromSliceOrFile. -// dataFromSliceOrFile returns data from the slice (if non-empty), or from the file, -// or an error if an error occurred reading the file -func dataFromSliceOrFile(data []byte, file string) ([]byte, error) { - if len(data) > 0 { - return data, nil - } - if len(file) > 0 { - fileData, err := ioutil.ReadFile(file) - if err != nil { - return []byte{}, err - } - return fileData, nil - } - return nil, nil -} - -// rootCertPool is a modified copy of k8s.io/kubernetes/pkg/client/transport.rootCertPool. -// rootCertPool returns nil if caData is empty. When passed along, this will mean "use system CAs". -// When caData is not empty, it will be the ONLY information used in the CertPool. -func rootCertPool(caData []byte) *x509.CertPool { - // What we really want is a copy of x509.systemRootsPool, but that isn't exposed. It's difficult to build (see the go - // code for a look at the platform specific insanity), so we'll use the fact that RootCAs == nil gives us the system values - // It doesn't allow trusting either/or, but hopefully that won't be an issue - if len(caData) == 0 { - return nil - } - - // if we have caData, use it - certPool := x509.NewCertPool() - certPool.AppendCertsFromPEM(caData) - return certPool -} - -// HasCA is a modified copy of k8s.io/kubernetes/pkg/client/transport.Config.HasCA. -// HasCA returns whether the configuration has a certificate authority or not. -func (c *restConfig) HasCA() bool { - return len(c.CAData) > 0 || len(c.CAFile) > 0 -} - -// HasCertAuth is a modified copy of k8s.io/kubernetes/pkg/client/transport.Config.HasCertAuth. -// HasCertAuth returns whether the configuration has certificate authentication or not. -func (c *restConfig) HasCertAuth() bool { - return len(c.CertData) != 0 || len(c.CertFile) != 0 -} - -// clientcmdConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.Config. -// Config holds the information needed to build connect to remote kubernetes clusters as a given user -// IMPORTANT if you add fields to this struct, please update IsConfigEmpty() -type clientcmdConfig struct { - // Clusters is a map of referencable names to cluster configs - Clusters clustersMap `json:"clusters"` - // AuthInfos is a map of referencable names to user configs - AuthInfos authInfosMap `json:"users"` - // Contexts is a map of referencable names to context configs - Contexts contextsMap `json:"contexts"` - // CurrentContext is the name of the context that you would like to use by default - CurrentContext string `json:"current-context"` -} - -type clustersMap map[string]*clientcmdCluster - -func (m *clustersMap) UnmarshalJSON(data []byte) error { - var a []v1NamedCluster - if err := json.Unmarshal(data, &a); err != nil { - return err - } - for _, e := range a { - cluster := e.Cluster // Allocates a new instance in each iteration - (*m)[e.Name] = &cluster - } - return nil -} - -type authInfosMap map[string]*clientcmdAuthInfo - -func (m *authInfosMap) UnmarshalJSON(data []byte) error { - var a []v1NamedAuthInfo - if err := json.Unmarshal(data, &a); err != nil { - return err - } - for _, e := range a { - authInfo := e.AuthInfo // Allocates a new instance in each iteration - (*m)[e.Name] = &authInfo - } - return nil -} - -type contextsMap map[string]*clientcmdContext - -func (m *contextsMap) UnmarshalJSON(data []byte) error { - var a []v1NamedContext - if err := json.Unmarshal(data, &a); err != nil { - return err - } - for _, e := range a { - context := e.Context // Allocates a new instance in each iteration - (*m)[e.Name] = &context - } - return nil -} - -// clientcmdNewConfig is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.NewConfig. -// NewConfig is a convenience function that returns a new Config object with non-nil maps -func clientcmdNewConfig() *clientcmdConfig { - return &clientcmdConfig{ - Clusters: make(map[string]*clientcmdCluster), - AuthInfos: make(map[string]*clientcmdAuthInfo), - Contexts: make(map[string]*clientcmdContext), - } -} - -// clientcmdCluster is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.Cluster. -// Cluster contains information about how to communicate with a kubernetes cluster -type clientcmdCluster struct { - // LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized. - LocationOfOrigin string - // Server is the address of the kubernetes cluster (https://hostname:port). - Server string `json:"server"` - // InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure. - InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"` - // CertificateAuthority is the path to a cert file for the certificate authority. - CertificateAuthority string `json:"certificate-authority,omitempty"` - // CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority - CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"` -} - -// clientcmdAuthInfo is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.AuthInfo. -// AuthInfo contains information that describes identity information. This is use to tell the kubernetes cluster who you are. -type clientcmdAuthInfo struct { - // LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized. - LocationOfOrigin string - // ClientCertificate is the path to a client cert file for TLS. - ClientCertificate string `json:"client-certificate,omitempty"` - // ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate - ClientCertificateData []byte `json:"client-certificate-data,omitempty"` - // ClientKey is the path to a client key file for TLS. - ClientKey string `json:"client-key,omitempty"` - // ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey - ClientKeyData []byte `json:"client-key-data,omitempty"` - // Token is the bearer token for authentication to the kubernetes cluster. - Token string `json:"token,omitempty"` - // Username is the username for basic authentication to the kubernetes cluster. - Username string `json:"username,omitempty"` - // Password is the password for basic authentication to the kubernetes cluster. - Password string `json:"password,omitempty"` -} - -// clientcmdContext is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.Context. -// Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) -type clientcmdContext struct { - // LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized. - LocationOfOrigin string - // Cluster is the name of the cluster for this context - Cluster string `json:"cluster"` - // AuthInfo is the name of the authInfo for this context - AuthInfo string `json:"user"` - // Namespace is the default namespace to use on unspecified requests - Namespace string `json:"namespace,omitempty"` -} - -// v1NamedCluster is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.v1.NamedCluster. -// NamedCluster relates nicknames to cluster information -type v1NamedCluster struct { - // Name is the nickname for this Cluster - Name string `json:"name"` - // Cluster holds the cluster information - Cluster clientcmdCluster `json:"cluster"` -} - -// v1NamedContext is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.v1.NamedContext. -// NamedContext relates nicknames to context information -type v1NamedContext struct { - // Name is the nickname for this Context - Name string `json:"name"` - // Context holds the context information - Context clientcmdContext `json:"context"` -} - -// v1NamedAuthInfo is a modified copy of k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api.v1.NamedAuthInfo. -// NamedAuthInfo relates nicknames to auth information -type v1NamedAuthInfo struct { - // Name is the nickname for this AuthInfo - Name string `json:"name"` - // AuthInfo holds the auth information - AuthInfo clientcmdAuthInfo `json:"user"` -} diff --git a/vendor/github.com/containers/image/openshift/openshift.go b/vendor/github.com/containers/image/openshift/openshift.go deleted file mode 100644 index 5465591444..0000000000 --- a/vendor/github.com/containers/image/openshift/openshift.go +++ /dev/null @@ -1,544 +0,0 @@ -package openshift - -import ( - "bytes" - "context" - "crypto/rand" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" - - "github.com/containers/image/docker" - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/containers/image/version" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// openshiftClient is configuration for dealing with a single image stream, for reading or writing. -type openshiftClient struct { - ref openshiftReference - baseURL *url.URL - // Values from Kubernetes configuration - httpClient *http.Client - bearerToken string // "" if not used - username string // "" if not used - password string // if username != "" -} - -// newOpenshiftClient creates a new openshiftClient for the specified reference. -func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) { - // We have already done this parsing in ParseReference, but thrown away - // httpClient. So, parse again. - // (We could also rework/split restClientFor to "get base URL" to be done - // in ParseReference, and "get httpClient" to be done here. But until/unless - // we support non-default clusters, this is good enough.) - - // Overall, this is modelled on openshift/origin/pkg/cmd/util/clientcmd.New().ClientConfig() and openshift/origin/pkg/client. - cmdConfig := defaultClientConfig() - logrus.Debugf("cmdConfig: %#v", cmdConfig) - restConfig, err := cmdConfig.ClientConfig() - if err != nil { - return nil, err - } - // REMOVED: SetOpenShiftDefaults (values are not overridable in config files, so hard-coded these defaults.) - logrus.Debugf("restConfig: %#v", restConfig) - baseURL, httpClient, err := restClientFor(restConfig) - if err != nil { - return nil, err - } - logrus.Debugf("URL: %#v", *baseURL) - - if httpClient == nil { - httpClient = http.DefaultClient - } - - return &openshiftClient{ - ref: ref, - baseURL: baseURL, - httpClient: httpClient, - bearerToken: restConfig.BearerToken, - username: restConfig.Username, - password: restConfig.Password, - }, nil -} - -// doRequest performs a correctly authenticated request to a specified path, and returns response body or an error object. -func (c *openshiftClient) doRequest(ctx context.Context, method, path string, requestBody []byte) ([]byte, error) { - url := *c.baseURL - url.Path = path - var requestBodyReader io.Reader - if requestBody != nil { - logrus.Debugf("Will send body: %s", requestBody) - requestBodyReader = bytes.NewReader(requestBody) - } - req, err := http.NewRequest(method, url.String(), requestBodyReader) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - - if len(c.bearerToken) != 0 { - req.Header.Set("Authorization", "Bearer "+c.bearerToken) - } else if len(c.username) != 0 { - req.SetBasicAuth(c.username, c.password) - } - req.Header.Set("Accept", "application/json, */*") - req.Header.Set("User-Agent", fmt.Sprintf("skopeo/%s", version.Version)) - if requestBody != nil { - req.Header.Set("Content-Type", "application/json") - } - - logrus.Debugf("%s %s", method, url) - res, err := c.httpClient.Do(req) - if err != nil { - return nil, err - } - defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - logrus.Debugf("Got body: %s", body) - // FIXME: Just throwing this useful information away only to try to guess later... - logrus.Debugf("Got content-type: %s", res.Header.Get("Content-Type")) - - var status status - statusValid := false - if err := json.Unmarshal(body, &status); err == nil && len(status.Status) > 0 { - statusValid = true - } - - switch { - case res.StatusCode == http.StatusSwitchingProtocols: // FIXME?! No idea why this weird case exists in k8s.io/kubernetes/pkg/client/restclient. - if statusValid && status.Status != "Success" { - return nil, errors.New(status.Message) - } - case res.StatusCode >= http.StatusOK && res.StatusCode <= http.StatusPartialContent: - // OK. - default: - if statusValid { - return nil, errors.New(status.Message) - } - return nil, errors.Errorf("HTTP error: status code: %d, body: %s", res.StatusCode, string(body)) - } - - return body, nil -} - -// getImage loads the specified image object. -func (c *openshiftClient) getImage(ctx context.Context, imageStreamImageName string) (*image, error) { - // FIXME: validate components per validation.IsValidPathSegmentName? - path := fmt.Sprintf("/oapi/v1/namespaces/%s/imagestreamimages/%s@%s", c.ref.namespace, c.ref.stream, imageStreamImageName) - body, err := c.doRequest(ctx, "GET", path, nil) - if err != nil { - return nil, err - } - // Note: This does absolutely no kind/version checking or conversions. - var isi imageStreamImage - if err := json.Unmarshal(body, &isi); err != nil { - return nil, err - } - return &isi.Image, nil -} - -// convertDockerImageReference takes an image API DockerImageReference value and returns a reference we can actually use; -// currently OpenShift stores the cluster-internal service IPs here, which are unusable from the outside. -func (c *openshiftClient) convertDockerImageReference(ref string) (string, error) { - parts := strings.SplitN(ref, "/", 2) - if len(parts) != 2 { - return "", errors.Errorf("Invalid format of docker reference %s: missing '/'", ref) - } - return reference.Domain(c.ref.dockerReference) + "/" + parts[1], nil -} - -type openshiftImageSource struct { - client *openshiftClient - // Values specific to this image - ctx *types.SystemContext - // State - docker types.ImageSource // The Docker Registry endpoint, or nil if not resolved yet - imageStreamImageName string // Resolved image identifier, or "" if not known yet -} - -// newImageSource creates a new ImageSource for the specified reference. -// The caller must call .Close() on the returned ImageSource. -func newImageSource(ctx *types.SystemContext, ref openshiftReference) (types.ImageSource, error) { - client, err := newOpenshiftClient(ref) - if err != nil { - return nil, err - } - - return &openshiftImageSource{ - client: client, - ctx: ctx, - }, nil -} - -// Reference returns the reference used to set up this source, _as specified by the user_ -// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. -func (s *openshiftImageSource) Reference() types.ImageReference { - return s.client.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *openshiftImageSource) Close() error { - if s.docker != nil { - err := s.docker.Close() - s.docker = nil - - return err - } - - return nil -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (s *openshiftImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if err := s.ensureImageIsResolved(context.TODO()); err != nil { - return nil, "", err - } - return s.docker.GetManifest(instanceDigest) -} - -// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). -func (s *openshiftImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - if err := s.ensureImageIsResolved(context.TODO()); err != nil { - return nil, 0, err - } - return s.docker.GetBlob(info) -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (s *openshiftImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - var imageName string - if instanceDigest == nil { - if err := s.ensureImageIsResolved(ctx); err != nil { - return nil, err - } - imageName = s.imageStreamImageName - } else { - imageName = instanceDigest.String() - } - image, err := s.client.getImage(ctx, imageName) - if err != nil { - return nil, err - } - var sigs [][]byte - for _, sig := range image.Signatures { - if sig.Type == imageSignatureTypeAtomic { - sigs = append(sigs, sig.Content) - } - } - return sigs, nil -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *openshiftImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} - -// ensureImageIsResolved sets up s.docker and s.imageStreamImageName -func (s *openshiftImageSource) ensureImageIsResolved(ctx context.Context) error { - if s.docker != nil { - return nil - } - - // FIXME: validate components per validation.IsValidPathSegmentName? - path := fmt.Sprintf("/oapi/v1/namespaces/%s/imagestreams/%s", s.client.ref.namespace, s.client.ref.stream) - body, err := s.client.doRequest(ctx, "GET", path, nil) - if err != nil { - return err - } - // Note: This does absolutely no kind/version checking or conversions. - var is imageStream - if err := json.Unmarshal(body, &is); err != nil { - return err - } - var te *tagEvent - for _, tag := range is.Status.Tags { - if tag.Tag != s.client.ref.dockerReference.Tag() { - continue - } - if len(tag.Items) > 0 { - te = &tag.Items[0] - break - } - } - if te == nil { - return errors.Errorf("No matching tag found") - } - logrus.Debugf("tag event %#v", te) - dockerRefString, err := s.client.convertDockerImageReference(te.DockerImageReference) - if err != nil { - return err - } - logrus.Debugf("Resolved reference %#v", dockerRefString) - dockerRef, err := docker.ParseReference("//" + dockerRefString) - if err != nil { - return err - } - d, err := dockerRef.NewImageSource(s.ctx) - if err != nil { - return err - } - s.docker = d - s.imageStreamImageName = te.Image - return nil -} - -type openshiftImageDestination struct { - client *openshiftClient - docker types.ImageDestination // The Docker Registry endpoint - // State - imageStreamImageName string // "" if not yet known -} - -// newImageDestination creates a new ImageDestination for the specified reference. -func newImageDestination(ctx *types.SystemContext, ref openshiftReference) (types.ImageDestination, error) { - client, err := newOpenshiftClient(ref) - if err != nil { - return nil, err - } - - // FIXME: Should this always use a digest, not a tag? Uploading to Docker by tag requires the tag _inside_ the manifest to match, - // i.e. a single signed image cannot be available under multiple tags. But with types.ImageDestination, we don't know - // the manifest digest at this point. - dockerRefString := fmt.Sprintf("//%s/%s/%s:%s", reference.Domain(client.ref.dockerReference), client.ref.namespace, client.ref.stream, client.ref.dockerReference.Tag()) - dockerRef, err := docker.ParseReference(dockerRefString) - if err != nil { - return nil, err - } - docker, err := dockerRef.NewImageDestination(ctx) - if err != nil { - return nil, err - } - - return &openshiftImageDestination{ - client: client, - docker: docker, - }, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *openshiftImageDestination) Reference() types.ImageReference { - return d.client.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *openshiftImageDestination) Close() error { - return d.docker.Close() -} - -func (d *openshiftImageDestination) SupportedManifestMIMETypes() []string { - return d.docker.SupportedManifestMIMETypes() -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *openshiftImageDestination) SupportsSignatures() error { - return nil -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *openshiftImageDestination) ShouldCompressLayers() bool { - return true -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *openshiftImageDestination) AcceptsForeignLayerURLs() bool { - return true -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *openshiftImageDestination) MustMatchRuntimeOS() bool { - return false -} - -// PutBlob writes contents of stream and returns data representing the result (with all data filled in). -// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. -// inputInfo.Size is the expected length of stream, if known. -// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available -// to any other readers for download using the supplied digest. -// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. -func (d *openshiftImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - return d.docker.PutBlob(stream, inputInfo) -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob. -// Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. -// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); -// it returns a non-nil error only on an unexpected failure. -func (d *openshiftImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - return d.docker.HasBlob(info) -} - -func (d *openshiftImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return d.docker.ReapplyBlob(info) -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *openshiftImageDestination) PutManifest(m []byte) error { - manifestDigest, err := manifest.Digest(m) - if err != nil { - return err - } - d.imageStreamImageName = manifestDigest.String() - - return d.docker.PutManifest(m) -} - -func (d *openshiftImageDestination) PutSignatures(signatures [][]byte) error { - if d.imageStreamImageName == "" { - return errors.Errorf("Internal error: Unknown manifest digest, can't add signatures") - } - // Because image signatures are a shared resource in Atomic Registry, the default upload - // always adds signatures. Eventually we should also allow removing signatures. - - if len(signatures) == 0 { - return nil // No need to even read the old state. - } - - image, err := d.client.getImage(context.TODO(), d.imageStreamImageName) - if err != nil { - return err - } - existingSigNames := map[string]struct{}{} - for _, sig := range image.Signatures { - existingSigNames[sig.objectMeta.Name] = struct{}{} - } - -sigExists: - for _, newSig := range signatures { - for _, existingSig := range image.Signatures { - if existingSig.Type == imageSignatureTypeAtomic && bytes.Equal(existingSig.Content, newSig) { - continue sigExists - } - } - - // The API expect us to invent a new unique name. This is racy, but hopefully good enough. - var signatureName string - for { - randBytes := make([]byte, 16) - n, err := rand.Read(randBytes) - if err != nil || n != 16 { - return errors.Wrapf(err, "Error generating random signature len %d", n) - } - signatureName = fmt.Sprintf("%s@%032x", d.imageStreamImageName, randBytes) - if _, ok := existingSigNames[signatureName]; !ok { - break - } - } - // Note: This does absolutely no kind/version checking or conversions. - sig := imageSignature{ - typeMeta: typeMeta{ - Kind: "ImageSignature", - APIVersion: "v1", - }, - objectMeta: objectMeta{Name: signatureName}, - Type: imageSignatureTypeAtomic, - Content: newSig, - } - body, err := json.Marshal(sig) - _, err = d.client.doRequest(context.TODO(), "POST", "/oapi/v1/imagesignatures", body) - if err != nil { - return err - } - } - - return nil -} - -// Commit marks the process of storing the image as successful and asks for the image to be persisted. -// WARNING: This does not have any transactional semantics: -// - Uploaded data MAY be visible to others before Commit() is called -// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) -func (d *openshiftImageDestination) Commit() error { - return d.docker.Commit() -} - -// These structs are subsets of github.com/openshift/origin/pkg/image/api/v1 and its dependencies. -type imageStream struct { - Status imageStreamStatus `json:"status,omitempty"` -} -type imageStreamStatus struct { - DockerImageRepository string `json:"dockerImageRepository"` - Tags []namedTagEventList `json:"tags,omitempty"` -} -type namedTagEventList struct { - Tag string `json:"tag"` - Items []tagEvent `json:"items"` -} -type tagEvent struct { - DockerImageReference string `json:"dockerImageReference"` - Image string `json:"image"` -} -type imageStreamImage struct { - Image image `json:"image"` -} -type image struct { - objectMeta `json:"metadata,omitempty"` - DockerImageReference string `json:"dockerImageReference,omitempty"` - // DockerImageMetadata runtime.RawExtension `json:"dockerImageMetadata,omitempty"` - DockerImageMetadataVersion string `json:"dockerImageMetadataVersion,omitempty"` - DockerImageManifest string `json:"dockerImageManifest,omitempty"` - // DockerImageLayers []ImageLayer `json:"dockerImageLayers"` - Signatures []imageSignature `json:"signatures,omitempty"` -} - -const imageSignatureTypeAtomic string = "atomic" - -type imageSignature struct { - typeMeta `json:",inline"` - objectMeta `json:"metadata,omitempty"` - Type string `json:"type"` - Content []byte `json:"content"` - // Conditions []SignatureCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` - // ImageIdentity string `json:"imageIdentity,omitempty"` - // SignedClaims map[string]string `json:"signedClaims,omitempty"` - // Created *unversioned.Time `json:"created,omitempty"` - // IssuedBy SignatureIssuer `json:"issuedBy,omitempty"` - // IssuedTo SignatureSubject `json:"issuedTo,omitempty"` -} -type typeMeta struct { - Kind string `json:"kind,omitempty"` - APIVersion string `json:"apiVersion,omitempty"` -} -type objectMeta struct { - Name string `json:"name,omitempty"` - GenerateName string `json:"generateName,omitempty"` - Namespace string `json:"namespace,omitempty"` - SelfLink string `json:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty"` - Generation int64 `json:"generation,omitempty"` - DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` -} - -// A subset of k8s.io/kubernetes/pkg/api/unversioned/Status -type status struct { - Status string `json:"status,omitempty"` - Message string `json:"message,omitempty"` - // Reason StatusReason `json:"reason,omitempty"` - // Details *StatusDetails `json:"details,omitempty"` - Code int32 `json:"code,omitempty"` -} diff --git a/vendor/github.com/containers/image/openshift/openshift_transport.go b/vendor/github.com/containers/image/openshift/openshift_transport.go deleted file mode 100644 index 686d806f76..0000000000 --- a/vendor/github.com/containers/image/openshift/openshift_transport.go +++ /dev/null @@ -1,156 +0,0 @@ -package openshift - -import ( - "fmt" - "regexp" - "strings" - - "github.com/containers/image/docker/policyconfiguration" - "github.com/containers/image/docker/reference" - genericImage "github.com/containers/image/image" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -func init() { - transports.Register(Transport) -} - -// Transport is an ImageTransport for OpenShift registry-hosted images. -var Transport = openshiftTransport{} - -type openshiftTransport struct{} - -func (t openshiftTransport) Name() string { - return "atomic" -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (t openshiftTransport) ParseReference(reference string) (types.ImageReference, error) { - return ParseReference(reference) -} - -// Note that imageNameRegexp is namespace/stream:tag, this -// is HOSTNAME/namespace/stream:tag or parent prefixes. -// Keep this in sync with imageNameRegexp! -var scopeRegexp = regexp.MustCompile("^[^/]*(/[^:/]*(/[^:/]*(:[^:/]*)?)?)?$") - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t openshiftTransport) ValidatePolicyConfigurationScope(scope string) error { - if scopeRegexp.FindStringIndex(scope) == nil { - return errors.Errorf("Invalid scope name %s", scope) - } - return nil -} - -// openshiftReference is an ImageReference for OpenShift images. -type openshiftReference struct { - dockerReference reference.NamedTagged - namespace string // Computed from dockerReference in advance. - stream string // Computed from dockerReference in advance. -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OpenShift ImageReference. -func ParseReference(ref string) (types.ImageReference, error) { - r, err := reference.ParseNormalizedNamed(ref) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse image reference %q", ref) - } - tagged, ok := r.(reference.NamedTagged) - if !ok { - return nil, errors.Errorf("invalid image reference %s, expected format: 'hostname/namespace/stream:tag'", ref) - } - return NewReference(tagged) -} - -// NewReference returns an OpenShift reference for a reference.NamedTagged -func NewReference(dockerRef reference.NamedTagged) (types.ImageReference, error) { - r := strings.SplitN(reference.Path(dockerRef), "/", 3) - if len(r) != 2 { - return nil, errors.Errorf("invalid image reference: %s, expected format: 'hostname/namespace/stream:tag'", - reference.FamiliarString(dockerRef)) - } - return openshiftReference{ - namespace: r[0], - stream: r[1], - dockerReference: dockerRef, - }, nil -} - -func (ref openshiftReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref openshiftReference) StringWithinTransport() string { - return reference.FamiliarString(ref.dockerReference) -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref openshiftReference) DockerReference() reference.Named { - return ref.dockerReference -} - -// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. -// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; -// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical -// (i.e. various references with exactly the same semantics should return the same configuration identity) -// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but -// not required/guaranteed that it will be a valid input to Transport().ParseReference(). -// Returns "" if configuration identities for these references are not supported. -func (ref openshiftReference) PolicyConfigurationIdentity() string { - res, err := policyconfiguration.DockerReferenceIdentity(ref.dockerReference) - if res == "" || err != nil { // Coverage: Should never happen, NewReference constructs a valid tagged reference. - panic(fmt.Sprintf("Internal inconsistency: policyconfiguration.DockerReferenceIdentity returned %#v, %v", res, err)) - } - return res -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref openshiftReference) PolicyConfigurationNamespaces() []string { - return policyconfiguration.DockerReferenceNamespaces(ref.dockerReference) -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (ref openshiftReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src, err := newImageSource(ctx, ref) - if err != nil { - return nil, err - } - return genericImage.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref openshiftReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(ctx, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref openshiftReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, ref) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref openshiftReference) DeleteImage(ctx *types.SystemContext) error { - return errors.Errorf("Deleting images not implemented for atomic: images") -} diff --git a/vendor/github.com/containers/image/ostree/ostree_dest.go b/vendor/github.com/containers/image/ostree/ostree_dest.go deleted file mode 100644 index d5f0ff80cc..0000000000 --- a/vendor/github.com/containers/image/ostree/ostree_dest.go +++ /dev/null @@ -1,456 +0,0 @@ -// +build !containers_image_ostree_stub - -package ostree - -import ( - "bytes" - "compress/gzip" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "syscall" - "time" - "unsafe" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/containers/storage/pkg/archive" - "github.com/opencontainers/go-digest" - selinux "github.com/opencontainers/selinux/go-selinux" - "github.com/ostreedev/ostree-go/pkg/otbuiltin" - "github.com/pkg/errors" - "github.com/vbatts/tar-split/tar/asm" - "github.com/vbatts/tar-split/tar/storage" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 ostree-1 libselinux -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -import "C" - -type blobToImport struct { - Size int64 - Digest digest.Digest - BlobPath string -} - -type descriptor struct { - Size int64 `json:"size"` - Digest digest.Digest `json:"digest"` -} - -type fsLayersSchema1 struct { - BlobSum digest.Digest `json:"blobSum"` -} - -type manifestSchema struct { - LayersDescriptors []descriptor `json:"layers"` - FSLayers []fsLayersSchema1 `json:"fsLayers"` -} - -type ostreeImageDestination struct { - ref ostreeReference - manifest string - schema manifestSchema - tmpDirPath string - blobs map[string]*blobToImport - digest digest.Digest - signaturesLen int - repo *C.struct_OstreeRepo -} - -// newImageDestination returns an ImageDestination for writing to an existing ostree. -func newImageDestination(ref ostreeReference, tmpDirPath string) (types.ImageDestination, error) { - tmpDirPath = filepath.Join(tmpDirPath, ref.branchName) - if err := ensureDirectoryExists(tmpDirPath); err != nil { - return nil, err - } - return &ostreeImageDestination{ref, "", manifestSchema{}, tmpDirPath, map[string]*blobToImport{}, "", 0, nil}, nil -} - -// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, -// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. -func (d *ostreeImageDestination) Reference() types.ImageReference { - return d.ref -} - -// Close removes resources associated with an initialized ImageDestination, if any. -func (d *ostreeImageDestination) Close() error { - if d.repo != nil { - C.g_object_unref(C.gpointer(d.repo)) - } - return os.RemoveAll(d.tmpDirPath) -} - -func (d *ostreeImageDestination) SupportedManifestMIMETypes() []string { - return []string{ - manifest.DockerV2Schema2MediaType, - } -} - -// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. -// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. -func (d *ostreeImageDestination) SupportsSignatures() error { - return nil -} - -// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. -func (d *ostreeImageDestination) ShouldCompressLayers() bool { - return false -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually -// uploaded to the image destination, true otherwise. -func (d *ostreeImageDestination) AcceptsForeignLayerURLs() bool { - return false -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (d *ostreeImageDestination) MustMatchRuntimeOS() bool { - return true -} - -func (d *ostreeImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) { - tmpDir, err := ioutil.TempDir(d.tmpDirPath, "blob") - if err != nil { - return types.BlobInfo{}, err - } - - blobPath := filepath.Join(tmpDir, "content") - blobFile, err := os.Create(blobPath) - if err != nil { - return types.BlobInfo{}, err - } - defer blobFile.Close() - - digester := digest.Canonical.Digester() - tee := io.TeeReader(stream, digester.Hash()) - - size, err := io.Copy(blobFile, tee) - if err != nil { - return types.BlobInfo{}, err - } - computedDigest := digester.Digest() - if inputInfo.Size != -1 && size != inputInfo.Size { - return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size) - } - if err := blobFile.Sync(); err != nil { - return types.BlobInfo{}, err - } - - hash := computedDigest.Hex() - d.blobs[hash] = &blobToImport{Size: size, Digest: computedDigest, BlobPath: blobPath} - return types.BlobInfo{Digest: computedDigest, Size: size}, nil -} - -func fixFiles(selinuxHnd *C.struct_selabel_handle, root string, dir string, usermode bool) error { - entries, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - - for _, info := range entries { - fullpath := filepath.Join(dir, info.Name()) - if info.Mode()&(os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 { - if err := os.Remove(fullpath); err != nil { - return err - } - continue - } - - if selinuxHnd != nil { - relPath, err := filepath.Rel(root, fullpath) - if err != nil { - return err - } - // Handle /exports/hostfs as a special case. Files under this directory are copied to the host, - // thus we benefit from maintaining the same SELinux label they would have on the host as we could - // use hard links instead of copying the files. - relPath = fmt.Sprintf("/%s", strings.TrimPrefix(relPath, "exports/hostfs/")) - - relPathC := C.CString(relPath) - defer C.free(unsafe.Pointer(relPathC)) - var context *C.char - - res, err := C.selabel_lookup_raw(selinuxHnd, &context, relPathC, C.int(info.Mode()&os.ModePerm)) - if int(res) < 0 && err != syscall.ENOENT { - return errors.Wrapf(err, "cannot selabel_lookup_raw %s", relPath) - } - if int(res) == 0 { - defer C.freecon(context) - fullpathC := C.CString(fullpath) - defer C.free(unsafe.Pointer(fullpathC)) - res, err = C.lsetfilecon_raw(fullpathC, context) - if int(res) < 0 { - return errors.Wrapf(err, "cannot setfilecon_raw %s", fullpath) - } - } - } - - if info.IsDir() { - if usermode { - if err := os.Chmod(fullpath, info.Mode()|0700); err != nil { - return err - } - } - err = fixFiles(selinuxHnd, root, fullpath, usermode) - if err != nil { - return err - } - } else if usermode && (info.Mode().IsRegular()) { - if err := os.Chmod(fullpath, info.Mode()|0600); err != nil { - return err - } - } - } - - return nil -} - -func (d *ostreeImageDestination) ostreeCommit(repo *otbuiltin.Repo, branch string, root string, metadata []string) error { - opts := otbuiltin.NewCommitOptions() - opts.AddMetadataString = metadata - opts.Timestamp = time.Now() - // OCI layers have no parent OSTree commit - opts.Parent = "0000000000000000000000000000000000000000000000000000000000000000" - _, err := repo.Commit(root, branch, opts) - return err -} - -func generateTarSplitMetadata(output *bytes.Buffer, file string) error { - mfz := gzip.NewWriter(output) - defer mfz.Close() - metaPacker := storage.NewJSONPacker(mfz) - - stream, err := os.OpenFile(file, os.O_RDONLY, 0) - if err != nil { - return err - } - defer stream.Close() - - gzReader, err := archive.DecompressStream(stream) - if err != nil { - return err - } - defer gzReader.Close() - - its, err := asm.NewInputTarStream(gzReader, metaPacker, nil) - if err != nil { - return err - } - - _, err = io.Copy(ioutil.Discard, its) - if err != nil { - return err - } - return nil -} - -func (d *ostreeImageDestination) importBlob(selinuxHnd *C.struct_selabel_handle, repo *otbuiltin.Repo, blob *blobToImport) error { - ostreeBranch := fmt.Sprintf("ociimage/%s", blob.Digest.Hex()) - destinationPath := filepath.Join(d.tmpDirPath, blob.Digest.Hex(), "root") - if err := ensureDirectoryExists(destinationPath); err != nil { - return err - } - defer func() { - os.Remove(blob.BlobPath) - os.RemoveAll(destinationPath) - }() - - var tarSplitOutput bytes.Buffer - if err := generateTarSplitMetadata(&tarSplitOutput, blob.BlobPath); err != nil { - return err - } - - if os.Getuid() == 0 { - if err := archive.UntarPath(blob.BlobPath, destinationPath); err != nil { - return err - } - if err := fixFiles(selinuxHnd, destinationPath, destinationPath, false); err != nil { - return err - } - } else { - os.MkdirAll(destinationPath, 0755) - if err := exec.Command("tar", "-C", destinationPath, "--no-same-owner", "--no-same-permissions", "--delay-directory-restore", "-xf", blob.BlobPath).Run(); err != nil { - return err - } - - if err := fixFiles(selinuxHnd, destinationPath, destinationPath, true); err != nil { - return err - } - } - return d.ostreeCommit(repo, ostreeBranch, destinationPath, []string{fmt.Sprintf("docker.size=%d", blob.Size), - fmt.Sprintf("tarsplit.output=%s", base64.StdEncoding.EncodeToString(tarSplitOutput.Bytes()))}) - -} - -func (d *ostreeImageDestination) importConfig(repo *otbuiltin.Repo, blob *blobToImport) error { - ostreeBranch := fmt.Sprintf("ociimage/%s", blob.Digest.Hex()) - destinationPath := filepath.Dir(blob.BlobPath) - - return d.ostreeCommit(repo, ostreeBranch, destinationPath, []string{fmt.Sprintf("docker.size=%d", blob.Size)}) -} - -func (d *ostreeImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) { - - if d.repo == nil { - repo, err := openRepo(d.ref.repo) - if err != nil { - return false, 0, err - } - d.repo = repo - } - branch := fmt.Sprintf("ociimage/%s", info.Digest.Hex()) - - found, data, err := readMetadata(d.repo, branch, "docker.size") - if err != nil || !found { - return found, -1, err - } - - size, err := strconv.ParseInt(data, 10, 64) - if err != nil { - return false, -1, err - } - - return true, size, nil -} - -func (d *ostreeImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) { - return info, nil -} - -// PutManifest writes manifest to the destination. -// FIXME? This should also receive a MIME type if known, to differentiate between schema versions. -// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), -// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. -func (d *ostreeImageDestination) PutManifest(manifestBlob []byte) error { - d.manifest = string(manifestBlob) - - if err := json.Unmarshal(manifestBlob, &d.schema); err != nil { - return err - } - - manifestPath := filepath.Join(d.tmpDirPath, d.ref.manifestPath()) - if err := ensureParentDirectoryExists(manifestPath); err != nil { - return err - } - - digest, err := manifest.Digest(manifestBlob) - if err != nil { - return err - } - d.digest = digest - - return ioutil.WriteFile(manifestPath, manifestBlob, 0644) -} - -func (d *ostreeImageDestination) PutSignatures(signatures [][]byte) error { - path := filepath.Join(d.tmpDirPath, d.ref.signaturePath(0)) - if err := ensureParentDirectoryExists(path); err != nil { - return err - } - - for i, sig := range signatures { - signaturePath := filepath.Join(d.tmpDirPath, d.ref.signaturePath(i)) - if err := ioutil.WriteFile(signaturePath, sig, 0644); err != nil { - return err - } - } - d.signaturesLen = len(signatures) - return nil -} - -func (d *ostreeImageDestination) Commit() error { - repo, err := otbuiltin.OpenRepo(d.ref.repo) - if err != nil { - return err - } - - _, err = repo.PrepareTransaction() - if err != nil { - return err - } - - var selinuxHnd *C.struct_selabel_handle - - if os.Getuid() == 0 && selinux.GetEnabled() { - selinuxHnd, err = C.selabel_open(C.SELABEL_CTX_FILE, nil, 0) - if selinuxHnd == nil { - return errors.Wrapf(err, "cannot open the SELinux DB") - } - - defer C.selabel_close(selinuxHnd) - } - - checkLayer := func(hash string) error { - blob := d.blobs[hash] - // if the blob is not present in d.blobs then it is already stored in OSTree, - // and we don't need to import it. - if blob == nil { - return nil - } - err := d.importBlob(selinuxHnd, repo, blob) - if err != nil { - return err - } - - delete(d.blobs, hash) - return nil - } - for _, layer := range d.schema.LayersDescriptors { - hash := layer.Digest.Hex() - if err = checkLayer(hash); err != nil { - return err - } - } - for _, layer := range d.schema.FSLayers { - hash := layer.BlobSum.Hex() - if err = checkLayer(hash); err != nil { - return err - } - } - - // Import the other blobs that are not layers - for _, blob := range d.blobs { - err := d.importConfig(repo, blob) - if err != nil { - return err - } - } - - manifestPath := filepath.Join(d.tmpDirPath, "manifest") - - metadata := []string{fmt.Sprintf("docker.manifest=%s", string(d.manifest)), - fmt.Sprintf("signatures=%d", d.signaturesLen), - fmt.Sprintf("docker.digest=%s", string(d.digest))} - err = d.ostreeCommit(repo, fmt.Sprintf("ociimage/%s", d.ref.branchName), manifestPath, metadata) - - _, err = repo.CommitTransaction() - return err -} - -func ensureDirectoryExists(path string) error { - if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - } - return nil -} - -func ensureParentDirectoryExists(path string) error { - return ensureDirectoryExists(filepath.Dir(path)) -} diff --git a/vendor/github.com/containers/image/ostree/ostree_src.go b/vendor/github.com/containers/image/ostree/ostree_src.go deleted file mode 100644 index c65a07b751..0000000000 --- a/vendor/github.com/containers/image/ostree/ostree_src.go +++ /dev/null @@ -1,354 +0,0 @@ -// +build !containers_image_ostree_stub - -package ostree - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/base64" - "fmt" - "io" - "io/ioutil" - "strconv" - "strings" - "unsafe" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/containers/storage/pkg/ioutils" - "github.com/opencontainers/go-digest" - glib "github.com/ostreedev/ostree-go/pkg/glibobject" - "github.com/pkg/errors" - "github.com/vbatts/tar-split/tar/asm" - "github.com/vbatts/tar-split/tar/storage" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 ostree-1 -// #include -// #include -// #include -// #include -// #include -// #include -import "C" - -type ostreeImageSource struct { - ref ostreeReference - tmpDir string - repo *C.struct_OstreeRepo -} - -// newImageSource returns an ImageSource for reading from an existing directory. -func newImageSource(ctx *types.SystemContext, tmpDir string, ref ostreeReference) (types.ImageSource, error) { - return &ostreeImageSource{ref: ref, tmpDir: tmpDir}, nil -} - -// Reference returns the reference used to set up this source. -func (s *ostreeImageSource) Reference() types.ImageReference { - return s.ref -} - -// Close removes resources associated with an initialized ImageSource, if any. -func (s *ostreeImageSource) Close() error { - if s.repo != nil { - C.g_object_unref(C.gpointer(s.repo)) - } - return nil -} - -func (s *ostreeImageSource) getLayerSize(blob string) (int64, error) { - b := fmt.Sprintf("ociimage/%s", blob) - found, data, err := readMetadata(s.repo, b, "docker.size") - if err != nil || !found { - return 0, err - } - return strconv.ParseInt(data, 10, 64) -} - -func (s *ostreeImageSource) getLenSignatures() (int64, error) { - b := fmt.Sprintf("ociimage/%s", s.ref.branchName) - found, data, err := readMetadata(s.repo, b, "signatures") - if err != nil { - return -1, err - } - if !found { - // if 'signatures' is not present, just return 0 signatures. - return 0, nil - } - return strconv.ParseInt(data, 10, 64) -} - -func (s *ostreeImageSource) getTarSplitData(blob string) ([]byte, error) { - b := fmt.Sprintf("ociimage/%s", blob) - found, out, err := readMetadata(s.repo, b, "tarsplit.output") - if err != nil || !found { - return nil, err - } - return base64.StdEncoding.DecodeString(out) -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -func (s *ostreeImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if instanceDigest != nil { - return nil, "", errors.Errorf(`Manifest lists are not supported by "ostree:"`) - } - if s.repo == nil { - repo, err := openRepo(s.ref.repo) - if err != nil { - return nil, "", err - } - s.repo = repo - } - - b := fmt.Sprintf("ociimage/%s", s.ref.branchName) - found, out, err := readMetadata(s.repo, b, "docker.manifest") - if err != nil { - return nil, "", err - } - if !found { - return nil, "", errors.New("manifest not found") - } - m := []byte(out) - return m, manifest.GuessMIMEType(m), nil -} - -func (s *ostreeImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) { - return nil, "", errors.New("manifest lists are not supported by this transport") -} - -func openRepo(path string) (*C.struct_OstreeRepo, error) { - var cerr *C.GError - cpath := C.CString(path) - defer C.free(unsafe.Pointer(cpath)) - pathc := C.g_file_new_for_path(cpath) - defer C.g_object_unref(C.gpointer(pathc)) - repo := C.ostree_repo_new(pathc) - r := glib.GoBool(glib.GBoolean(C.ostree_repo_open(repo, nil, &cerr))) - if !r { - C.g_object_unref(C.gpointer(repo)) - return nil, glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - return repo, nil -} - -type ostreePathFileGetter struct { - repo *C.struct_OstreeRepo - parentRoot *C.GFile -} - -type ostreeReader struct { - stream *C.GFileInputStream -} - -func (o ostreeReader) Close() error { - C.g_object_unref(C.gpointer(o.stream)) - return nil -} -func (o ostreeReader) Read(p []byte) (int, error) { - var cerr *C.GError - instanceCast := C.g_type_check_instance_cast((*C.GTypeInstance)(unsafe.Pointer(o.stream)), C.g_input_stream_get_type()) - stream := (*C.GInputStream)(unsafe.Pointer(instanceCast)) - - b := C.g_input_stream_read_bytes(stream, (C.gsize)(cap(p)), nil, &cerr) - if b == nil { - return 0, glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - defer C.g_bytes_unref(b) - - count := int(C.g_bytes_get_size(b)) - if count == 0 { - return 0, io.EOF - } - data := (*[1 << 30]byte)(unsafe.Pointer(C.g_bytes_get_data(b, nil)))[:count:count] - copy(p, data) - return count, nil -} - -func readMetadata(repo *C.struct_OstreeRepo, commit, key string) (bool, string, error) { - var cerr *C.GError - var ref *C.char - defer C.free(unsafe.Pointer(ref)) - - cCommit := C.CString(commit) - defer C.free(unsafe.Pointer(cCommit)) - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_resolve_rev(repo, cCommit, C.gboolean(1), &ref, &cerr))) { - return false, "", glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - - if ref == nil { - return false, "", nil - } - - var variant *C.GVariant - if !glib.GoBool(glib.GBoolean(C.ostree_repo_load_variant(repo, C.OSTREE_OBJECT_TYPE_COMMIT, ref, &variant, &cerr))) { - return false, "", glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - defer C.g_variant_unref(variant) - if variant != nil { - cKey := C.CString(key) - defer C.free(unsafe.Pointer(cKey)) - - metadata := C.g_variant_get_child_value(variant, 0) - defer C.g_variant_unref(metadata) - - data := C.g_variant_lookup_value(metadata, (*C.gchar)(cKey), nil) - if data != nil { - defer C.g_variant_unref(data) - ptr := (*C.char)(C.g_variant_get_string(data, nil)) - val := C.GoString(ptr) - return true, val, nil - } - } - return false, "", nil -} - -func newOSTreePathFileGetter(repo *C.struct_OstreeRepo, commit string) (*ostreePathFileGetter, error) { - var cerr *C.GError - var parentRoot *C.GFile - cCommit := C.CString(commit) - defer C.free(unsafe.Pointer(cCommit)) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_read_commit(repo, cCommit, &parentRoot, nil, nil, &cerr))) { - return &ostreePathFileGetter{}, glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - - C.g_object_ref(C.gpointer(repo)) - - return &ostreePathFileGetter{repo: repo, parentRoot: parentRoot}, nil -} - -func (o ostreePathFileGetter) Get(filename string) (io.ReadCloser, error) { - var file *C.GFile - if strings.HasPrefix(filename, "./") { - filename = filename[2:] - } - cfilename := C.CString(filename) - defer C.free(unsafe.Pointer(cfilename)) - - file = (*C.GFile)(C.g_file_resolve_relative_path(o.parentRoot, cfilename)) - - var cerr *C.GError - stream := C.g_file_read(file, nil, &cerr) - if stream == nil { - return nil, glib.ConvertGError(glib.ToGError(unsafe.Pointer(cerr))) - } - - return &ostreeReader{stream: stream}, nil -} - -func (o ostreePathFileGetter) Close() { - C.g_object_unref(C.gpointer(o.repo)) - C.g_object_unref(C.gpointer(o.parentRoot)) -} - -func (s *ostreeImageSource) readSingleFile(commit, path string) (io.ReadCloser, error) { - getter, err := newOSTreePathFileGetter(s.repo, commit) - if err != nil { - return nil, err - } - defer getter.Close() - - return getter.Get(path) -} - -// GetBlob returns a stream for the specified blob, and the blob's size. -func (s *ostreeImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { - blob := info.Digest.Hex() - branch := fmt.Sprintf("ociimage/%s", blob) - - if s.repo == nil { - repo, err := openRepo(s.ref.repo) - if err != nil { - return nil, 0, err - } - s.repo = repo - } - - layerSize, err := s.getLayerSize(blob) - if err != nil { - return nil, 0, err - } - - tarsplit, err := s.getTarSplitData(blob) - if err != nil { - return nil, 0, err - } - - // if tarsplit is nil we are looking at the manifest. Return directly the file in /content - if tarsplit == nil { - file, err := s.readSingleFile(branch, "/content") - if err != nil { - return nil, 0, err - } - return file, layerSize, nil - } - - mf := bytes.NewReader(tarsplit) - mfz, err := gzip.NewReader(mf) - if err != nil { - return nil, 0, err - } - defer mfz.Close() - metaUnpacker := storage.NewJSONUnpacker(mfz) - - getter, err := newOSTreePathFileGetter(s.repo, branch) - if err != nil { - return nil, 0, err - } - - ots := asm.NewOutputTarStream(getter, metaUnpacker) - - pipeReader, pipeWriter := io.Pipe() - go func() { - io.Copy(pipeWriter, ots) - pipeWriter.Close() - }() - - rc := ioutils.NewReadCloserWrapper(pipeReader, func() error { - getter.Close() - return ots.Close() - }) - return rc, layerSize, nil -} - -func (s *ostreeImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - if instanceDigest != nil { - return nil, errors.New("manifest lists are not supported by this transport") - } - lenSignatures, err := s.getLenSignatures() - if err != nil { - return nil, err - } - branch := fmt.Sprintf("ociimage/%s", s.ref.branchName) - - if s.repo == nil { - repo, err := openRepo(s.ref.repo) - if err != nil { - return nil, err - } - s.repo = repo - } - - signatures := [][]byte{} - for i := int64(1); i <= lenSignatures; i++ { - sigReader, err := s.readSingleFile(branch, fmt.Sprintf("/signature-%d", i)) - if err != nil { - return nil, err - } - defer sigReader.Close() - - sig, err := ioutil.ReadAll(sigReader) - if err != nil { - return nil, err - } - signatures = append(signatures, sig) - } - return signatures, nil -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (s *ostreeImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/ostree/ostree_transport.go b/vendor/github.com/containers/image/ostree/ostree_transport.go deleted file mode 100644 index cc85a43ff1..0000000000 --- a/vendor/github.com/containers/image/ostree/ostree_transport.go +++ /dev/null @@ -1,251 +0,0 @@ -// +build !containers_image_ostree_stub - -package ostree - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/containers/image/directory/explicitfilepath" - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -const defaultOSTreeRepo = "/ostree/repo" - -// Transport is an ImageTransport for ostree paths. -var Transport = ostreeTransport{} - -type ostreeTransport struct{} - -func (t ostreeTransport) Name() string { - return "ostree" -} - -func init() { - transports.Register(Transport) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (t ostreeTransport) ValidatePolicyConfigurationScope(scope string) error { - sep := strings.Index(scope, ":") - if sep < 0 { - return errors.Errorf("Invalid ostree: scope %s: Must include a repo", scope) - } - repo := scope[:sep] - - if !strings.HasPrefix(repo, "/") { - return errors.Errorf("Invalid ostree: scope %s: repository must be an absolute path", scope) - } - cleaned := filepath.Clean(repo) - if cleaned != repo { - return errors.Errorf(`Invalid ostree: scope %s: Uses non-canonical path format, perhaps try with path %s`, scope, cleaned) - } - - // FIXME? In the namespaces within a repo, - // we could be verifying the various character set and length restrictions - // from docker/distribution/reference.regexp.go, but other than that there - // are few semantically invalid strings. - return nil -} - -// ostreeReference is an ImageReference for ostree paths. -type ostreeReference struct { - image string - branchName string - repo string -} - -type ostreeImageCloser struct { - types.ImageCloser - size int64 -} - -func (t ostreeTransport) ParseReference(ref string) (types.ImageReference, error) { - var repo = "" - var image = "" - s := strings.SplitN(ref, "@/", 2) - if len(s) == 1 { - image, repo = s[0], defaultOSTreeRepo - } else { - image, repo = s[0], "/"+s[1] - } - - return NewReference(image, repo) -} - -// NewReference returns an OSTree reference for a specified repo and image. -func NewReference(image string, repo string) (types.ImageReference, error) { - // image is not _really_ in a containers/image/docker/reference format; - // as far as the libOSTree ociimage/* namespace is concerned, it is more or - // less an arbitrary string with an implied tag. - // Parse the image using reference.ParseNormalizedNamed so that we can - // check whether the images has a tag specified and we can add ":latest" if needed - ostreeImage, err := reference.ParseNormalizedNamed(image) - if err != nil { - return nil, err - } - - if reference.IsNameOnly(ostreeImage) { - image = image + ":latest" - } - - resolved, err := explicitfilepath.ResolvePathToFullyExplicit(repo) - if err != nil { - // With os.IsNotExist(err), the parent directory of repo is also not existent; - // that should ordinarily not happen, but it would be a bit weird to reject - // references which do not specify a repo just because the implicit defaultOSTreeRepo - // does not exist. - if os.IsNotExist(err) && repo == defaultOSTreeRepo { - resolved = repo - } else { - return nil, err - } - } - // This is necessary to prevent directory paths returned by PolicyConfigurationNamespaces - // from being ambiguous with values of PolicyConfigurationIdentity. - if strings.Contains(resolved, ":") { - return nil, errors.Errorf("Invalid OSTree reference %s@%s: path %s contains a colon", image, repo, resolved) - } - - return ostreeReference{ - image: image, - branchName: encodeOStreeRef(image), - repo: resolved, - }, nil -} - -func (ref ostreeReference) Transport() types.ImageTransport { - return Transport -} - -// StringWithinTransport returns a string representation of the reference, which MUST be such that -// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. -// NOTE: The returned string is not promised to be equal to the original input to ParseReference; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. -func (ref ostreeReference) StringWithinTransport() string { - return fmt.Sprintf("%s@%s", ref.image, ref.repo) -} - -// DockerReference returns a Docker reference associated with this reference -// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, -// not e.g. after redirect or alias processing), or nil if unknown/not applicable. -func (ref ostreeReference) DockerReference() reference.Named { - return nil -} - -func (ref ostreeReference) PolicyConfigurationIdentity() string { - return fmt.Sprintf("%s:%s", ref.repo, ref.image) -} - -// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search -// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed -// in order, terminating on first match, and an implicit "" is always checked at the end. -// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), -// and each following element to be a prefix of the element preceding it. -func (ref ostreeReference) PolicyConfigurationNamespaces() []string { - s := strings.SplitN(ref.image, ":", 2) - if len(s) != 2 { // Coverage: Should never happen, NewReference above ensures ref.image has a :tag. - panic(fmt.Sprintf("Internal inconsistency: ref.image value %q does not have a :tag", ref.image)) - } - name := s[0] - res := []string{} - for { - res = append(res, fmt.Sprintf("%s:%s", ref.repo, name)) - - lastSlash := strings.LastIndex(name, "/") - if lastSlash == -1 { - break - } - name = name[:lastSlash] - } - return res -} - -func (s *ostreeImageCloser) Size() (int64, error) { - return s.size, nil -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -func (ref ostreeReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - var tmpDir string - if ctx == nil || ctx.OSTreeTmpDirPath == "" { - tmpDir = os.TempDir() - } else { - tmpDir = ctx.OSTreeTmpDirPath - } - src, err := newImageSource(ctx, tmpDir, ref) - if err != nil { - return nil, err - } - return image.FromSource(ctx, src) -} - -// NewImageSource returns a types.ImageSource for this reference. -// The caller must call .Close() on the returned ImageSource. -func (ref ostreeReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - var tmpDir string - if ctx == nil || ctx.OSTreeTmpDirPath == "" { - tmpDir = os.TempDir() - } else { - tmpDir = ctx.OSTreeTmpDirPath - } - return newImageSource(ctx, tmpDir, ref) -} - -// NewImageDestination returns a types.ImageDestination for this reference. -// The caller must call .Close() on the returned ImageDestination. -func (ref ostreeReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - var tmpDir string - if ctx == nil || ctx.OSTreeTmpDirPath == "" { - tmpDir = os.TempDir() - } else { - tmpDir = ctx.OSTreeTmpDirPath - } - return newImageDestination(ref, tmpDir) -} - -// DeleteImage deletes the named image from the registry, if supported. -func (ref ostreeReference) DeleteImage(ctx *types.SystemContext) error { - return errors.Errorf("Deleting images not implemented for ostree: images") -} - -var ostreeRefRegexp = regexp.MustCompile(`^[A-Za-z0-9.-]$`) - -func encodeOStreeRef(in string) string { - var buffer bytes.Buffer - for i := range in { - sub := in[i : i+1] - if ostreeRefRegexp.MatchString(sub) { - buffer.WriteString(sub) - } else { - buffer.WriteString(fmt.Sprintf("_%02X", sub[0])) - } - - } - return buffer.String() -} - -// manifestPath returns a path for the manifest within a ostree using our conventions. -func (ref ostreeReference) manifestPath() string { - return filepath.Join("manifest", "manifest.json") -} - -// signaturePath returns a path for a signature within a ostree using our conventions. -func (ref ostreeReference) signaturePath(index int) string { - return filepath.Join("manifest", fmt.Sprintf("signature-%d", index+1)) -} diff --git a/vendor/github.com/containers/image/pkg/compression/compression.go b/vendor/github.com/containers/image/pkg/compression/compression.go deleted file mode 100644 index c19d962ee5..0000000000 --- a/vendor/github.com/containers/image/pkg/compression/compression.go +++ /dev/null @@ -1,67 +0,0 @@ -package compression - -import ( - "bytes" - "compress/bzip2" - "compress/gzip" - "io" - - "github.com/pkg/errors" - - "github.com/sirupsen/logrus" -) - -// DecompressorFunc returns the decompressed stream, given a compressed stream. -type DecompressorFunc func(io.Reader) (io.Reader, error) - -// GzipDecompressor is a DecompressorFunc for the gzip compression algorithm. -func GzipDecompressor(r io.Reader) (io.Reader, error) { - return gzip.NewReader(r) -} - -// Bzip2Decompressor is a DecompressorFunc for the bzip2 compression algorithm. -func Bzip2Decompressor(r io.Reader) (io.Reader, error) { - return bzip2.NewReader(r), nil -} - -// XzDecompressor is a DecompressorFunc for the xz compression algorithm. -func XzDecompressor(r io.Reader) (io.Reader, error) { - return nil, errors.New("Decompressing xz streams is not supported") -} - -// compressionAlgos is an internal implementation detail of DetectCompression -var compressionAlgos = map[string]struct { - prefix []byte - decompressor DecompressorFunc -}{ - "gzip": {[]byte{0x1F, 0x8B, 0x08}, GzipDecompressor}, // gzip (RFC 1952) - "bzip2": {[]byte{0x42, 0x5A, 0x68}, Bzip2Decompressor}, // bzip2 (decompress.c:BZ2_decompress) - "xz": {[]byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, XzDecompressor}, // xz (/usr/share/doc/xz/xz-file-format.txt) -} - -// DetectCompression returns a DecompressorFunc if the input is recognized as a compressed format, nil otherwise. -// Because it consumes the start of input, other consumers must use the returned io.Reader instead to also read from the beginning. -func DetectCompression(input io.Reader) (DecompressorFunc, io.Reader, error) { - buffer := [8]byte{} - - n, err := io.ReadAtLeast(input, buffer[:], len(buffer)) - if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { - // This is a “real” error. We could just ignore it this time, process the data we have, and hope that the source will report the same error again. - // Instead, fail immediately with the original error cause instead of a possibly secondary/misleading error returned later. - return nil, nil, err - } - - var decompressor DecompressorFunc - for name, algo := range compressionAlgos { - if bytes.HasPrefix(buffer[:n], algo.prefix) { - logrus.Debugf("Detected compression format %s", name) - decompressor = algo.decompressor - break - } - } - if decompressor == nil { - logrus.Debugf("No compression detected") - } - - return decompressor, io.MultiReader(bytes.NewReader(buffer[:n]), input), nil -} diff --git a/vendor/github.com/containers/image/pkg/docker/config/config.go b/vendor/github.com/containers/image/pkg/docker/config/config.go deleted file mode 100644 index fd0ae7d84d..0000000000 --- a/vendor/github.com/containers/image/pkg/docker/config/config.go +++ /dev/null @@ -1,295 +0,0 @@ -package config - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/containers/image/types" - helperclient "github.com/docker/docker-credential-helpers/client" - "github.com/docker/docker-credential-helpers/credentials" - "github.com/docker/docker/pkg/homedir" - "github.com/pkg/errors" -) - -type dockerAuthConfig struct { - Auth string `json:"auth,omitempty"` -} - -type dockerConfigFile struct { - AuthConfigs map[string]dockerAuthConfig `json:"auths"` - CredHelpers map[string]string `json:"credHelpers,omitempty"` -} - -const ( - defaultPath = "/run/user" - authCfg = "containers" - authCfgFileName = "auth.json" - dockerCfg = ".docker" - dockerCfgFileName = "config.json" - dockerLegacyCfg = ".dockercfg" -) - -var ( - // ErrNotLoggedIn is returned for users not logged into a registry - // that they are trying to logout of - ErrNotLoggedIn = errors.New("not logged in") -) - -// SetAuthentication stores the username and password in the auth.json file -func SetAuthentication(ctx *types.SystemContext, registry, username, password string) error { - return modifyJSON(ctx, func(auths *dockerConfigFile) (bool, error) { - if ch, exists := auths.CredHelpers[registry]; exists { - return false, setAuthToCredHelper(ch, registry, username, password) - } - - creds := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) - newCreds := dockerAuthConfig{Auth: creds} - auths.AuthConfigs[registry] = newCreds - return true, nil - }) -} - -// GetAuthentication returns the registry credentials stored in -// either auth.json file or .docker/config.json -// If an entry is not found empty strings are returned for the username and password -func GetAuthentication(ctx *types.SystemContext, registry string) (string, string, error) { - if ctx != nil && ctx.DockerAuthConfig != nil { - return ctx.DockerAuthConfig.Username, ctx.DockerAuthConfig.Password, nil - } - - dockerLegacyPath := filepath.Join(homedir.Get(), dockerLegacyCfg) - paths := [3]string{getPathToAuth(ctx), filepath.Join(homedir.Get(), dockerCfg, dockerCfgFileName), dockerLegacyPath} - - for _, path := range paths { - legacyFormat := path == dockerLegacyPath - username, password, err := findAuthentication(registry, path, legacyFormat) - if err != nil { - return "", "", err - } - if username != "" && password != "" { - return username, password, nil - } - } - return "", "", nil -} - -// GetUserLoggedIn returns the username logged in to registry from either -// auth.json or XDG_RUNTIME_DIR -// Used to tell the user if someone is logged in to the registry when logging in -func GetUserLoggedIn(ctx *types.SystemContext, registry string) string { - path := getPathToAuth(ctx) - username, _, _ := findAuthentication(registry, path, false) - if username != "" { - return username - } - return "" -} - -// RemoveAuthentication deletes the credentials stored in auth.json -func RemoveAuthentication(ctx *types.SystemContext, registry string) error { - return modifyJSON(ctx, func(auths *dockerConfigFile) (bool, error) { - // First try cred helpers. - if ch, exists := auths.CredHelpers[registry]; exists { - return false, deleteAuthFromCredHelper(ch, registry) - } - - if _, ok := auths.AuthConfigs[registry]; ok { - delete(auths.AuthConfigs, registry) - } else if _, ok := auths.AuthConfigs[normalizeRegistry(registry)]; ok { - delete(auths.AuthConfigs, normalizeRegistry(registry)) - } else { - return false, ErrNotLoggedIn - } - return true, nil - }) -} - -// RemoveAllAuthentication deletes all the credentials stored in auth.json -func RemoveAllAuthentication(ctx *types.SystemContext) error { - return modifyJSON(ctx, func(auths *dockerConfigFile) (bool, error) { - auths.CredHelpers = make(map[string]string) - auths.AuthConfigs = make(map[string]dockerAuthConfig) - return true, nil - }) -} - -// getPath gets the path of the auth.json file -// The path can be overriden by the user if the overwrite-path flag is set -// If the flag is not set and XDG_RUNTIME_DIR is ser, the auth.json file is saved in XDG_RUNTIME_DIR/containers -// Otherwise, the auth.json file is stored in /run/user/UID/containers -func getPathToAuth(ctx *types.SystemContext) string { - if ctx != nil { - if ctx.AuthFilePath != "" { - return ctx.AuthFilePath - } - if ctx.RootForImplicitAbsolutePaths != "" { - return filepath.Join(ctx.RootForImplicitAbsolutePaths, defaultPath, strconv.Itoa(os.Getuid()), authCfg, authCfgFileName) - } - } - runtimeDir := os.Getenv("XDG_RUNTIME_DIR") - if runtimeDir == "" { - runtimeDir = filepath.Join(defaultPath, strconv.Itoa(os.Getuid())) - } - return filepath.Join(runtimeDir, authCfg, authCfgFileName) -} - -// readJSONFile unmarshals the authentications stored in the auth.json file and returns it -// or returns an empty dockerConfigFile data structure if auth.json does not exist -// if the file exists and is empty, readJSONFile returns an error -func readJSONFile(path string, legacyFormat bool) (dockerConfigFile, error) { - var auths dockerConfigFile - - raw, err := ioutil.ReadFile(path) - if os.IsNotExist(err) { - auths.AuthConfigs = map[string]dockerAuthConfig{} - return auths, nil - } - - if legacyFormat { - if err = json.Unmarshal(raw, &auths.AuthConfigs); err != nil { - return dockerConfigFile{}, errors.Wrapf(err, "error unmarshaling JSON at %q", path) - } - return auths, nil - } - - if err = json.Unmarshal(raw, &auths); err != nil { - return dockerConfigFile{}, errors.Wrapf(err, "error unmarshaling JSON at %q", path) - } - - return auths, nil -} - -// modifyJSON writes to auth.json if the dockerConfigFile has been updated -func modifyJSON(ctx *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) error { - path := getPathToAuth(ctx) - dir := filepath.Dir(path) - if _, err := os.Stat(dir); os.IsNotExist(err) { - if err = os.Mkdir(dir, 0700); err != nil { - return errors.Wrapf(err, "error creating directory %q", dir) - } - } - - auths, err := readJSONFile(path, false) - if err != nil { - return errors.Wrapf(err, "error reading JSON file %q", path) - } - - updated, err := editor(&auths) - if err != nil { - return errors.Wrapf(err, "error updating %q", path) - } - if updated { - newData, err := json.MarshalIndent(auths, "", "\t") - if err != nil { - return errors.Wrapf(err, "error marshaling JSON %q", path) - } - - if err = ioutil.WriteFile(path, newData, 0755); err != nil { - return errors.Wrapf(err, "error writing to file %q", path) - } - } - - return nil -} - -func getAuthFromCredHelper(credHelper, registry string) (string, string, error) { - helperName := fmt.Sprintf("docker-credential-%s", credHelper) - p := helperclient.NewShellProgramFunc(helperName) - creds, err := helperclient.Get(p, registry) - if err != nil { - return "", "", err - } - return creds.Username, creds.Secret, nil -} - -func setAuthToCredHelper(credHelper, registry, username, password string) error { - helperName := fmt.Sprintf("docker-credential-%s", credHelper) - p := helperclient.NewShellProgramFunc(helperName) - creds := &credentials.Credentials{ - ServerURL: registry, - Username: username, - Secret: password, - } - return helperclient.Store(p, creds) -} - -func deleteAuthFromCredHelper(credHelper, registry string) error { - helperName := fmt.Sprintf("docker-credential-%s", credHelper) - p := helperclient.NewShellProgramFunc(helperName) - return helperclient.Erase(p, registry) -} - -// findAuthentication looks for auth of registry in path -func findAuthentication(registry, path string, legacyFormat bool) (string, string, error) { - auths, err := readJSONFile(path, legacyFormat) - if err != nil { - return "", "", errors.Wrapf(err, "error reading JSON file %q", path) - } - - // First try cred helpers. They should always be normalized. - if ch, exists := auths.CredHelpers[registry]; exists { - return getAuthFromCredHelper(ch, registry) - } - - // I'm feeling lucky - if val, exists := auths.AuthConfigs[registry]; exists { - return decodeDockerAuth(val.Auth) - } - - // bad luck; let's normalize the entries first - registry = normalizeRegistry(registry) - normalizedAuths := map[string]dockerAuthConfig{} - for k, v := range auths.AuthConfigs { - normalizedAuths[normalizeRegistry(k)] = v - } - if val, exists := normalizedAuths[registry]; exists { - return decodeDockerAuth(val.Auth) - } - return "", "", nil -} - -func decodeDockerAuth(s string) (string, string, error) { - decoded, err := base64.StdEncoding.DecodeString(s) - if err != nil { - return "", "", err - } - parts := strings.SplitN(string(decoded), ":", 2) - if len(parts) != 2 { - // if it's invalid just skip, as docker does - return "", "", nil - } - user := parts[0] - password := strings.Trim(parts[1], "\x00") - return user, password, nil -} - -// convertToHostname converts a registry url which has http|https prepended -// to just an hostname. -// Copied from github.com/docker/docker/registry/auth.go -func convertToHostname(url string) string { - stripped := url - if strings.HasPrefix(url, "http://") { - stripped = strings.TrimPrefix(url, "http://") - } else if strings.HasPrefix(url, "https://") { - stripped = strings.TrimPrefix(url, "https://") - } - - nameParts := strings.SplitN(stripped, "/", 2) - - return nameParts[0] -} - -func normalizeRegistry(registry string) string { - normalized := convertToHostname(registry) - switch normalized { - case "registry-1.docker.io", "docker.io": - return "index.docker.io" - } - return normalized -} diff --git a/vendor/github.com/containers/image/pkg/strslice/strslice.go b/vendor/github.com/containers/image/pkg/strslice/strslice.go deleted file mode 100644 index bad493fb89..0000000000 --- a/vendor/github.com/containers/image/pkg/strslice/strslice.go +++ /dev/null @@ -1,30 +0,0 @@ -package strslice - -import "encoding/json" - -// StrSlice represents a string or an array of strings. -// We need to override the json decoder to accept both options. -type StrSlice []string - -// UnmarshalJSON decodes the byte slice whether it's a string or an array of -// strings. This method is needed to implement json.Unmarshaler. -func (e *StrSlice) UnmarshalJSON(b []byte) error { - if len(b) == 0 { - // With no input, we preserve the existing value by returning nil and - // leaving the target alone. This allows defining default values for - // the type. - return nil - } - - p := make([]string, 0, 1) - if err := json.Unmarshal(b, &p); err != nil { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - p = append(p, s) - } - - *e = p - return nil -} diff --git a/vendor/github.com/containers/image/pkg/tlsclientconfig/tlsclientconfig.go b/vendor/github.com/containers/image/pkg/tlsclientconfig/tlsclientconfig.go deleted file mode 100644 index 0a32861ced..0000000000 --- a/vendor/github.com/containers/image/pkg/tlsclientconfig/tlsclientconfig.go +++ /dev/null @@ -1,102 +0,0 @@ -package tlsclientconfig - -import ( - "crypto/tls" - "io/ioutil" - "net" - "net/http" - "os" - "path/filepath" - "strings" - "time" - - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// SetupCertificates opens all .crt, .cert, and .key files in dir and appends / loads certs and key pairs as appropriate to tlsc -func SetupCertificates(dir string, tlsc *tls.Config) error { - logrus.Debugf("Looking for TLS certificates and private keys in %s", dir) - fs, err := ioutil.ReadDir(dir) - if err != nil { - if os.IsNotExist(err) { - return nil - } - if os.IsPermission(err) { - logrus.Debugf("Skipping scan of %s due to permission error: %v", dir, err) - return nil - } - return err - } - - for _, f := range fs { - fullPath := filepath.Join(dir, f.Name()) - if strings.HasSuffix(f.Name(), ".crt") { - systemPool, err := tlsconfig.SystemCertPool() - if err != nil { - return errors.Wrap(err, "unable to get system cert pool") - } - tlsc.RootCAs = systemPool - logrus.Debugf(" crt: %s", fullPath) - data, err := ioutil.ReadFile(fullPath) - if err != nil { - return err - } - tlsc.RootCAs.AppendCertsFromPEM(data) - } - if strings.HasSuffix(f.Name(), ".cert") { - certName := f.Name() - keyName := certName[:len(certName)-5] + ".key" - logrus.Debugf(" cert: %s", fullPath) - if !hasFile(fs, keyName) { - return errors.Errorf("missing key %s for client certificate %s. Note that CA certificates should use the extension .crt", keyName, certName) - } - cert, err := tls.LoadX509KeyPair(filepath.Join(dir, certName), filepath.Join(dir, keyName)) - if err != nil { - return err - } - tlsc.Certificates = append(tlsc.Certificates, cert) - } - if strings.HasSuffix(f.Name(), ".key") { - keyName := f.Name() - certName := keyName[:len(keyName)-4] + ".cert" - logrus.Debugf(" key: %s", fullPath) - if !hasFile(fs, certName) { - return errors.Errorf("missing client certificate %s for key %s", certName, keyName) - } - } - } - return nil -} - -func hasFile(files []os.FileInfo, name string) bool { - for _, f := range files { - if f.Name() == name { - return true - } - } - return false -} - -// NewTransport Creates a default transport -func NewTransport() *http.Transport { - direct := &net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - } - tr := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: direct.Dial, - TLSHandshakeTimeout: 10 * time.Second, - // TODO(dmcgowan): Call close idle connections when complete and use keep alive - DisableKeepAlives: true, - } - proxyDialer, err := sockets.DialerFromEnvironment(direct) - if err == nil { - tr.Dial = proxyDialer.Dial - } - return tr -} diff --git a/vendor/github.com/containers/image/signature/docker.go b/vendor/github.com/containers/image/signature/docker.go deleted file mode 100644 index 16eb3f7993..0000000000 --- a/vendor/github.com/containers/image/signature/docker.go +++ /dev/null @@ -1,65 +0,0 @@ -// Note: Consider the API unstable until the code supports at least three different image formats or transports. - -package signature - -import ( - "fmt" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/manifest" - "github.com/opencontainers/go-digest" -) - -// SignDockerManifest returns a signature for manifest as the specified dockerReference, -// using mech and keyIdentity. -func SignDockerManifest(m []byte, dockerReference string, mech SigningMechanism, keyIdentity string) ([]byte, error) { - manifestDigest, err := manifest.Digest(m) - if err != nil { - return nil, err - } - sig := newUntrustedSignature(manifestDigest, dockerReference) - return sig.sign(mech, keyIdentity) -} - -// VerifyDockerManifestSignature checks that unverifiedSignature uses expectedKeyIdentity to sign unverifiedManifest as expectedDockerReference, -// using mech. -func VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest []byte, - expectedDockerReference string, mech SigningMechanism, expectedKeyIdentity string) (*Signature, error) { - expectedRef, err := reference.ParseNormalizedNamed(expectedDockerReference) - if err != nil { - return nil, err - } - sig, err := verifyAndExtractSignature(mech, unverifiedSignature, signatureAcceptanceRules{ - validateKeyIdentity: func(keyIdentity string) error { - if keyIdentity != expectedKeyIdentity { - return InvalidSignatureError{msg: fmt.Sprintf("Signature by %s does not match expected fingerprint %s", keyIdentity, expectedKeyIdentity)} - } - return nil - }, - validateSignedDockerReference: func(signedDockerReference string) error { - signedRef, err := reference.ParseNormalizedNamed(signedDockerReference) - if err != nil { - return InvalidSignatureError{msg: fmt.Sprintf("Invalid docker reference %s in signature", signedDockerReference)} - } - if signedRef.String() != expectedRef.String() { - return InvalidSignatureError{msg: fmt.Sprintf("Docker reference %s does not match %s", - signedDockerReference, expectedDockerReference)} - } - return nil - }, - validateSignedDockerManifestDigest: func(signedDockerManifestDigest digest.Digest) error { - matches, err := manifest.MatchesDigest(unverifiedManifest, signedDockerManifestDigest) - if err != nil { - return err - } - if !matches { - return InvalidSignatureError{msg: fmt.Sprintf("Signature for docker digest %q does not match", signedDockerManifestDigest)} - } - return nil - }, - }) - if err != nil { - return nil, err - } - return sig, nil -} diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/manifest.json b/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/manifest.json deleted file mode 120000 index 3dee14b4a8..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../v2s1-invalid-signatures.manifest.json \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/signature-1 b/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/signature-1 deleted file mode 120000 index f010fd4c41..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-manifest-digest-error/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/manifest.json b/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/manifest.json deleted file mode 120000 index ff7d2ffadf..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-1 b/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-1 deleted file mode 120000 index b27cdc4585..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../invalid-blob.signature \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-2 b/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-2 deleted file mode 120000 index f010fd4c41..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-mixed/signature-2 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-modified-manifest/signature-1 b/vendor/github.com/containers/image/signature/fixtures/dir-img-modified-manifest/signature-1 deleted file mode 120000 index f010fd4c41..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-modified-manifest/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-no-manifest/signature-1 b/vendor/github.com/containers/image/signature/fixtures/dir-img-no-manifest/signature-1 deleted file mode 120000 index f010fd4c41..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-no-manifest/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-unsigned/manifest.json b/vendor/github.com/containers/image/signature/fixtures/dir-img-unsigned/manifest.json deleted file mode 120000 index ff7d2ffadf..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-unsigned/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/manifest.json b/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/manifest.json deleted file mode 120000 index ff7d2ffadf..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/signature-1 b/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/signature-1 deleted file mode 120000 index f010fd4c41..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid-2/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid/manifest.json b/vendor/github.com/containers/image/signature/fixtures/dir-img-valid/manifest.json deleted file mode 120000 index c5bd25431f..0000000000 --- a/vendor/github.com/containers/image/signature/fixtures/dir-img-valid/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../image.manifest.json \ No newline at end of file diff --git a/vendor/github.com/containers/image/signature/json.go b/vendor/github.com/containers/image/signature/json.go deleted file mode 100644 index 9e592863da..0000000000 --- a/vendor/github.com/containers/image/signature/json.go +++ /dev/null @@ -1,88 +0,0 @@ -package signature - -import ( - "bytes" - "encoding/json" - "fmt" - "io" -) - -// jsonFormatError is returned when JSON does not match expected format. -type jsonFormatError string - -func (err jsonFormatError) Error() string { - return string(err) -} - -// paranoidUnmarshalJSONObject unmarshals data as a JSON object, but failing on the slightest unexpected aspect -// (including duplicated keys, unrecognized keys, and non-matching types). Uses fieldResolver to -// determine the destination for a field value, which should return a pointer to the destination if valid, or nil if the key is rejected. -// -// The fieldResolver approach is useful for decoding the Policy.Transports map; using it for structs is a bit lazy, -// we could use reflection to automate this. Later? -func paranoidUnmarshalJSONObject(data []byte, fieldResolver func(string) interface{}) error { - seenKeys := map[string]struct{}{} - - dec := json.NewDecoder(bytes.NewReader(data)) - t, err := dec.Token() - if err != nil { - return jsonFormatError(err.Error()) - } - if t != json.Delim('{') { - return jsonFormatError(fmt.Sprintf("JSON object expected, got \"%s\"", t)) - } - for { - t, err := dec.Token() - if err != nil { - return jsonFormatError(err.Error()) - } - if t == json.Delim('}') { - break - } - - key, ok := t.(string) - if !ok { - // Coverage: This should never happen, dec.Token() rejects non-string-literals in this state. - return jsonFormatError(fmt.Sprintf("Key string literal expected, got \"%s\"", t)) - } - if _, ok := seenKeys[key]; ok { - return jsonFormatError(fmt.Sprintf("Duplicate key \"%s\"", key)) - } - seenKeys[key] = struct{}{} - - valuePtr := fieldResolver(key) - if valuePtr == nil { - return jsonFormatError(fmt.Sprintf("Unknown key \"%s\"", key)) - } - // This works like json.Unmarshal, in particular it allows us to implement UnmarshalJSON to implement strict parsing of the field value. - if err := dec.Decode(valuePtr); err != nil { - return jsonFormatError(err.Error()) - } - } - if _, err := dec.Token(); err != io.EOF { - return jsonFormatError("Unexpected data after JSON object") - } - return nil -} - -// paranoidUnmarshalJSONObject unmarshals data as a JSON object, but failing on the slightest unexpected aspect -// (including duplicated keys, unrecognized keys, and non-matching types). Each of the fields in exactFields -// must be present exactly once, and none other fields are accepted. -func paranoidUnmarshalJSONObjectExactFields(data []byte, exactFields map[string]interface{}) error { - seenKeys := map[string]struct{}{} - if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { - if valuePtr, ok := exactFields[key]; ok { - seenKeys[key] = struct{}{} - return valuePtr - } - return nil - }); err != nil { - return err - } - for key := range exactFields { - if _, ok := seenKeys[key]; !ok { - return jsonFormatError(fmt.Sprintf(`Key "%s" missing in a JSON object`, key)) - } - } - return nil -} diff --git a/vendor/github.com/containers/image/signature/mechanism.go b/vendor/github.com/containers/image/signature/mechanism.go deleted file mode 100644 index bdf26c531f..0000000000 --- a/vendor/github.com/containers/image/signature/mechanism.go +++ /dev/null @@ -1,85 +0,0 @@ -// Note: Consider the API unstable until the code supports at least three different image formats or transports. - -package signature - -import ( - "bytes" - "errors" - "fmt" - "io/ioutil" - "strings" - - "golang.org/x/crypto/openpgp" -) - -// SigningMechanism abstracts a way to sign binary blobs and verify their signatures. -// Each mechanism should eventually be closed by calling Close(). -// FIXME: Eventually expand on keyIdentity (namespace them between mechanisms to -// eliminate ambiguities, support CA signatures and perhaps other key properties) -type SigningMechanism interface { - // Close removes resources associated with the mechanism, if any. - Close() error - // SupportsSigning returns nil if the mechanism supports signing, or a SigningNotSupportedError. - SupportsSigning() error - // Sign creates a (non-detached) signature of input using keyIdentity. - // Fails with a SigningNotSupportedError if the mechanism does not support signing. - Sign(input []byte, keyIdentity string) ([]byte, error) - // Verify parses unverifiedSignature and returns the content and the signer's identity - Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) - // UntrustedSignatureContents returns UNTRUSTED contents of the signature WITHOUT ANY VERIFICATION, - // along with a short identifier of the key used for signing. - // WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys) - // is NOT the same as a "key identity" used in other calls ot this interface, and - // the values may have no recognizable relationship if the public key is not available. - UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) -} - -// SigningNotSupportedError is returned when trying to sign using a mechanism which does not support that. -type SigningNotSupportedError string - -func (err SigningNotSupportedError) Error() string { - return string(err) -} - -// NewGPGSigningMechanism returns a new GPG/OpenPGP signing mechanism for the user’s default -// GPG configuration ($GNUPGHOME / ~/.gnupg) -// The caller must call .Close() on the returned SigningMechanism. -func NewGPGSigningMechanism() (SigningMechanism, error) { - return newGPGSigningMechanismInDirectory("") -} - -// NewEphemeralGPGSigningMechanism returns a new GPG/OpenPGP signing mechanism which -// recognizes _only_ public keys from the supplied blob, and returns the identities -// of these keys. -// The caller must call .Close() on the returned SigningMechanism. -func NewEphemeralGPGSigningMechanism(blob []byte) (SigningMechanism, []string, error) { - return newEphemeralGPGSigningMechanism(blob) -} - -// gpgUntrustedSignatureContents returns UNTRUSTED contents of the signature WITHOUT ANY VERIFICATION, -// along with a short identifier of the key used for signing. -// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys) -// is NOT the same as a "key identity" used in other calls ot this interface, and -// the values may have no recognizable relationship if the public key is not available. -func gpgUntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) { - // This uses the Golang-native OpenPGP implementation instead of gpgme because we are not doing any cryptography. - md, err := openpgp.ReadMessage(bytes.NewReader(untrustedSignature), openpgp.EntityList{}, nil, nil) - if err != nil { - return nil, "", err - } - if !md.IsSigned { - return nil, "", errors.New("The input is not a signature") - } - content, err := ioutil.ReadAll(md.UnverifiedBody) - if err != nil { - // Coverage: An error during reading the body can happen only if - // 1) the message is encrypted, which is not our case (and we don’t give ReadMessage the key - // to decrypt the contents anyway), or - // 2) the message is signed AND we give ReadMessage a correspnding public key, which we don’t. - return nil, "", err - } - - // Uppercase the key ID for minimal consistency with the gpgme-returned fingerprints - // (but note that key ID is a suffix of the fingerprint only for V4 keys, not V3)! - return content, strings.ToUpper(fmt.Sprintf("%016X", md.SignedByKeyId)), nil -} diff --git a/vendor/github.com/containers/image/signature/mechanism_gpgme.go b/vendor/github.com/containers/image/signature/mechanism_gpgme.go deleted file mode 100644 index 4825ab27c6..0000000000 --- a/vendor/github.com/containers/image/signature/mechanism_gpgme.go +++ /dev/null @@ -1,175 +0,0 @@ -// +build !containers_image_openpgp - -package signature - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - - "github.com/mtrmac/gpgme" -) - -// A GPG/OpenPGP signing mechanism, implemented using gpgme. -type gpgmeSigningMechanism struct { - ctx *gpgme.Context - ephemeralDir string // If not "", a directory to be removed on Close() -} - -// newGPGSigningMechanismInDirectory returns a new GPG/OpenPGP signing mechanism, using optionalDir if not empty. -// The caller must call .Close() on the returned SigningMechanism. -func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, error) { - ctx, err := newGPGMEContext(optionalDir) - if err != nil { - return nil, err - } - return &gpgmeSigningMechanism{ - ctx: ctx, - ephemeralDir: "", - }, nil -} - -// newEphemeralGPGSigningMechanism returns a new GPG/OpenPGP signing mechanism which -// recognizes _only_ public keys from the supplied blob, and returns the identities -// of these keys. -// The caller must call .Close() on the returned SigningMechanism. -func newEphemeralGPGSigningMechanism(blob []byte) (SigningMechanism, []string, error) { - dir, err := ioutil.TempDir("", "containers-ephemeral-gpg-") - if err != nil { - return nil, nil, err - } - removeDir := true - defer func() { - if removeDir { - os.RemoveAll(dir) - } - }() - ctx, err := newGPGMEContext(dir) - if err != nil { - return nil, nil, err - } - mech := &gpgmeSigningMechanism{ - ctx: ctx, - ephemeralDir: dir, - } - keyIdentities, err := mech.importKeysFromBytes(blob) - if err != nil { - return nil, nil, err - } - - removeDir = false - return mech, keyIdentities, nil -} - -// newGPGMEContext returns a new *gpgme.Context, using optionalDir if not empty. -func newGPGMEContext(optionalDir string) (*gpgme.Context, error) { - ctx, err := gpgme.New() - if err != nil { - return nil, err - } - if err = ctx.SetProtocol(gpgme.ProtocolOpenPGP); err != nil { - return nil, err - } - if optionalDir != "" { - err := ctx.SetEngineInfo(gpgme.ProtocolOpenPGP, "", optionalDir) - if err != nil { - return nil, err - } - } - ctx.SetArmor(false) - ctx.SetTextMode(false) - return ctx, nil -} - -func (m *gpgmeSigningMechanism) Close() error { - if m.ephemeralDir != "" { - os.RemoveAll(m.ephemeralDir) // Ignore an error, if any - } - return nil -} - -// importKeysFromBytes imports public keys from the supplied blob and returns their identities. -// The blob is assumed to have an appropriate format (the caller is expected to know which one). -// NOTE: This may modify long-term state (e.g. key storage in a directory underlying the mechanism); -// but we do not make this public, it can only be used through newEphemeralGPGSigningMechanism. -func (m *gpgmeSigningMechanism) importKeysFromBytes(blob []byte) ([]string, error) { - inputData, err := gpgme.NewDataBytes(blob) - if err != nil { - return nil, err - } - res, err := m.ctx.Import(inputData) - if err != nil { - return nil, err - } - keyIdentities := []string{} - for _, i := range res.Imports { - if i.Result == nil { - keyIdentities = append(keyIdentities, i.Fingerprint) - } - } - return keyIdentities, nil -} - -// SupportsSigning returns nil if the mechanism supports signing, or a SigningNotSupportedError. -func (m *gpgmeSigningMechanism) SupportsSigning() error { - return nil -} - -// Sign creates a (non-detached) signature of input using keyIdentity. -// Fails with a SigningNotSupportedError if the mechanism does not support signing. -func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) { - key, err := m.ctx.GetKey(keyIdentity, true) - if err != nil { - return nil, err - } - inputData, err := gpgme.NewDataBytes(input) - if err != nil { - return nil, err - } - var sigBuffer bytes.Buffer - sigData, err := gpgme.NewDataWriter(&sigBuffer) - if err != nil { - return nil, err - } - if err = m.ctx.Sign([]*gpgme.Key{key}, inputData, sigData, gpgme.SigModeNormal); err != nil { - return nil, err - } - return sigBuffer.Bytes(), nil -} - -// Verify parses unverifiedSignature and returns the content and the signer's identity -func (m gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) { - signedBuffer := bytes.Buffer{} - signedData, err := gpgme.NewDataWriter(&signedBuffer) - if err != nil { - return nil, "", err - } - unverifiedSignatureData, err := gpgme.NewDataBytes(unverifiedSignature) - if err != nil { - return nil, "", err - } - _, sigs, err := m.ctx.Verify(unverifiedSignatureData, nil, signedData) - if err != nil { - return nil, "", err - } - if len(sigs) != 1 { - return nil, "", InvalidSignatureError{msg: fmt.Sprintf("Unexpected GPG signature count %d", len(sigs))} - } - sig := sigs[0] - // This is sig.Summary == gpgme.SigSumValid except for key trust, which we handle ourselves - if sig.Status != nil || sig.Validity == gpgme.ValidityNever || sig.ValidityReason != nil || sig.WrongKeyUsage { - // FIXME: Better error reporting eventually - return nil, "", InvalidSignatureError{msg: fmt.Sprintf("Invalid GPG signature: %#v", sig)} - } - return signedBuffer.Bytes(), sig.Fingerprint, nil -} - -// UntrustedSignatureContents returns UNTRUSTED contents of the signature WITHOUT ANY VERIFICATION, -// along with a short identifier of the key used for signing. -// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys) -// is NOT the same as a "key identity" used in other calls ot this interface, and -// the values may have no recognizable relationship if the public key is not available. -func (m gpgmeSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) { - return gpgUntrustedSignatureContents(untrustedSignature) -} diff --git a/vendor/github.com/containers/image/signature/mechanism_openpgp.go b/vendor/github.com/containers/image/signature/mechanism_openpgp.go deleted file mode 100644 index eccd610c9d..0000000000 --- a/vendor/github.com/containers/image/signature/mechanism_openpgp.go +++ /dev/null @@ -1,159 +0,0 @@ -// +build containers_image_openpgp - -package signature - -import ( - "bytes" - "errors" - "fmt" - "io/ioutil" - "os" - "path" - "strings" - "time" - - "github.com/containers/storage/pkg/homedir" - "golang.org/x/crypto/openpgp" -) - -// A GPG/OpenPGP signing mechanism, implemented using x/crypto/openpgp. -type openpgpSigningMechanism struct { - keyring openpgp.EntityList -} - -// newGPGSigningMechanismInDirectory returns a new GPG/OpenPGP signing mechanism, using optionalDir if not empty. -// The caller must call .Close() on the returned SigningMechanism. -func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, error) { - m := &openpgpSigningMechanism{ - keyring: openpgp.EntityList{}, - } - - gpgHome := optionalDir - if gpgHome == "" { - gpgHome = os.Getenv("GNUPGHOME") - if gpgHome == "" { - gpgHome = path.Join(homedir.Get(), ".gnupg") - } - } - - pubring, err := ioutil.ReadFile(path.Join(gpgHome, "pubring.gpg")) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } - } else { - _, err := m.importKeysFromBytes(pubring) - if err != nil { - return nil, err - } - } - return m, nil -} - -// newEphemeralGPGSigningMechanism returns a new GPG/OpenPGP signing mechanism which -// recognizes _only_ public keys from the supplied blob, and returns the identities -// of these keys. -// The caller must call .Close() on the returned SigningMechanism. -func newEphemeralGPGSigningMechanism(blob []byte) (SigningMechanism, []string, error) { - m := &openpgpSigningMechanism{ - keyring: openpgp.EntityList{}, - } - keyIdentities, err := m.importKeysFromBytes(blob) - if err != nil { - return nil, nil, err - } - return m, keyIdentities, nil -} - -func (m *openpgpSigningMechanism) Close() error { - return nil -} - -// importKeysFromBytes imports public keys from the supplied blob and returns their identities. -// The blob is assumed to have an appropriate format (the caller is expected to know which one). -func (m *openpgpSigningMechanism) importKeysFromBytes(blob []byte) ([]string, error) { - keyring, err := openpgp.ReadKeyRing(bytes.NewReader(blob)) - if err != nil { - k, e2 := openpgp.ReadArmoredKeyRing(bytes.NewReader(blob)) - if e2 != nil { - return nil, err // The original error -- FIXME: is this better? - } - keyring = k - } - - keyIdentities := []string{} - for _, entity := range keyring { - if entity.PrimaryKey == nil { - // Coverage: This should never happen, openpgp.ReadEntity fails with a - // openpgp.errors.StructuralError instead of returning an entity with this - // field set to nil. - continue - } - // Uppercase the fingerprint to be compatible with gpgme - keyIdentities = append(keyIdentities, strings.ToUpper(fmt.Sprintf("%x", entity.PrimaryKey.Fingerprint))) - m.keyring = append(m.keyring, entity) - } - return keyIdentities, nil -} - -// SupportsSigning returns nil if the mechanism supports signing, or a SigningNotSupportedError. -func (m *openpgpSigningMechanism) SupportsSigning() error { - return SigningNotSupportedError("signing is not supported in github.com/containers/image built with the containers_image_openpgp build tag") -} - -// Sign creates a (non-detached) signature of input using keyIdentity. -// Fails with a SigningNotSupportedError if the mechanism does not support signing. -func (m *openpgpSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) { - return nil, SigningNotSupportedError("signing is not supported in github.com/containers/image built with the containers_image_openpgp build tag") -} - -// Verify parses unverifiedSignature and returns the content and the signer's identity -func (m *openpgpSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) { - md, err := openpgp.ReadMessage(bytes.NewReader(unverifiedSignature), m.keyring, nil, nil) - if err != nil { - return nil, "", err - } - if !md.IsSigned { - return nil, "", errors.New("not signed") - } - content, err := ioutil.ReadAll(md.UnverifiedBody) - if err != nil { - // Coverage: md.UnverifiedBody.Read only fails if the body is encrypted - // (and possibly also signed, but it _must_ be encrypted) and the signing - // “modification detection code” detects a mismatch. But in that case, - // we would expect the signature verification to fail as well, and that is checked - // first. Besides, we are not supplying any decryption keys, so we really - // can never reach this “encrypted data MDC mismatch” path. - return nil, "", err - } - if md.SignatureError != nil { - return nil, "", fmt.Errorf("signature error: %v", md.SignatureError) - } - if md.SignedBy == nil { - return nil, "", InvalidSignatureError{msg: fmt.Sprintf("Invalid GPG signature: %#v", md.Signature)} - } - if md.Signature != nil { - if md.Signature.SigLifetimeSecs != nil { - expiry := md.Signature.CreationTime.Add(time.Duration(*md.Signature.SigLifetimeSecs) * time.Second) - if time.Now().After(expiry) { - return nil, "", InvalidSignatureError{msg: fmt.Sprintf("Signature expired on %s", expiry)} - } - } - } else if md.SignatureV3 == nil { - // Coverage: If md.SignedBy != nil, the final md.UnverifiedBody.Read() either sets one of md.Signature or md.SignatureV3, - // or sets md.SignatureError. - return nil, "", InvalidSignatureError{msg: "Unexpected openpgp.MessageDetails: neither Signature nor SignatureV3 is set"} - } - - // Uppercase the fingerprint to be compatible with gpgme - return content, strings.ToUpper(fmt.Sprintf("%x", md.SignedBy.PublicKey.Fingerprint)), nil -} - -// UntrustedSignatureContents returns UNTRUSTED contents of the signature WITHOUT ANY VERIFICATION, -// along with a short identifier of the key used for signing. -// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys) -// is NOT the same as a "key identity" used in other calls ot this interface, and -// the values may have no recognizable relationship if the public key is not available. -func (m openpgpSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) { - return gpgUntrustedSignatureContents(untrustedSignature) -} diff --git a/vendor/github.com/containers/image/signature/policy_config.go b/vendor/github.com/containers/image/signature/policy_config.go deleted file mode 100644 index 42cc12ab1b..0000000000 --- a/vendor/github.com/containers/image/signature/policy_config.go +++ /dev/null @@ -1,688 +0,0 @@ -// policy_config.go hanles creation of policy objects, either by parsing JSON -// or by programs building them programmatically. - -// The New* constructors are intended to be a stable API. FIXME: after an independent review. - -// Do not invoke the internals of the JSON marshaling/unmarshaling directly. - -// We can't just blindly call json.Unmarshal because that would silently ignore -// typos, and that would just not do for security policy. - -// FIXME? This is by no means an user-friendly parser: No location information in error messages, no other context. -// But at least it is not worse than blind json.Unmarshal()… - -package signature - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "path/filepath" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -// systemDefaultPolicyPath is the policy path used for DefaultPolicy(). -// You can override this at build time with -// -ldflags '-X github.com/containers/image/signature.systemDefaultPolicyPath=$your_path' -var systemDefaultPolicyPath = builtinDefaultPolicyPath - -// builtinDefaultPolicyPath is the policy pat used for DefaultPolicy(). -// DO NOT change this, instead see systemDefaultPolicyPath above. -const builtinDefaultPolicyPath = "/etc/containers/policy.json" - -// InvalidPolicyFormatError is returned when parsing an invalid policy configuration. -type InvalidPolicyFormatError string - -func (err InvalidPolicyFormatError) Error() string { - return string(err) -} - -// DefaultPolicy returns the default policy of the system. -// Most applications should be using this method to get the policy configured -// by the system administrator. -// ctx should usually be nil, can be set to override the default. -// NOTE: When this function returns an error, report it to the user and abort. -// DO NOT hard-code fallback policies in your application. -func DefaultPolicy(ctx *types.SystemContext) (*Policy, error) { - return NewPolicyFromFile(defaultPolicyPath(ctx)) -} - -// defaultPolicyPath returns a path to the default policy of the system. -func defaultPolicyPath(ctx *types.SystemContext) string { - if ctx != nil { - if ctx.SignaturePolicyPath != "" { - return ctx.SignaturePolicyPath - } - if ctx.RootForImplicitAbsolutePaths != "" { - return filepath.Join(ctx.RootForImplicitAbsolutePaths, systemDefaultPolicyPath) - } - } - return systemDefaultPolicyPath -} - -// NewPolicyFromFile returns a policy configured in the specified file. -func NewPolicyFromFile(fileName string) (*Policy, error) { - contents, err := ioutil.ReadFile(fileName) - if err != nil { - return nil, err - } - policy, err := NewPolicyFromBytes(contents) - if err != nil { - return nil, errors.Wrapf(err, "invalid policy in %q", fileName) - } - return policy, nil -} - -// NewPolicyFromBytes returns a policy parsed from the specified blob. -// Use this function instead of calling json.Unmarshal directly. -func NewPolicyFromBytes(data []byte) (*Policy, error) { - p := Policy{} - if err := json.Unmarshal(data, &p); err != nil { - return nil, InvalidPolicyFormatError(err.Error()) - } - return &p, nil -} - -// Compile-time check that Policy implements json.Unmarshaler. -var _ json.Unmarshaler = (*Policy)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (p *Policy) UnmarshalJSON(data []byte) error { - *p = Policy{} - transports := policyTransportsMap{} - if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { - switch key { - case "default": - return &p.Default - case "transports": - return &transports - default: - return nil - } - }); err != nil { - return err - } - - if p.Default == nil { - return InvalidPolicyFormatError("Default policy is missing") - } - p.Transports = map[string]PolicyTransportScopes(transports) - return nil -} - -// policyTransportsMap is a specialization of this map type for the strict JSON parsing semantics appropriate for the Policy.Transports member. -type policyTransportsMap map[string]PolicyTransportScopes - -// Compile-time check that policyTransportsMap implements json.Unmarshaler. -var _ json.Unmarshaler = (*policyTransportsMap)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (m *policyTransportsMap) UnmarshalJSON(data []byte) error { - // We can't unmarshal directly into map values because it is not possible to take an address of a map value. - // So, use a temporary map of pointers-to-slices and convert. - tmpMap := map[string]*PolicyTransportScopes{} - if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { - // transport can be nil - transport := transports.Get(key) - // paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe. - if _, ok := tmpMap[key]; ok { - return nil - } - ptsWithTransport := policyTransportScopesWithTransport{ - transport: transport, - dest: &PolicyTransportScopes{}, // This allocates a new instance on each call. - } - tmpMap[key] = ptsWithTransport.dest - return &ptsWithTransport - }); err != nil { - return err - } - for key, ptr := range tmpMap { - (*m)[key] = *ptr - } - return nil -} - -// Compile-time check that PolicyTransportScopes "implements"" json.Unmarshaler. -// we want to only use policyTransportScopesWithTransport -var _ json.Unmarshaler = (*PolicyTransportScopes)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (m *PolicyTransportScopes) UnmarshalJSON(data []byte) error { - return errors.New("Do not try to unmarshal PolicyTransportScopes directly") -} - -// policyTransportScopesWithTransport is a way to unmarshal a PolicyTransportScopes -// while validating using a specific ImageTransport if not nil. -type policyTransportScopesWithTransport struct { - transport types.ImageTransport - dest *PolicyTransportScopes -} - -// Compile-time check that policyTransportScopesWithTransport implements json.Unmarshaler. -var _ json.Unmarshaler = (*policyTransportScopesWithTransport)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (m *policyTransportScopesWithTransport) UnmarshalJSON(data []byte) error { - // We can't unmarshal directly into map values because it is not possible to take an address of a map value. - // So, use a temporary map of pointers-to-slices and convert. - tmpMap := map[string]*PolicyRequirements{} - if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { - // paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe. - if _, ok := tmpMap[key]; ok { - return nil - } - if key != "" && m.transport != nil { - if err := m.transport.ValidatePolicyConfigurationScope(key); err != nil { - return nil - } - } - ptr := &PolicyRequirements{} // This allocates a new instance on each call. - tmpMap[key] = ptr - return ptr - }); err != nil { - return err - } - for key, ptr := range tmpMap { - (*m.dest)[key] = *ptr - } - return nil -} - -// Compile-time check that PolicyRequirements implements json.Unmarshaler. -var _ json.Unmarshaler = (*PolicyRequirements)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (m *PolicyRequirements) UnmarshalJSON(data []byte) error { - reqJSONs := []json.RawMessage{} - if err := json.Unmarshal(data, &reqJSONs); err != nil { - return err - } - if len(reqJSONs) == 0 { - return InvalidPolicyFormatError("List of verification policy requirements must not be empty") - } - res := make([]PolicyRequirement, len(reqJSONs)) - for i, reqJSON := range reqJSONs { - req, err := newPolicyRequirementFromJSON(reqJSON) - if err != nil { - return err - } - res[i] = req - } - *m = res - return nil -} - -// newPolicyRequirementFromJSON parses JSON data into a PolicyRequirement implementation. -func newPolicyRequirementFromJSON(data []byte) (PolicyRequirement, error) { - var typeField prCommon - if err := json.Unmarshal(data, &typeField); err != nil { - return nil, err - } - var res PolicyRequirement - switch typeField.Type { - case prTypeInsecureAcceptAnything: - res = &prInsecureAcceptAnything{} - case prTypeReject: - res = &prReject{} - case prTypeSignedBy: - res = &prSignedBy{} - case prTypeSignedBaseLayer: - res = &prSignedBaseLayer{} - default: - return nil, InvalidPolicyFormatError(fmt.Sprintf("Unknown policy requirement type \"%s\"", typeField.Type)) - } - if err := json.Unmarshal(data, &res); err != nil { - return nil, err - } - return res, nil -} - -// newPRInsecureAcceptAnything is NewPRInsecureAcceptAnything, except it returns the private type. -func newPRInsecureAcceptAnything() *prInsecureAcceptAnything { - return &prInsecureAcceptAnything{prCommon{Type: prTypeInsecureAcceptAnything}} -} - -// NewPRInsecureAcceptAnything returns a new "insecureAcceptAnything" PolicyRequirement. -func NewPRInsecureAcceptAnything() PolicyRequirement { - return newPRInsecureAcceptAnything() -} - -// Compile-time check that prInsecureAcceptAnything implements json.Unmarshaler. -var _ json.Unmarshaler = (*prInsecureAcceptAnything)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (pr *prInsecureAcceptAnything) UnmarshalJSON(data []byte) error { - *pr = prInsecureAcceptAnything{} - var tmp prInsecureAcceptAnything - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - }); err != nil { - return err - } - - if tmp.Type != prTypeInsecureAcceptAnything { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - *pr = *newPRInsecureAcceptAnything() - return nil -} - -// newPRReject is NewPRReject, except it returns the private type. -func newPRReject() *prReject { - return &prReject{prCommon{Type: prTypeReject}} -} - -// NewPRReject returns a new "reject" PolicyRequirement. -func NewPRReject() PolicyRequirement { - return newPRReject() -} - -// Compile-time check that prReject implements json.Unmarshaler. -var _ json.Unmarshaler = (*prReject)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (pr *prReject) UnmarshalJSON(data []byte) error { - *pr = prReject{} - var tmp prReject - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - }); err != nil { - return err - } - - if tmp.Type != prTypeReject { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - *pr = *newPRReject() - return nil -} - -// newPRSignedBy returns a new prSignedBy if parameters are valid. -func newPRSignedBy(keyType sbKeyType, keyPath string, keyData []byte, signedIdentity PolicyReferenceMatch) (*prSignedBy, error) { - if !keyType.IsValid() { - return nil, InvalidPolicyFormatError(fmt.Sprintf("invalid keyType \"%s\"", keyType)) - } - if len(keyPath) > 0 && len(keyData) > 0 { - return nil, InvalidPolicyFormatError("keyType and keyData cannot be used simultaneously") - } - if signedIdentity == nil { - return nil, InvalidPolicyFormatError("signedIdentity not specified") - } - return &prSignedBy{ - prCommon: prCommon{Type: prTypeSignedBy}, - KeyType: keyType, - KeyPath: keyPath, - KeyData: keyData, - SignedIdentity: signedIdentity, - }, nil -} - -// newPRSignedByKeyPath is NewPRSignedByKeyPath, except it returns the private type. -func newPRSignedByKeyPath(keyType sbKeyType, keyPath string, signedIdentity PolicyReferenceMatch) (*prSignedBy, error) { - return newPRSignedBy(keyType, keyPath, nil, signedIdentity) -} - -// NewPRSignedByKeyPath returns a new "signedBy" PolicyRequirement using a KeyPath -func NewPRSignedByKeyPath(keyType sbKeyType, keyPath string, signedIdentity PolicyReferenceMatch) (PolicyRequirement, error) { - return newPRSignedByKeyPath(keyType, keyPath, signedIdentity) -} - -// newPRSignedByKeyData is NewPRSignedByKeyData, except it returns the private type. -func newPRSignedByKeyData(keyType sbKeyType, keyData []byte, signedIdentity PolicyReferenceMatch) (*prSignedBy, error) { - return newPRSignedBy(keyType, "", keyData, signedIdentity) -} - -// NewPRSignedByKeyData returns a new "signedBy" PolicyRequirement using a KeyData -func NewPRSignedByKeyData(keyType sbKeyType, keyData []byte, signedIdentity PolicyReferenceMatch) (PolicyRequirement, error) { - return newPRSignedByKeyData(keyType, keyData, signedIdentity) -} - -// Compile-time check that prSignedBy implements json.Unmarshaler. -var _ json.Unmarshaler = (*prSignedBy)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (pr *prSignedBy) UnmarshalJSON(data []byte) error { - *pr = prSignedBy{} - var tmp prSignedBy - var gotKeyPath, gotKeyData = false, false - var signedIdentity json.RawMessage - if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { - switch key { - case "type": - return &tmp.Type - case "keyType": - return &tmp.KeyType - case "keyPath": - gotKeyPath = true - return &tmp.KeyPath - case "keyData": - gotKeyData = true - return &tmp.KeyData - case "signedIdentity": - return &signedIdentity - default: - return nil - } - }); err != nil { - return err - } - - if tmp.Type != prTypeSignedBy { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - if signedIdentity == nil { - tmp.SignedIdentity = NewPRMMatchRepoDigestOrExact() - } else { - si, err := newPolicyReferenceMatchFromJSON(signedIdentity) - if err != nil { - return err - } - tmp.SignedIdentity = si - } - - var res *prSignedBy - var err error - switch { - case gotKeyPath && gotKeyData: - return InvalidPolicyFormatError("keyPath and keyData cannot be used simultaneously") - case gotKeyPath && !gotKeyData: - res, err = newPRSignedByKeyPath(tmp.KeyType, tmp.KeyPath, tmp.SignedIdentity) - case !gotKeyPath && gotKeyData: - res, err = newPRSignedByKeyData(tmp.KeyType, tmp.KeyData, tmp.SignedIdentity) - case !gotKeyPath && !gotKeyData: - return InvalidPolicyFormatError("At least one of keyPath and keyData mus be specified") - default: // Coverage: This should never happen - return errors.Errorf("Impossible keyPath/keyData presence combination!?") - } - if err != nil { - return err - } - *pr = *res - - return nil -} - -// IsValid returns true iff kt is a recognized value -func (kt sbKeyType) IsValid() bool { - switch kt { - case SBKeyTypeGPGKeys, SBKeyTypeSignedByGPGKeys, - SBKeyTypeX509Certificates, SBKeyTypeSignedByX509CAs: - return true - default: - return false - } -} - -// Compile-time check that sbKeyType implements json.Unmarshaler. -var _ json.Unmarshaler = (*sbKeyType)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (kt *sbKeyType) UnmarshalJSON(data []byte) error { - *kt = sbKeyType("") - var s string - if err := json.Unmarshal(data, &s); err != nil { - return err - } - if !sbKeyType(s).IsValid() { - return InvalidPolicyFormatError(fmt.Sprintf("Unrecognized keyType value \"%s\"", s)) - } - *kt = sbKeyType(s) - return nil -} - -// newPRSignedBaseLayer is NewPRSignedBaseLayer, except it returns the private type. -func newPRSignedBaseLayer(baseLayerIdentity PolicyReferenceMatch) (*prSignedBaseLayer, error) { - if baseLayerIdentity == nil { - return nil, InvalidPolicyFormatError("baseLayerIdentity not specified") - } - return &prSignedBaseLayer{ - prCommon: prCommon{Type: prTypeSignedBaseLayer}, - BaseLayerIdentity: baseLayerIdentity, - }, nil -} - -// NewPRSignedBaseLayer returns a new "signedBaseLayer" PolicyRequirement. -func NewPRSignedBaseLayer(baseLayerIdentity PolicyReferenceMatch) (PolicyRequirement, error) { - return newPRSignedBaseLayer(baseLayerIdentity) -} - -// Compile-time check that prSignedBaseLayer implements json.Unmarshaler. -var _ json.Unmarshaler = (*prSignedBaseLayer)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (pr *prSignedBaseLayer) UnmarshalJSON(data []byte) error { - *pr = prSignedBaseLayer{} - var tmp prSignedBaseLayer - var baseLayerIdentity json.RawMessage - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - "baseLayerIdentity": &baseLayerIdentity, - }); err != nil { - return err - } - - if tmp.Type != prTypeSignedBaseLayer { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - bli, err := newPolicyReferenceMatchFromJSON(baseLayerIdentity) - if err != nil { - return err - } - res, err := newPRSignedBaseLayer(bli) - if err != nil { - // Coverage: This should never happen, newPolicyReferenceMatchFromJSON has ensured bli is valid. - return err - } - *pr = *res - return nil -} - -// newPolicyReferenceMatchFromJSON parses JSON data into a PolicyReferenceMatch implementation. -func newPolicyReferenceMatchFromJSON(data []byte) (PolicyReferenceMatch, error) { - var typeField prmCommon - if err := json.Unmarshal(data, &typeField); err != nil { - return nil, err - } - var res PolicyReferenceMatch - switch typeField.Type { - case prmTypeMatchExact: - res = &prmMatchExact{} - case prmTypeMatchRepoDigestOrExact: - res = &prmMatchRepoDigestOrExact{} - case prmTypeMatchRepository: - res = &prmMatchRepository{} - case prmTypeExactReference: - res = &prmExactReference{} - case prmTypeExactRepository: - res = &prmExactRepository{} - default: - return nil, InvalidPolicyFormatError(fmt.Sprintf("Unknown policy reference match type \"%s\"", typeField.Type)) - } - if err := json.Unmarshal(data, &res); err != nil { - return nil, err - } - return res, nil -} - -// newPRMMatchExact is NewPRMMatchExact, except it resturns the private type. -func newPRMMatchExact() *prmMatchExact { - return &prmMatchExact{prmCommon{Type: prmTypeMatchExact}} -} - -// NewPRMMatchExact returns a new "matchExact" PolicyReferenceMatch. -func NewPRMMatchExact() PolicyReferenceMatch { - return newPRMMatchExact() -} - -// Compile-time check that prmMatchExact implements json.Unmarshaler. -var _ json.Unmarshaler = (*prmMatchExact)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (prm *prmMatchExact) UnmarshalJSON(data []byte) error { - *prm = prmMatchExact{} - var tmp prmMatchExact - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - }); err != nil { - return err - } - - if tmp.Type != prmTypeMatchExact { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - *prm = *newPRMMatchExact() - return nil -} - -// newPRMMatchRepoDigestOrExact is NewPRMMatchRepoDigestOrExact, except it resturns the private type. -func newPRMMatchRepoDigestOrExact() *prmMatchRepoDigestOrExact { - return &prmMatchRepoDigestOrExact{prmCommon{Type: prmTypeMatchRepoDigestOrExact}} -} - -// NewPRMMatchRepoDigestOrExact returns a new "matchRepoDigestOrExact" PolicyReferenceMatch. -func NewPRMMatchRepoDigestOrExact() PolicyReferenceMatch { - return newPRMMatchRepoDigestOrExact() -} - -// Compile-time check that prmMatchRepoDigestOrExact implements json.Unmarshaler. -var _ json.Unmarshaler = (*prmMatchRepoDigestOrExact)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (prm *prmMatchRepoDigestOrExact) UnmarshalJSON(data []byte) error { - *prm = prmMatchRepoDigestOrExact{} - var tmp prmMatchRepoDigestOrExact - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - }); err != nil { - return err - } - - if tmp.Type != prmTypeMatchRepoDigestOrExact { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - *prm = *newPRMMatchRepoDigestOrExact() - return nil -} - -// newPRMMatchRepository is NewPRMMatchRepository, except it resturns the private type. -func newPRMMatchRepository() *prmMatchRepository { - return &prmMatchRepository{prmCommon{Type: prmTypeMatchRepository}} -} - -// NewPRMMatchRepository returns a new "matchRepository" PolicyReferenceMatch. -func NewPRMMatchRepository() PolicyReferenceMatch { - return newPRMMatchRepository() -} - -// Compile-time check that prmMatchRepository implements json.Unmarshaler. -var _ json.Unmarshaler = (*prmMatchRepository)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (prm *prmMatchRepository) UnmarshalJSON(data []byte) error { - *prm = prmMatchRepository{} - var tmp prmMatchRepository - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - }); err != nil { - return err - } - - if tmp.Type != prmTypeMatchRepository { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - *prm = *newPRMMatchRepository() - return nil -} - -// newPRMExactReference is NewPRMExactReference, except it resturns the private type. -func newPRMExactReference(dockerReference string) (*prmExactReference, error) { - ref, err := reference.ParseNormalizedNamed(dockerReference) - if err != nil { - return nil, InvalidPolicyFormatError(fmt.Sprintf("Invalid format of dockerReference %s: %s", dockerReference, err.Error())) - } - if reference.IsNameOnly(ref) { - return nil, InvalidPolicyFormatError(fmt.Sprintf("dockerReference %s contains neither a tag nor digest", dockerReference)) - } - return &prmExactReference{ - prmCommon: prmCommon{Type: prmTypeExactReference}, - DockerReference: dockerReference, - }, nil -} - -// NewPRMExactReference returns a new "exactReference" PolicyReferenceMatch. -func NewPRMExactReference(dockerReference string) (PolicyReferenceMatch, error) { - return newPRMExactReference(dockerReference) -} - -// Compile-time check that prmExactReference implements json.Unmarshaler. -var _ json.Unmarshaler = (*prmExactReference)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (prm *prmExactReference) UnmarshalJSON(data []byte) error { - *prm = prmExactReference{} - var tmp prmExactReference - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - "dockerReference": &tmp.DockerReference, - }); err != nil { - return err - } - - if tmp.Type != prmTypeExactReference { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - - res, err := newPRMExactReference(tmp.DockerReference) - if err != nil { - return err - } - *prm = *res - return nil -} - -// newPRMExactRepository is NewPRMExactRepository, except it resturns the private type. -func newPRMExactRepository(dockerRepository string) (*prmExactRepository, error) { - if _, err := reference.ParseNormalizedNamed(dockerRepository); err != nil { - return nil, InvalidPolicyFormatError(fmt.Sprintf("Invalid format of dockerRepository %s: %s", dockerRepository, err.Error())) - } - return &prmExactRepository{ - prmCommon: prmCommon{Type: prmTypeExactRepository}, - DockerRepository: dockerRepository, - }, nil -} - -// NewPRMExactRepository returns a new "exactRepository" PolicyRepositoryMatch. -func NewPRMExactRepository(dockerRepository string) (PolicyReferenceMatch, error) { - return newPRMExactRepository(dockerRepository) -} - -// Compile-time check that prmExactRepository implements json.Unmarshaler. -var _ json.Unmarshaler = (*prmExactRepository)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (prm *prmExactRepository) UnmarshalJSON(data []byte) error { - *prm = prmExactRepository{} - var tmp prmExactRepository - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "type": &tmp.Type, - "dockerRepository": &tmp.DockerRepository, - }); err != nil { - return err - } - - if tmp.Type != prmTypeExactRepository { - return InvalidPolicyFormatError(fmt.Sprintf("Unexpected policy requirement type \"%s\"", tmp.Type)) - } - - res, err := newPRMExactRepository(tmp.DockerRepository) - if err != nil { - return err - } - *prm = *res - return nil -} diff --git a/vendor/github.com/containers/image/signature/policy_eval.go b/vendor/github.com/containers/image/signature/policy_eval.go deleted file mode 100644 index f818eb095a..0000000000 --- a/vendor/github.com/containers/image/signature/policy_eval.go +++ /dev/null @@ -1,289 +0,0 @@ -// This defines the top-level policy evaluation API. -// To the extent possible, the interface of the fuctions provided -// here is intended to be completely unambiguous, and stable for users -// to rely on. - -package signature - -import ( - "context" - - "github.com/containers/image/types" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// PolicyRequirementError is an explanatory text for rejecting a signature or an image. -type PolicyRequirementError string - -func (err PolicyRequirementError) Error() string { - return string(err) -} - -// signatureAcceptanceResult is the principal value returned by isSignatureAuthorAccepted. -type signatureAcceptanceResult string - -const ( - sarAccepted signatureAcceptanceResult = "sarAccepted" - sarRejected signatureAcceptanceResult = "sarRejected" - sarUnknown signatureAcceptanceResult = "sarUnknown" -) - -// PolicyRequirement is a rule which must be satisfied by at least one of the signatures of an image. -// The type is public, but its definition is private. -type PolicyRequirement interface { - // FIXME: For speed, we should support creating per-context state (not stored in the PolicyRequirement), to cache - // costly initialization like creating temporary GPG home directories and reading files. - // Setup() (someState, error) - // Then, the operations below would be done on the someState object, not directly on a PolicyRequirement. - - // isSignatureAuthorAccepted, given an image and a signature blob, returns: - // - sarAccepted if the signature has been verified against the appropriate public key - // (where "appropriate public key" may depend on the contents of the signature); - // in that case a parsed Signature should be returned. - // - sarRejected if the signature has not been verified; - // in that case error must be non-nil, and should be an PolicyRequirementError if evaluation - // succeeded but the result was rejection. - // - sarUnknown if if this PolicyRequirement does not deal with signatures. - // NOTE: sarUnknown should not be returned if this PolicyRequirement should make a decision but something failed. - // Returning sarUnknown and a non-nil error value is invalid. - // WARNING: This makes the signature contents acceptable for futher processing, - // but it does not necessarily mean that the contents of the signature are - // consistent with local policy. - // For example: - // - Do not use a true value to determine whether to run - // a container based on this image; use IsRunningImageAllowed instead. - // - Just because a signature is accepted does not automatically mean the contents of the - // signature are authorized to run code as root, or to affect system or cluster configuration. - isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) - - // isRunningImageAllowed returns true if the requirement allows running an image. - // If it returns false, err must be non-nil, and should be an PolicyRequirementError if evaluation - // succeeded but the result was rejection. - // WARNING: This validates signatures and the manifest, but does not download or validate the - // layers. Users must validate that the layers match their expected digests. - isRunningImageAllowed(image types.UnparsedImage) (bool, error) -} - -// PolicyReferenceMatch specifies a set of image identities accepted in PolicyRequirement. -// The type is public, but its implementation is private. -type PolicyReferenceMatch interface { - // matchesDockerReference decides whether a specific image identity is accepted for an image - // (or, usually, for the image's Reference().DockerReference()). Note that - // image.Reference().DockerReference() may be nil. - matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool -} - -// PolicyContext encapsulates a policy and possible cached state -// for speeding up its evaluation. -type PolicyContext struct { - Policy *Policy - state policyContextState // Internal consistency checking -} - -// policyContextState is used internally to verify the users are not misusing a PolicyContext. -type policyContextState string - -const ( - pcInvalid policyContextState = "" - pcInitializing policyContextState = "Initializing" - pcReady policyContextState = "Ready" - pcInUse policyContextState = "InUse" - pcDestroying policyContextState = "Destroying" - pcDestroyed policyContextState = "Destroyed" -) - -// changeContextState changes pc.state, or fails if the state is unexpected -func (pc *PolicyContext) changeState(expected, new policyContextState) error { - if pc.state != expected { - return errors.Errorf(`"Invalid PolicyContext state, expected "%s", found "%s"`, expected, pc.state) - } - pc.state = new - return nil -} - -// NewPolicyContext sets up and initializes a context for the specified policy. -// The policy must not be modified while the context exists. FIXME: make a deep copy? -// If this function succeeds, the caller should call PolicyContext.Destroy() when done. -func NewPolicyContext(policy *Policy) (*PolicyContext, error) { - pc := &PolicyContext{Policy: policy, state: pcInitializing} - // FIXME: initialize - if err := pc.changeState(pcInitializing, pcReady); err != nil { - // Huh?! This should never fail, we didn't give the pointer to anybody. - // Just give up and leave unclean state around. - return nil, err - } - return pc, nil -} - -// Destroy should be called when the user of the context is done with it. -func (pc *PolicyContext) Destroy() error { - if err := pc.changeState(pcReady, pcDestroying); err != nil { - return err - } - // FIXME: destroy - return pc.changeState(pcDestroying, pcDestroyed) -} - -// policyIdentityLogName returns a string description of the image identity for policy purposes. -// ONLY use this for log messages, not for any decisions! -func policyIdentityLogName(ref types.ImageReference) string { - return ref.Transport().Name() + ":" + ref.PolicyConfigurationIdentity() -} - -// requirementsForImageRef selects the appropriate requirements for ref. -func (pc *PolicyContext) requirementsForImageRef(ref types.ImageReference) PolicyRequirements { - // Do we have a PolicyTransportScopes for this transport? - transportName := ref.Transport().Name() - if transportScopes, ok := pc.Policy.Transports[transportName]; ok { - // Look for a full match. - identity := ref.PolicyConfigurationIdentity() - if req, ok := transportScopes[identity]; ok { - logrus.Debugf(` Using transport "%s" policy section %s`, transportName, identity) - return req - } - - // Look for a match of the possible parent namespaces. - for _, name := range ref.PolicyConfigurationNamespaces() { - if req, ok := transportScopes[name]; ok { - logrus.Debugf(` Using transport "%s" specific policy section %s`, transportName, name) - return req - } - } - - // Look for a default match for the transport. - if req, ok := transportScopes[""]; ok { - logrus.Debugf(` Using transport "%s" policy section ""`, transportName) - return req - } - } - - logrus.Debugf(" Using default policy section") - return pc.Policy.Default -} - -// GetSignaturesWithAcceptedAuthor returns those signatures from an image -// for which the policy accepts the author (and which have been successfully -// verified). -// NOTE: This may legitimately return an empty list and no error, if the image -// has no signatures or only invalid signatures. -// WARNING: This makes the signature contents acceptable for futher processing, -// but it does not necessarily mean that the contents of the signature are -// consistent with local policy. -// For example: -// - Do not use a an existence of an accepted signature to determine whether to run -// a container based on this image; use IsRunningImageAllowed instead. -// - Just because a signature is accepted does not automatically mean the contents of the -// signature are authorized to run code as root, or to affect system or cluster configuration. -func (pc *PolicyContext) GetSignaturesWithAcceptedAuthor(image types.UnparsedImage) (sigs []*Signature, finalErr error) { - if err := pc.changeState(pcReady, pcInUse); err != nil { - return nil, err - } - defer func() { - if err := pc.changeState(pcInUse, pcReady); err != nil { - sigs = nil - finalErr = err - } - }() - - logrus.Debugf("GetSignaturesWithAcceptedAuthor for image %s", policyIdentityLogName(image.Reference())) - reqs := pc.requirementsForImageRef(image.Reference()) - - // FIXME: rename Signatures to UnverifiedSignatures - // FIXME: pass context.Context - unverifiedSignatures, err := image.Signatures(context.TODO()) - if err != nil { - return nil, err - } - - res := make([]*Signature, 0, len(unverifiedSignatures)) - for sigNumber, sig := range unverifiedSignatures { - var acceptedSig *Signature // non-nil if accepted - rejected := false - // FIXME? Say more about the contents of the signature, i.e. parse it even before verification?! - logrus.Debugf("Evaluating signature %d:", sigNumber) - interpretingReqs: - for reqNumber, req := range reqs { - // FIXME: Log the requirement itself? For now, we use just the number. - // FIXME: supply state - switch res, as, err := req.isSignatureAuthorAccepted(image, sig); res { - case sarAccepted: - if as == nil { // Coverage: this should never happen - logrus.Debugf(" Requirement %d: internal inconsistency: sarAccepted but no parsed contents", reqNumber) - rejected = true - break interpretingReqs - } - logrus.Debugf(" Requirement %d: signature accepted", reqNumber) - if acceptedSig == nil { - acceptedSig = as - } else if *as != *acceptedSig { // Coverage: this should never happen - // Huh?! Two ways of verifying the same signature blob resulted in two different parses of its already accepted contents? - logrus.Debugf(" Requirement %d: internal inconsistency: sarAccepted but different parsed contents", reqNumber) - rejected = true - acceptedSig = nil - break interpretingReqs - } - case sarRejected: - logrus.Debugf(" Requirement %d: signature rejected: %s", reqNumber, err.Error()) - rejected = true - break interpretingReqs - case sarUnknown: - if err != nil { // Coverage: this should never happen - logrus.Debugf(" Requirement %d: internal inconsistency: sarUnknown but an error message %s", reqNumber, err.Error()) - rejected = true - break interpretingReqs - } - logrus.Debugf(" Requirement %d: signature state unknown, continuing", reqNumber) - default: // Coverage: this should never happen - logrus.Debugf(" Requirement %d: internal inconsistency: unknown result %#v", reqNumber, string(res)) - rejected = true - break interpretingReqs - } - } - // This also handles the (invalid) case of empty reqs, by rejecting the signature. - if acceptedSig != nil && !rejected { - logrus.Debugf(" Overall: OK, signature accepted") - res = append(res, acceptedSig) - } else { - logrus.Debugf(" Overall: Signature not accepted") - } - } - return res, nil -} - -// IsRunningImageAllowed returns true iff the policy allows running the image. -// If it returns false, err must be non-nil, and should be an PolicyRequirementError if evaluation -// succeeded but the result was rejection. -// WARNING: This validates signatures and the manifest, but does not download or validate the -// layers. Users must validate that the layers match their expected digests. -func (pc *PolicyContext) IsRunningImageAllowed(image types.UnparsedImage) (res bool, finalErr error) { - if err := pc.changeState(pcReady, pcInUse); err != nil { - return false, err - } - defer func() { - if err := pc.changeState(pcInUse, pcReady); err != nil { - res = false - finalErr = err - } - }() - - logrus.Debugf("IsRunningImageAllowed for image %s", policyIdentityLogName(image.Reference())) - reqs := pc.requirementsForImageRef(image.Reference()) - - if len(reqs) == 0 { - return false, PolicyRequirementError("List of verification policy requirements must not be empty") - } - - for reqNumber, req := range reqs { - // FIXME: supply state - allowed, err := req.isRunningImageAllowed(image) - if !allowed { - logrus.Debugf("Requirement %d: denied, done", reqNumber) - return false, err - } - logrus.Debugf(" Requirement %d: allowed", reqNumber) - } - // We have tested that len(reqs) != 0, so at least one req must have explicitly allowed this image. - logrus.Debugf("Overall: allowed") - return true, nil -} diff --git a/vendor/github.com/containers/image/signature/policy_eval_baselayer.go b/vendor/github.com/containers/image/signature/policy_eval_baselayer.go deleted file mode 100644 index 898958012e..0000000000 --- a/vendor/github.com/containers/image/signature/policy_eval_baselayer.go +++ /dev/null @@ -1,18 +0,0 @@ -// Policy evaluation for prSignedBaseLayer. - -package signature - -import ( - "github.com/containers/image/types" - "github.com/sirupsen/logrus" -) - -func (pr *prSignedBaseLayer) isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) { - return sarUnknown, nil, nil -} - -func (pr *prSignedBaseLayer) isRunningImageAllowed(image types.UnparsedImage) (bool, error) { - // FIXME? Reject this at policy parsing time already? - logrus.Errorf("signedBaseLayer not implemented yet!") - return false, PolicyRequirementError("signedBaseLayer not implemented yet!") -} diff --git a/vendor/github.com/containers/image/signature/policy_eval_signedby.go b/vendor/github.com/containers/image/signature/policy_eval_signedby.go deleted file mode 100644 index 56665124c0..0000000000 --- a/vendor/github.com/containers/image/signature/policy_eval_signedby.go +++ /dev/null @@ -1,131 +0,0 @@ -// Policy evaluation for prSignedBy. - -package signature - -import ( - "context" - "fmt" - "io/ioutil" - "strings" - - "github.com/pkg/errors" - - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/opencontainers/go-digest" -) - -func (pr *prSignedBy) isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) { - switch pr.KeyType { - case SBKeyTypeGPGKeys: - case SBKeyTypeSignedByGPGKeys, SBKeyTypeX509Certificates, SBKeyTypeSignedByX509CAs: - // FIXME? Reject this at policy parsing time already? - return sarRejected, nil, errors.Errorf(`"Unimplemented "keyType" value "%s"`, string(pr.KeyType)) - default: - // This should never happen, newPRSignedBy ensures KeyType.IsValid() - return sarRejected, nil, errors.Errorf(`"Unknown "keyType" value "%s"`, string(pr.KeyType)) - } - - if pr.KeyPath != "" && pr.KeyData != nil { - return sarRejected, nil, errors.New(`Internal inconsistency: both "keyPath" and "keyData" specified`) - } - // FIXME: move this to per-context initialization - var data []byte - if pr.KeyData != nil { - data = pr.KeyData - } else { - d, err := ioutil.ReadFile(pr.KeyPath) - if err != nil { - return sarRejected, nil, err - } - data = d - } - - // FIXME: move this to per-context initialization - mech, trustedIdentities, err := NewEphemeralGPGSigningMechanism(data) - if err != nil { - return sarRejected, nil, err - } - defer mech.Close() - if len(trustedIdentities) == 0 { - return sarRejected, nil, PolicyRequirementError("No public keys imported") - } - - signature, err := verifyAndExtractSignature(mech, sig, signatureAcceptanceRules{ - validateKeyIdentity: func(keyIdentity string) error { - for _, trustedIdentity := range trustedIdentities { - if keyIdentity == trustedIdentity { - return nil - } - } - // Coverage: We use a private GPG home directory and only import trusted keys, so this should - // not be reachable. - return PolicyRequirementError(fmt.Sprintf("Signature by key %s is not accepted", keyIdentity)) - }, - validateSignedDockerReference: func(ref string) error { - if !pr.SignedIdentity.matchesDockerReference(image, ref) { - return PolicyRequirementError(fmt.Sprintf("Signature for identity %s is not accepted", ref)) - } - return nil - }, - validateSignedDockerManifestDigest: func(digest digest.Digest) error { - m, _, err := image.Manifest() - if err != nil { - return err - } - digestMatches, err := manifest.MatchesDigest(m, digest) - if err != nil { - return err - } - if !digestMatches { - return PolicyRequirementError(fmt.Sprintf("Signature for digest %s does not match", digest)) - } - return nil - }, - }) - if err != nil { - return sarRejected, nil, err - } - - return sarAccepted, signature, nil -} - -func (pr *prSignedBy) isRunningImageAllowed(image types.UnparsedImage) (bool, error) { - // FIXME: pass context.Context - sigs, err := image.Signatures(context.TODO()) - if err != nil { - return false, err - } - var rejections []error - for _, s := range sigs { - var reason error - switch res, _, err := pr.isSignatureAuthorAccepted(image, s); res { - case sarAccepted: - // One accepted signature is enough. - return true, nil - case sarRejected: - reason = err - case sarUnknown: - // Huh?! This should not happen at all; treat it as any other invalid value. - fallthrough - default: - reason = errors.Errorf(`Internal error: Unexpected signature verification result "%s"`, string(res)) - } - rejections = append(rejections, reason) - } - var summary error - switch len(rejections) { - case 0: - summary = PolicyRequirementError("A signature was required, but no signature exists") - case 1: - summary = rejections[0] - default: - var msgs []string - for _, e := range rejections { - msgs = append(msgs, e.Error()) - } - summary = PolicyRequirementError(fmt.Sprintf("None of the signatures were accepted, reasons: %s", - strings.Join(msgs, "; "))) - } - return false, summary -} diff --git a/vendor/github.com/containers/image/signature/policy_eval_simple.go b/vendor/github.com/containers/image/signature/policy_eval_simple.go deleted file mode 100644 index 19a71e6d99..0000000000 --- a/vendor/github.com/containers/image/signature/policy_eval_simple.go +++ /dev/null @@ -1,28 +0,0 @@ -// Policy evaluation for the various simple PolicyRequirement types. - -package signature - -import ( - "fmt" - - "github.com/containers/image/transports" - "github.com/containers/image/types" -) - -func (pr *prInsecureAcceptAnything) isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) { - // prInsecureAcceptAnything semantics: Every image is allowed to run, - // but this does not consider the signature as verified. - return sarUnknown, nil, nil -} - -func (pr *prInsecureAcceptAnything) isRunningImageAllowed(image types.UnparsedImage) (bool, error) { - return true, nil -} - -func (pr *prReject) isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) { - return sarRejected, nil, PolicyRequirementError(fmt.Sprintf("Any signatures for image %s are rejected by policy.", transports.ImageName(image.Reference()))) -} - -func (pr *prReject) isRunningImageAllowed(image types.UnparsedImage) (bool, error) { - return false, PolicyRequirementError(fmt.Sprintf("Running image %s is rejected by policy.", transports.ImageName(image.Reference()))) -} diff --git a/vendor/github.com/containers/image/signature/policy_reference_match.go b/vendor/github.com/containers/image/signature/policy_reference_match.go deleted file mode 100644 index a8dad67701..0000000000 --- a/vendor/github.com/containers/image/signature/policy_reference_match.go +++ /dev/null @@ -1,101 +0,0 @@ -// PolicyReferenceMatch implementations. - -package signature - -import ( - "fmt" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/transports" - "github.com/containers/image/types" -) - -// parseImageAndDockerReference converts an image and a reference string into two parsed entities, failing on any error and handling unidentified images. -func parseImageAndDockerReference(image types.UnparsedImage, s2 string) (reference.Named, reference.Named, error) { - r1 := image.Reference().DockerReference() - if r1 == nil { - return nil, nil, PolicyRequirementError(fmt.Sprintf("Docker reference match attempted on image %s with no known Docker reference identity", - transports.ImageName(image.Reference()))) - } - r2, err := reference.ParseNormalizedNamed(s2) - if err != nil { - return nil, nil, err - } - return r1, r2, nil -} - -func (prm *prmMatchExact) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { - intended, signature, err := parseImageAndDockerReference(image, signatureDockerReference) - if err != nil { - return false - } - // Do not add default tags: image.Reference().DockerReference() should contain it already, and signatureDockerReference should be exact; so, verify that now. - if reference.IsNameOnly(intended) || reference.IsNameOnly(signature) { - return false - } - return signature.String() == intended.String() -} - -func (prm *prmMatchRepoDigestOrExact) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { - intended, signature, err := parseImageAndDockerReference(image, signatureDockerReference) - if err != nil { - return false - } - - // Do not add default tags: image.Reference().DockerReference() should contain it already, and signatureDockerReference should be exact; so, verify that now. - if reference.IsNameOnly(signature) { - return false - } - switch intended.(type) { - case reference.NamedTagged: // Includes the case when intended has both a tag and a digest. - return signature.String() == intended.String() - case reference.Canonical: - // We don’t actually compare the manifest digest against the signature here; that happens prSignedBy.in UnparsedImage.Manifest. - // Becase UnparsedImage.Manifest verifies the intended.Digest() against the manifest, and prSignedBy verifies the signature digest against the manifest, - // we know that signature digest matches intended.Digest() (but intended.Digest() and signature digest may use different algorithms) - return signature.Name() == intended.Name() - default: // !reference.IsNameOnly(intended) - return false - } -} - -func (prm *prmMatchRepository) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { - intended, signature, err := parseImageAndDockerReference(image, signatureDockerReference) - if err != nil { - return false - } - return signature.Name() == intended.Name() -} - -// parseDockerReferences converts two reference strings into parsed entities, failing on any error -func parseDockerReferences(s1, s2 string) (reference.Named, reference.Named, error) { - r1, err := reference.ParseNormalizedNamed(s1) - if err != nil { - return nil, nil, err - } - r2, err := reference.ParseNormalizedNamed(s2) - if err != nil { - return nil, nil, err - } - return r1, r2, nil -} - -func (prm *prmExactReference) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { - intended, signature, err := parseDockerReferences(prm.DockerReference, signatureDockerReference) - if err != nil { - return false - } - // prm.DockerReference and signatureDockerReference should be exact; so, verify that now. - if reference.IsNameOnly(intended) || reference.IsNameOnly(signature) { - return false - } - return signature.String() == intended.String() -} - -func (prm *prmExactRepository) matchesDockerReference(image types.UnparsedImage, signatureDockerReference string) bool { - intended, signature, err := parseDockerReferences(prm.DockerRepository, signatureDockerReference) - if err != nil { - return false - } - return signature.Name() == intended.Name() -} diff --git a/vendor/github.com/containers/image/signature/policy_types.go b/vendor/github.com/containers/image/signature/policy_types.go deleted file mode 100644 index 4cd770f11c..0000000000 --- a/vendor/github.com/containers/image/signature/policy_types.go +++ /dev/null @@ -1,152 +0,0 @@ -// Note: Consider the API unstable until the code supports at least three different image formats or transports. - -// This defines types used to represent a signature verification policy in memory. -// Do not use the private types directly; either parse a configuration file, or construct a Policy from PolicyRequirements -// built using the constructor functions provided in policy_config.go. - -package signature - -// NOTE: Keep this in sync with docs/policy.json.md! - -// Policy defines requirements for considering a signature, or an image, valid. -type Policy struct { - // Default applies to any image which does not have a matching policy in Transports. - // Note that this can happen even if a matching PolicyTransportScopes exists in Transports - // if the image matches none of the scopes. - Default PolicyRequirements `json:"default"` - Transports map[string]PolicyTransportScopes `json:"transports"` -} - -// PolicyTransportScopes defines policies for images for a specific transport, -// for various scopes, the map keys. -// Scopes are defined by the transport (types.ImageReference.PolicyConfigurationIdentity etc.); -// there is one scope precisely matching to a single image, and namespace scopes as prefixes -// of the single-image scope. (e.g. hostname[/zero[/or[/more[/namespaces[/individualimage]]]]]) -// The empty scope, if exists, is considered a parent namespace of all other scopes. -// Most specific scope wins, duplication is prohibited (hard failure). -type PolicyTransportScopes map[string]PolicyRequirements - -// PolicyRequirements is a set of requirements applying to a set of images; each of them must be satisfied (though perhaps each by a different signature). -// Must not be empty, frequently will only contain a single element. -type PolicyRequirements []PolicyRequirement - -// PolicyRequirement is a rule which must be satisfied by at least one of the signatures of an image. -// The type is public, but its definition is private. - -// prCommon is the common type field in a JSON encoding of PolicyRequirement. -type prCommon struct { - Type prTypeIdentifier `json:"type"` -} - -// prTypeIdentifier is string designating a kind of a PolicyRequirement. -type prTypeIdentifier string - -const ( - prTypeInsecureAcceptAnything prTypeIdentifier = "insecureAcceptAnything" - prTypeReject prTypeIdentifier = "reject" - prTypeSignedBy prTypeIdentifier = "signedBy" - prTypeSignedBaseLayer prTypeIdentifier = "signedBaseLayer" -) - -// prInsecureAcceptAnything is a PolicyRequirement with type = prTypeInsecureAcceptAnything: -// every image is allowed to run. -// Note that because PolicyRequirements are implicitly ANDed, this is necessary only if it is the only rule (to make the list non-empty and the policy explicit). -// NOTE: This allows the image to run; it DOES NOT consider the signature verified (per IsSignatureAuthorAccepted). -// FIXME? Better name? -type prInsecureAcceptAnything struct { - prCommon -} - -// prReject is a PolicyRequirement with type = prTypeReject: every image is rejected. -type prReject struct { - prCommon -} - -// prSignedBy is a PolicyRequirement with type = prTypeSignedBy: the image is signed by trusted keys for a specified identity -type prSignedBy struct { - prCommon - - // KeyType specifies what kind of key reference KeyPath/KeyData is. - // Acceptable values are “GPGKeys” | “signedByGPGKeys” “X.509Certificates” | “signedByX.509CAs” - // FIXME: eventually also support GPGTOFU, X.509TOFU, with KeyPath only - KeyType sbKeyType `json:"keyType"` - - // KeyPath is a pathname to a local file containing the trusted key(s). Exactly one of KeyPath and KeyData must be specified. - KeyPath string `json:"keyPath,omitempty"` - // KeyData contains the trusted key(s), base64-encoded. Exactly one of KeyPath and KeyData must be specified. - KeyData []byte `json:"keyData,omitempty"` - - // SignedIdentity specifies what image identity the signature must be claiming about the image. - // Defaults to "match-exact" if not specified. - SignedIdentity PolicyReferenceMatch `json:"signedIdentity"` -} - -// sbKeyType are the allowed values for prSignedBy.KeyType -type sbKeyType string - -const ( - // SBKeyTypeGPGKeys refers to keys contained in a GPG keyring - SBKeyTypeGPGKeys sbKeyType = "GPGKeys" - // SBKeyTypeSignedByGPGKeys refers to keys signed by keys in a GPG keyring - SBKeyTypeSignedByGPGKeys sbKeyType = "signedByGPGKeys" - // SBKeyTypeX509Certificates refers to keys in a set of X.509 certificates - // FIXME: PEM, DER? - SBKeyTypeX509Certificates sbKeyType = "X509Certificates" - // SBKeyTypeSignedByX509CAs refers to keys signed by one of the X.509 CAs - // FIXME: PEM, DER? - SBKeyTypeSignedByX509CAs sbKeyType = "signedByX509CAs" -) - -// prSignedBaseLayer is a PolicyRequirement with type = prSignedBaseLayer: the image has a specified, correctly signed, base image. -type prSignedBaseLayer struct { - prCommon - // BaseLayerIdentity specifies the base image to look for. "match-exact" is rejected, "match-repository" is unlikely to be useful. - BaseLayerIdentity PolicyReferenceMatch `json:"baseLayerIdentity"` -} - -// PolicyReferenceMatch specifies a set of image identities accepted in PolicyRequirement. -// The type is public, but its implementation is private. - -// prmCommon is the common type field in a JSON encoding of PolicyReferenceMatch. -type prmCommon struct { - Type prmTypeIdentifier `json:"type"` -} - -// prmTypeIdentifier is string designating a kind of a PolicyReferenceMatch. -type prmTypeIdentifier string - -const ( - prmTypeMatchExact prmTypeIdentifier = "matchExact" - prmTypeMatchRepoDigestOrExact prmTypeIdentifier = "matchRepoDigestOrExact" - prmTypeMatchRepository prmTypeIdentifier = "matchRepository" - prmTypeExactReference prmTypeIdentifier = "exactReference" - prmTypeExactRepository prmTypeIdentifier = "exactRepository" -) - -// prmMatchExact is a PolicyReferenceMatch with type = prmMatchExact: the two references must match exactly. -type prmMatchExact struct { - prmCommon -} - -// prmMatchRepoDigestOrExact is a PolicyReferenceMatch with type = prmMatchExactOrDigest: the two references must match exactly, -// except that digest references are also accepted if the repository name matches (regardless of tag/digest) and the signature applies to the referenced digest -type prmMatchRepoDigestOrExact struct { - prmCommon -} - -// prmMatchRepository is a PolicyReferenceMatch with type = prmMatchRepository: the two references must use the same repository, may differ in the tag. -type prmMatchRepository struct { - prmCommon -} - -// prmExactReference is a PolicyReferenceMatch with type = prmExactReference: matches a specified reference exactly. -type prmExactReference struct { - prmCommon - DockerReference string `json:"dockerReference"` -} - -// prmExactRepository is a PolicyReferenceMatch with type = prmExactRepository: matches a specified repository, with any tag. -type prmExactRepository struct { - prmCommon - DockerRepository string `json:"dockerRepository"` -} diff --git a/vendor/github.com/containers/image/signature/signature.go b/vendor/github.com/containers/image/signature/signature.go deleted file mode 100644 index 41f13f72fd..0000000000 --- a/vendor/github.com/containers/image/signature/signature.go +++ /dev/null @@ -1,280 +0,0 @@ -// Note: Consider the API unstable until the code supports at least three different image formats or transports. - -// NOTE: Keep this in sync with docs/atomic-signature.md and docs/atomic-signature-embedded.json! - -package signature - -import ( - "encoding/json" - "fmt" - "time" - - "github.com/pkg/errors" - - "github.com/containers/image/version" - "github.com/opencontainers/go-digest" -) - -const ( - signatureType = "atomic container signature" -) - -// InvalidSignatureError is returned when parsing an invalid signature. -type InvalidSignatureError struct { - msg string -} - -func (err InvalidSignatureError) Error() string { - return err.msg -} - -// Signature is a parsed content of a signature. -// The only way to get this structure from a blob should be as a return value from a successful call to verifyAndExtractSignature below. -type Signature struct { - DockerManifestDigest digest.Digest - DockerReference string // FIXME: more precise type? -} - -// untrustedSignature is a parsed content of a signature. -type untrustedSignature struct { - UntrustedDockerManifestDigest digest.Digest - UntrustedDockerReference string // FIXME: more precise type? - UntrustedCreatorID *string - // This is intentionally an int64; the native JSON float64 type would allow to represent _some_ sub-second precision, - // but not nearly enough (with current timestamp values, a single unit in the last place is on the order of hundreds of nanoseconds). - // So, this is explicitly an int64, and we reject fractional values. If we did need more precise timestamps eventually, - // we would add another field, UntrustedTimestampNS int64. - UntrustedTimestamp *int64 -} - -// UntrustedSignatureInformation is information available in an untrusted signature. -// This may be useful when debugging signature verification failures, -// or when managing a set of signatures on a single image. -// -// WARNING: Do not use the contents of this for ANY security decisions, -// and be VERY CAREFUL about showing this information to humans in any way which suggest that these values “are probably” reliable. -// There is NO REASON to expect the values to be correct, or not intentionally misleading -// (including things like “✅ Verified by $authority”) -type UntrustedSignatureInformation struct { - UntrustedDockerManifestDigest digest.Digest - UntrustedDockerReference string // FIXME: more precise type? - UntrustedCreatorID *string - UntrustedTimestamp *time.Time - UntrustedShortKeyIdentifier string -} - -// newUntrustedSignature returns an untrustedSignature object with -// the specified primary contents and appropriate metadata. -func newUntrustedSignature(dockerManifestDigest digest.Digest, dockerReference string) untrustedSignature { - // Use intermediate variables for these values so that we can take their addresses. - // Golang guarantees that they will have a new address on every execution. - creatorID := "atomic " + version.Version - timestamp := time.Now().Unix() - return untrustedSignature{ - UntrustedDockerManifestDigest: dockerManifestDigest, - UntrustedDockerReference: dockerReference, - UntrustedCreatorID: &creatorID, - UntrustedTimestamp: ×tamp, - } -} - -// Compile-time check that untrustedSignature implements json.Marshaler -var _ json.Marshaler = (*untrustedSignature)(nil) - -// MarshalJSON implements the json.Marshaler interface. -func (s untrustedSignature) MarshalJSON() ([]byte, error) { - if s.UntrustedDockerManifestDigest == "" || s.UntrustedDockerReference == "" { - return nil, errors.New("Unexpected empty signature content") - } - critical := map[string]interface{}{ - "type": signatureType, - "image": map[string]string{"docker-manifest-digest": s.UntrustedDockerManifestDigest.String()}, - "identity": map[string]string{"docker-reference": s.UntrustedDockerReference}, - } - optional := map[string]interface{}{} - if s.UntrustedCreatorID != nil { - optional["creator"] = *s.UntrustedCreatorID - } - if s.UntrustedTimestamp != nil { - optional["timestamp"] = *s.UntrustedTimestamp - } - signature := map[string]interface{}{ - "critical": critical, - "optional": optional, - } - return json.Marshal(signature) -} - -// Compile-time check that untrustedSignature implements json.Unmarshaler -var _ json.Unmarshaler = (*untrustedSignature)(nil) - -// UnmarshalJSON implements the json.Unmarshaler interface -func (s *untrustedSignature) UnmarshalJSON(data []byte) error { - err := s.strictUnmarshalJSON(data) - if err != nil { - if _, ok := err.(jsonFormatError); ok { - err = InvalidSignatureError{msg: err.Error()} - } - } - return err -} - -// strictUnmarshalJSON is UnmarshalJSON, except that it may return the internal jsonFormatError error type. -// Splitting it into a separate function allows us to do the jsonFormatError → InvalidSignatureError in a single place, the caller. -func (s *untrustedSignature) strictUnmarshalJSON(data []byte) error { - var critical, optional json.RawMessage - if err := paranoidUnmarshalJSONObjectExactFields(data, map[string]interface{}{ - "critical": &critical, - "optional": &optional, - }); err != nil { - return err - } - - var creatorID string - var timestamp float64 - var gotCreatorID, gotTimestamp = false, false - if err := paranoidUnmarshalJSONObject(optional, func(key string) interface{} { - switch key { - case "creator": - gotCreatorID = true - return &creatorID - case "timestamp": - gotTimestamp = true - return ×tamp - default: - var ignore interface{} - return &ignore - } - }); err != nil { - return err - } - if gotCreatorID { - s.UntrustedCreatorID = &creatorID - } - if gotTimestamp { - intTimestamp := int64(timestamp) - if float64(intTimestamp) != timestamp { - return InvalidSignatureError{msg: "Field optional.timestamp is not is not an integer"} - } - s.UntrustedTimestamp = &intTimestamp - } - - var t string - var image, identity json.RawMessage - if err := paranoidUnmarshalJSONObjectExactFields(critical, map[string]interface{}{ - "type": &t, - "image": &image, - "identity": &identity, - }); err != nil { - return err - } - if t != signatureType { - return InvalidSignatureError{msg: fmt.Sprintf("Unrecognized signature type %s", t)} - } - - var digestString string - if err := paranoidUnmarshalJSONObjectExactFields(image, map[string]interface{}{ - "docker-manifest-digest": &digestString, - }); err != nil { - return err - } - s.UntrustedDockerManifestDigest = digest.Digest(digestString) - - return paranoidUnmarshalJSONObjectExactFields(identity, map[string]interface{}{ - "docker-reference": &s.UntrustedDockerReference, - }) -} - -// Sign formats the signature and returns a blob signed using mech and keyIdentity -// (If it seems surprising that this is a method on untrustedSignature, note that there -// isn’t a good reason to think that a key used by the user is trusted by any component -// of the system just because it is a private key — actually the presence of a private key -// on the system increases the likelihood of an a successful attack on that private key -// on that particular system.) -func (s untrustedSignature) sign(mech SigningMechanism, keyIdentity string) ([]byte, error) { - json, err := json.Marshal(s) - if err != nil { - return nil, err - } - - return mech.Sign(json, keyIdentity) -} - -// signatureAcceptanceRules specifies how to decide whether an untrusted signature is acceptable. -// We centralize the actual parsing and data extraction in verifyAndExtractSignature; this supplies -// the policy. We use an object instead of supplying func parameters to verifyAndExtractSignature -// because the functions have the same or similar types, so there is a risk of exchanging the functions; -// named members of this struct are more explicit. -type signatureAcceptanceRules struct { - validateKeyIdentity func(string) error - validateSignedDockerReference func(string) error - validateSignedDockerManifestDigest func(digest.Digest) error -} - -// verifyAndExtractSignature verifies that unverifiedSignature has been signed, and that its principial components -// match expected values, both as specified by rules, and returns it -func verifyAndExtractSignature(mech SigningMechanism, unverifiedSignature []byte, rules signatureAcceptanceRules) (*Signature, error) { - signed, keyIdentity, err := mech.Verify(unverifiedSignature) - if err != nil { - return nil, err - } - if err := rules.validateKeyIdentity(keyIdentity); err != nil { - return nil, err - } - - var unmatchedSignature untrustedSignature - if err := json.Unmarshal(signed, &unmatchedSignature); err != nil { - return nil, InvalidSignatureError{msg: err.Error()} - } - if err := rules.validateSignedDockerManifestDigest(unmatchedSignature.UntrustedDockerManifestDigest); err != nil { - return nil, err - } - if err := rules.validateSignedDockerReference(unmatchedSignature.UntrustedDockerReference); err != nil { - return nil, err - } - // signatureAcceptanceRules have accepted this value. - return &Signature{ - DockerManifestDigest: unmatchedSignature.UntrustedDockerManifestDigest, - DockerReference: unmatchedSignature.UntrustedDockerReference, - }, nil -} - -// GetUntrustedSignatureInformationWithoutVerifying extracts information available in an untrusted signature, -// WITHOUT doing any cryptographic verification. -// This may be useful when debugging signature verification failures, -// or when managing a set of signatures on a single image. -// -// WARNING: Do not use the contents of this for ANY security decisions, -// and be VERY CAREFUL about showing this information to humans in any way which suggest that these values “are probably” reliable. -// There is NO REASON to expect the values to be correct, or not intentionally misleading -// (including things like “✅ Verified by $authority”) -func GetUntrustedSignatureInformationWithoutVerifying(untrustedSignatureBytes []byte) (*UntrustedSignatureInformation, error) { - // NOTE: This should eventualy do format autodetection. - mech, _, err := NewEphemeralGPGSigningMechanism([]byte{}) - if err != nil { - return nil, err - } - defer mech.Close() - - untrustedContents, shortKeyIdentifier, err := mech.UntrustedSignatureContents(untrustedSignatureBytes) - if err != nil { - return nil, err - } - var untrustedDecodedContents untrustedSignature - if err := json.Unmarshal(untrustedContents, &untrustedDecodedContents); err != nil { - return nil, InvalidSignatureError{msg: err.Error()} - } - - var timestamp *time.Time // = nil - if untrustedDecodedContents.UntrustedTimestamp != nil { - ts := time.Unix(*untrustedDecodedContents.UntrustedTimestamp, 0) - timestamp = &ts - } - return &UntrustedSignatureInformation{ - UntrustedDockerManifestDigest: untrustedDecodedContents.UntrustedDockerManifestDigest, - UntrustedDockerReference: untrustedDecodedContents.UntrustedDockerReference, - UntrustedCreatorID: untrustedDecodedContents.UntrustedCreatorID, - UntrustedTimestamp: timestamp, - UntrustedShortKeyIdentifier: shortKeyIdentifier, - }, nil -} diff --git a/vendor/github.com/containers/image/storage/storage_image.go b/vendor/github.com/containers/image/storage/storage_image.go deleted file mode 100644 index 038195c16c..0000000000 --- a/vendor/github.com/containers/image/storage/storage_image.go +++ /dev/null @@ -1,808 +0,0 @@ -// +build !containers_image_storage_stub - -package storage - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sync/atomic" - - "github.com/containers/image/image" - "github.com/containers/image/manifest" - "github.com/containers/image/types" - "github.com/containers/storage" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/ioutils" - digest "github.com/opencontainers/go-digest" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -const temporaryDirectoryForBigFiles = "/var/tmp" // Do not use the system default of os.TempDir(), usually /tmp, because with systemd it could be a tmpfs. - -var ( - // ErrBlobDigestMismatch is returned when PutBlob() is given a blob - // with a digest-based name that doesn't match its contents. - ErrBlobDigestMismatch = errors.New("blob digest mismatch") - // ErrBlobSizeMismatch is returned when PutBlob() is given a blob - // with an expected size that doesn't match the reader. - ErrBlobSizeMismatch = errors.New("blob size mismatch") - // ErrNoManifestLists is returned when GetManifest() is called. - // with a non-nil instanceDigest. - ErrNoManifestLists = errors.New("manifest lists are not supported by this transport") - // ErrNoSuchImage is returned when we attempt to access an image which - // doesn't exist in the storage area. - ErrNoSuchImage = storage.ErrNotAnImage -) - -type storageImageSource struct { - imageRef storageReference - ID string - layerPosition map[digest.Digest]int // Where we are in reading a blob's layers - cachedManifest []byte // A cached copy of the manifest, if already known, or nil - SignatureSizes []int `json:"signature-sizes,omitempty"` // List of sizes of each signature slice -} - -type storageImageDestination struct { - image types.ImageCloser - systemContext *types.SystemContext - imageRef storageReference // The reference we'll use to name the image - publicRef storageReference // The reference we return when asked about the name we'll give to the image - directory string // Temporary directory where we store blobs until Commit() time - nextTempFileID int32 // A counter that we use for computing filenames to assign to blobs - manifest []byte // Manifest contents, temporary - signatures []byte // Signature contents, temporary - blobDiffIDs map[digest.Digest]digest.Digest // Mapping from layer blobsums to their corresponding DiffIDs - fileSizes map[digest.Digest]int64 // Mapping from layer blobsums to their sizes - filenames map[digest.Digest]string // Mapping from layer blobsums to names of files we used to hold them - SignatureSizes []int `json:"signature-sizes,omitempty"` // List of sizes of each signature slice -} - -type storageImageCloser struct { - types.ImageCloser - size int64 -} - -// newImageSource sets up an image for reading. -func newImageSource(imageRef storageReference) (*storageImageSource, error) { - // First, locate the image. - img, err := imageRef.resolveImage() - if err != nil { - return nil, err - } - - // Build the reader object. - image := &storageImageSource{ - imageRef: imageRef, - ID: img.ID, - layerPosition: make(map[digest.Digest]int), - SignatureSizes: []int{}, - } - if img.Metadata != "" { - if err := json.Unmarshal([]byte(img.Metadata), image); err != nil { - return nil, errors.Wrap(err, "error decoding metadata for source image") - } - } - return image, nil -} - -// Reference returns the image reference that we used to find this image. -func (s storageImageSource) Reference() types.ImageReference { - return s.imageRef -} - -// Close cleans up any resources we tied up while reading the image. -func (s storageImageSource) Close() error { - return nil -} - -// GetBlob reads the data blob or filesystem layer which matches the digest and size, if given. -func (s *storageImageSource) GetBlob(info types.BlobInfo) (rc io.ReadCloser, n int64, err error) { - rc, n, _, err = s.getBlobAndLayerID(info) - return rc, n, err -} - -// getBlobAndLayer reads the data blob or filesystem layer which matches the digest and size, if given. -func (s *storageImageSource) getBlobAndLayerID(info types.BlobInfo) (rc io.ReadCloser, n int64, layerID string, err error) { - var layer storage.Layer - var diffOptions *storage.DiffOptions - // We need a valid digest value. - err = info.Digest.Validate() - if err != nil { - return nil, -1, "", err - } - // Check if the blob corresponds to a diff that was used to initialize any layers. Our - // callers should try to retrieve layers using their uncompressed digests, so no need to - // check if they're using one of the compressed digests, which we can't reproduce anyway. - layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(info.Digest) - // If it's not a layer, then it must be a data item. - if len(layers) == 0 { - b, err := s.imageRef.transport.store.ImageBigData(s.ID, info.Digest.String()) - if err != nil { - return nil, -1, "", err - } - r := bytes.NewReader(b) - logrus.Debugf("exporting opaque data as blob %q", info.Digest.String()) - return ioutil.NopCloser(r), int64(r.Len()), "", nil - } - // Step through the list of matching layers. Tests may want to verify that if we have multiple layers - // which claim to have the same contents, that we actually do have multiple layers, otherwise we could - // just go ahead and use the first one every time. - i := s.layerPosition[info.Digest] - s.layerPosition[info.Digest] = i + 1 - if len(layers) > 0 { - layer = layers[i%len(layers)] - } - // Force the storage layer to not try to match any compression that was used when the layer was first - // handed to it. - noCompression := archive.Uncompressed - diffOptions = &storage.DiffOptions{ - Compression: &noCompression, - } - if layer.UncompressedSize < 0 { - n = -1 - } else { - n = layer.UncompressedSize - } - logrus.Debugf("exporting filesystem layer %q without compression for blob %q", layer.ID, info.Digest) - rc, err = s.imageRef.transport.store.Diff("", layer.ID, diffOptions) - if err != nil { - return nil, -1, "", err - } - return rc, n, layer.ID, err -} - -// GetManifest() reads the image's manifest. -func (s *storageImageSource) GetManifest(instanceDigest *digest.Digest) (manifestBlob []byte, MIMEType string, err error) { - if instanceDigest != nil { - return nil, "", ErrNoManifestLists - } - if len(s.cachedManifest) == 0 { - // We stored the manifest as an item named after storage.ImageDigestBigDataKey. - cachedBlob, err := s.imageRef.transport.store.ImageBigData(s.ID, storage.ImageDigestBigDataKey) - if err != nil { - return nil, "", err - } - s.cachedManifest = cachedBlob - } - return s.cachedManifest, manifest.GuessMIMEType(s.cachedManifest), err -} - -// LayerInfosForCopy() returns the list of layer blobs that make up the root filesystem of -// the image, after they've been decompressed. -func (s *storageImageSource) LayerInfosForCopy() []types.BlobInfo { - simg, err := s.imageRef.transport.store.Image(s.ID) - if err != nil { - logrus.Errorf("error reading image %q: %v", s.ID, err) - return nil - } - updatedBlobInfos := []types.BlobInfo{} - layerID := simg.TopLayer - _, manifestType, err := s.GetManifest(nil) - if err != nil { - logrus.Errorf("error reading image manifest for %q: %v", s.ID, err) - return nil - } - uncompressedLayerType := "" - switch manifestType { - case imgspecv1.MediaTypeImageManifest: - uncompressedLayerType = imgspecv1.MediaTypeImageLayer - case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema2MediaType: - // This is actually a compressed type, but there's no uncompressed type defined - uncompressedLayerType = manifest.DockerV2Schema2LayerMediaType - } - for layerID != "" { - layer, err := s.imageRef.transport.store.Layer(layerID) - if err != nil { - logrus.Errorf("error reading layer %q in image %q: %v", layerID, s.ID, err) - return nil - } - if layer.UncompressedDigest == "" { - logrus.Errorf("uncompressed digest for layer %q is unknown", layerID) - return nil - } - if layer.UncompressedSize < 0 { - logrus.Errorf("uncompressed size for layer %q is unknown", layerID) - return nil - } - blobInfo := types.BlobInfo{ - Digest: layer.UncompressedDigest, - Size: layer.UncompressedSize, - MediaType: uncompressedLayerType, - } - updatedBlobInfos = append([]types.BlobInfo{blobInfo}, updatedBlobInfos...) - layerID = layer.Parent - } - return updatedBlobInfos -} - -// GetSignatures() parses the image's signatures blob into a slice of byte slices. -func (s *storageImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) (signatures [][]byte, err error) { - if instanceDigest != nil { - return nil, ErrNoManifestLists - } - var offset int - sigslice := [][]byte{} - signature := []byte{} - if len(s.SignatureSizes) > 0 { - signatureBlob, err := s.imageRef.transport.store.ImageBigData(s.ID, "signatures") - if err != nil { - return nil, errors.Wrapf(err, "error looking up signatures data for image %q", s.ID) - } - signature = signatureBlob - } - for _, length := range s.SignatureSizes { - sigslice = append(sigslice, signature[offset:offset+length]) - offset += length - } - if offset != len(signature) { - return nil, errors.Errorf("signatures data contained %d extra bytes", len(signatures)-offset) - } - return sigslice, nil -} - -// newImageDestination sets us up to write a new image, caching blobs in a temporary directory until -// it's time to Commit() the image -func newImageDestination(ctx *types.SystemContext, imageRef storageReference) (*storageImageDestination, error) { - directory, err := ioutil.TempDir(temporaryDirectoryForBigFiles, "storage") - if err != nil { - return nil, errors.Wrapf(err, "error creating a temporary directory") - } - // Break reading of the reference we're writing, so that copy.Image() won't try to rewrite - // schema1 image manifests to remove embedded references, since that changes the manifest's - // digest, and that makes the image unusable if we subsequently try to access it using a - // reference that mentions the no-longer-correct digest. - publicRef := imageRef - publicRef.name = nil - image := &storageImageDestination{ - systemContext: ctx, - imageRef: imageRef, - publicRef: publicRef, - directory: directory, - blobDiffIDs: make(map[digest.Digest]digest.Digest), - fileSizes: make(map[digest.Digest]int64), - filenames: make(map[digest.Digest]string), - SignatureSizes: []int{}, - } - return image, nil -} - -// Reference returns a mostly-usable image reference that can't return a DockerReference, to -// avoid triggering logic in copy.Image() that rewrites schema 1 image manifests in order to -// remove image names that they contain which don't match the value we're using. -func (s storageImageDestination) Reference() types.ImageReference { - return s.publicRef -} - -// Close cleans up the temporary directory. -func (s *storageImageDestination) Close() error { - return os.RemoveAll(s.directory) -} - -// ShouldCompressLayers indicates whether or not a caller should compress not-already-compressed -// data when handing it to us. -func (s storageImageDestination) ShouldCompressLayers() bool { - // We ultimately have to decompress layers to populate trees on disk, so callers shouldn't - // bother compressing them before handing them to us, if they're not already compressed. - return false -} - -// PutBlob stores a layer or data blob in our temporary directory, checking that any information -// in the blobinfo matches the incoming data. -func (s *storageImageDestination) PutBlob(stream io.Reader, blobinfo types.BlobInfo) (types.BlobInfo, error) { - errorBlobInfo := types.BlobInfo{ - Digest: "", - Size: -1, - } - // Set up to digest the blob and count its size while saving it to a file. - hasher := digest.Canonical.Digester() - if blobinfo.Digest.Validate() == nil { - if a := blobinfo.Digest.Algorithm(); a.Available() { - hasher = a.Digester() - } - } - diffID := digest.Canonical.Digester() - filename := filepath.Join(s.directory, fmt.Sprintf("%d", atomic.AddInt32(&s.nextTempFileID, 1))) - file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL, 0600) - if err != nil { - return errorBlobInfo, errors.Wrapf(err, "error creating temporary file %q", filename) - } - defer file.Close() - counter := ioutils.NewWriteCounter(hasher.Hash()) - reader := io.TeeReader(io.TeeReader(stream, counter), file) - decompressed, err := archive.DecompressStream(reader) - if err != nil { - return errorBlobInfo, errors.Wrap(err, "error setting up to decompress blob") - } - // Copy the data to the file. - _, err = io.Copy(diffID.Hash(), decompressed) - decompressed.Close() - if err != nil { - return errorBlobInfo, errors.Wrapf(err, "error storing blob to file %q", filename) - } - // Ensure that any information that we were given about the blob is correct. - if blobinfo.Digest.Validate() == nil && blobinfo.Digest != hasher.Digest() { - return errorBlobInfo, ErrBlobDigestMismatch - } - if blobinfo.Size >= 0 && blobinfo.Size != counter.Count { - return errorBlobInfo, ErrBlobSizeMismatch - } - // Record information about the blob. - s.blobDiffIDs[hasher.Digest()] = diffID.Digest() - s.fileSizes[hasher.Digest()] = counter.Count - s.filenames[hasher.Digest()] = filename - blobDigest := blobinfo.Digest - if blobDigest.Validate() != nil { - blobDigest = hasher.Digest() - } - blobSize := blobinfo.Size - if blobSize < 0 { - blobSize = counter.Count - } - return types.BlobInfo{ - Digest: blobDigest, - Size: blobSize, - MediaType: blobinfo.MediaType, - }, nil -} - -// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be -// reapplied using ReapplyBlob. -// -// Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. -// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); -// it returns a non-nil error only on an unexpected failure. -func (s *storageImageDestination) HasBlob(blobinfo types.BlobInfo) (bool, int64, error) { - if blobinfo.Digest == "" { - return false, -1, errors.Errorf(`Can not check for a blob with unknown digest`) - } - if err := blobinfo.Digest.Validate(); err != nil { - return false, -1, errors.Wrapf(err, `Can not check for a blob with invalid digest`) - } - // Check if we've already cached it in a file. - if size, ok := s.fileSizes[blobinfo.Digest]; ok { - return true, size, nil - } - // Check if we have a wasn't-compressed layer in storage that's based on that blob. - layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(blobinfo.Digest) - if err != nil && errors.Cause(err) != storage.ErrLayerUnknown { - return false, -1, errors.Wrapf(err, `Error looking for layers with digest %q`, blobinfo.Digest) - } - if len(layers) > 0 { - // Save this for completeness. - s.blobDiffIDs[blobinfo.Digest] = layers[0].UncompressedDigest - return true, layers[0].UncompressedSize, nil - } - // Check if we have a was-compressed layer in storage that's based on that blob. - layers, err = s.imageRef.transport.store.LayersByCompressedDigest(blobinfo.Digest) - if err != nil && errors.Cause(err) != storage.ErrLayerUnknown { - return false, -1, errors.Wrapf(err, `Error looking for compressed layers with digest %q`, blobinfo.Digest) - } - if len(layers) > 0 { - // Record the uncompressed value so that we can use it to calculate layer IDs. - s.blobDiffIDs[blobinfo.Digest] = layers[0].UncompressedDigest - return true, layers[0].CompressedSize, nil - } - // Nope, we don't have it. - return false, -1, nil -} - -// ReapplyBlob is now a no-op, assuming HasBlob() says we already have it, since Commit() can just apply the -// same one when it walks the list in the manifest. -func (s *storageImageDestination) ReapplyBlob(blobinfo types.BlobInfo) (types.BlobInfo, error) { - present, size, err := s.HasBlob(blobinfo) - if !present { - return types.BlobInfo{}, errors.Errorf("error reapplying blob %+v: blob was not previously applied", blobinfo) - } - if err != nil { - return types.BlobInfo{}, errors.Wrapf(err, "error reapplying blob %+v", blobinfo) - } - blobinfo.Size = size - return blobinfo, nil -} - -// computeID computes a recommended image ID based on information we have so far. If -// the manifest is not of a type that we recognize, we return an empty value, indicating -// that since we don't have a recommendation, a random ID should be used if one needs -// to be allocated. -func (s *storageImageDestination) computeID(m manifest.Manifest) string { - // Build the diffID list. We need the decompressed sums that we've been calculating to - // fill in the DiffIDs. It's expected (but not enforced by us) that the number of - // diffIDs corresponds to the number of non-EmptyLayer entries in the history. - var diffIDs []digest.Digest - switch m.(type) { - case *manifest.Schema1: - // Build a list of the diffIDs we've generated for the non-throwaway FS layers, - // in reverse of the order in which they were originally listed. - s1, ok := m.(*manifest.Schema1) - if !ok { - // Shouldn't happen - logrus.Debugf("internal error reading schema 1 manifest") - return "" - } - for i, history := range s1.History { - compat := manifest.Schema1V1Compatibility{} - if err := json.Unmarshal([]byte(history.V1Compatibility), &compat); err != nil { - logrus.Debugf("internal error reading schema 1 history: %v", err) - return "" - } - if compat.ThrowAway { - continue - } - blobSum := s1.FSLayers[i].BlobSum - diffID, ok := s.blobDiffIDs[blobSum] - if !ok { - logrus.Infof("error looking up diffID for layer %q", blobSum.String()) - return "" - } - diffIDs = append([]digest.Digest{diffID}, diffIDs...) - } - case *manifest.Schema2, *manifest.OCI1: - // We know the ID calculation for these formats doesn't actually use the diffIDs, - // so we don't need to populate the diffID list. - } - id, err := m.ImageID(diffIDs) - if err != nil { - return "" - } - return id -} - -// getConfigBlob exists only to let us retrieve the configuration blob so that the manifest package can dig -// information out of it for Inspect(). -func (s *storageImageDestination) getConfigBlob(info types.BlobInfo) ([]byte, error) { - if info.Digest == "" { - return nil, errors.Errorf(`no digest supplied when reading blob`) - } - if err := info.Digest.Validate(); err != nil { - return nil, errors.Wrapf(err, `invalid digest supplied when reading blob`) - } - // Assume it's a file, since we're only calling this from a place that expects to read files. - if filename, ok := s.filenames[info.Digest]; ok { - contents, err2 := ioutil.ReadFile(filename) - if err2 != nil { - return nil, errors.Wrapf(err2, `error reading blob from file %q`, filename) - } - return contents, nil - } - // If it's not a file, it's a bug, because we're not expecting to be asked for a layer. - return nil, errors.New("blob not found") -} - -func (s *storageImageDestination) Commit() error { - // Find the list of layer blobs. - if len(s.manifest) == 0 { - return errors.New("Internal error: storageImageDestination.Commit() called without PutManifest()") - } - man, err := manifest.FromBlob(s.manifest, manifest.GuessMIMEType(s.manifest)) - if err != nil { - return errors.Wrapf(err, "error parsing manifest") - } - layerBlobs := man.LayerInfos() - // Extract or find the layers. - lastLayer := "" - addedLayers := []string{} - for _, blob := range layerBlobs { - var diff io.ReadCloser - // Check if there's already a layer with the ID that we'd give to the result of applying - // this layer blob to its parent, if it has one, or the blob's hex value otherwise. - diffID, haveDiffID := s.blobDiffIDs[blob.Digest] - if !haveDiffID { - // Check if it's elsewhere and the caller just forgot to pass it to us in a PutBlob(), - // or to even check if we had it. - logrus.Debugf("looking for diffID for blob %+v", blob.Digest) - has, _, err := s.HasBlob(blob) - if err != nil { - return errors.Wrapf(err, "error checking for a layer based on blob %q", blob.Digest.String()) - } - if !has { - return errors.Errorf("error determining uncompressed digest for blob %q", blob.Digest.String()) - } - diffID, haveDiffID = s.blobDiffIDs[blob.Digest] - if !haveDiffID { - return errors.Errorf("we have blob %q, but don't know its uncompressed digest", blob.Digest.String()) - } - } - id := diffID.Hex() - if lastLayer != "" { - id = digest.Canonical.FromBytes([]byte(lastLayer + "+" + diffID.Hex())).Hex() - } - if layer, err2 := s.imageRef.transport.store.Layer(id); layer != nil && err2 == nil { - // There's already a layer that should have the right contents, just reuse it. - lastLayer = layer.ID - continue - } - // Check if we cached a file with that blobsum. If we didn't already have a layer with - // the blob's contents, we should have gotten a copy. - if filename, ok := s.filenames[blob.Digest]; ok { - // Use the file's contents to initialize the layer. - file, err2 := os.Open(filename) - if err2 != nil { - return errors.Wrapf(err2, "error opening file %q", filename) - } - defer file.Close() - diff = file - } - if diff == nil { - // Try to find a layer with contents matching that blobsum. - layer := "" - layers, err2 := s.imageRef.transport.store.LayersByUncompressedDigest(blob.Digest) - if err2 == nil && len(layers) > 0 { - layer = layers[0].ID - } else { - layers, err2 = s.imageRef.transport.store.LayersByCompressedDigest(blob.Digest) - if err2 == nil && len(layers) > 0 { - layer = layers[0].ID - } - } - if layer == "" { - return errors.Wrapf(err2, "error locating layer for blob %q", blob.Digest) - } - // Use the layer's contents to initialize the new layer. - noCompression := archive.Uncompressed - diffOptions := &storage.DiffOptions{ - Compression: &noCompression, - } - diff, err2 = s.imageRef.transport.store.Diff("", layer, diffOptions) - if err2 != nil { - return errors.Wrapf(err2, "error reading layer %q for blob %q", layer, blob.Digest) - } - defer diff.Close() - } - if diff == nil { - // This shouldn't have happened. - return errors.Errorf("error applying blob %q: content not found", blob.Digest) - } - // Build the new layer using the diff, regardless of where it came from. - layer, _, err := s.imageRef.transport.store.PutLayer(id, lastLayer, nil, "", false, diff) - if err != nil { - return errors.Wrapf(err, "error adding layer with blob %q", blob.Digest) - } - lastLayer = layer.ID - addedLayers = append([]string{lastLayer}, addedLayers...) - } - // If one of those blobs was a configuration blob, then we can try to dig out the date when the image - // was originally created, in case we're just copying it. If not, no harm done. - options := &storage.ImageOptions{} - if inspect, err := man.Inspect(s.getConfigBlob); err == nil { - logrus.Debugf("setting image creation date to %s", inspect.Created) - options.CreationDate = inspect.Created - } - if manifestDigest, err := manifest.Digest(s.manifest); err == nil { - options.Digest = manifestDigest - } - // Create the image record, pointing to the most-recently added layer. - intendedID := s.imageRef.id - if intendedID == "" { - intendedID = s.computeID(man) - } - oldNames := []string{} - img, err := s.imageRef.transport.store.CreateImage(intendedID, nil, lastLayer, "", options) - if err != nil { - if errors.Cause(err) != storage.ErrDuplicateID { - logrus.Debugf("error creating image: %q", err) - return errors.Wrapf(err, "error creating image %q", intendedID) - } - img, err = s.imageRef.transport.store.Image(intendedID) - if err != nil { - return errors.Wrapf(err, "error reading image %q", intendedID) - } - if img.TopLayer != lastLayer { - logrus.Debugf("error creating image: image with ID %q exists, but uses different layers", intendedID) - return errors.Wrapf(storage.ErrDuplicateID, "image with ID %q already exists, but uses a different top layer", intendedID) - } - logrus.Debugf("reusing image ID %q", img.ID) - oldNames = append(oldNames, img.Names...) - } else { - logrus.Debugf("created new image ID %q", img.ID) - } - // Add the non-layer blobs as data items. Since we only share layers, they should all be in files, so - // we just need to screen out the ones that are actually layers to get the list of non-layers. - dataBlobs := make(map[digest.Digest]struct{}) - for blob := range s.filenames { - dataBlobs[blob] = struct{}{} - } - for _, layerBlob := range layerBlobs { - delete(dataBlobs, layerBlob.Digest) - } - for blob := range dataBlobs { - v, err := ioutil.ReadFile(s.filenames[blob]) - if err != nil { - return errors.Wrapf(err, "error copying non-layer blob %q to image", blob) - } - if err := s.imageRef.transport.store.SetImageBigData(img.ID, blob.String(), v); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error saving big data %q for image %q: %v", blob.String(), img.ID, err) - return errors.Wrapf(err, "error saving big data %q for image %q", blob.String(), img.ID) - } - } - // Set the reference's name on the image. - if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil { - names := []string{} - if name != nil { - names = append(names, verboseName(name)) - } - if len(oldNames) > 0 { - names = append(names, oldNames...) - } - if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err) - return errors.Wrapf(err, "error setting names %v on image %q", names, img.ID) - } - logrus.Debugf("set names of image %q to %v", img.ID, names) - } - // Save the manifest. Use storage.ImageDigestBigDataKey as the item's - // name, so that its digest can be used to locate the image in the Store. - if err := s.imageRef.transport.store.SetImageBigData(img.ID, storage.ImageDigestBigDataKey, s.manifest); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error saving manifest for image %q: %v", img.ID, err) - return err - } - // Save the signatures, if we have any. - if len(s.signatures) > 0 { - if err := s.imageRef.transport.store.SetImageBigData(img.ID, "signatures", s.signatures); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error saving signatures for image %q: %v", img.ID, err) - return err - } - } - // Save our metadata. - metadata, err := json.Marshal(s) - if err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error encoding metadata for image %q: %v", img.ID, err) - return err - } - if len(metadata) != 0 { - if err = s.imageRef.transport.store.SetMetadata(img.ID, string(metadata)); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error saving metadata for image %q: %v", img.ID, err) - return err - } - logrus.Debugf("saved image metadata %q", string(metadata)) - } - return nil -} - -var manifestMIMETypes = []string{ - imgspecv1.MediaTypeImageManifest, - manifest.DockerV2Schema2MediaType, - manifest.DockerV2Schema1SignedMediaType, - manifest.DockerV2Schema1MediaType, -} - -func (s *storageImageDestination) SupportedManifestMIMETypes() []string { - return manifestMIMETypes -} - -// PutManifest writes the manifest to the destination. -func (s *storageImageDestination) PutManifest(manifest []byte) error { - s.manifest = make([]byte, len(manifest)) - copy(s.manifest, manifest) - return nil -} - -// SupportsSignatures returns an error if we can't expect GetSignatures() to return data that was -// previously supplied to PutSignatures(). -func (s *storageImageDestination) SupportsSignatures() error { - return nil -} - -// AcceptsForeignLayerURLs returns false iff foreign layers in the manifest should actually be -// uploaded to the image destination, true otherwise. -func (s *storageImageDestination) AcceptsForeignLayerURLs() bool { - return false -} - -// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. -func (s *storageImageDestination) MustMatchRuntimeOS() bool { - return true -} - -// PutSignatures records the image's signatures for committing as a single data blob. -func (s *storageImageDestination) PutSignatures(signatures [][]byte) error { - sizes := []int{} - sigblob := []byte{} - for _, sig := range signatures { - sizes = append(sizes, len(sig)) - newblob := make([]byte, len(sigblob)+len(sig)) - copy(newblob, sigblob) - copy(newblob[len(sigblob):], sig) - sigblob = newblob - } - s.signatures = sigblob - s.SignatureSizes = sizes - return nil -} - -// getSize() adds up the sizes of the image's data blobs (which includes the configuration blob), the -// signatures, and the uncompressed sizes of all of the image's layers. -func (s *storageImageSource) getSize() (int64, error) { - var sum int64 - // Size up the data blobs. - dataNames, err := s.imageRef.transport.store.ListImageBigData(s.ID) - if err != nil { - return -1, errors.Wrapf(err, "error reading image %q", s.ID) - } - for _, dataName := range dataNames { - bigSize, err := s.imageRef.transport.store.ImageBigDataSize(s.ID, dataName) - if err != nil { - return -1, errors.Wrapf(err, "error reading data blob size %q for %q", dataName, s.ID) - } - sum += bigSize - } - // Add the signature sizes. - for _, sigSize := range s.SignatureSizes { - sum += int64(sigSize) - } - // Prepare to walk the layer list. - img, err := s.imageRef.transport.store.Image(s.ID) - if err != nil { - return -1, errors.Wrapf(err, "error reading image info %q", s.ID) - } - // Walk the layer list. - layerID := img.TopLayer - for layerID != "" { - layer, err := s.imageRef.transport.store.Layer(layerID) - if err != nil { - return -1, err - } - if layer.UncompressedDigest == "" || layer.UncompressedSize < 0 { - return -1, errors.Errorf("size for layer %q is unknown, failing getSize()", layerID) - } - sum += layer.UncompressedSize - if layer.Parent == "" { - break - } - layerID = layer.Parent - } - return sum, nil -} - -// Size() adds up the sizes of the image's data blobs (which includes the configuration blob), the -// signatures, and the uncompressed sizes of all of the image's layers. -func (s *storageImageSource) Size() (int64, error) { - return s.getSize() -} - -// Size() returns the previously-computed size of the image, with no error. -func (s *storageImageCloser) Size() (int64, error) { - return s.size, nil -} - -// newImage creates an image that also knows its size -func newImage(ctx *types.SystemContext, s storageReference) (types.ImageCloser, error) { - src, err := newImageSource(s) - if err != nil { - return nil, err - } - img, err := image.FromSource(ctx, src) - if err != nil { - return nil, err - } - size, err := src.getSize() - if err != nil { - return nil, err - } - return &storageImageCloser{ImageCloser: img, size: size}, nil -} diff --git a/vendor/github.com/containers/image/storage/storage_reference.go b/vendor/github.com/containers/image/storage/storage_reference.go deleted file mode 100644 index bcb00f60eb..0000000000 --- a/vendor/github.com/containers/image/storage/storage_reference.go +++ /dev/null @@ -1,209 +0,0 @@ -// +build !containers_image_storage_stub - -package storage - -import ( - "strings" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/types" - "github.com/containers/storage" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// A storageReference holds an arbitrary name and/or an ID, which is a 32-byte -// value hex-encoded into a 64-character string, and a reference to a Store -// where an image is, or would be, kept. -type storageReference struct { - transport storageTransport - reference string - id string - name reference.Named - tag string - digest digest.Digest -} - -func newReference(transport storageTransport, reference, id string, name reference.Named, tag string, digest digest.Digest) *storageReference { - // We take a copy of the transport, which contains a pointer to the - // store that it used for resolving this reference, so that the - // transport that we'll return from Transport() won't be affected by - // further calls to the original transport's SetStore() method. - return &storageReference{ - transport: transport, - reference: reference, - id: id, - name: name, - tag: tag, - digest: digest, - } -} - -// Resolve the reference's name to an image ID in the store, if there's already -// one present with the same name or ID, and return the image. -func (s *storageReference) resolveImage() (*storage.Image, error) { - if s.id == "" { - // Look for an image that has the expanded reference name as an explicit Name value. - image, err := s.transport.store.Image(s.reference) - if image != nil && err == nil { - s.id = image.ID - } - } - if s.id == "" && s.name != nil && s.digest != "" { - // Look for an image with the specified digest that has the same name, - // though possibly with a different tag or digest, as a Name value, so - // that the canonical reference can be implicitly resolved to the image. - images, err := s.transport.store.ImagesByDigest(s.digest) - if images != nil && err == nil { - repo := reference.FamiliarName(reference.TrimNamed(s.name)) - search: - for _, image := range images { - for _, name := range image.Names { - if named, err := reference.ParseNormalizedNamed(name); err == nil { - if reference.FamiliarName(reference.TrimNamed(named)) == repo { - s.id = image.ID - break search - } - } - } - } - } - } - if s.id == "" { - logrus.Debugf("reference %q does not resolve to an image ID", s.StringWithinTransport()) - return nil, errors.Wrapf(ErrNoSuchImage, "reference %q does not resolve to an image ID", s.StringWithinTransport()) - } - img, err := s.transport.store.Image(s.id) - if err != nil { - return nil, errors.Wrapf(err, "error reading image %q", s.id) - } - if s.name != nil { - repo := reference.FamiliarName(reference.TrimNamed(s.name)) - nameMatch := false - for _, name := range img.Names { - if named, err := reference.ParseNormalizedNamed(name); err == nil { - if reference.FamiliarName(reference.TrimNamed(named)) == repo { - nameMatch = true - break - } - } - } - if !nameMatch { - logrus.Errorf("no image matching reference %q found", s.StringWithinTransport()) - return nil, ErrNoSuchImage - } - } - return img, nil -} - -// Return a Transport object that defaults to using the same store that we used -// to build this reference object. -func (s storageReference) Transport() types.ImageTransport { - return &storageTransport{ - store: s.transport.store, - defaultUIDMap: s.transport.defaultUIDMap, - defaultGIDMap: s.transport.defaultGIDMap, - } -} - -// Return a name with a tag or digest, if we have either, else return it bare. -func (s storageReference) DockerReference() reference.Named { - if s.name == nil { - return nil - } - if s.tag != "" { - if namedTagged, err := reference.WithTag(s.name, s.tag); err == nil { - return namedTagged - } - } - if s.digest != "" { - if canonical, err := reference.WithDigest(s.name, s.digest); err == nil { - return canonical - } - } - return s.name -} - -// Return a name with a tag, prefixed with the graph root and driver name, to -// disambiguate between images which may be present in multiple stores and -// share only their names. -func (s storageReference) StringWithinTransport() string { - optionsList := "" - options := s.transport.store.GraphOptions() - if len(options) > 0 { - optionsList = ":" + strings.Join(options, ",") - } - storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "+" + s.transport.store.RunRoot() + optionsList + "]" - if s.reference == "" { - return storeSpec + "@" + s.id - } - if s.id == "" { - return storeSpec + s.reference - } - return storeSpec + s.reference + "@" + s.id -} - -func (s storageReference) PolicyConfigurationIdentity() string { - storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "]" - if s.name == nil { - return storeSpec + "@" + s.id - } - if s.id == "" { - return storeSpec + s.reference - } - return storeSpec + s.reference + "@" + s.id -} - -// Also accept policy that's tied to the combination of the graph root and -// driver name, to apply to all images stored in the Store, and to just the -// graph root, in case we're using multiple drivers in the same directory for -// some reason. -func (s storageReference) PolicyConfigurationNamespaces() []string { - storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "]" - driverlessStoreSpec := "[" + s.transport.store.GraphRoot() + "]" - namespaces := []string{} - if s.name != nil { - name := reference.TrimNamed(s.name) - components := strings.Split(name.String(), "/") - for len(components) > 0 { - namespaces = append(namespaces, storeSpec+strings.Join(components, "/")) - components = components[:len(components)-1] - } - } - namespaces = append(namespaces, storeSpec) - namespaces = append(namespaces, driverlessStoreSpec) - return namespaces -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (s storageReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - return newImage(ctx, s) -} - -func (s storageReference) DeleteImage(ctx *types.SystemContext) error { - img, err := s.resolveImage() - if err != nil { - return err - } - layers, err := s.transport.store.DeleteImage(img.ID, true) - if err == nil { - logrus.Debugf("deleted image %q", img.ID) - for _, layer := range layers { - logrus.Debugf("deleted layer %q", layer) - } - } - return err -} - -func (s storageReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - return newImageSource(s) -} - -func (s storageReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return newImageDestination(ctx, s) -} diff --git a/vendor/github.com/containers/image/storage/storage_transport.go b/vendor/github.com/containers/image/storage/storage_transport.go deleted file mode 100644 index f6ebcdc4a3..0000000000 --- a/vendor/github.com/containers/image/storage/storage_transport.go +++ /dev/null @@ -1,450 +0,0 @@ -// +build !containers_image_storage_stub - -package storage - -import ( - "path/filepath" - "strings" - - "github.com/pkg/errors" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/containers/storage" - "github.com/containers/storage/pkg/idtools" - digest "github.com/opencontainers/go-digest" - "github.com/sirupsen/logrus" -) - -const ( - minimumTruncatedIDLength = 3 -) - -func init() { - transports.Register(Transport) -} - -var ( - // Transport is an ImageTransport that uses either a default - // storage.Store or one that's it's explicitly told to use. - Transport StoreTransport = &storageTransport{} - // ErrInvalidReference is returned when ParseReference() is passed an - // empty reference. - ErrInvalidReference = errors.New("invalid reference") - // ErrPathNotAbsolute is returned when a graph root is not an absolute - // path name. - ErrPathNotAbsolute = errors.New("path name is not absolute") -) - -// StoreTransport is an ImageTransport that uses a storage.Store to parse -// references, either its own default or one that it's told to use. -type StoreTransport interface { - types.ImageTransport - // SetStore sets the default store for this transport. - SetStore(storage.Store) - // GetImage retrieves the image from the transport's store that's named - // by the reference. - GetImage(types.ImageReference) (*storage.Image, error) - // GetStoreImage retrieves the image from a specified store that's named - // by the reference. - GetStoreImage(storage.Store, types.ImageReference) (*storage.Image, error) - // ParseStoreReference parses a reference, overriding any store - // specification that it may contain. - ParseStoreReference(store storage.Store, reference string) (*storageReference, error) - // SetDefaultUIDMap sets the default UID map to use when opening stores. - SetDefaultUIDMap(idmap []idtools.IDMap) - // SetDefaultGIDMap sets the default GID map to use when opening stores. - SetDefaultGIDMap(idmap []idtools.IDMap) - // DefaultUIDMap returns the default UID map used when opening stores. - DefaultUIDMap() []idtools.IDMap - // DefaultGIDMap returns the default GID map used when opening stores. - DefaultGIDMap() []idtools.IDMap -} - -type storageTransport struct { - store storage.Store - defaultUIDMap []idtools.IDMap - defaultGIDMap []idtools.IDMap -} - -func (s *storageTransport) Name() string { - // Still haven't really settled on a name. - return "containers-storage" -} - -// SetStore sets the Store object which the Transport will use for parsing -// references when information about a Store is not directly specified as part -// of the reference. If one is not set, the library will attempt to initialize -// one with default settings when a reference needs to be parsed. Calling -// SetStore does not affect previously parsed references. -func (s *storageTransport) SetStore(store storage.Store) { - s.store = store -} - -// SetDefaultUIDMap sets the default UID map to use when opening stores. -func (s *storageTransport) SetDefaultUIDMap(idmap []idtools.IDMap) { - s.defaultUIDMap = idmap -} - -// SetDefaultGIDMap sets the default GID map to use when opening stores. -func (s *storageTransport) SetDefaultGIDMap(idmap []idtools.IDMap) { - s.defaultGIDMap = idmap -} - -// DefaultUIDMap returns the default UID map used when opening stores. -func (s *storageTransport) DefaultUIDMap() []idtools.IDMap { - return s.defaultUIDMap -} - -// DefaultGIDMap returns the default GID map used when opening stores. -func (s *storageTransport) DefaultGIDMap() []idtools.IDMap { - return s.defaultGIDMap -} - -// ParseStoreReference takes a name or an ID, tries to figure out which it is -// relative to the given store, and returns it in a reference object. -func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (*storageReference, error) { - var name reference.Named - if ref == "" { - return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference") - } - if ref[0] == '[' { - // Ignore the store specifier. - closeIndex := strings.IndexRune(ref, ']') - if closeIndex < 1 { - return nil, errors.Wrapf(ErrInvalidReference, "store specifier in %q did not end", ref) - } - ref = ref[closeIndex+1:] - } - - // The last segment, if there's more than one, is either a digest from a reference, or an image ID. - split := strings.LastIndex(ref, "@") - idOrDigest := "" - if split != -1 { - // Peel off that last bit so that we can work on the rest. - idOrDigest = ref[split+1:] - if idOrDigest == "" { - return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like a digest or image ID", idOrDigest) - } - ref = ref[:split] - } - - // The middle segment (now the last segment), if there is one, is a digest. - split = strings.LastIndex(ref, "@") - sum := digest.Digest("") - if split != -1 { - sum = digest.Digest(ref[split+1:]) - if sum == "" { - return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image digest", sum) - } - ref = ref[:split] - } - - // If we have something that unambiguously should be a digest, validate it, and then the third part, - // if we have one, as an ID. - id := "" - if sum != "" { - if idSum, err := digest.Parse("sha256:" + idOrDigest); err != nil || idSum.Validate() != nil { - return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image ID", idOrDigest) - } - if err := sum.Validate(); err != nil { - return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image digest", sum) - } - id = idOrDigest - if img, err := store.Image(idOrDigest); err == nil && img != nil && len(idOrDigest) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, idOrDigest) { - // The ID is a truncated version of the ID of an image that's present in local storage, - // so we might as well use the expanded value. - id = img.ID - } - } else if idOrDigest != "" { - // There was no middle portion, so the final portion could be either a digest or an ID. - if idSum, err := digest.Parse("sha256:" + idOrDigest); err == nil && idSum.Validate() == nil { - // It's an ID. - id = idOrDigest - } else if idSum, err := digest.Parse(idOrDigest); err == nil && idSum.Validate() == nil { - // It's a digest. - sum = idSum - } else if img, err := store.Image(idOrDigest); err == nil && img != nil && len(idOrDigest) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, idOrDigest) { - // It's a truncated version of the ID of an image that's present in local storage, - // and we may need the expanded value. - id = img.ID - } else { - return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like a digest or image ID", idOrDigest) - } - } - - // If we only had one portion, then _maybe_ it's a truncated image ID. Only check on that if it's - // at least of what we guess is a reasonable minimum length, because we don't want a really short value - // like "a" matching an image by ID prefix when the input was actually meant to specify an image name. - if len(ref) >= minimumTruncatedIDLength && sum == "" && id == "" { - if img, err := store.Image(ref); err == nil && img != nil && strings.HasPrefix(img.ID, ref) { - // It's a truncated version of the ID of an image that's present in local storage; - // we need to expand it. - id = img.ID - ref = "" - } - } - - // The initial portion is probably a name, possibly with a tag. - if ref != "" { - var err error - if name, err = reference.ParseNormalizedNamed(ref); err != nil { - return nil, errors.Wrapf(err, "error parsing named reference %q", ref) - } - } - if name == nil && sum == "" && id == "" { - return nil, errors.Errorf("error parsing reference") - } - - // Construct a copy of the store spec. - optionsList := "" - options := store.GraphOptions() - if len(options) > 0 { - optionsList = ":" + strings.Join(options, ",") - } - storeSpec := "[" + store.GraphDriverName() + "@" + store.GraphRoot() + "+" + store.RunRoot() + optionsList + "]" - - // Convert the name back into a reference string, if we got a name. - refname := "" - tag := "" - if name != nil { - if sum.Validate() == nil { - canonical, err := reference.WithDigest(name, sum) - if err != nil { - return nil, errors.Wrapf(err, "error mixing name %q with digest %q", name, sum) - } - refname = verboseName(canonical) - } else { - name = reference.TagNameOnly(name) - tagged, ok := name.(reference.Tagged) - if !ok { - return nil, errors.Errorf("error parsing possibly-tagless name %q", ref) - } - refname = verboseName(name) - tag = tagged.Tag() - } - } - if refname == "" { - logrus.Debugf("parsed reference to id into %q", storeSpec+"@"+id) - } else if id == "" { - logrus.Debugf("parsed reference to refname into %q", storeSpec+refname) - } else { - logrus.Debugf("parsed reference to refname@id into %q", storeSpec+refname+"@"+id) - } - return newReference(storageTransport{store: store, defaultUIDMap: s.defaultUIDMap, defaultGIDMap: s.defaultGIDMap}, refname, id, name, tag, sum), nil -} - -func (s *storageTransport) GetStore() (storage.Store, error) { - // Return the transport's previously-set store. If we don't have one - // of those, initialize one now. - if s.store == nil { - options := storage.DefaultStoreOptions - options.UIDMap = s.defaultUIDMap - options.GIDMap = s.defaultGIDMap - store, err := storage.GetStore(options) - if err != nil { - return nil, err - } - s.store = store - } - return s.store, nil -} - -// ParseReference takes a name and a tag or digest and/or ID -// ("_name_"/"@_id_"/"_name_:_tag_"/"_name_:_tag_@_id_"/"_name_@_digest_"/"_name_@_digest_@_id_"), -// possibly prefixed with a store specifier in the form "[_graphroot_]" or -// "[_driver_@_graphroot_]" or "[_driver_@_graphroot_+_runroot_]" or -// "[_driver_@_graphroot_:_options_]" or "[_driver_@_graphroot_+_runroot_:_options_]", -// tries to figure out which it is, and returns it in a reference object. -// If _id_ is the ID of an image that's present in local storage, it can be truncated, and -// even be specified as if it were a _name_, value. -func (s *storageTransport) ParseReference(reference string) (types.ImageReference, error) { - var store storage.Store - // Check if there's a store location prefix. If there is, then it - // needs to match a store that was previously initialized using - // storage.GetStore(), or be enough to let the storage library fill out - // the rest using knowledge that it has from elsewhere. - if reference[0] == '[' { - closeIndex := strings.IndexRune(reference, ']') - if closeIndex < 1 { - return nil, ErrInvalidReference - } - storeSpec := reference[1:closeIndex] - reference = reference[closeIndex+1:] - // Peel off a "driver@" from the start. - driverInfo := "" - driverSplit := strings.SplitN(storeSpec, "@", 2) - if len(driverSplit) != 2 { - if storeSpec == "" { - return nil, ErrInvalidReference - } - } else { - driverInfo = driverSplit[0] - if driverInfo == "" { - return nil, ErrInvalidReference - } - storeSpec = driverSplit[1] - if storeSpec == "" { - return nil, ErrInvalidReference - } - } - // Peel off a ":options" from the end. - var options []string - optionsSplit := strings.SplitN(storeSpec, ":", 2) - if len(optionsSplit) == 2 { - options = strings.Split(optionsSplit[1], ",") - storeSpec = optionsSplit[0] - } - // Peel off a "+runroot" from the new end. - runRootInfo := "" - runRootSplit := strings.SplitN(storeSpec, "+", 2) - if len(runRootSplit) == 2 { - runRootInfo = runRootSplit[1] - storeSpec = runRootSplit[0] - } - // The rest is our graph root. - rootInfo := storeSpec - // Check that any paths are absolute paths. - if rootInfo != "" && !filepath.IsAbs(rootInfo) { - return nil, ErrPathNotAbsolute - } - if runRootInfo != "" && !filepath.IsAbs(runRootInfo) { - return nil, ErrPathNotAbsolute - } - store2, err := storage.GetStore(storage.StoreOptions{ - GraphDriverName: driverInfo, - GraphRoot: rootInfo, - RunRoot: runRootInfo, - GraphDriverOptions: options, - UIDMap: s.defaultUIDMap, - GIDMap: s.defaultGIDMap, - }) - if err != nil { - return nil, err - } - store = store2 - } else { - // We didn't have a store spec, so use the default. - store2, err := s.GetStore() - if err != nil { - return nil, err - } - store = store2 - } - return s.ParseStoreReference(store, reference) -} - -func (s storageTransport) GetStoreImage(store storage.Store, ref types.ImageReference) (*storage.Image, error) { - dref := ref.DockerReference() - if dref != nil { - if img, err := store.Image(verboseName(dref)); err == nil { - return img, nil - } - } - if sref, ok := ref.(*storageReference); ok { - if sref.id != "" { - if img, err := store.Image(sref.id); err == nil { - return img, nil - } - } - tmpRef := *sref - if img, err := tmpRef.resolveImage(); err == nil { - return img, nil - } - } - return nil, storage.ErrImageUnknown -} - -func (s *storageTransport) GetImage(ref types.ImageReference) (*storage.Image, error) { - store, err := s.GetStore() - if err != nil { - return nil, err - } - return s.GetStoreImage(store, ref) -} - -func (s storageTransport) ValidatePolicyConfigurationScope(scope string) error { - // Check that there's a store location prefix. Values we're passed are - // expected to come from PolicyConfigurationIdentity or - // PolicyConfigurationNamespaces, so if there's no store location, - // something's wrong. - if scope[0] != '[' { - return ErrInvalidReference - } - // Parse the store location prefix. - closeIndex := strings.IndexRune(scope, ']') - if closeIndex < 1 { - return ErrInvalidReference - } - storeSpec := scope[1:closeIndex] - scope = scope[closeIndex+1:] - storeInfo := strings.SplitN(storeSpec, "@", 2) - if len(storeInfo) == 1 && storeInfo[0] != "" { - // One component: the graph root. - if !filepath.IsAbs(storeInfo[0]) { - return ErrPathNotAbsolute - } - } else if len(storeInfo) == 2 && storeInfo[0] != "" && storeInfo[1] != "" { - // Two components: the driver type and the graph root. - if !filepath.IsAbs(storeInfo[1]) { - return ErrPathNotAbsolute - } - } else { - // Anything else: scope specified in a form we don't - // recognize. - return ErrInvalidReference - } - // That might be all of it, and that's okay. - if scope == "" { - return nil - } - // But if there is anything left, it has to be a name, with or without - // a tag, with or without an ID, since we don't return namespace values - // that are just bare IDs. - scopeInfo := strings.SplitN(scope, "@", 2) - if len(scopeInfo) == 1 && scopeInfo[0] != "" { - _, err := reference.ParseNormalizedNamed(scopeInfo[0]) - if err != nil { - return err - } - } else if len(scopeInfo) == 2 && scopeInfo[0] != "" && scopeInfo[1] != "" { - _, err := reference.ParseNormalizedNamed(scopeInfo[0]) - if err != nil { - return err - } - _, err = digest.Parse("sha256:" + scopeInfo[1]) - if err != nil { - return err - } - } else { - return ErrInvalidReference - } - return nil -} - -func verboseName(r reference.Reference) string { - if r == nil { - return "" - } - named, isNamed := r.(reference.Named) - digested, isDigested := r.(reference.Digested) - tagged, isTagged := r.(reference.Tagged) - name := "" - tag := "" - sum := "" - if isNamed { - name = (reference.TrimNamed(named)).String() - } - if isTagged { - if tagged.Tag() != "" { - tag = ":" + tagged.Tag() - } - } - if isDigested { - if digested.Digest().Validate() == nil { - sum = "@" + digested.Digest().String() - } - } - return name + tag + sum -} diff --git a/vendor/github.com/containers/image/tarball/doc.go b/vendor/github.com/containers/image/tarball/doc.go deleted file mode 100644 index a6ced5a0ee..0000000000 --- a/vendor/github.com/containers/image/tarball/doc.go +++ /dev/null @@ -1,48 +0,0 @@ -// Package tarball provides a way to generate images using one or more layer -// tarballs and an optional template configuration. -// -// An example: -// package main -// -// import ( -// "fmt" -// -// cp "github.com/containers/image/copy" -// "github.com/containers/image/tarball" -// "github.com/containers/image/transports/alltransports" -// -// imgspecv1 "github.com/containers/image/transports/alltransports" -// ) -// -// func imageFromTarball() { -// src, err := alltransports.ParseImageName("tarball:/var/cache/mock/fedora-26-x86_64/root_cache/cache.tar.gz") -// // - or - -// // src, err := tarball.Transport.ParseReference("/var/cache/mock/fedora-26-x86_64/root_cache/cache.tar.gz") -// if err != nil { -// panic(err) -// } -// updater, ok := src.(tarball.ConfigUpdater) -// if !ok { -// panic("unexpected: a tarball reference should implement tarball.ConfigUpdater") -// } -// config := imgspecv1.Image{ -// Config: imgspecv1.ImageConfig{ -// Cmd: []string{"/bin/bash"}, -// }, -// } -// annotations := make(map[string]string) -// annotations[imgspecv1.AnnotationDescription] = "test image built from a mock root cache" -// err = updater.ConfigUpdate(config, annotations) -// if err != nil { -// panic(err) -// } -// dest, err := alltransports.ParseImageName("docker-daemon:mock:latest") -// if err != nil { -// panic(err) -// } -// err = cp.Image(nil, dest, src, nil) -// if err != nil { -// panic(err) -// } -// } -package tarball diff --git a/vendor/github.com/containers/image/tarball/tarball_reference.go b/vendor/github.com/containers/image/tarball/tarball_reference.go deleted file mode 100644 index a0819ac580..0000000000 --- a/vendor/github.com/containers/image/tarball/tarball_reference.go +++ /dev/null @@ -1,93 +0,0 @@ -package tarball - -import ( - "fmt" - "os" - "strings" - - "github.com/containers/image/docker/reference" - "github.com/containers/image/image" - "github.com/containers/image/types" - - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -// ConfigUpdater is an interface that ImageReferences for "tarball" images also -// implement. It can be used to set values for a configuration, and to set -// image annotations which will be present in the images returned by the -// reference's NewImage() or NewImageSource() methods. -type ConfigUpdater interface { - ConfigUpdate(config imgspecv1.Image, annotations map[string]string) error -} - -type tarballReference struct { - transport types.ImageTransport - config imgspecv1.Image - annotations map[string]string - filenames []string - stdin []byte -} - -// ConfigUpdate updates the image's default configuration and adds annotations -// which will be visible in source images created using this reference. -func (r *tarballReference) ConfigUpdate(config imgspecv1.Image, annotations map[string]string) error { - r.config = config - if r.annotations == nil { - r.annotations = make(map[string]string) - } - for k, v := range annotations { - r.annotations[k] = v - } - return nil -} - -func (r *tarballReference) Transport() types.ImageTransport { - return r.transport -} - -func (r *tarballReference) StringWithinTransport() string { - return strings.Join(r.filenames, ":") -} - -func (r *tarballReference) DockerReference() reference.Named { - return nil -} - -func (r *tarballReference) PolicyConfigurationIdentity() string { - return "" -} - -func (r *tarballReference) PolicyConfigurationNamespaces() []string { - return nil -} - -// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. -// The caller must call .Close() on the returned ImageCloser. -// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, -// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. -// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. -func (r *tarballReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) { - src, err := r.NewImageSource(ctx) - if err != nil { - return nil, err - } - img, err := image.FromSource(ctx, src) - if err != nil { - src.Close() - return nil, err - } - return img, nil -} - -func (r *tarballReference) DeleteImage(ctx *types.SystemContext) error { - for _, filename := range r.filenames { - if err := os.Remove(filename); err != nil && !os.IsNotExist(err) { - return fmt.Errorf("error removing %q: %v", filename, err) - } - } - return nil -} - -func (r *tarballReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) { - return nil, fmt.Errorf(`"tarball:" locations can only be read from, not written to`) -} diff --git a/vendor/github.com/containers/image/tarball/tarball_src.go b/vendor/github.com/containers/image/tarball/tarball_src.go deleted file mode 100644 index 8b5b496dae..0000000000 --- a/vendor/github.com/containers/image/tarball/tarball_src.go +++ /dev/null @@ -1,260 +0,0 @@ -package tarball - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "runtime" - "strings" - "time" - - "github.com/containers/image/types" - - digest "github.com/opencontainers/go-digest" - imgspecs "github.com/opencontainers/image-spec/specs-go" - imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -type tarballImageSource struct { - reference tarballReference - filenames []string - diffIDs []digest.Digest - diffSizes []int64 - blobIDs []digest.Digest - blobSizes []int64 - blobTypes []string - config []byte - configID digest.Digest - configSize int64 - manifest []byte -} - -func (r *tarballReference) NewImageSource(ctx *types.SystemContext) (types.ImageSource, error) { - // Gather up the digests, sizes, and date information for all of the files. - filenames := []string{} - diffIDs := []digest.Digest{} - diffSizes := []int64{} - blobIDs := []digest.Digest{} - blobSizes := []int64{} - blobTimes := []time.Time{} - blobTypes := []string{} - for _, filename := range r.filenames { - var file *os.File - var err error - var blobSize int64 - var blobTime time.Time - var reader io.Reader - if filename == "-" { - blobSize = int64(len(r.stdin)) - blobTime = time.Now() - reader = bytes.NewReader(r.stdin) - } else { - file, err = os.Open(filename) - if err != nil { - return nil, fmt.Errorf("error opening %q for reading: %v", filename, err) - } - defer file.Close() - reader = file - fileinfo, err := file.Stat() - if err != nil { - return nil, fmt.Errorf("error reading size of %q: %v", filename, err) - } - blobSize = fileinfo.Size() - blobTime = fileinfo.ModTime() - } - - // Default to assuming the layer is compressed. - layerType := imgspecv1.MediaTypeImageLayerGzip - - // Set up to digest the file as it is. - blobIDdigester := digest.Canonical.Digester() - reader = io.TeeReader(reader, blobIDdigester.Hash()) - - // Set up to digest the file after we maybe decompress it. - diffIDdigester := digest.Canonical.Digester() - uncompressed, err := gzip.NewReader(reader) - if err == nil { - // It is compressed, so the diffID is the digest of the uncompressed version - reader = io.TeeReader(uncompressed, diffIDdigester.Hash()) - } else { - // It is not compressed, so the diffID and the blobID are going to be the same - diffIDdigester = blobIDdigester - layerType = imgspecv1.MediaTypeImageLayer - uncompressed = nil - } - n, err := io.Copy(ioutil.Discard, reader) - if err != nil { - return nil, fmt.Errorf("error reading %q: %v", filename, err) - } - if uncompressed != nil { - uncompressed.Close() - } - - // Grab our uncompressed and possibly-compressed digests and sizes. - filenames = append(filenames, filename) - diffIDs = append(diffIDs, diffIDdigester.Digest()) - diffSizes = append(diffSizes, n) - blobIDs = append(blobIDs, blobIDdigester.Digest()) - blobSizes = append(blobSizes, blobSize) - blobTimes = append(blobTimes, blobTime) - blobTypes = append(blobTypes, layerType) - } - - // Build the rootfs and history for the configuration blob. - rootfs := imgspecv1.RootFS{ - Type: "layers", - DiffIDs: diffIDs, - } - created := time.Time{} - history := []imgspecv1.History{} - // Pick up the layer comment from the configuration's history list, if one is set. - comment := "imported from tarball" - if len(r.config.History) > 0 && r.config.History[0].Comment != "" { - comment = r.config.History[0].Comment - } - for i := range diffIDs { - createdBy := fmt.Sprintf("/bin/sh -c #(nop) ADD file:%s in %c", diffIDs[i].Hex(), os.PathSeparator) - history = append(history, imgspecv1.History{ - Created: &blobTimes[i], - CreatedBy: createdBy, - Comment: comment, - }) - // Use the mtime of the most recently modified file as the image's creation time. - if created.Before(blobTimes[i]) { - created = blobTimes[i] - } - } - - // Pick up other defaults from the config in the reference. - config := r.config - if config.Created == nil { - config.Created = &created - } - if config.Architecture == "" { - config.Architecture = runtime.GOARCH - } - if config.OS == "" { - config.OS = runtime.GOOS - } - config.RootFS = rootfs - config.History = history - - // Encode and digest the image configuration blob. - configBytes, err := json.Marshal(&config) - if err != nil { - return nil, fmt.Errorf("error generating configuration blob for %q: %v", strings.Join(r.filenames, separator), err) - } - configID := digest.Canonical.FromBytes(configBytes) - configSize := int64(len(configBytes)) - - // Populate a manifest with the configuration blob and the file as the single layer. - layerDescriptors := []imgspecv1.Descriptor{} - for i := range blobIDs { - layerDescriptors = append(layerDescriptors, imgspecv1.Descriptor{ - Digest: blobIDs[i], - Size: blobSizes[i], - MediaType: blobTypes[i], - }) - } - annotations := make(map[string]string) - for k, v := range r.annotations { - annotations[k] = v - } - manifest := imgspecv1.Manifest{ - Versioned: imgspecs.Versioned{ - SchemaVersion: 2, - }, - Config: imgspecv1.Descriptor{ - Digest: configID, - Size: configSize, - MediaType: imgspecv1.MediaTypeImageConfig, - }, - Layers: layerDescriptors, - Annotations: annotations, - } - - // Encode the manifest. - manifestBytes, err := json.Marshal(&manifest) - if err != nil { - return nil, fmt.Errorf("error generating manifest for %q: %v", strings.Join(r.filenames, separator), err) - } - - // Return the image. - src := &tarballImageSource{ - reference: *r, - filenames: filenames, - diffIDs: diffIDs, - diffSizes: diffSizes, - blobIDs: blobIDs, - blobSizes: blobSizes, - blobTypes: blobTypes, - config: configBytes, - configID: configID, - configSize: configSize, - manifest: manifestBytes, - } - - return src, nil -} - -func (is *tarballImageSource) Close() error { - return nil -} - -func (is *tarballImageSource) GetBlob(blobinfo types.BlobInfo) (io.ReadCloser, int64, error) { - // We should only be asked about things in the manifest. Maybe the configuration blob. - if blobinfo.Digest == is.configID { - return ioutil.NopCloser(bytes.NewBuffer(is.config)), is.configSize, nil - } - // Maybe one of the layer blobs. - for i := range is.blobIDs { - if blobinfo.Digest == is.blobIDs[i] { - // We want to read that layer: open the file or memory block and hand it back. - if is.filenames[i] == "-" { - return ioutil.NopCloser(bytes.NewBuffer(is.reference.stdin)), int64(len(is.reference.stdin)), nil - } - reader, err := os.Open(is.filenames[i]) - if err != nil { - return nil, -1, fmt.Errorf("error opening %q: %v", is.filenames[i], err) - } - return reader, is.blobSizes[i], nil - } - } - return nil, -1, fmt.Errorf("no blob with digest %q found", blobinfo.Digest.String()) -} - -// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). -// It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); -// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). -func (is *tarballImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) { - if instanceDigest != nil { - return nil, "", fmt.Errorf("manifest lists are not supported by the %q transport", transportName) - } - return is.manifest, imgspecv1.MediaTypeImageManifest, nil -} - -// GetSignatures returns the image's signatures. It may use a remote (= slow) service. -// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for -// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list -// (e.g. if the source never returns manifest lists). -func (*tarballImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) { - if instanceDigest != nil { - return nil, fmt.Errorf("manifest lists are not supported by the %q transport", transportName) - } - return nil, nil -} - -func (is *tarballImageSource) Reference() types.ImageReference { - return &is.reference -} - -// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified. -func (*tarballImageSource) LayerInfosForCopy() []types.BlobInfo { - return nil -} diff --git a/vendor/github.com/containers/image/tarball/tarball_transport.go b/vendor/github.com/containers/image/tarball/tarball_transport.go deleted file mode 100644 index 72558b5e83..0000000000 --- a/vendor/github.com/containers/image/tarball/tarball_transport.go +++ /dev/null @@ -1,66 +0,0 @@ -package tarball - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "strings" - - "github.com/containers/image/transports" - "github.com/containers/image/types" -) - -const ( - transportName = "tarball" - separator = ":" -) - -var ( - // Transport implements the types.ImageTransport interface for "tarball:" images, - // which are makeshift images constructed using one or more possibly-compressed tar - // archives. - Transport = &tarballTransport{} -) - -type tarballTransport struct { -} - -func (t *tarballTransport) Name() string { - return transportName -} - -func (t *tarballTransport) ParseReference(reference string) (types.ImageReference, error) { - var stdin []byte - var err error - filenames := strings.Split(reference, separator) - for _, filename := range filenames { - if filename == "-" { - stdin, err = ioutil.ReadAll(os.Stdin) - if err != nil { - return nil, fmt.Errorf("error buffering stdin: %v", err) - } - continue - } - f, err := os.Open(filename) - if err != nil { - return nil, fmt.Errorf("error opening %q: %v", filename, err) - } - f.Close() - } - ref := &tarballReference{ - transport: t, - filenames: filenames, - stdin: stdin, - } - return ref, nil -} - -func (t *tarballTransport) ValidatePolicyConfigurationScope(scope string) error { - // See the explanation in daemonReference.PolicyConfigurationIdentity. - return errors.New(`tarball: does not support any scopes except the default "" one`) -} - -func init() { - transports.Register(Transport) -} diff --git a/vendor/github.com/containers/image/transports/alltransports/alltransports.go b/vendor/github.com/containers/image/transports/alltransports/alltransports.go deleted file mode 100644 index b4552df669..0000000000 --- a/vendor/github.com/containers/image/transports/alltransports/alltransports.go +++ /dev/null @@ -1,35 +0,0 @@ -package alltransports - -import ( - "strings" - - // register all known transports - // NOTE: Make sure docs/policy.json.md is updated when adding or updating - // a transport. - _ "github.com/containers/image/directory" - _ "github.com/containers/image/docker" - _ "github.com/containers/image/docker/archive" - _ "github.com/containers/image/docker/daemon" - _ "github.com/containers/image/oci/archive" - _ "github.com/containers/image/oci/layout" - _ "github.com/containers/image/openshift" - _ "github.com/containers/image/tarball" - // The ostree transport is registered by ostree*.go - // The storage transport is registered by storage*.go - "github.com/containers/image/transports" - "github.com/containers/image/types" - "github.com/pkg/errors" -) - -// ParseImageName converts a URL-like image name to a types.ImageReference. -func ParseImageName(imgName string) (types.ImageReference, error) { - parts := strings.SplitN(imgName, ":", 2) - if len(parts) != 2 { - return nil, errors.Errorf(`Invalid image name "%s", expected colon-separated transport:reference`, imgName) - } - transport := transports.Get(parts[0]) - if transport == nil { - return nil, errors.Errorf(`Invalid image name "%s", unknown transport "%s"`, imgName, parts[0]) - } - return transport.ParseReference(parts[1]) -} diff --git a/vendor/github.com/containers/image/transports/alltransports/ostree.go b/vendor/github.com/containers/image/transports/alltransports/ostree.go deleted file mode 100644 index 0fc5d7ef79..0000000000 --- a/vendor/github.com/containers/image/transports/alltransports/ostree.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !containers_image_ostree_stub - -package alltransports - -import ( - // Register the ostree transport - _ "github.com/containers/image/ostree" -) diff --git a/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go b/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go deleted file mode 100644 index 8b01afe7cc..0000000000 --- a/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build containers_image_ostree_stub - -package alltransports - -import "github.com/containers/image/transports" - -func init() { - transports.Register(transports.NewStubTransport("ostree")) -} diff --git a/vendor/github.com/containers/image/transports/alltransports/storage.go b/vendor/github.com/containers/image/transports/alltransports/storage.go deleted file mode 100644 index a867c66446..0000000000 --- a/vendor/github.com/containers/image/transports/alltransports/storage.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !containers_image_storage_stub - -package alltransports - -import ( - // Register the storage transport - _ "github.com/containers/image/storage" -) diff --git a/vendor/github.com/containers/image/transports/alltransports/storage_stub.go b/vendor/github.com/containers/image/transports/alltransports/storage_stub.go deleted file mode 100644 index 4ac684e58f..0000000000 --- a/vendor/github.com/containers/image/transports/alltransports/storage_stub.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build containers_image_storage_stub - -package alltransports - -import "github.com/containers/image/transports" - -func init() { - transports.Register(transports.NewStubTransport("containers-storage")) -} diff --git a/vendor/github.com/containers/image/transports/stub.go b/vendor/github.com/containers/image/transports/stub.go deleted file mode 100644 index 087f69b6ea..0000000000 --- a/vendor/github.com/containers/image/transports/stub.go +++ /dev/null @@ -1,36 +0,0 @@ -package transports - -import ( - "fmt" - - "github.com/containers/image/types" -) - -// stubTransport is an implementation of types.ImageTransport which has a name, but rejects any references with “the transport $name: is not supported in this build”. -type stubTransport string - -// NewStubTransport returns an implementation of types.ImageTransport which has a name, but rejects any references with “the transport $name: is not supported in this build”. -func NewStubTransport(name string) types.ImageTransport { - return stubTransport(name) -} - -// Name returns the name of the transport, which must be unique among other transports. -func (s stubTransport) Name() string { - return string(s) -} - -// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. -func (s stubTransport) ParseReference(reference string) (types.ImageReference, error) { - return nil, fmt.Errorf(`The transport "%s:" is not supported in this build`, string(s)) -} - -// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys -// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). -// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. -// scope passed to this function will not be "", that value is always allowed. -func (s stubTransport) ValidatePolicyConfigurationScope(scope string) error { - // Allowing any reference in here allows tools with some transports stubbed-out to still - // use signature verification policies which refer to these stubbed-out transports. - // See also the treatment of unknown transports in policyTransportScopesWithTransport.UnmarshalJSON . - return nil -} diff --git a/vendor/github.com/containers/image/transports/transports.go b/vendor/github.com/containers/image/transports/transports.go deleted file mode 100644 index 687d0a44e3..0000000000 --- a/vendor/github.com/containers/image/transports/transports.go +++ /dev/null @@ -1,90 +0,0 @@ -package transports - -import ( - "fmt" - "sort" - "sync" - - "github.com/containers/image/types" -) - -// knownTransports is a registry of known ImageTransport instances. -type knownTransports struct { - transports map[string]types.ImageTransport - mu sync.Mutex -} - -func (kt *knownTransports) Get(k string) types.ImageTransport { - kt.mu.Lock() - t := kt.transports[k] - kt.mu.Unlock() - return t -} - -func (kt *knownTransports) Remove(k string) { - kt.mu.Lock() - delete(kt.transports, k) - kt.mu.Unlock() -} - -func (kt *knownTransports) Add(t types.ImageTransport) { - kt.mu.Lock() - defer kt.mu.Unlock() - name := t.Name() - if t := kt.transports[name]; t != nil { - panic(fmt.Sprintf("Duplicate image transport name %s", name)) - } - kt.transports[name] = t -} - -var kt *knownTransports - -func init() { - kt = &knownTransports{ - transports: make(map[string]types.ImageTransport), - } -} - -// Get returns the transport specified by name or nil when unavailable. -func Get(name string) types.ImageTransport { - return kt.Get(name) -} - -// Delete deletes a transport from the registered transports. -func Delete(name string) { - kt.Remove(name) -} - -// Register registers a transport. -func Register(t types.ImageTransport) { - kt.Add(t) -} - -// ImageName converts a types.ImageReference into an URL-like image name, which MUST be such that -// ParseImageName(ImageName(reference)) returns an equivalent reference. -// -// This is the generally recommended way to refer to images in the UI. -// -// NOTE: The returned string is not promised to be equal to the original input to ParseImageName; -// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. -func ImageName(ref types.ImageReference) string { - return ref.Transport().Name() + ":" + ref.StringWithinTransport() -} - -// ListNames returns a list of non deprecated transport names. -// Deprecated transports can be used, but are not presented to users. -func ListNames() []string { - kt.mu.Lock() - defer kt.mu.Unlock() - deprecated := map[string]bool{ - "atomic": true, - } - var names []string - for _, transport := range kt.transports { - if !deprecated[transport.Name()] { - names = append(names, transport.Name()) - } - } - sort.Strings(names) - return names -} diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go deleted file mode 100644 index 2e9c7105d3..0000000000 --- a/vendor/github.com/containers/image/types/types.go +++ /dev/null @@ -1,388 +0,0 @@ -package types - -import ( - "context" - "io" - "time" - - "github.com/containers/image/docker/reference" - "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" -) - -// ImageTransport is a top-level namespace for ways to to store/load an image. -// It should generally correspond to ImageSource/ImageDestination implementations. -// -// Note that ImageTransport is based on "ways the users refer to image storage", not necessarily on the underlying physical transport. -// For example, all Docker References would be used within a single "docker" transport, regardless of whether the images are pulled over HTTP or HTTPS -// (or, even, IPv4 or IPv6). -// -// OTOH all images using the same transport should (apart from versions of the image format), be interoperable. -// For example, several different ImageTransport implementations may be based on local filesystem paths, -// but using completely different formats for the contents of that path (a single tar file, a directory containing tarballs, a fully expanded container filesystem, ...) -// -// See also transports.KnownTransports. -type ImageTransport interface { - // Name returns the name of the transport, which must be unique among other transports. - Name() string - // ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference. - ParseReference(reference string) (ImageReference, error) - // ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys - // (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value). - // It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion. - // scope passed to this function will not be "", that value is always allowed. - ValidatePolicyConfigurationScope(scope string) error -} - -// ImageReference is an abstracted way to refer to an image location, namespaced within an ImageTransport. -// -// The object should preferably be immutable after creation, with any parsing/state-dependent resolving happening -// within an ImageTransport.ParseReference() or equivalent API creating the reference object. -// That's also why the various identification/formatting methods of this type do not support returning errors. -// -// WARNING: While this design freezes the content of the reference within this process, it can not freeze the outside -// world: paths may be replaced by symlinks elsewhere, HTTP APIs may start returning different results, and so on. -type ImageReference interface { - Transport() ImageTransport - // StringWithinTransport returns a string representation of the reference, which MUST be such that - // reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference. - // NOTE: The returned string is not promised to be equal to the original input to ParseReference; - // e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa. - // WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix; - // instead, see transports.ImageName(). - StringWithinTransport() string - - // DockerReference returns a Docker reference associated with this reference - // (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent, - // not e.g. after redirect or alias processing), or nil if unknown/not applicable. - DockerReference() reference.Named - - // PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup. - // This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases; - // The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical - // (i.e. various references with exactly the same semantics should return the same configuration identity) - // It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but - // not required/guaranteed that it will be a valid input to Transport().ParseReference(). - // Returns "" if configuration identities for these references are not supported. - PolicyConfigurationIdentity() string - - // PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search - // for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed - // in order, terminating on first match, and an implicit "" is always checked at the end. - // It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), - // and each following element to be a prefix of the element preceding it. - PolicyConfigurationNamespaces() []string - - // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. - // The caller must call .Close() on the returned ImageCloser. - // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, - // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. - // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details. - NewImage(ctx *SystemContext) (ImageCloser, error) - // NewImageSource returns a types.ImageSource for this reference. - // The caller must call .Close() on the returned ImageSource. - NewImageSource(ctx *SystemContext) (ImageSource, error) - // NewImageDestination returns a types.ImageDestination for this reference. - // The caller must call .Close() on the returned ImageDestination. - NewImageDestination(ctx *SystemContext) (ImageDestination, error) - - // DeleteImage deletes the named image from the registry, if supported. - DeleteImage(ctx *SystemContext) error -} - -// BlobInfo collects known information about a blob (layer/config). -// In some situations, some fields may be unknown, in others they may be mandatory; documenting an “unknown” value here does not override that. -type BlobInfo struct { - Digest digest.Digest // "" if unknown. - Size int64 // -1 if unknown - URLs []string - Annotations map[string]string - MediaType string -} - -// ImageSource is a service, possibly remote (= slow), to download components of a single image or a named image set (manifest list). -// This is primarily useful for copying images around; for examining their properties, Image (below) -// is usually more useful. -// Each ImageSource should eventually be closed by calling Close(). -// -// WARNING: Various methods which return an object identified by digest generally do not -// validate that the returned data actually matches that digest; this is the caller’s responsibility. -type ImageSource interface { - // Reference returns the reference used to set up this source, _as specified by the user_ - // (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. - Reference() ImageReference - // Close removes resources associated with an initialized ImageSource, if any. - Close() error - // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). - // It may use a remote (= slow) service. - // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list); - // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists). - GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) - // GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown). - // The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. - GetBlob(BlobInfo) (io.ReadCloser, int64, error) - // GetSignatures returns the image's signatures. It may use a remote (= slow) service. - // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for - // (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list - // (e.g. if the source never returns manifest lists). - GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) - // LayerInfosForCopy returns either nil (meaning the values in the manifest are fine), or updated values for the layer blobsums that are listed in the image's manifest. - // The Digest field is guaranteed to be provided; Size may be -1. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfosForCopy() []BlobInfo -} - -// ImageDestination is a service, possibly remote (= slow), to store components of a single image. -// -// There is a specific required order for some of the calls: -// PutBlob on the various blobs, if any, MUST be called before PutManifest (manifest references blobs, which may be created or compressed only at push time) -// ReapplyBlob, if used, MUST only be called if HasBlob returned true for the same blob digest -// PutSignatures, if called, MUST be called after PutManifest (signatures reference manifest contents) -// Finally, Commit MUST be called if the caller wants the image, as formed by the components saved above, to persist. -// -// Each ImageDestination should eventually be closed by calling Close(). -type ImageDestination interface { - // Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent, - // e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects. - Reference() ImageReference - // Close removes resources associated with an initialized ImageDestination, if any. - Close() error - - // SupportedManifestMIMETypes tells which manifest mime types the destination supports - // If an empty slice or nil it's returned, then any mime type can be tried to upload - SupportedManifestMIMETypes() []string - // SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures. - // Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil. - SupportsSignatures() error - // ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination. - ShouldCompressLayers() bool - // AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually - // uploaded to the image destination, true otherwise. - AcceptsForeignLayerURLs() bool - // MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise. - MustMatchRuntimeOS() bool - // PutBlob writes contents of stream and returns data representing the result. - // inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it. - // inputInfo.Size is the expected length of stream, if known. - // inputInfo.MediaType describes the blob format, if known. - // WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available - // to any other readers for download using the supplied digest. - // If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far. - PutBlob(stream io.Reader, inputInfo BlobInfo) (BlobInfo, error) - // HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob. - // Unlike PutBlob, the digest can not be empty. If HasBlob returns true, the size of the blob must also be returned. - // If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil); - // it returns a non-nil error only on an unexpected failure. - HasBlob(info BlobInfo) (bool, int64, error) - // ReapplyBlob informs the image destination that a blob for which HasBlob previously returned true would have been passed to PutBlob if it had returned false. Like HasBlob and unlike PutBlob, the digest can not be empty. If the blob is a filesystem layer, this signifies that the changes it describes need to be applied again when composing a filesystem tree. - ReapplyBlob(info BlobInfo) (BlobInfo, error) - // PutManifest writes manifest to the destination. - // FIXME? This should also receive a MIME type if known, to differentiate between schema versions. - // If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema), - // but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. - PutManifest(manifest []byte) error - PutSignatures(signatures [][]byte) error - // Commit marks the process of storing the image as successful and asks for the image to be persisted. - // WARNING: This does not have any transactional semantics: - // - Uploaded data MAY be visible to others before Commit() is called - // - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) - Commit() error -} - -// ManifestTypeRejectedError is returned by ImageDestination.PutManifest if the destination is in principle available, -// refuses specifically this manifest type, but may accept a different manifest type. -type ManifestTypeRejectedError struct { // We only use a struct to allow a type assertion, without limiting the contents of the error otherwise. - Err error -} - -func (e ManifestTypeRejectedError) Error() string { - return e.Err.Error() -} - -// UnparsedImage is an Image-to-be; until it is verified and accepted, it only caries its identity and caches manifest and signature blobs. -// Thus, an UnparsedImage can be created from an ImageSource simply by fetching blobs without interpreting them, -// allowing cryptographic signature verification to happen first, before even fetching the manifest, or parsing anything else. -// This also makes the UnparsedImage→Image conversion an explicitly visible step. -// -// An UnparsedImage is a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance. -// -// The UnparsedImage must not be used after the underlying ImageSource is Close()d. -type UnparsedImage interface { - // Reference returns the reference used to set up this source, _as specified by the user_ - // (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. - Reference() ImageReference - // Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need. - Manifest() ([]byte, string, error) - // Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. - Signatures(ctx context.Context) ([][]byte, error) - // LayerInfosForCopy returns either nil (meaning the values in the manifest are fine), or updated values for the layer blobsums that are listed in the image's manifest. - // The Digest field is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfosForCopy() []BlobInfo -} - -// Image is the primary API for inspecting properties of images. -// An Image is based on a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance. -// -// The Image must not be used after the underlying ImageSource is Close()d. -type Image interface { - // Note that Reference may return nil in the return value of UpdatedImage! - UnparsedImage - // ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object. - // Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below. - ConfigInfo() BlobInfo - // ConfigBlob returns the blob described by ConfigInfo, if ConfigInfo().Digest != ""; nil otherwise. - // The result is cached; it is OK to call this however often you need. - ConfigBlob() ([]byte, error) - // OCIConfig returns the image configuration as per OCI v1 image-spec. Information about - // layers in the resulting configuration isn't guaranteed to be returned to due how - // old image manifests work (docker v2s1 especially). - OCIConfig() (*v1.Image, error) - // LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers). - // The Digest field is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfos() []BlobInfo - // EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. - // It returns false if the manifest does not embed a Docker reference. - // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) - EmbeddedDockerReferenceConflicts(ref reference.Named) bool - // Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. - Inspect() (*ImageInspectInfo, error) - // UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. - // This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute - // (most importantly it forces us to download the full layers even if they are already present at the destination). - UpdatedImageNeedsLayerDiffIDs(options ManifestUpdateOptions) bool - // UpdatedImage returns a types.Image modified according to options. - // Everything in options.InformationOnly should be provided, other fields should be set only if a modification is desired. - // This does not change the state of the original Image object. - UpdatedImage(options ManifestUpdateOptions) (Image, error) - // Size returns an approximation of the amount of disk space which is consumed by the image in its current - // location. If the size is not known, -1 will be returned. - Size() (int64, error) -} - -// ImageCloser is an Image with a Close() method which must be called by the user. -// This is returned by ImageReference.NewImage, which transparently instantiates a types.ImageSource, -// to ensure that the ImageSource is closed. -type ImageCloser interface { - Image - // Close removes resources associated with an initialized ImageCloser. - Close() error -} - -// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest -type ManifestUpdateOptions struct { - LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls+annotations) which should replace the originals, in order (the root layer first, and then successive layered layers). BlobInfos' MediaType fields are ignored. - EmbeddedDockerReference reference.Named - ManifestMIMEType string - // The values below are NOT requests to modify the image; they provide optional context which may or may not be used. - InformationOnly ManifestUpdateInformation -} - -// ManifestUpdateInformation is a component of ManifestUpdateOptions, named here -// only to make writing struct literals possible. -type ManifestUpdateInformation struct { - Destination ImageDestination // and yes, UpdatedManifest may write to Destination (see the schema2 → schema1 conversion logic in image/docker_schema2.go) - LayerInfos []BlobInfo // Complete BlobInfos (size+digest) which have been uploaded, in order (the root layer first, and then successive layered layers) - LayerDiffIDs []digest.Digest // Digest values for the _uncompressed_ contents of the blobs which have been uploaded, in the same order. -} - -// ImageInspectInfo is a set of metadata describing Docker images, primarily their manifest and configuration. -// The Tag field is a legacy field which is here just for the Docker v2s1 manifest. It won't be supported -// for other manifest types. -type ImageInspectInfo struct { - Tag string - Created time.Time - DockerVersion string - Labels map[string]string - Architecture string - Os string - Layers []string -} - -// DockerAuthConfig contains authorization information for connecting to a registry. -type DockerAuthConfig struct { - Username string - Password string -} - -// SystemContext allows parameterizing access to implicitly-accessed resources, -// like configuration files in /etc and users' login state in their home directory. -// Various components can share the same field only if their semantics is exactly -// the same; if in doubt, add a new field. -// It is always OK to pass nil instead of a SystemContext. -type SystemContext struct { - // If not "", prefixed to any absolute paths used by default by the library (e.g. in /etc/). - // Not used for any of the more specific path overrides available in this struct. - // Not used for any paths specified by users in config files (even if the location of the config file _was_ affected by it). - // NOTE: If this is set, environment-variable overrides of paths are ignored (to keep the semantics simple: to create an /etc replacement, just set RootForImplicitAbsolutePaths . - // and there is no need to worry about the environment.) - // NOTE: This does NOT affect paths starting by $HOME. - RootForImplicitAbsolutePaths string - - // === Global configuration overrides === - // If not "", overrides the system's default path for signature.Policy configuration. - SignaturePolicyPath string - // If not "", overrides the system's default path for registries.d (Docker signature storage configuration) - RegistriesDirPath string - // Path to the system-wide registries configuration file - SystemRegistriesConfPath string - // If not "", overrides the default path for the authentication file - AuthFilePath string - // If not "", overrides the use of platform.GOARCH when choosing an image or verifying architecture match. - ArchitectureChoice string - // If not "", overrides the use of platform.GOOS when choosing an image or verifying OS match. - OSChoice string - - // === OCI.Transport overrides === - // If not "", a directory containing a CA certificate (ending with ".crt"), - // a client certificate (ending with ".cert") and a client ceritificate key - // (ending with ".key") used when downloading OCI image layers. - OCICertPath string - // Allow downloading OCI image layers over HTTP, or HTTPS with failed TLS verification. Note that this does not affect other TLS connections. - OCIInsecureSkipTLSVerify bool - // If not "", use a shared directory for storing blobs rather than within OCI layouts - OCISharedBlobDirPath string - - // === docker.Transport overrides === - // If not "", a directory containing a CA certificate (ending with ".crt"), - // a client certificate (ending with ".cert") and a client ceritificate key - // (ending with ".key") used when talking to a Docker Registry. - DockerCertPath string - // If not "", overrides the system’s default path for a directory containing host[:port] subdirectories with the same structure as DockerCertPath above. - // Ignored if DockerCertPath is non-empty. - DockerPerHostCertDirPath string - // Allow contacting docker registries over HTTP, or HTTPS with failed TLS verification. Note that this does not affect other TLS connections. - DockerInsecureSkipTLSVerify bool - // if nil, the library tries to parse ~/.docker/config.json to retrieve credentials - DockerAuthConfig *DockerAuthConfig - // if not "", an User-Agent header is added to each request when contacting a registry. - DockerRegistryUserAgent string - // if true, a V1 ping attempt isn't done to give users a better error. Default is false. - // Note that this field is used mainly to integrate containers/image into projectatomic/docker - // in order to not break any existing docker's integration tests. - DockerDisableV1Ping bool - // Directory to use for OSTree temporary files - OSTreeTmpDirPath string - - // === docker/daemon.Transport overrides === - // A directory containing a CA certificate (ending with ".crt"), - // a client certificate (ending with ".cert") and a client certificate key - // (ending with ".key") used when talking to a Docker daemon. - DockerDaemonCertPath string - // The hostname or IP to the Docker daemon. If not set (aka ""), client.DefaultDockerHost is assumed. - DockerDaemonHost string - // Used to skip TLS verification, off by default. To take effect DockerDaemonCertPath needs to be specified as well. - DockerDaemonInsecureSkipTLSVerify bool - - // === dir.Transport overrides === - // DirForceCompress compresses the image layers if set to true - DirForceCompress bool -} - -// ProgressProperties is used to pass information from the copy code to a monitor which -// can use the real-time information to produce output or react to changes. -type ProgressProperties struct { - Artifact BlobInfo - Offset uint64 -} diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go deleted file mode 100644 index 6644bcff3b..0000000000 --- a/vendor/github.com/containers/image/version/version.go +++ /dev/null @@ -1,18 +0,0 @@ -package version - -import "fmt" - -const ( - // VersionMajor is for an API incompatible changes - VersionMajor = 0 - // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 1 - // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 - - // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "-dev" -) - -// Version is the specification version that the package types support. -var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev) diff --git a/vendor/github.com/containers/storage/AUTHORS b/vendor/github.com/containers/storage/AUTHORS deleted file mode 100644 index 11cd83d14e..0000000000 --- a/vendor/github.com/containers/storage/AUTHORS +++ /dev/null @@ -1,1522 +0,0 @@ -# This file lists all individuals having contributed content to the repository. -# For how it is generated, see `hack/generate-authors.sh`. - -Aanand Prasad -Aaron Davidson -Aaron Feng -Aaron Huslage -Aaron Lehmann -Aaron Welch -Abel Muiño -Abhijeet Kasurde -Abhinav Ajgaonkar -Abhishek Chanda -Abin Shahab -Adam Miller -Adam Singer -Aditi Rajagopal -Aditya -Adria Casas -Adrian Mouat -Adrian Oprea -Adrien Folie -Adrien Gallouët -Ahmed Kamal -Ahmet Alp Balkan -Aidan Feldman -Aidan Hobson Sayers -AJ Bowen -Ajey Charantimath -ajneu -Akihiro Suda -Al Tobey -alambike -Alan Scherger -Alan Thompson -Albert Callarisa -Albert Zhang -Aleksa Sarai -Aleksandrs Fadins -Alena Prokharchyk -Alessandro Boch -Alessio Biancalana -Alex Chan -Alex Crawford -Alex Ellis -Alex Gaynor -Alex Samorukov -Alex Warhawk -Alexander Artemenko -Alexander Boyd -Alexander Larsson -Alexander Morozov -Alexander Shopov -Alexandre Beslic -Alexandre González -Alexandru Sfirlogea -Alexey Guskov -Alexey Kotlyarov -Alexey Shamrin -Alexis THOMAS -Ali Dehghani -Allen Madsen -Allen Sun -almoehi -Alvin Richards -amangoel -Amen Belayneh -Amit Bakshi -Amit Krishnan -Amy Lindburg -Anand Patil -AnandkumarPatel -Anatoly Borodin -Anchal Agrawal -Anders Janmyr -Andre Dublin <81dublin@gmail.com> -Andre Granovsky -Andrea Luzzardi -Andrea Turli -Andreas Köhler -Andreas Savvides -Andreas Tiefenthaler -Andrew C. Bodine -Andrew Clay Shafer -Andrew Duckworth -Andrew France -Andrew Gerrand -Andrew Guenther -Andrew Kuklewicz -Andrew Macgregor -Andrew Macpherson -Andrew Martin -Andrew Munsell -Andrew Weiss -Andrew Williams -Andrews Medina -Andrey Petrov -Andrey Stolbovsky -André Martins -andy -Andy Chambers -andy diller -Andy Goldstein -Andy Kipp -Andy Rothfusz -Andy Smith -Andy Wilson -Anes Hasicic -Anil Belur -Ankush Agarwal -Anonmily -Anthon van der Neut -Anthony Baire -Anthony Bishopric -Anthony Dahanne -Anton Löfgren -Anton Nikitin -Anton Polonskiy -Anton Tiurin -Antonio Murdaca -Antony Messerli -Anuj Bahuguna -Anusha Ragunathan -apocas -ArikaChen -Arnaud Porterie -Arthur Barr -Arthur Gautier -Artur Meyster -Arun Gupta -Asbjørn Enge -averagehuman -Avi Das -Avi Miller -ayoshitake -Azat Khuyiyakhmetov -Bardia Keyoumarsi -Barnaby Gray -Barry Allard -Bartłomiej Piotrowski -Bastiaan Bakker -bdevloed -Ben Firshman -Ben Golub -Ben Hall -Ben Sargent -Ben Severson -Ben Toews -Ben Wiklund -Benjamin Atkin -Benoit Chesneau -Bernerd Schaefer -Bert Goethals -Bharath Thiruveedula -Bhiraj Butala -Bill W -bin liu -Blake Geno -Boaz Shuster -bobby abbott -boucher -Bouke Haarsma -Boyd Hemphill -boynux -Bradley Cicenas -Bradley Wright -Brandon Liu -Brandon Philips -Brandon Rhodes -Brendan Dixon -Brent Salisbury -Brett Higgins -Brett Kochendorfer -Brian (bex) Exelbierd -Brian Bland -Brian DeHamer -Brian Dorsey -Brian Flad -Brian Goff -Brian McCallister -Brian Olsen -Brian Shumate -Brian Torres-Gil -Brian Trump -Brice Jaglin -Briehan Lombaard -Bruno Bigras -Bruno Binet -Bruno Gazzera -Bruno Renié -Bryan Bess -Bryan Boreham -Bryan Matsuo -Bryan Murphy -buddhamagnet -Burke Libbey -Byung Kang -Caleb Spare -Calen Pennington -Cameron Boehmer -Cameron Spear -Campbell Allen -Candid Dauth -Carl Henrik Lunde -Carl X. Su -Carlos Alexandro Becker -Carlos Sanchez -Carol Fager-Higgins -Cary -Casey Bisson -Cedric Davies -Cezar Sa Espinola -Chad Swenson -Chance Zibolski -Chander G -Charles Chan -Charles Hooper -Charles Law -Charles Lindsay -Charles Merriam -Charles Sarrazin -Charlie Lewis -Chase Bolt -ChaYoung You -Chen Chao -Chen Hanxiao -cheney90 -Chewey -Chia-liang Kao -chli -Cholerae Hu -Chris Alfonso -Chris Armstrong -Chris Dituri -Chris Fordham -Chris Khoo -Chris McKinnel -Chris Seto -Chris Snow -Chris St. Pierre -Chris Stivers -Chris Swan -Chris Wahl -Chris Weyl -chrismckinnel -Christian Berendt -Christian Böhme -Christian Persson -Christian Rotzoll -Christian Simon -Christian Stefanescu -ChristoperBiscardi -Christophe Mehay -Christophe Troestler -Christopher Currie -Christopher Jones -Christopher Latham -Christopher Rigor -Christy Perez -Chun Chen -Ciro S. Costa -Clayton Coleman -Clinton Kitson -Coenraad Loubser -Colin Dunklau -Colin Rice -Colin Walters -Collin Guarino -Colm Hally -companycy -Cory Forsyth -cressie176 -Cristian Staretu -cristiano balducci -Cruceru Calin-Cristian -Cyril F -Daan van Berkel -Daehyeok Mun -Dafydd Crosby -dalanlan -Damien Nadé -Damien Nozay -Damjan Georgievski -Dan Anolik -Dan Buch -Dan Cotora -Dan Griffin -Dan Hirsch -Dan Keder -Dan Levy -Dan McPherson -Dan Stine -Dan Walsh -Dan Williams -Daniel Antlinger -Daniel Exner -Daniel Farrell -Daniel Garcia -Daniel Gasienica -Daniel Hiltgen -Daniel Menet -Daniel Mizyrycki -Daniel Nephin -Daniel Norberg -Daniel Nordberg -Daniel Robinson -Daniel S -Daniel Von Fange -Daniel YC Lin -Daniel Zhang -Daniel, Dao Quang Minh -Danny Berger -Danny Yates -Darren Coxall -Darren Shepherd -Darren Stahl -Dave Barboza -Dave Henderson -Dave MacDonald -Dave Tucker -David Anderson -David Calavera -David Corking -David Cramer -David Currie -David Davis -David Gageot -David Gebler -David Lawrence -David Mackey -David Mat -David Mcanulty -David Pelaez -David R. Jenni -David Röthlisberger -David Sheets -David Sissitka -David Xia -David Young -Davide Ceretti -Dawn Chen -dcylabs -decadent -deed02392 -Deng Guangxing -Deni Bertovic -Denis Gladkikh -Denis Ollier -Dennis Docter -Derek -Derek -Derek Ch -Derek McGowan -Deric Crago -Deshi Xiao -devmeyster -Devvyn Murphy -Dharmit Shah -Dieter Reuter -Dima Stopel -Dimitri John Ledkov -Dimitry Andric -Dinesh Subhraveti -Diogo Monica -DiuDiugirl -Djibril Koné -dkumor -Dmitri Logvinenko -Dmitry Demeshchuk -Dmitry Gusev -Dmitry V. Krivenok -Dmitry Vorobev -Dolph Mathews -Dominik Finkbeiner -Dominik Honnef -Don Kirkby -Don Kjer -Don Spaulding -Donald Huang -Dong Chen -Donovan Jones -Doug Davis -Doug MacEachern -Doug Tangren -Dr Nic Williams -dragon788 -Dražen Lučanin -Dustin Sallings -Ed Costello -Edmund Wagner -Eiichi Tsukata -Eike Herzbach -Eivind Uggedal -Elan Ruusamäe -Elias Probst -Elijah Zupancic -eluck -Elvir Kuric -Emil Hernvall -Emily Maier -Emily Rose -Emir Ozer -Enguerran -Eohyung Lee -Eric Hanchrow -Eric Lee -Eric Myhre -Eric Paris -Eric Rafaloff -Eric Rosenberg -Eric Sage -Eric Windisch -Eric Yang -Eric-Olivier Lamey -Erik Bray -Erik Dubbelboer -Erik Hollensbe -Erik Inge Bolsø -Erik Kristensen -Erik Weathers -Erno Hopearuoho -Erwin van der Koogh -Euan -Eugene Yakubovich -eugenkrizo -evalle -Evan Allrich -Evan Carmi -Evan Hazlett -Evan Krall -Evan Phoenix -Evan Wies -Evgeny Vereshchagin -Ewa Czechowska -Eystein Måløy Stenberg -ezbercih -Fabiano Rosas -Fabio Falci -Fabio Rehm -Fabrizio Regini -Fabrizio Soppelsa -Faiz Khan -falmp -Fangyuan Gao <21551127@zju.edu.cn> -Fareed Dudhia -Fathi Boudra -Federico Gimenez -Felix Geisendörfer -Felix Hupfeld -Felix Rabe -Felix Schindler -Ferenc Szabo -Fernando -Fero Volar -Filipe Brandenburger -Filipe Oliveira -fl0yd -Flavio Castelli -FLGMwt -Florian -Florian Klein -Florian Maier -Florian Weingarten -Florin Asavoaie -Francesc Campoy -Francisco Carriedo -Francisco Souza -Frank Groeneveld -Frank Herrmann -Frank Macreery -Frank Rosquin -Fred Lifton -Frederick F. Kautz IV -Frederik Loeffert -Frederik Nordahl Jul Sabroe -Freek Kalter -fy2462 -Félix Baylac-Jacqué -Félix Cantournet -Gabe Rosenhouse -Gabor Nagy -Gabriel Monroy -GabrielNicolasAvellaneda -Galen Sampson -Gareth Rushgrove -Garrett Barboza -Gaurav -gautam, prasanna -GennadySpb -Geoffrey Bachelet -George MacRorie -George Xie -Georgi Hristozov -Gereon Frey -German DZ -Gert van Valkenhoef -Gianluca Borello -Gildas Cuisinier -gissehel -Giuseppe Mazzotta -Gleb Fotengauer-Malinovskiy -Gleb M Borisov -Glyn Normington -GoBella -Goffert van Gool -Gosuke Miyashita -Gou Rao -Govinda Fichtner -Grant Reaber -Graydon Hoare -Greg Fausak -Greg Thornton -grossws -grunny -gs11 -Guilhem Lettron -Guilherme Salgado -Guillaume Dufour -Guillaume J. Charmes -guoxiuyan -Gurjeet Singh -Guruprasad -gwx296173 -Günter Zöchbauer -Hans Kristian Flaatten -Hans Rødtang -Hao Shu Wei -Hao Zhang <21521210@zju.edu.cn> -Harald Albers -Harley Laue -Harold Cooper -Harry Zhang -He Simei -heartlock <21521209@zju.edu.cn> -Hector Castro -Henning Sprang -Hobofan -Hollie Teal -Hong Xu -hsinko <21551195@zju.edu.cn> -Hu Keping -Hu Tao -Huanzhong Zhang -Huayi Zhang -Hugo Duncan -Hugo Marisco <0x6875676f@gmail.com> -Hunter Blanks -huqun -Huu Nguyen -hyeongkyu.lee -hyp3rdino -Hyzhou <1187766782@qq.com> -Ian Babrou -Ian Bishop -Ian Bull -Ian Calvert -Ian Lee -Ian Main -Ian Truslove -Iavael -Icaro Seara -Igor Dolzhikov -Ilkka Laukkanen -Ilya Dmitrichenko -Ilya Gusev -ILYA Khlopotov -imre Fitos -inglesp -Ingo Gottwald -Isaac Dupree -Isabel Jimenez -Isao Jonas -Ivan Babrou -Ivan Fraixedes -Ivan Grcic -J Bruni -J. Nunn -Jack Danger Canty -Jacob Atzen -Jacob Edelman -Jake Champlin -Jake Moshenko -jakedt -James Allen -James Carey -James Carr -James DeFelice -James Harrison Fisher -James Kyburz -James Kyle -James Lal -James Mills -James Nugent -James Turnbull -Jamie Hannaford -Jamshid Afshar -Jan Keromnes -Jan Koprowski -Jan Pazdziora -Jan Toebes -Jan-Gerd Tenberge -Jan-Jaap Driessen -Jana Radhakrishnan -Januar Wayong -Jared Biel -Jared Hocutt -Jaroslaw Zabiello -jaseg -Jasmine Hegman -Jason Divock -Jason Giedymin -Jason Green -Jason Hall -Jason Heiss -Jason Livesay -Jason McVetta -Jason Plum -Jason Shepherd -Jason Smith -Jason Sommer -Jason Stangroome -jaxgeller -Jay -Jay -Jay Kamat -Jean-Baptiste Barth -Jean-Baptiste Dalido -Jean-Paul Calderone -Jean-Tiare Le Bigot -Jeff Anderson -Jeff Johnston -Jeff Lindsay -Jeff Mickey -Jeff Minard -Jeff Nickoloff -Jeff Welch -Jeffrey Bolle -Jeffrey Morgan -Jeffrey van Gogh -Jenny Gebske -Jeremy Grosser -Jeremy Price -Jeremy Qian -Jeremy Unruh -Jeroen Jacobs -Jesse Dearing -Jesse Dubay -Jessica Frazelle -Jezeniel Zapanta -jgeiger -Jhon Honce -Jian Zhang -jianbosun -Jilles Oldenbeuving -Jim Alateras -Jim Perrin -Jimmy Cuadra -Jimmy Puckett -jimmyxian -Jinsoo Park -Jiri Popelka -Jiří Župka -jjy -jmzwcn -Joe Beda -Joe Doliner -Joe Ferguson -Joe Gordon -Joe Shaw -Joe Van Dyk -Joel Friedly -Joel Handwell -Joel Hansson -Joel Wurtz -Joey Geiger -Joey Gibson -Joffrey F -Johan Euphrosine -Johan Rydberg -Johannes 'fish' Ziemke -John Costa -John Feminella -John Gardiner Myers -John Gossman -John Howard (VM) -John OBrien III -John Starks -John Tims -John Warwick -John Willis -Jon Wedaman -Jonas Pfenniger -Jonathan A. Sternberg -Jonathan Boulle -Jonathan Camp -Jonathan Dowland -Jonathan Lebon -Jonathan McCrohan -Jonathan Mueller -Jonathan Pares -Jonathan Rudenberg -Joost Cassee -Jordan -Jordan Arentsen -Jordan Sissel -Jose Diaz-Gonzalez -Joseph Anthony Pasquale Holsten -Joseph Hager -Joseph Kern -Josh -Josh Hawn -Josh Poimboeuf -Josiah Kiehl -José Tomás Albornoz -JP -jrabbit -Julian Taylor -Julien Barbier -Julien Bisconti -Julien Bordellier -Julien Dubois -Julien Pervillé -Julio Montes -Jun-Ru Chang -Jussi Nummelin -Justas Brazauskas -Justin Cormack -Justin Force -Justin Plock -Justin Simonelis -Justin Terry -Jyrki Puttonen -Jérôme Petazzoni -Jörg Thalheim -Kai Blin -Kai Qiang Wu(Kennan) -Kamil Domański -kamjar gerami -Kanstantsin Shautsou -Karan Lyons -Kareem Khazem -kargakis -Karl Grzeszczak -Karol Duleba -Katie McLaughlin -Kato Kazuyoshi -Katrina Owen -Kawsar Saiyeed -kayrus -Ke Xu -Keli Hu -Ken Cochrane -Ken ICHIKAWA -Kenfe-Mickael Laventure -Kenjiro Nakayama -Kent Johnson -Kevin "qwazerty" Houdebert -Kevin Clark -Kevin J. Lynagh -Kevin Menard -Kevin P. Kucharczyk -Kevin Shi -Kevin Wallace -Kevin Yap -kevinmeredith -Keyvan Fatehi -kies -Kim BKC Carlbacker -Kim Eik -Kimbro Staken -Kir Kolyshkin -Kiran Gangadharan -Kirill SIbirev -knappe -Kohei Tsuruta -Koichi Shiraishi -Konrad Kleine -Konstantin Pelykh -Krasimir Georgiev -Kristian Haugene -Kristina Zabunova -krrg -Kun Zhang -Kunal Kushwaha -Kyle Conroy -kyu -Lachlan Coote -Lai Jiangshan -Lajos Papp -Lakshan Perera -Lalatendu Mohanty -lalyos -Lance Chen -Lance Kinley -Lars Butler -Lars Kellogg-Stedman -Lars R. Damerow -Laszlo Meszaros -Laurent Erignoux -Laurie Voss -Leandro Siqueira -Lee, Meng-Han -leeplay -Lei Jitang -Len Weincier -Lennie -Leszek Kowalski -Levi Blackstone -Levi Gross -Lewis Marshall -Lewis Peckover -Liana Lo -Liang Mingqiang -Liang-Chi Hsieh -liaoqingwei -limsy -Lin Lu -LingFaKe -Linus Heckemann -Liran Tal -Liron Levin -Liu Bo -Liu Hua -LIZAO LI -Lloyd Dewolf -Lokesh Mandvekar -longliqiang88 <394564827@qq.com> -Lorenz Leutgeb -Lorenzo Fontana -Louis Opter -Luca Marturana -Luca Orlandi -Luca-Bogdan Grigorescu -Lucas Chan -Luis Martínez de Bartolomé Izquierdo -Lukas Waslowski -lukaspustina -Lukasz Zajaczkowski -lukemarsden -Lynda O'Leary -Lénaïc Huard -Ma Shimiao -Mabin -Madhav Puri -Madhu Venugopal -Mageee <21521230.zju.edu.cn> -Mahesh Tiyyagura -malnick -Malte Janduda -manchoz -Manfred Touron -Manfred Zabarauskas -mansinahar -Manuel Meurer -Manuel Woelker -mapk0y -Marc Abramowitz -Marc Kuo -Marc Tamsky -Marcelo Salazar -Marco Hennings -Marcus Farkas -Marcus Linke -Marcus Ramberg -Marek Goldmann -Marian Marinov -Marianna Tessel -Mario Loriedo -Marius Gundersen -Marius Sturm -Marius Voila -Mark Allen -Mark McGranaghan -Mark McKinstry -Mark West -Marko Mikulicic -Marko Tibold -Markus Fix -Martijn Dwars -Martijn van Oosterhout -Martin Honermeyer -Martin Kelly -Martin Mosegaard Amdisen -Martin Redmond -Mary Anthony -Masahito Zembutsu -Mason Malone -Mateusz Sulima -Mathias Monnerville -Mathieu Le Marec - Pasquet -Matt Apperson -Matt Bachmann -Matt Bentley -Matt Haggard -Matt McCormick -Matt Moore -Matt Robenolt -Matthew Heon -Matthew Mayer -Matthew Mueller -Matthew Riley -Matthias Klumpp -Matthias Kühnle -Matthias Rampke -Matthieu Hauglustaine -mattymo -mattyw -Mauricio Garavaglia -mauriyouth -Max Shytikov -Maxim Ivanov -Maxim Kulkin -Maxim Treskin -Maxime Petazzoni -Meaglith Ma -meejah -Megan Kostick -Mehul Kar -Mengdi Gao -Mert Yazıcıoğlu -Micah Zoltu -Michael A. Smith -Michael Bridgen -Michael Brown -Michael Chiang -Michael Crosby -Michael Currie -Michael Friis -Michael Gorsuch -Michael Grauer -Michael Holzheu -Michael Hudson-Doyle -Michael Huettermann -Michael Käufl -Michael Neale -Michael Prokop -Michael Scharf -Michael Stapelberg -Michael Steinert -Michael Thies -Michael West -Michal Fojtik -Michal Gebauer -Michal Jemala -Michal Minar -Michaël Pailloncy -Michał Czeraszkiewicz -Michiel@unhosted -Miguel Angel Fernández -Miguel Morales -Mihai Borobocea -Mihuleacc Sergiu -Mike Brown -Mike Chelen -Mike Danese -Mike Dillon -Mike Dougherty -Mike Gaffney -Mike Goelzer -Mike Leone -Mike MacCana -Mike Naberezny -Mike Snitzer -mikelinjie <294893458@qq.com> -Mikhail Sobolev -Miloslav Trmač -mingqing -Mingzhen Feng -Mitch Capper -mlarcher -Mohammad Banikazemi -Mohammed Aaqib Ansari -Mohit Soni -Morgan Bauer -Morgante Pell -Morgy93 -Morten Siebuhr -Morton Fox -Moysés Borges -mqliang -Mrunal Patel -msabansal -mschurenko -muge -Mustafa Akın -Muthukumar R -Máximo Cuadros -Médi-Rémi Hashim -Nahum Shalman -Nakul Pathak -Nalin Dahyabhai -Nan Monnand Deng -Naoki Orii -Natalie Parker -Natanael Copa -Nate Brennand -Nate Eagleson -Nate Jones -Nathan Hsieh -Nathan Kleyn -Nathan LeClaire -Nathan McCauley -Nathan Williams -Neal McBurnett -Nelson Chen -Nghia Tran -Niall O'Higgins -Nicholas E. Rabenau -Nick Irvine -Nick Parker -Nick Payne -Nick Stenning -Nick Stinemates -Nicolas Borboën -Nicolas De loof -Nicolas Dudebout -Nicolas Goy -Nicolas Kaiser -Nicolás Hock Isaza -Nigel Poulton -NikolaMandic -nikolas -Nirmal Mehta -Nishant Totla -NIWA Hideyuki -noducks -Nolan Darilek -nponeccop -Nuutti Kotivuori -nzwsch -O.S. Tezer -objectified -OddBloke -odk- -Oguz Bilgic -Oh Jinkyun -Ohad Schneider -Ole Reifschneider -Oliver Neal -Olivier Gambier -Olle Jonsson -Oriol Francès -Otto Kekäläinen -oyld -ozlerhakan -paetling -pandrew -panticz -Paolo G. Giarrusso -Pascal Borreli -Pascal Hartig -Patrick Devine -Patrick Hemmer -Patrick Stapleton -pattichen -Paul -paul -Paul Annesley -Paul Bellamy -Paul Bowsher -Paul Hammond -Paul Jimenez -Paul Lietar -Paul Liljenberg -Paul Morie -Paul Nasrat -Paul Weaver -Pavel Lobashov -Pavel Pospisil -Pavel Sutyrin -Pavel Tikhomirov -Pavlos Ratis -Peeyush Gupta -Peggy Li -Pei Su -Penghan Wang -perhapszzy@sina.com -Peter Bourgon -Peter Braden -Peter Choi -Peter Dave Hello -Peter Edge -Peter Ericson -Peter Esbensen -Peter Malmgren -Peter Salvatore -Peter Volpe -Peter Waller -Phil -Phil Estes -Phil Spitler -Philip Monroe -Philipp Wahala -Philipp Weissensteiner -Phillip Alexander -pidster -Piergiuliano Bossi -Pierre -Pierre Carrier -Pierre Wacrenier -Pierre-Alain RIVIERE -Piotr Bogdan -pixelistik -Porjo -Poul Kjeldager Sørensen -Pradeep Chhetri -Prasanna Gautam -Prayag Verma -Przemek Hejman -pysqz -qg <1373319223@qq.com> -qhuang -Qiang Huang -qq690388648 <690388648@qq.com> -Quentin Brossard -Quentin Perez -Quentin Tayssier -r0n22 -Rafal Jeczalik -Rafe Colton -Raghavendra K T -Raghuram Devarakonda -Rajat Pandit -Rajdeep Dua -Ralle -Ralph Bean -Ramkumar Ramachandra -Ramon van Alteren -Ray Tsang -ReadmeCritic -Recursive Madman -Regan McCooey -Remi Rampin -Renato Riccieri Santos Zannon -resouer -rgstephens -Rhys Hiltner -Rich Seymour -Richard -Richard Burnison -Richard Harvey -Richard Metzler -Richard Scothern -Richo Healey -Rick Bradley -Rick van de Loo -Rick Wieman -Rik Nijessen -Riku Voipio -Riley Guerin -Ritesh H Shukla -Riyaz Faizullabhoy -Rob Vesse -Robert Bachmann -Robert Bittle -Robert Obryk -Robert Stern -Robert Wallis -Roberto G. Hashioka -Robin Naundorf -Robin Schneider -Robin Speekenbrink -robpc -Rodolfo Carvalho -Rodrigo Vaz -Roel Van Nyen -Roger Peppe -Rohit Jnagal -Rohit Kadam -Roland Huß -Roland Kammerer -Roland Moriz -Roma Sokolov -Roman Strashkin -Ron Smits -root -root -root -root -Rory Hunter -Rory McCune -Ross Boucher -Rovanion Luckey -Rozhnov Alexandr -rsmoorthy -Rudolph Gottesheim -Rui Lopes -Ryan Anderson -Ryan Aslett -Ryan Belgrave -Ryan Detzel -Ryan Fowler -Ryan McLaughlin -Ryan O'Donnell -Ryan Seto -Ryan Thomas -Ryan Trauntvein -Ryan Wallner -RyanDeng -Rémy Greinhofer -s. rannou -s00318865 -Sabin Basyal -Sachin Joshi -Sagar Hani -Sainath Grandhi -Sally O'Malley -Sam Abed -Sam Alba -Sam Bailey -Sam J Sharpe -Sam Neirinck -Sam Reis -Sam Rijs -Sambuddha Basu -Sami Wagiaalla -Samuel Andaya -Samuel Dion-Girardeau -Samuel Karp -Samuel PHAN -Sankar சங்கர் -Sanket Saurav -Santhosh Manohar -sapphiredev -Satnam Singh -satoru -Satoshi Amemiya -scaleoutsean -Scott Bessler -Scott Collier -Scott Johnston -Scott Stamp -Scott Walls -sdreyesg -Sean Christopherson -Sean Cronin -Sean OMeara -Sean P. Kane -Sebastiaan van Steenis -Sebastiaan van Stijn -Senthil Kumar Selvaraj -Senthil Kumaran -SeongJae Park -Seongyeol Lim -Serge Hallyn -Sergey Alekseev -Sergey Evstifeev -Sevki Hasirci -Shane Canon -Shane da Silva -shaunol -Shawn Landden -Shawn Siefkas -Shekhar Gulati -Sheng Yang -Shengbo Song -Shih-Yuan Lee -Shijiang Wei -Shishir Mahajan -shuai-z -Shuwei Hao -Sian Lerk Lau -sidharthamani -Silas Sewell -Simei He -Simon Eskildsen -Simon Leinen -Simon Taranto -Sindhu S -Sjoerd Langkemper -Solganik Alexander -Solomon Hykes -Song Gao -Soshi Katsuta -Soulou -Spencer Brown -Spencer Smith -Sridatta Thatipamala -Sridhar Ratnakumar -Srini Brahmaroutu -srinsriv -Steeve Morin -Stefan Berger -Stefan J. Wernli -Stefan Praszalowicz -Stefan Scherer -Stefan Staudenmeyer -Stefan Weil -Stephen Crosby -Stephen Day -Stephen Rust -Steve Durrheimer -Steve Francia -Steve Koch -Steven Burgess -Steven Iveson -Steven Merrill -Steven Richards -Steven Taylor -Subhajit Ghosh -Sujith Haridasan -Suryakumar Sudar -Sven Dowideit -Swapnil Daingade -Sylvain Baubeau -Sylvain Bellemare -Sébastien -Sébastien Luttringer -Sébastien Stormacq -TAGOMORI Satoshi -tang0th -Tangi COLIN -Tatsuki Sugiura -Tatsushi Inagaki -Taylor Jones -tbonza -Ted M. Young -Tehmasp Chaudhri -Tejesh Mehta -terryding77 <550147740@qq.com> -tgic -Thatcher Peskens -theadactyl -Thell 'Bo' Fowler -Thermionix -Thijs Terlouw -Thomas Bikeev -Thomas Frössman -Thomas Gazagnaire -Thomas Grainger -Thomas Hansen -Thomas Leonard -Thomas LEVEIL -Thomas Orozco -Thomas Riccardi -Thomas Schroeter -Thomas Sjögren -Thomas Swift -Thomas Tanaka -Thomas Texier -Tianon Gravi -Tibor Vass -Tiffany Low -Tim Bosse -Tim Dettrick -Tim Düsterhus -Tim Hockin -Tim Ruffles -Tim Smith -Tim Terhorst -Tim Wang -Tim Waugh -Tim Wraight -Timothy Hobbs -tjwebb123 -tobe -Tobias Bieniek -Tobias Bradtke -Tobias Gesellchen -Tobias Klauser -Tobias Schmidt -Tobias Schwab -Todd Crane -Todd Lunter -Todd Whiteman -Toli Kuznets -Tom Barlow -Tom Denham -Tom Fotherby -Tom Howe -Tom Hulihan -Tom Maaswinkel -Tom X. Tobin -Tomas Tomecek -Tomasz Kopczynski -Tomasz Lipinski -Tomasz Nurkiewicz -Tommaso Visconti -Tomáš Hrčka -Tonis Tiigi -Tonny Xu -Tony Daws -Tony Miller -toogley -Torstein Husebø -tpng -tracylihui <793912329@qq.com> -Travis Cline -Travis Thieman -Trent Ogren -Trevor -Trevor Pounds -trishnaguha -Tristan Carel -Troy Denton -Tyler Brock -Tzu-Jung Lee -Tõnis Tiigi -Ulysse Carion -unknown -vagrant -Vaidas Jablonskis -Veres Lajos -vgeta -Victor Coisne -Victor Costan -Victor I. Wood -Victor Lyuboslavsky -Victor Marmol -Victor Palma -Victor Vieux -Victoria Bialas -Vijaya Kumar K -Viktor Stanchev -Viktor Vojnovski -VinayRaghavanKS -Vincent Batts -Vincent Bernat -Vincent Bernat -Vincent Demeester -Vincent Giersch -Vincent Mayers -Vincent Woo -Vinod Kulkarni -Vishal Doshi -Vishnu Kannan -Vitor Monteiro -Vivek Agarwal -Vivek Dasgupta -Vivek Goyal -Vladimir Bulyga -Vladimir Kirillov -Vladimir Rutsky -Vladimir Varankin -VladimirAus -Vojtech Vitek (V-Teq) -waitingkuo -Walter Leibbrandt -Walter Stanish -WANG Chao -Wang Xing -Ward Vandewege -WarheadsSE -Wayne Chang -Wei-Ting Kuo -weiyan -Weiyang Zhu -Wen Cheng Ma -Wendel Fleming -Wenxuan Zhao -Wenyu You <21551128@zju.edu.cn> -Wes Morgan -Will Dietz -Will Rouesnel -Will Weaver -willhf -William Delanoue -William Henry -William Hubbs -William Riancho -William Thurston -WiseTrem -wlan0 -Wolfgang Powisch -wonderflow -xamyzhao -XiaoBing Jiang -Xiaoxu Chen -xiekeyang -Xinzi Zhou -Xiuming Chen -xlgao-zju -xuzhaokui -Yahya -YAMADA Tsuyoshi -Yan Feng -Yang Bai -yangshukui -Yasunori Mahata -Yestin Sun -Yi EungJun -Yibai Zhang -Yihang Ho -Ying Li -Yohei Ueda -Yong Tang -Yongzhi Pan -yorkie -Youcef YEKHLEF -Yuan Sun -yuchangchun -yuchengxia -Yurii Rashkovskii -yuzou -Zac Dover -Zach Borboa -Zachary Jaffee -Zain Memon -Zaiste! -Zane DeGraffenried -Zefan Li -Zen Lin(Zhinan Lin) -Zhang Kun -Zhang Wei -Zhang Wentao -Zhenan Ye <21551168@zju.edu.cn> -Zhu Guihua -Zhuoyun Wei -Zilin Du -zimbatm -Ziming Dong -ZJUshuaizhou <21551191@zju.edu.cn> -zmarouf -Zoltan Tombol -zqh -Zuhayr Elahi -Zunayed Ali -Álex González -Álvaro Lázaro -Átila Camurça Alves -尹吉峰 -搏通 diff --git a/vendor/github.com/containers/storage/LICENSE b/vendor/github.com/containers/storage/LICENSE deleted file mode 100644 index 8f3fee627a..0000000000 --- a/vendor/github.com/containers/storage/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2013-2016 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/containers/storage/NOTICE b/vendor/github.com/containers/storage/NOTICE deleted file mode 100644 index 8a37c1c7bc..0000000000 --- a/vendor/github.com/containers/storage/NOTICE +++ /dev/null @@ -1,19 +0,0 @@ -Docker -Copyright 2012-2016 Docker, Inc. - -This product includes software developed at Docker, Inc. (https://www.docker.com). - -This product contains software (https://github.com/kr/pty) developed -by Keith Rarick, licensed under the MIT License. - -The following is courtesy of our legal counsel: - - -Use and transfer of Docker may be subject to certain restrictions by the -United States and other governments. -It is your responsibility to ensure that your use and/or transfer does not -violate applicable laws. - -For more information, please see https://www.bis.doc.gov - -See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/vendor/github.com/containers/storage/containers.go b/vendor/github.com/containers/storage/containers.go deleted file mode 100644 index 5631e31c3e..0000000000 --- a/vendor/github.com/containers/storage/containers.go +++ /dev/null @@ -1,531 +0,0 @@ -package storage - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "time" - - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/stringid" - "github.com/containers/storage/pkg/truncindex" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// A Container is a reference to a read-write layer with metadata. -type Container struct { - // ID is either one which was specified at create-time, or a random - // value which was generated by the library. - ID string `json:"id"` - - // Names is an optional set of user-defined convenience values. The - // container can be referred to by its ID or any of its names. Names - // are unique among containers. - Names []string `json:"names,omitempty"` - - // ImageID is the ID of the image which was used to create the container. - ImageID string `json:"image"` - - // LayerID is the ID of the read-write layer for the container itself. - // It is assumed that the image's top layer is the parent of the container's - // read-write layer. - LayerID string `json:"layer"` - - // Metadata is data we keep for the convenience of the caller. It is not - // expected to be large, since it is kept in memory. - Metadata string `json:"metadata,omitempty"` - - // BigDataNames is a list of names of data items that we keep for the - // convenience of the caller. They can be large, and are only in - // memory when being read from or written to disk. - BigDataNames []string `json:"big-data-names,omitempty"` - - // BigDataSizes maps the names in BigDataNames to the sizes of the data - // that has been stored, if they're known. - BigDataSizes map[string]int64 `json:"big-data-sizes,omitempty"` - - // BigDataDigests maps the names in BigDataNames to the digests of the - // data that has been stored, if they're known. - BigDataDigests map[string]digest.Digest `json:"big-data-digests,omitempty"` - - // Created is the datestamp for when this container was created. Older - // versions of the library did not track this information, so callers - // will likely want to use the IsZero() method to verify that a value - // is set before using it. - Created time.Time `json:"created,omitempty"` - - Flags map[string]interface{} `json:"flags,omitempty"` -} - -// ContainerStore provides bookkeeping for information about Containers. -type ContainerStore interface { - FileBasedStore - MetadataStore - BigDataStore - FlaggableStore - - // Create creates a container that has a specified ID (or generates a - // random one if an empty value is supplied) and optional names, - // based on the specified image, using the specified layer as its - // read-write layer. - Create(id string, names []string, image, layer, metadata string) (*Container, error) - - // SetNames updates the list of names associated with the container - // with the specified ID. - SetNames(id string, names []string) error - - // Get retrieves information about a container given an ID or name. - Get(id string) (*Container, error) - - // Exists checks if there is a container with the given ID or name. - Exists(id string) bool - - // Delete removes the record of the container. - Delete(id string) error - - // Wipe removes records of all containers. - Wipe() error - - // Lookup attempts to translate a name to an ID. Most methods do this - // implicitly. - Lookup(name string) (string, error) - - // Containers returns a slice enumerating the known containers. - Containers() ([]Container, error) -} - -type containerStore struct { - lockfile Locker - dir string - containers []*Container - idindex *truncindex.TruncIndex - byid map[string]*Container - bylayer map[string]*Container - byname map[string]*Container -} - -func (r *containerStore) Containers() ([]Container, error) { - containers := make([]Container, len(r.containers)) - for i := range r.containers { - containers[i] = *(r.containers[i]) - } - return containers, nil -} - -func (r *containerStore) containerspath() string { - return filepath.Join(r.dir, "containers.json") -} - -func (r *containerStore) datadir(id string) string { - return filepath.Join(r.dir, id) -} - -func (r *containerStore) datapath(id, key string) string { - return filepath.Join(r.datadir(id), makeBigDataBaseName(key)) -} - -func (r *containerStore) Load() error { - needSave := false - rpath := r.containerspath() - data, err := ioutil.ReadFile(rpath) - if err != nil && !os.IsNotExist(err) { - return err - } - containers := []*Container{} - layers := make(map[string]*Container) - idlist := []string{} - ids := make(map[string]*Container) - names := make(map[string]*Container) - if err = json.Unmarshal(data, &containers); len(data) == 0 || err == nil { - idlist = make([]string, 0, len(containers)) - for n, container := range containers { - idlist = append(idlist, container.ID) - ids[container.ID] = containers[n] - layers[container.LayerID] = containers[n] - for _, name := range container.Names { - if conflict, ok := names[name]; ok { - r.removeName(conflict, name) - needSave = true - } - names[name] = containers[n] - } - } - } - r.containers = containers - r.idindex = truncindex.NewTruncIndex(idlist) - r.byid = ids - r.bylayer = layers - r.byname = names - if needSave { - return r.Save() - } - return nil -} - -func (r *containerStore) Save() error { - rpath := r.containerspath() - if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { - return err - } - jdata, err := json.Marshal(&r.containers) - if err != nil { - return err - } - defer r.Touch() - return ioutils.AtomicWriteFile(rpath, jdata, 0600) -} - -func newContainerStore(dir string) (ContainerStore, error) { - if err := os.MkdirAll(dir, 0700); err != nil { - return nil, err - } - lockfile, err := GetLockfile(filepath.Join(dir, "containers.lock")) - if err != nil { - return nil, err - } - lockfile.Lock() - defer lockfile.Unlock() - cstore := containerStore{ - lockfile: lockfile, - dir: dir, - containers: []*Container{}, - byid: make(map[string]*Container), - bylayer: make(map[string]*Container), - byname: make(map[string]*Container), - } - if err := cstore.Load(); err != nil { - return nil, err - } - return &cstore, nil -} - -func (r *containerStore) lookup(id string) (*Container, bool) { - if container, ok := r.byid[id]; ok { - return container, ok - } else if container, ok := r.byname[id]; ok { - return container, ok - } else if container, ok := r.bylayer[id]; ok { - return container, ok - } else if longid, err := r.idindex.Get(id); err == nil { - if container, ok := r.byid[longid]; ok { - return container, ok - } - } - return nil, false -} - -func (r *containerStore) ClearFlag(id string, flag string) error { - container, ok := r.lookup(id) - if !ok { - return ErrContainerUnknown - } - delete(container.Flags, flag) - return r.Save() -} - -func (r *containerStore) SetFlag(id string, flag string, value interface{}) error { - container, ok := r.lookup(id) - if !ok { - return ErrContainerUnknown - } - if container.Flags == nil { - container.Flags = make(map[string]interface{}) - } - container.Flags[flag] = value - return r.Save() -} - -func (r *containerStore) Create(id string, names []string, image, layer, metadata string) (container *Container, err error) { - if id == "" { - id = stringid.GenerateRandomID() - _, idInUse := r.byid[id] - for idInUse { - id = stringid.GenerateRandomID() - _, idInUse = r.byid[id] - } - } - if _, idInUse := r.byid[id]; idInUse { - return nil, ErrDuplicateID - } - names = dedupeNames(names) - for _, name := range names { - if _, nameInUse := r.byname[name]; nameInUse { - return nil, ErrDuplicateName - } - } - if err == nil { - container = &Container{ - ID: id, - Names: names, - ImageID: image, - LayerID: layer, - Metadata: metadata, - BigDataNames: []string{}, - BigDataSizes: make(map[string]int64), - BigDataDigests: make(map[string]digest.Digest), - Created: time.Now().UTC(), - Flags: make(map[string]interface{}), - } - r.containers = append(r.containers, container) - r.byid[id] = container - r.idindex.Add(id) - r.bylayer[layer] = container - for _, name := range names { - r.byname[name] = container - } - err = r.Save() - } - return container, err -} - -func (r *containerStore) Metadata(id string) (string, error) { - if container, ok := r.lookup(id); ok { - return container.Metadata, nil - } - return "", ErrContainerUnknown -} - -func (r *containerStore) SetMetadata(id, metadata string) error { - if container, ok := r.lookup(id); ok { - container.Metadata = metadata - return r.Save() - } - return ErrContainerUnknown -} - -func (r *containerStore) removeName(container *Container, name string) { - container.Names = stringSliceWithoutValue(container.Names, name) -} - -func (r *containerStore) SetNames(id string, names []string) error { - names = dedupeNames(names) - if container, ok := r.lookup(id); ok { - for _, name := range container.Names { - delete(r.byname, name) - } - for _, name := range names { - if otherContainer, ok := r.byname[name]; ok { - r.removeName(otherContainer, name) - } - r.byname[name] = container - } - container.Names = names - return r.Save() - } - return ErrContainerUnknown -} - -func (r *containerStore) Delete(id string) error { - container, ok := r.lookup(id) - if !ok { - return ErrContainerUnknown - } - id = container.ID - toDeleteIndex := -1 - for i, candidate := range r.containers { - if candidate.ID == id { - toDeleteIndex = i - break - } - } - delete(r.byid, id) - r.idindex.Delete(id) - delete(r.bylayer, container.LayerID) - for _, name := range container.Names { - delete(r.byname, name) - } - if toDeleteIndex != -1 { - // delete the container at toDeleteIndex - if toDeleteIndex == len(r.containers)-1 { - r.containers = r.containers[:len(r.containers)-1] - } else { - r.containers = append(r.containers[:toDeleteIndex], r.containers[toDeleteIndex+1:]...) - } - } - if err := r.Save(); err != nil { - return err - } - if err := os.RemoveAll(r.datadir(id)); err != nil { - return err - } - return nil -} - -func (r *containerStore) Get(id string) (*Container, error) { - if container, ok := r.lookup(id); ok { - return container, nil - } - return nil, ErrContainerUnknown -} - -func (r *containerStore) Lookup(name string) (id string, err error) { - if container, ok := r.lookup(name); ok { - return container.ID, nil - } - return "", ErrContainerUnknown -} - -func (r *containerStore) Exists(id string) bool { - _, ok := r.lookup(id) - return ok -} - -func (r *containerStore) BigData(id, key string) ([]byte, error) { - if key == "" { - return nil, errors.Wrapf(ErrInvalidBigDataName, "can't retrieve container big data value for empty name") - } - c, ok := r.lookup(id) - if !ok { - return nil, ErrContainerUnknown - } - return ioutil.ReadFile(r.datapath(c.ID, key)) -} - -func (r *containerStore) BigDataSize(id, key string) (int64, error) { - if key == "" { - return -1, errors.Wrapf(ErrInvalidBigDataName, "can't retrieve size of container big data with empty name") - } - c, ok := r.lookup(id) - if !ok { - return -1, ErrContainerUnknown - } - if c.BigDataSizes == nil { - c.BigDataSizes = make(map[string]int64) - } - if size, ok := c.BigDataSizes[key]; ok { - return size, nil - } - if data, err := r.BigData(id, key); err == nil && data != nil { - if r.SetBigData(id, key, data) == nil { - c, ok := r.lookup(id) - if !ok { - return -1, ErrContainerUnknown - } - if size, ok := c.BigDataSizes[key]; ok { - return size, nil - } - } - } - return -1, ErrSizeUnknown -} - -func (r *containerStore) BigDataDigest(id, key string) (digest.Digest, error) { - if key == "" { - return "", errors.Wrapf(ErrInvalidBigDataName, "can't retrieve digest of container big data value with empty name") - } - c, ok := r.lookup(id) - if !ok { - return "", ErrContainerUnknown - } - if c.BigDataDigests == nil { - c.BigDataDigests = make(map[string]digest.Digest) - } - if d, ok := c.BigDataDigests[key]; ok { - return d, nil - } - if data, err := r.BigData(id, key); err == nil && data != nil { - if r.SetBigData(id, key, data) == nil { - c, ok := r.lookup(id) - if !ok { - return "", ErrContainerUnknown - } - if d, ok := c.BigDataDigests[key]; ok { - return d, nil - } - } - } - return "", ErrDigestUnknown -} - -func (r *containerStore) BigDataNames(id string) ([]string, error) { - c, ok := r.lookup(id) - if !ok { - return nil, ErrContainerUnknown - } - return c.BigDataNames, nil -} - -func (r *containerStore) SetBigData(id, key string, data []byte) error { - if key == "" { - return errors.Wrapf(ErrInvalidBigDataName, "can't set empty name for container big data item") - } - c, ok := r.lookup(id) - if !ok { - return ErrContainerUnknown - } - if err := os.MkdirAll(r.datadir(c.ID), 0700); err != nil { - return err - } - err := ioutils.AtomicWriteFile(r.datapath(c.ID, key), data, 0600) - if err == nil { - save := false - if c.BigDataSizes == nil { - c.BigDataSizes = make(map[string]int64) - } - oldSize, sizeOk := c.BigDataSizes[key] - c.BigDataSizes[key] = int64(len(data)) - if c.BigDataDigests == nil { - c.BigDataDigests = make(map[string]digest.Digest) - } - oldDigest, digestOk := c.BigDataDigests[key] - newDigest := digest.Canonical.FromBytes(data) - c.BigDataDigests[key] = newDigest - if !sizeOk || oldSize != c.BigDataSizes[key] || !digestOk || oldDigest != newDigest { - save = true - } - addName := true - for _, name := range c.BigDataNames { - if name == key { - addName = false - break - } - } - if addName { - c.BigDataNames = append(c.BigDataNames, key) - save = true - } - if save { - err = r.Save() - } - } - return err -} - -func (r *containerStore) Wipe() error { - ids := make([]string, 0, len(r.byid)) - for id := range r.byid { - ids = append(ids, id) - } - for _, id := range ids { - if err := r.Delete(id); err != nil { - return err - } - } - return nil -} - -func (r *containerStore) Lock() { - r.lockfile.Lock() -} - -func (r *containerStore) Unlock() { - r.lockfile.Unlock() -} - -func (r *containerStore) Touch() error { - return r.lockfile.Touch() -} - -func (r *containerStore) Modified() (bool, error) { - return r.lockfile.Modified() -} - -func (r *containerStore) IsReadWrite() bool { - return r.lockfile.IsReadWrite() -} - -func (r *containerStore) TouchedSince(when time.Time) bool { - return r.lockfile.TouchedSince(when) -} diff --git a/vendor/github.com/containers/storage/containers_ffjson.go b/vendor/github.com/containers/storage/containers_ffjson.go deleted file mode 100644 index 9526198061..0000000000 --- a/vendor/github.com/containers/storage/containers_ffjson.go +++ /dev/null @@ -1,1194 +0,0 @@ -// Code generated by ffjson . DO NOT EDIT. -// source: containers.go - -package storage - -import ( - "bytes" - "encoding/json" - "fmt" - "github.com/opencontainers/go-digest" - fflib "github.com/pquerna/ffjson/fflib/v1" -) - -// MarshalJSON marshal bytes to json - template -func (j *Container) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *Container) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{ "id":`) - fflib.WriteJsonString(buf, string(j.ID)) - buf.WriteByte(',') - if len(j.Names) != 0 { - buf.WriteString(`"names":`) - if j.Names != nil { - buf.WriteString(`[`) - for i, v := range j.Names { - if i != 0 { - buf.WriteString(`,`) - } - fflib.WriteJsonString(buf, string(v)) - } - buf.WriteString(`]`) - } else { - buf.WriteString(`null`) - } - buf.WriteByte(',') - } - buf.WriteString(`"image":`) - fflib.WriteJsonString(buf, string(j.ImageID)) - buf.WriteString(`,"layer":`) - fflib.WriteJsonString(buf, string(j.LayerID)) - buf.WriteByte(',') - if len(j.Metadata) != 0 { - buf.WriteString(`"metadata":`) - fflib.WriteJsonString(buf, string(j.Metadata)) - buf.WriteByte(',') - } - if len(j.BigDataNames) != 0 { - buf.WriteString(`"big-data-names":`) - if j.BigDataNames != nil { - buf.WriteString(`[`) - for i, v := range j.BigDataNames { - if i != 0 { - buf.WriteString(`,`) - } - fflib.WriteJsonString(buf, string(v)) - } - buf.WriteString(`]`) - } else { - buf.WriteString(`null`) - } - buf.WriteByte(',') - } - if len(j.BigDataSizes) != 0 { - if j.BigDataSizes == nil { - buf.WriteString(`"big-data-sizes":null`) - } else { - buf.WriteString(`"big-data-sizes":{ `) - for key, value := range j.BigDataSizes { - fflib.WriteJsonString(buf, key) - buf.WriteString(`:`) - fflib.FormatBits2(buf, uint64(value), 10, value < 0) - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - } - buf.WriteByte(',') - } - if len(j.BigDataDigests) != 0 { - if j.BigDataDigests == nil { - buf.WriteString(`"big-data-digests":null`) - } else { - buf.WriteString(`"big-data-digests":{ `) - for key, value := range j.BigDataDigests { - fflib.WriteJsonString(buf, key) - buf.WriteString(`:`) - fflib.WriteJsonString(buf, string(value)) - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - } - buf.WriteByte(',') - } - if true { - buf.WriteString(`"created":`) - - { - - obj, err = j.Created.MarshalJSON() - if err != nil { - return err - } - buf.Write(obj) - - } - buf.WriteByte(',') - } - if len(j.Flags) != 0 { - buf.WriteString(`"flags":`) - /* Falling back. type=map[string]interface {} kind=map */ - err = buf.Encode(j.Flags) - if err != nil { - return err - } - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - return nil -} - -const ( - ffjtContainerbase = iota - ffjtContainernosuchkey - - ffjtContainerID - - ffjtContainerNames - - ffjtContainerImageID - - ffjtContainerLayerID - - ffjtContainerMetadata - - ffjtContainerBigDataNames - - ffjtContainerBigDataSizes - - ffjtContainerBigDataDigests - - ffjtContainerCreated - - ffjtContainerFlags -) - -var ffjKeyContainerID = []byte("id") - -var ffjKeyContainerNames = []byte("names") - -var ffjKeyContainerImageID = []byte("image") - -var ffjKeyContainerLayerID = []byte("layer") - -var ffjKeyContainerMetadata = []byte("metadata") - -var ffjKeyContainerBigDataNames = []byte("big-data-names") - -var ffjKeyContainerBigDataSizes = []byte("big-data-sizes") - -var ffjKeyContainerBigDataDigests = []byte("big-data-digests") - -var ffjKeyContainerCreated = []byte("created") - -var ffjKeyContainerFlags = []byte("flags") - -// UnmarshalJSON umarshall json - template of ffjson -func (j *Container) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *Container) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtContainerbase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtContainernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - case 'b': - - if bytes.Equal(ffjKeyContainerBigDataNames, kn) { - currentKey = ffjtContainerBigDataNames - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyContainerBigDataSizes, kn) { - currentKey = ffjtContainerBigDataSizes - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyContainerBigDataDigests, kn) { - currentKey = ffjtContainerBigDataDigests - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'c': - - if bytes.Equal(ffjKeyContainerCreated, kn) { - currentKey = ffjtContainerCreated - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'f': - - if bytes.Equal(ffjKeyContainerFlags, kn) { - currentKey = ffjtContainerFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'i': - - if bytes.Equal(ffjKeyContainerID, kn) { - currentKey = ffjtContainerID - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyContainerImageID, kn) { - currentKey = ffjtContainerImageID - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'l': - - if bytes.Equal(ffjKeyContainerLayerID, kn) { - currentKey = ffjtContainerLayerID - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'm': - - if bytes.Equal(ffjKeyContainerMetadata, kn) { - currentKey = ffjtContainerMetadata - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'n': - - if bytes.Equal(ffjKeyContainerNames, kn) { - currentKey = ffjtContainerNames - state = fflib.FFParse_want_colon - goto mainparse - } - - } - - if fflib.EqualFoldRight(ffjKeyContainerFlags, kn) { - currentKey = ffjtContainerFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyContainerCreated, kn) { - currentKey = ffjtContainerCreated - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyContainerBigDataDigests, kn) { - currentKey = ffjtContainerBigDataDigests - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyContainerBigDataSizes, kn) { - currentKey = ffjtContainerBigDataSizes - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyContainerBigDataNames, kn) { - currentKey = ffjtContainerBigDataNames - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyContainerMetadata, kn) { - currentKey = ffjtContainerMetadata - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyContainerLayerID, kn) { - currentKey = ffjtContainerLayerID - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyContainerImageID, kn) { - currentKey = ffjtContainerImageID - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyContainerNames, kn) { - currentKey = ffjtContainerNames - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyContainerID, kn) { - currentKey = ffjtContainerID - state = fflib.FFParse_want_colon - goto mainparse - } - - currentKey = ffjtContainernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtContainerID: - goto handle_ID - - case ffjtContainerNames: - goto handle_Names - - case ffjtContainerImageID: - goto handle_ImageID - - case ffjtContainerLayerID: - goto handle_LayerID - - case ffjtContainerMetadata: - goto handle_Metadata - - case ffjtContainerBigDataNames: - goto handle_BigDataNames - - case ffjtContainerBigDataSizes: - goto handle_BigDataSizes - - case ffjtContainerBigDataDigests: - goto handle_BigDataDigests - - case ffjtContainerCreated: - goto handle_Created - - case ffjtContainerFlags: - goto handle_Flags - - case ffjtContainernosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -handle_ID: - - /* handler: j.ID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.ID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Names: - - /* handler: j.Names type=[]string kind=slice quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Names = nil - } else { - - j.Names = []string{} - - wantVal := true - - for { - - var tmpJNames string - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_brace { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: tmpJNames type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJNames = string(string(outBuf)) - - } - } - - j.Names = append(j.Names, tmpJNames) - - wantVal = false - } - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_ImageID: - - /* handler: j.ImageID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.ImageID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_LayerID: - - /* handler: j.LayerID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.LayerID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Metadata: - - /* handler: j.Metadata type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.Metadata = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataNames: - - /* handler: j.BigDataNames type=[]string kind=slice quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataNames = nil - } else { - - j.BigDataNames = []string{} - - wantVal := true - - for { - - var tmpJBigDataNames string - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_brace { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: tmpJBigDataNames type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJBigDataNames = string(string(outBuf)) - - } - } - - j.BigDataNames = append(j.BigDataNames, tmpJBigDataNames) - - wantVal = false - } - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataSizes: - - /* handler: j.BigDataSizes type=map[string]int64 kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataSizes = nil - } else { - - j.BigDataSizes = make(map[string]int64, 0) - - wantVal := true - - for { - - var k string - - var tmpJBigDataSizes int64 - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJBigDataSizes type=int64 kind=int64 quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - tmpJBigDataSizes = int64(tval) - - } - } - - j.BigDataSizes[k] = tmpJBigDataSizes - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataDigests: - - /* handler: j.BigDataDigests type=map[string]digest.Digest kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataDigests = nil - } else { - - j.BigDataDigests = make(map[string]digest.Digest, 0) - - wantVal := true - - for { - - var k string - - var tmpJBigDataDigests digest.Digest - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJBigDataDigests type=digest.Digest kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJBigDataDigests = digest.Digest(string(outBuf)) - - } - } - - j.BigDataDigests[k] = tmpJBigDataDigests - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Created: - - /* handler: j.Created type=time.Time kind=struct quoted=false*/ - - { - if tok == fflib.FFTok_null { - - } else { - - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = j.Created.UnmarshalJSON(tbuf) - if err != nil { - return fs.WrapErr(err) - } - } - state = fflib.FFParse_after_value - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Flags: - - /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Flags = nil - } else { - - j.Flags = make(map[string]interface{}, 0) - - wantVal := true - - for { - - var k string - - var tmpJFlags interface{} - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/ - - { - /* Falling back. type=interface {} kind=interface */ - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = json.Unmarshal(tbuf, &tmpJFlags) - if err != nil { - return fs.WrapErr(err) - } - } - - j.Flags[k] = tmpJFlags - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *containerStore) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *containerStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{}`) - return nil -} - -const ( - ffjtcontainerStorebase = iota - ffjtcontainerStorenosuchkey -) - -// UnmarshalJSON umarshall json - template of ffjson -func (j *containerStore) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *containerStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtcontainerStorebase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtcontainerStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - } - - currentKey = ffjtcontainerStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtcontainerStorenosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go deleted file mode 100644 index c1cfabee99..0000000000 --- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go +++ /dev/null @@ -1,691 +0,0 @@ -// +build linux - -/* - -aufs driver directory structure - - . - ├── layers // Metadata of layers - │ ├── 1 - │ ├── 2 - │ └── 3 - ├── diff // Content of the layer - │ ├── 1 // Contains layers that need to be mounted for the id - │ ├── 2 - │ └── 3 - └── mnt // Mount points for the rw layers to be mounted - ├── 1 - ├── 2 - └── 3 - -*/ - -package aufs - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "sync" - "time" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/directory" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/locker" - mountpk "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/system" - rsystem "github.com/opencontainers/runc/libcontainer/system" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/vbatts/tar-split/tar/storage" - "golang.org/x/sys/unix" -) - -var ( - // ErrAufsNotSupported is returned if aufs is not supported by the host. - ErrAufsNotSupported = fmt.Errorf("AUFS was not found in /proc/filesystems") - // ErrAufsNested means aufs cannot be used bc we are in a user namespace - ErrAufsNested = fmt.Errorf("AUFS cannot be used in non-init user namespace") - backingFs = "" - - enableDirpermLock sync.Once - enableDirperm bool -) - -func init() { - graphdriver.Register("aufs", Init) -} - -// Driver contains information about the filesystem mounted. -type Driver struct { - sync.Mutex - root string - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - ctr *graphdriver.RefCounter - pathCacheLock sync.Mutex - pathCache map[string]string - naiveDiff graphdriver.DiffDriver - locker *locker.Locker -} - -// Init returns a new AUFS driver. -// An error is returned if AUFS is not supported. -func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - - // Try to load the aufs kernel module - if err := supportsAufs(); err != nil { - return nil, errors.Wrap(graphdriver.ErrNotSupported, "kernel does not support aufs") - - } - - fsMagic, err := graphdriver.GetFSMagic(root) - if err != nil { - return nil, err - } - if fsName, ok := graphdriver.FsNames[fsMagic]; ok { - backingFs = fsName - } - - switch fsMagic { - case graphdriver.FsMagicAufs, graphdriver.FsMagicBtrfs, graphdriver.FsMagicEcryptfs: - logrus.Errorf("AUFS is not supported over %s", backingFs) - return nil, errors.Wrapf(graphdriver.ErrIncompatibleFS, "AUFS is not supported over %q", backingFs) - } - - paths := []string{ - "mnt", - "diff", - "layers", - } - - a := &Driver{ - root: root, - uidMaps: uidMaps, - gidMaps: gidMaps, - pathCache: make(map[string]string), - ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)), - locker: locker.New(), - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - // Create the root aufs driver dir and return - // if it already exists - // If not populate the dir structure - if err := idtools.MkdirAllAs(root, 0700, rootUID, rootGID); err != nil { - if os.IsExist(err) { - return a, nil - } - return nil, err - } - - if err := mountpk.MakePrivate(root); err != nil { - return nil, err - } - - // Populate the dir structure - for _, p := range paths { - if err := idtools.MkdirAllAs(path.Join(root, p), 0700, rootUID, rootGID); err != nil { - return nil, err - } - } - logger := logrus.WithFields(logrus.Fields{ - "module": "graphdriver", - "driver": "aufs", - }) - - for _, path := range []string{"mnt", "diff"} { - p := filepath.Join(root, path) - entries, err := ioutil.ReadDir(p) - if err != nil { - logger.WithError(err).WithField("dir", p).Error("error reading dir entries") - continue - } - for _, entry := range entries { - if !entry.IsDir() { - continue - } - if strings.HasSuffix(entry.Name(), "-removing") { - logger.WithField("dir", entry.Name()).Debug("Cleaning up stale layer dir") - if err := system.EnsureRemoveAll(filepath.Join(p, entry.Name())); err != nil { - logger.WithField("dir", entry.Name()).WithError(err).Error("Error removing stale layer dir") - } - } - } - } - - a.naiveDiff = graphdriver.NewNaiveDiffDriver(a, uidMaps, gidMaps) - return a, nil -} - -// Return a nil error if the kernel supports aufs -// We cannot modprobe because inside dind modprobe fails -// to run -func supportsAufs() error { - // We can try to modprobe aufs first before looking at - // proc/filesystems for when aufs is supported - exec.Command("modprobe", "aufs").Run() - - if rsystem.RunningInUserNS() { - return ErrAufsNested - } - - f, err := os.Open("/proc/filesystems") - if err != nil { - return err - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - if strings.Contains(s.Text(), "aufs") { - return nil - } - } - return ErrAufsNotSupported -} - -func (a *Driver) rootPath() string { - return a.root -} - -func (*Driver) String() string { - return "aufs" -} - -// Status returns current information about the filesystem such as root directory, number of directories mounted, etc. -func (a *Driver) Status() [][2]string { - ids, _ := loadIds(path.Join(a.rootPath(), "layers")) - return [][2]string{ - {"Root Dir", a.rootPath()}, - {"Backing Filesystem", backingFs}, - {"Dirs", fmt.Sprintf("%d", len(ids))}, - {"Dirperm1 Supported", fmt.Sprintf("%v", useDirperm())}, - } -} - -// Metadata not implemented -func (a *Driver) Metadata(id string) (map[string]string, error) { - return nil, nil -} - -// Exists returns true if the given id is registered with -// this driver -func (a *Driver) Exists(id string) bool { - if _, err := os.Lstat(path.Join(a.rootPath(), "layers", id)); err != nil { - return false - } - return true -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (a *Driver) AdditionalImageStores() []string { - return nil -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (a *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - return a.Create(id, parent, opts) -} - -// Create three folders for each id -// mnt, layers, and diff -func (a *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - - if opts != nil && len(opts.StorageOpt) != 0 { - return fmt.Errorf("--storage-opt is not supported for aufs") - } - - if err := a.createDirsFor(id); err != nil { - return err - } - // Write the layers metadata - f, err := os.Create(path.Join(a.rootPath(), "layers", id)) - if err != nil { - return err - } - defer f.Close() - - if parent != "" { - ids, err := getParentIDs(a.rootPath(), parent) - if err != nil { - return err - } - - if _, err := fmt.Fprintln(f, parent); err != nil { - return err - } - for _, i := range ids { - if _, err := fmt.Fprintln(f, i); err != nil { - return err - } - } - } - - return nil -} - -// createDirsFor creates two directories for the given id. -// mnt and diff -func (a *Driver) createDirsFor(id string) error { - paths := []string{ - "mnt", - "diff", - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(a.uidMaps, a.gidMaps) - if err != nil { - return err - } - // Directory permission is 0755. - // The path of directories are /mnt/ - // and /diff/ - for _, p := range paths { - if err := idtools.MkdirAllAs(path.Join(a.rootPath(), p, id), 0755, rootUID, rootGID); err != nil { - return err - } - } - return nil -} - -// Remove will unmount and remove the given id. -func (a *Driver) Remove(id string) error { - a.locker.Lock(id) - defer a.locker.Unlock(id) - a.pathCacheLock.Lock() - mountpoint, exists := a.pathCache[id] - a.pathCacheLock.Unlock() - if !exists { - mountpoint = a.getMountpoint(id) - } - - logger := logrus.WithFields(logrus.Fields{ - "module": "graphdriver", - "driver": "aufs", - "layer": id, - }) - - var retries int - for { - mounted, err := a.mounted(mountpoint) - if err != nil { - if os.IsNotExist(err) { - break - } - return err - } - if !mounted { - break - } - - err = a.unmount(mountpoint) - if err == nil { - break - } - - if err != unix.EBUSY { - return errors.Wrapf(err, "aufs: unmount error: %s", mountpoint) - } - if retries >= 5 { - return errors.Wrapf(err, "aufs: unmount error after retries: %s", mountpoint) - } - // If unmount returns EBUSY, it could be a transient error. Sleep and retry. - retries++ - logger.Warnf("unmount failed due to EBUSY: retry count: %d", retries) - time.Sleep(100 * time.Millisecond) - } - - // Remove the layers file for the id - if err := os.Remove(path.Join(a.rootPath(), "layers", id)); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing layers dir for %s", id) - } - - if err := atomicRemove(a.getDiffPath(id)); err != nil { - return errors.Wrapf(err, "could not remove diff path for id %s", id) - } - - // Atomically remove each directory in turn by first moving it out of the - // way (so that container runtime doesn't find it anymore) before doing removal of - // the whole tree. - if err := atomicRemove(mountpoint); err != nil { - if errors.Cause(err) == unix.EBUSY { - logger.WithField("dir", mountpoint).WithError(err).Warn("error performing atomic remove due to EBUSY") - } - return errors.Wrapf(err, "could not remove mountpoint for id %s", id) - } - - a.pathCacheLock.Lock() - delete(a.pathCache, id) - a.pathCacheLock.Unlock() - return nil -} - -func atomicRemove(source string) error { - target := source + "-removing" - - err := os.Rename(source, target) - switch { - case err == nil, os.IsNotExist(err): - case os.IsExist(err): - // Got error saying the target dir already exists, maybe the source doesn't exist due to a previous (failed) remove - if _, e := os.Stat(source); !os.IsNotExist(e) { - return errors.Wrapf(err, "target rename dir '%s' exists but should not, this needs to be manually cleaned up") - } - default: - return errors.Wrapf(err, "error preparing atomic delete") - } - - return system.EnsureRemoveAll(target) -} - -// Get returns the rootfs path for the id. -// This will mount the dir at its given path -func (a *Driver) Get(id, mountLabel string) (string, error) { - a.locker.Lock(id) - defer a.locker.Unlock(id) - parents, err := a.getParentLayerPaths(id) - if err != nil && !os.IsNotExist(err) { - return "", err - } - - a.pathCacheLock.Lock() - m, exists := a.pathCache[id] - a.pathCacheLock.Unlock() - - if !exists { - m = a.getDiffPath(id) - if len(parents) > 0 { - m = a.getMountpoint(id) - } - } - if count := a.ctr.Increment(m); count > 1 { - return m, nil - } - - // If a dir does not have a parent ( no layers )do not try to mount - // just return the diff path to the data - if len(parents) > 0 { - if err := a.mount(id, m, mountLabel, parents); err != nil { - return "", err - } - } - - a.pathCacheLock.Lock() - a.pathCache[id] = m - a.pathCacheLock.Unlock() - return m, nil -} - -// Put unmounts and updates list of active mounts. -func (a *Driver) Put(id string) error { - a.locker.Lock(id) - defer a.locker.Unlock(id) - a.pathCacheLock.Lock() - m, exists := a.pathCache[id] - if !exists { - m = a.getMountpoint(id) - a.pathCache[id] = m - } - a.pathCacheLock.Unlock() - if count := a.ctr.Decrement(m); count > 0 { - return nil - } - - err := a.unmount(m) - if err != nil { - logrus.Debugf("Failed to unmount %s aufs: %v", id, err) - } - return err -} - -// isParent returns if the passed in parent is the direct parent of the passed in layer -func (a *Driver) isParent(id, parent string) bool { - parents, _ := getParentIDs(a.rootPath(), id) - if parent == "" && len(parents) > 0 { - return false - } - return !(len(parents) > 0 && parent != parents[0]) -} - -// Diff produces an archive of the changes between the specified -// layer and its parent layer which may be "". -func (a *Driver) Diff(id, parent, mountLabel string) (io.ReadCloser, error) { - if !a.isParent(id, parent) { - return a.naiveDiff.Diff(id, parent, mountLabel) - } - - // AUFS doesn't need the parent layer to produce a diff. - return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{ - Compression: archive.Uncompressed, - ExcludePatterns: []string{archive.WhiteoutMetaPrefix + "*", "!" + archive.WhiteoutOpaqueDir}, - UIDMaps: a.uidMaps, - GIDMaps: a.gidMaps, - }) -} - -type fileGetNilCloser struct { - storage.FileGetter -} - -func (f fileGetNilCloser) Close() error { - return nil -} - -// DiffGetter returns a FileGetCloser that can read files from the directory that -// contains files for the layer differences. Used for direct access for tar-split. -func (a *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) { - p := path.Join(a.rootPath(), "diff", id) - return fileGetNilCloser{storage.NewPathFileGetter(p)}, nil -} - -func (a *Driver) applyDiff(id string, diff io.Reader) error { - return chrootarchive.UntarUncompressed(diff, path.Join(a.rootPath(), "diff", id), &archive.TarOptions{ - UIDMaps: a.uidMaps, - GIDMaps: a.gidMaps, - }) -} - -// DiffSize calculates the changes between the specified id -// and its parent and returns the size in bytes of the changes -// relative to its base filesystem directory. -func (a *Driver) DiffSize(id, parent, mountLabel string) (size int64, err error) { - if !a.isParent(id, parent) { - return a.naiveDiff.DiffSize(id, parent, mountLabel) - } - // AUFS doesn't need the parent layer to calculate the diff size. - return directory.Size(path.Join(a.rootPath(), "diff", id)) -} - -// ApplyDiff extracts the changeset from the given diff into the -// layer with the specified id and parent, returning the size of the -// new layer in bytes. -func (a *Driver) ApplyDiff(id, parent, mountLabel string, diff io.Reader) (size int64, err error) { - if !a.isParent(id, parent) { - return a.naiveDiff.ApplyDiff(id, parent, mountLabel, diff) - } - - // AUFS doesn't need the parent id to apply the diff if it is the direct parent. - if err = a.applyDiff(id, diff); err != nil { - return - } - - return a.DiffSize(id, parent, mountLabel) -} - -// Changes produces a list of changes between the specified layer -// and its parent layer. If parent is "", then all changes will be ADD changes. -func (a *Driver) Changes(id, parent, mountLabel string) ([]archive.Change, error) { - if !a.isParent(id, parent) { - return a.naiveDiff.Changes(id, parent, mountLabel) - } - - // AUFS doesn't have snapshots, so we need to get changes from all parent - // layers. - layers, err := a.getParentLayerPaths(id) - if err != nil { - return nil, err - } - return archive.Changes(layers, path.Join(a.rootPath(), "diff", id)) -} - -func (a *Driver) getParentLayerPaths(id string) ([]string, error) { - parentIds, err := getParentIDs(a.rootPath(), id) - if err != nil { - return nil, err - } - layers := make([]string, len(parentIds)) - - // Get the diff paths for all the parent ids - for i, p := range parentIds { - layers[i] = path.Join(a.rootPath(), "diff", p) - } - return layers, nil -} - -func (a *Driver) mount(id string, target string, mountLabel string, layers []string) error { - a.Lock() - defer a.Unlock() - - // If the id is mounted or we get an error return - if mounted, err := a.mounted(target); err != nil || mounted { - return err - } - - rw := a.getDiffPath(id) - - if err := a.aufsMount(layers, rw, target, mountLabel); err != nil { - return fmt.Errorf("error creating aufs mount to %s: %v", target, err) - } - return nil -} - -func (a *Driver) unmount(mountPath string) error { - a.Lock() - defer a.Unlock() - - if mounted, err := a.mounted(mountPath); err != nil || !mounted { - return err - } - if err := Unmount(mountPath); err != nil { - return err - } - return nil -} - -func (a *Driver) mounted(mountpoint string) (bool, error) { - return graphdriver.Mounted(graphdriver.FsMagicAufs, mountpoint) -} - -// Cleanup aufs and unmount all mountpoints -func (a *Driver) Cleanup() error { - var dirs []string - if err := filepath.Walk(a.mntPath(), func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - return nil - } - dirs = append(dirs, path) - return nil - }); err != nil { - return err - } - - for _, m := range dirs { - if err := a.unmount(m); err != nil { - logrus.Debugf("aufs error unmounting %s: %s", m, err) - } - } - return mountpk.Unmount(a.root) -} - -func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) { - defer func() { - if err != nil { - Unmount(target) - } - }() - - // Mount options are clipped to page size(4096 bytes). If there are more - // layers then these are remounted individually using append. - - offset := 54 - if useDirperm() { - offset += len(",dirperm1") - } - b := make([]byte, unix.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel - bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) - - index := 0 - for ; index < len(ro); index++ { - layer := fmt.Sprintf(":%s=ro+wh", ro[index]) - if bp+len(layer) > len(b) { - break - } - bp += copy(b[bp:], layer) - } - - opts := "dio,xino=/dev/shm/aufs.xino" - if useDirperm() { - opts += ",dirperm1" - } - data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel) - if err = mount("none", target, "aufs", 0, data); err != nil { - return - } - - for ; index < len(ro); index++ { - layer := fmt.Sprintf(":%s=ro+wh", ro[index]) - data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel) - if err = mount("none", target, "aufs", unix.MS_REMOUNT, data); err != nil { - return - } - } - - return -} - -// useDirperm checks dirperm1 mount option can be used with the current -// version of aufs. -func useDirperm() bool { - enableDirpermLock.Do(func() { - base, err := ioutil.TempDir("", "storage-aufs-base") - if err != nil { - logrus.Errorf("error checking dirperm1: %v", err) - return - } - defer os.RemoveAll(base) - - union, err := ioutil.TempDir("", "storage-aufs-union") - if err != nil { - logrus.Errorf("error checking dirperm1: %v", err) - return - } - defer os.RemoveAll(union) - - opts := fmt.Sprintf("br:%s,dirperm1,xino=/dev/shm/aufs.xino", base) - if err := mount("none", union, "aufs", 0, opts); err != nil { - return - } - enableDirperm = true - if err := Unmount(union); err != nil { - logrus.Errorf("error checking dirperm1: failed to unmount %v", err) - } - }) - return enableDirperm -} diff --git a/vendor/github.com/containers/storage/drivers/aufs/dirs.go b/vendor/github.com/containers/storage/drivers/aufs/dirs.go deleted file mode 100644 index d2325fc46c..0000000000 --- a/vendor/github.com/containers/storage/drivers/aufs/dirs.go +++ /dev/null @@ -1,64 +0,0 @@ -// +build linux - -package aufs - -import ( - "bufio" - "io/ioutil" - "os" - "path" -) - -// Return all the directories -func loadIds(root string) ([]string, error) { - dirs, err := ioutil.ReadDir(root) - if err != nil { - return nil, err - } - out := []string{} - for _, d := range dirs { - if !d.IsDir() { - out = append(out, d.Name()) - } - } - return out, nil -} - -// Read the layers file for the current id and return all the -// layers represented by new lines in the file -// -// If there are no lines in the file then the id has no parent -// and an empty slice is returned. -func getParentIDs(root, id string) ([]string, error) { - f, err := os.Open(path.Join(root, "layers", id)) - if err != nil { - return nil, err - } - defer f.Close() - - out := []string{} - s := bufio.NewScanner(f) - - for s.Scan() { - if t := s.Text(); t != "" { - out = append(out, s.Text()) - } - } - return out, s.Err() -} - -func (a *Driver) getMountpoint(id string) string { - return path.Join(a.mntPath(), id) -} - -func (a *Driver) mntPath() string { - return path.Join(a.rootPath(), "mnt") -} - -func (a *Driver) getDiffPath(id string) string { - return path.Join(a.diffPath(), id) -} - -func (a *Driver) diffPath() string { - return path.Join(a.rootPath(), "diff") -} diff --git a/vendor/github.com/containers/storage/drivers/aufs/mount.go b/vendor/github.com/containers/storage/drivers/aufs/mount.go deleted file mode 100644 index 100e7537a9..0000000000 --- a/vendor/github.com/containers/storage/drivers/aufs/mount.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build linux - -package aufs - -import ( - "os/exec" - - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// Unmount the target specified. -func Unmount(target string) error { - if err := exec.Command("auplink", target, "flush").Run(); err != nil { - logrus.Warnf("Couldn't run auplink before unmount %s: %s", target, err) - } - if err := unix.Unmount(target, 0); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/aufs/mount_linux.go b/vendor/github.com/containers/storage/drivers/aufs/mount_linux.go deleted file mode 100644 index 937104ba3f..0000000000 --- a/vendor/github.com/containers/storage/drivers/aufs/mount_linux.go +++ /dev/null @@ -1,7 +0,0 @@ -package aufs - -import "golang.org/x/sys/unix" - -func mount(source string, target string, fstype string, flags uintptr, data string) error { - return unix.Mount(source, target, fstype, flags, data) -} diff --git a/vendor/github.com/containers/storage/drivers/aufs/mount_unsupported.go b/vendor/github.com/containers/storage/drivers/aufs/mount_unsupported.go deleted file mode 100644 index d030b06637..0000000000 --- a/vendor/github.com/containers/storage/drivers/aufs/mount_unsupported.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !linux - -package aufs - -import "errors" - -// MsRemount declared to specify a non-linux system mount. -const MsRemount = 0 - -func mount(source string, target string, fstype string, flags uintptr, data string) (err error) { - return errors.New("mount is not implemented on this platform") -} diff --git a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go deleted file mode 100644 index abc856c836..0000000000 --- a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go +++ /dev/null @@ -1,677 +0,0 @@ -// +build linux - -package btrfs - -/* -#include -#include -#include -#include - -static void set_name_btrfs_ioctl_vol_args_v2(struct btrfs_ioctl_vol_args_v2* btrfs_struct, const char* value) { - snprintf(btrfs_struct->name, BTRFS_SUBVOL_NAME_MAX, "%s", value); -} -*/ -import "C" - -import ( - "fmt" - "io/ioutil" - "math" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "sync" - "unsafe" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/parsers" - "github.com/containers/storage/pkg/system" - "github.com/docker/go-units" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -func init() { - graphdriver.Register("btrfs", Init) -} - -type btrfsOptions struct { - minSpace uint64 - size uint64 -} - -// Init returns a new BTRFS driver. -// An error is returned if BTRFS is not supported. -func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - - fsMagic, err := graphdriver.GetFSMagic(home) - if err != nil { - return nil, err - } - - if fsMagic != graphdriver.FsMagicBtrfs { - return nil, errors.Wrapf(graphdriver.ErrPrerequisites, "%q is not on a btrfs filesystem", home) - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { - return nil, err - } - - if err := mount.MakePrivate(home); err != nil { - return nil, err - } - - opt, userDiskQuota, err := parseOptions(options) - if err != nil { - return nil, err - } - - driver := &Driver{ - home: home, - uidMaps: uidMaps, - gidMaps: gidMaps, - options: opt, - } - - if userDiskQuota { - if err := driver.subvolEnableQuota(); err != nil { - return nil, err - } - } - - return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil -} - -func parseOptions(opt []string) (btrfsOptions, bool, error) { - var options btrfsOptions - userDiskQuota := false - for _, option := range opt { - key, val, err := parsers.ParseKeyValueOpt(option) - if err != nil { - return options, userDiskQuota, err - } - key = strings.ToLower(key) - switch key { - case "btrfs.min_space": - minSpace, err := units.RAMInBytes(val) - if err != nil { - return options, userDiskQuota, err - } - userDiskQuota = true - options.minSpace = uint64(minSpace) - default: - return options, userDiskQuota, fmt.Errorf("Unknown option %s", key) - } - } - return options, userDiskQuota, nil -} - -// Driver contains information about the filesystem mounted. -type Driver struct { - //root of the file system - home string - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - options btrfsOptions - quotaEnabled bool - once sync.Once -} - -// String prints the name of the driver (btrfs). -func (d *Driver) String() string { - return "btrfs" -} - -// Status returns current driver information in a two dimensional string array. -// Output contains "Build Version" and "Library Version" of the btrfs libraries used. -// Version information can be used to check compatibility with your kernel. -func (d *Driver) Status() [][2]string { - status := [][2]string{} - if bv := btrfsBuildVersion(); bv != "-" { - status = append(status, [2]string{"Build Version", bv}) - } - if lv := btrfsLibVersion(); lv != -1 { - status = append(status, [2]string{"Library Version", fmt.Sprintf("%d", lv)}) - } - return status -} - -// Metadata returns empty metadata for this driver. -func (d *Driver) Metadata(id string) (map[string]string, error) { - return nil, nil -} - -// Cleanup unmounts the home directory. -func (d *Driver) Cleanup() error { - if err := d.subvolDisableQuota(); err != nil { - return err - } - - return mount.Unmount(d.home) -} - -func free(p *C.char) { - C.free(unsafe.Pointer(p)) -} - -func openDir(path string) (*C.DIR, error) { - Cpath := C.CString(path) - defer free(Cpath) - - dir := C.opendir(Cpath) - if dir == nil { - return nil, fmt.Errorf("Can't open dir") - } - return dir, nil -} - -func closeDir(dir *C.DIR) { - if dir != nil { - C.closedir(dir) - } -} - -func getDirFd(dir *C.DIR) uintptr { - return uintptr(C.dirfd(dir)) -} - -func subvolCreate(path, name string) error { - dir, err := openDir(path) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_vol_args - for i, c := range []byte(name) { - args.name[i] = C.char(c) - } - - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SUBVOL_CREATE, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to create btrfs subvolume: %v", errno.Error()) - } - return nil -} - -func subvolSnapshot(src, dest, name string) error { - srcDir, err := openDir(src) - if err != nil { - return err - } - defer closeDir(srcDir) - - destDir, err := openDir(dest) - if err != nil { - return err - } - defer closeDir(destDir) - - var args C.struct_btrfs_ioctl_vol_args_v2 - args.fd = C.__s64(getDirFd(srcDir)) - - var cs = C.CString(name) - C.set_name_btrfs_ioctl_vol_args_v2(&args, cs) - C.free(unsafe.Pointer(cs)) - - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(destDir), C.BTRFS_IOC_SNAP_CREATE_V2, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to create btrfs snapshot: %v", errno.Error()) - } - return nil -} - -func isSubvolume(p string) (bool, error) { - var bufStat unix.Stat_t - if err := unix.Lstat(p, &bufStat); err != nil { - return false, err - } - - // return true if it is a btrfs subvolume - return bufStat.Ino == C.BTRFS_FIRST_FREE_OBJECTID, nil -} - -func subvolDelete(dirpath, name string, quotaEnabled bool) error { - dir, err := openDir(dirpath) - if err != nil { - return err - } - defer closeDir(dir) - fullPath := path.Join(dirpath, name) - - var args C.struct_btrfs_ioctl_vol_args - - // walk the btrfs subvolumes - walkSubvolumes := func(p string, f os.FileInfo, err error) error { - if err != nil { - if os.IsNotExist(err) && p != fullPath { - // missing most likely because the path was a subvolume that got removed in the previous iteration - // since it's gone anyway, we don't care - return nil - } - return fmt.Errorf("error walking subvolumes: %v", err) - } - // we want to check children only so skip itself - // it will be removed after the filepath walk anyways - if f.IsDir() && p != fullPath { - sv, err := isSubvolume(p) - if err != nil { - return fmt.Errorf("Failed to test if %s is a btrfs subvolume: %v", p, err) - } - if sv { - if err := subvolDelete(path.Dir(p), f.Name(), quotaEnabled); err != nil { - return fmt.Errorf("Failed to destroy btrfs child subvolume (%s) of parent (%s): %v", p, dirpath, err) - } - } - } - return nil - } - if err := filepath.Walk(path.Join(dirpath, name), walkSubvolumes); err != nil { - return fmt.Errorf("Recursively walking subvolumes for %s failed: %v", dirpath, err) - } - - if quotaEnabled { - if qgroupid, err := subvolLookupQgroup(fullPath); err == nil { - var args C.struct_btrfs_ioctl_qgroup_create_args - args.qgroupid = C.__u64(qgroupid) - - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QGROUP_CREATE, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - logrus.Errorf("Failed to delete btrfs qgroup %v for %s: %v", qgroupid, fullPath, errno.Error()) - } - } else { - logrus.Errorf("Failed to lookup btrfs qgroup for %s: %v", fullPath, err.Error()) - } - } - - // all subvolumes have been removed - // now remove the one originally passed in - for i, c := range []byte(name) { - args.name[i] = C.char(c) - } - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to destroy btrfs snapshot %s for %s: %v", dirpath, name, errno.Error()) - } - return nil -} - -func (d *Driver) updateQuotaStatus() { - d.once.Do(func() { - if !d.quotaEnabled { - // In case quotaEnabled is not set, check qgroup and update quotaEnabled as needed - if err := subvolQgroupStatus(d.home); err != nil { - // quota is still not enabled - return - } - d.quotaEnabled = true - } - }) -} - -func (d *Driver) subvolEnableQuota() error { - d.updateQuotaStatus() - - if d.quotaEnabled { - return nil - } - - dir, err := openDir(d.home) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_quota_ctl_args - args.cmd = C.BTRFS_QUOTA_CTL_ENABLE - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QUOTA_CTL, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to enable btrfs quota for %s: %v", dir, errno.Error()) - } - - d.quotaEnabled = true - - return nil -} - -func (d *Driver) subvolDisableQuota() error { - d.updateQuotaStatus() - - if !d.quotaEnabled { - return nil - } - - dir, err := openDir(d.home) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_quota_ctl_args - args.cmd = C.BTRFS_QUOTA_CTL_DISABLE - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QUOTA_CTL, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to disable btrfs quota for %s: %v", dir, errno.Error()) - } - - d.quotaEnabled = false - - return nil -} - -func (d *Driver) subvolRescanQuota() error { - d.updateQuotaStatus() - - if !d.quotaEnabled { - return nil - } - - dir, err := openDir(d.home) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_quota_rescan_args - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QUOTA_RESCAN_WAIT, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to rescan btrfs quota for %s: %v", dir, errno.Error()) - } - - return nil -} - -func subvolLimitQgroup(path string, size uint64) error { - dir, err := openDir(path) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_qgroup_limit_args - args.lim.max_referenced = C.__u64(size) - args.lim.flags = C.BTRFS_QGROUP_LIMIT_MAX_RFER - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QGROUP_LIMIT, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to limit qgroup for %s: %v", dir, errno.Error()) - } - - return nil -} - -// subvolQgroupStatus performs a BTRFS_IOC_TREE_SEARCH on the root path -// with search key of BTRFS_QGROUP_STATUS_KEY. -// In case qgroup is enabled, the retuned key type will match BTRFS_QGROUP_STATUS_KEY. -// For more details please see https://github.com/kdave/btrfs-progs/blob/v4.9/qgroup.c#L1035 -func subvolQgroupStatus(path string) error { - dir, err := openDir(path) - if err != nil { - return err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_search_args - args.key.tree_id = C.BTRFS_QUOTA_TREE_OBJECTID - args.key.min_type = C.BTRFS_QGROUP_STATUS_KEY - args.key.max_type = C.BTRFS_QGROUP_STATUS_KEY - args.key.max_objectid = C.__u64(math.MaxUint64) - args.key.max_offset = C.__u64(math.MaxUint64) - args.key.max_transid = C.__u64(math.MaxUint64) - args.key.nr_items = 4096 - - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_TREE_SEARCH, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return fmt.Errorf("Failed to search qgroup for %s: %v", path, errno.Error()) - } - sh := (*C.struct_btrfs_ioctl_search_header)(unsafe.Pointer(&args.buf)) - if sh._type != C.BTRFS_QGROUP_STATUS_KEY { - return fmt.Errorf("Invalid qgroup search header type for %s: %v", path, sh._type) - } - return nil -} - -func subvolLookupQgroup(path string) (uint64, error) { - dir, err := openDir(path) - if err != nil { - return 0, err - } - defer closeDir(dir) - - var args C.struct_btrfs_ioctl_ino_lookup_args - args.objectid = C.BTRFS_FIRST_FREE_OBJECTID - - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_INO_LOOKUP, - uintptr(unsafe.Pointer(&args))) - if errno != 0 { - return 0, fmt.Errorf("Failed to lookup qgroup for %s: %v", dir, errno.Error()) - } - if args.treeid == 0 { - return 0, fmt.Errorf("Invalid qgroup id for %s: 0", dir) - } - - return uint64(args.treeid), nil -} - -func (d *Driver) subvolumesDir() string { - return path.Join(d.home, "subvolumes") -} - -func (d *Driver) subvolumesDirID(id string) string { - return path.Join(d.subvolumesDir(), id) -} - -func (d *Driver) quotasDir() string { - return path.Join(d.home, "quotas") -} - -func (d *Driver) quotasDirID(id string) string { - return path.Join(d.quotasDir(), id) -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - return d.Create(id, parent, opts) -} - -// Create the filesystem with given id. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - quotas := path.Join(d.home, "quotas") - subvolumes := path.Join(d.home, "subvolumes") - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - return err - } - if err := idtools.MkdirAllAs(subvolumes, 0700, rootUID, rootGID); err != nil { - return err - } - if parent == "" { - if err := subvolCreate(subvolumes, id); err != nil { - return err - } - } else { - parentDir := d.subvolumesDirID(parent) - st, err := os.Stat(parentDir) - if err != nil { - return err - } - if !st.IsDir() { - return fmt.Errorf("%s: not a directory", parentDir) - } - if err := subvolSnapshot(parentDir, subvolumes, id); err != nil { - return err - } - } - - var storageOpt map[string]string - if opts != nil { - storageOpt = opts.StorageOpt - } - - if _, ok := storageOpt["size"]; ok { - driver := &Driver{} - if err := d.parseStorageOpt(storageOpt, driver); err != nil { - return err - } - - if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil { - return err - } - if err := idtools.MkdirAllAs(quotas, 0700, rootUID, rootGID); err != nil { - return err - } - if err := ioutil.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0644); err != nil { - return err - } - } - - // if we have a remapped root (user namespaces enabled), change the created snapshot - // dir ownership to match - if rootUID != 0 || rootGID != 0 { - if err := os.Chown(path.Join(subvolumes, id), rootUID, rootGID); err != nil { - return err - } - } - - mountLabel := "" - if opts != nil { - mountLabel = opts.MountLabel - } - - return label.Relabel(path.Join(subvolumes, id), mountLabel, false) -} - -// Parse btrfs storage options -func (d *Driver) parseStorageOpt(storageOpt map[string]string, driver *Driver) error { - // Read size to change the subvolume disk quota per container - for key, val := range storageOpt { - key := strings.ToLower(key) - switch key { - case "size": - size, err := units.RAMInBytes(val) - if err != nil { - return err - } - driver.options.size = uint64(size) - default: - return fmt.Errorf("Unknown option %s", key) - } - } - - return nil -} - -// Set btrfs storage size -func (d *Driver) setStorageSize(dir string, driver *Driver) error { - if driver.options.size <= 0 { - return fmt.Errorf("btrfs: invalid storage size: %s", units.HumanSize(float64(driver.options.size))) - } - if d.options.minSpace > 0 && driver.options.size < d.options.minSpace { - return fmt.Errorf("btrfs: storage size cannot be less than %s", units.HumanSize(float64(d.options.minSpace))) - } - - if err := d.subvolEnableQuota(); err != nil { - return err - } - - if err := subvolLimitQgroup(dir, driver.options.size); err != nil { - return err - } - - return nil -} - -// Remove the filesystem with given id. -func (d *Driver) Remove(id string) error { - dir := d.subvolumesDirID(id) - if _, err := os.Stat(dir); err != nil { - return err - } - quotasDir := d.quotasDirID(id) - if _, err := os.Stat(quotasDir); err == nil { - if err := os.Remove(quotasDir); err != nil { - return err - } - } else if !os.IsNotExist(err) { - return err - } - - // Call updateQuotaStatus() to invoke status update - d.updateQuotaStatus() - - if err := subvolDelete(d.subvolumesDir(), id, d.quotaEnabled); err != nil { - return err - } - if err := system.EnsureRemoveAll(dir); err != nil { - return err - } - if err := d.subvolRescanQuota(); err != nil { - return err - } - return nil -} - -// Get the requested filesystem id. -func (d *Driver) Get(id, mountLabel string) (string, error) { - dir := d.subvolumesDirID(id) - st, err := os.Stat(dir) - if err != nil { - return "", err - } - - if !st.IsDir() { - return "", fmt.Errorf("%s: not a directory", dir) - } - - if quota, err := ioutil.ReadFile(d.quotasDirID(id)); err == nil { - if size, err := strconv.ParseUint(string(quota), 10, 64); err == nil && size >= d.options.minSpace { - if err := d.subvolEnableQuota(); err != nil { - return "", err - } - if err := subvolLimitQgroup(dir, size); err != nil { - return "", err - } - } - } - - return dir, nil -} - -// Put is not implemented for BTRFS as there is no cleanup required for the id. -func (d *Driver) Put(id string) error { - // Get() creates no runtime resources (like e.g. mounts) - // so this doesn't need to do anything. - return nil -} - -// Exists checks if the id exists in the filesystem. -func (d *Driver) Exists(id string) bool { - dir := d.subvolumesDirID(id) - _, err := os.Stat(dir) - return err == nil -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/btrfs/dummy_unsupported.go b/vendor/github.com/containers/storage/drivers/btrfs/dummy_unsupported.go deleted file mode 100644 index f07088887a..0000000000 --- a/vendor/github.com/containers/storage/drivers/btrfs/dummy_unsupported.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build !linux !cgo - -package btrfs diff --git a/vendor/github.com/containers/storage/drivers/btrfs/version.go b/vendor/github.com/containers/storage/drivers/btrfs/version.go deleted file mode 100644 index 73d90cdd71..0000000000 --- a/vendor/github.com/containers/storage/drivers/btrfs/version.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build linux,!btrfs_noversion - -package btrfs - -/* -#include - -// around version 3.16, they did not define lib version yet -#ifndef BTRFS_LIB_VERSION -#define BTRFS_LIB_VERSION -1 -#endif - -// upstream had removed it, but now it will be coming back -#ifndef BTRFS_BUILD_VERSION -#define BTRFS_BUILD_VERSION "-" -#endif -*/ -import "C" - -func btrfsBuildVersion() string { - return string(C.BTRFS_BUILD_VERSION) -} - -func btrfsLibVersion() int { - return int(C.BTRFS_LIB_VERSION) -} diff --git a/vendor/github.com/containers/storage/drivers/btrfs/version_none.go b/vendor/github.com/containers/storage/drivers/btrfs/version_none.go deleted file mode 100644 index f802fbc629..0000000000 --- a/vendor/github.com/containers/storage/drivers/btrfs/version_none.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build linux,btrfs_noversion - -package btrfs - -// TODO(vbatts) remove this work-around once supported linux distros are on -// btrfs utilities of >= 3.16.1 - -func btrfsBuildVersion() string { - return "-" -} - -func btrfsLibVersion() int { - return -1 -} diff --git a/vendor/github.com/containers/storage/drivers/counter.go b/vendor/github.com/containers/storage/drivers/counter.go deleted file mode 100644 index 72551a38d4..0000000000 --- a/vendor/github.com/containers/storage/drivers/counter.go +++ /dev/null @@ -1,59 +0,0 @@ -package graphdriver - -import "sync" - -type minfo struct { - check bool - count int -} - -// RefCounter is a generic counter for use by graphdriver Get/Put calls -type RefCounter struct { - counts map[string]*minfo - mu sync.Mutex - checker Checker -} - -// NewRefCounter returns a new RefCounter -func NewRefCounter(c Checker) *RefCounter { - return &RefCounter{ - checker: c, - counts: make(map[string]*minfo), - } -} - -// Increment increases the ref count for the given id and returns the current count -func (c *RefCounter) Increment(path string) int { - return c.incdec(path, func(minfo *minfo) { - minfo.count++ - }) -} - -// Decrement decreases the ref count for the given id and returns the current count -func (c *RefCounter) Decrement(path string) int { - return c.incdec(path, func(minfo *minfo) { - minfo.count-- - }) -} - -func (c *RefCounter) incdec(path string, infoOp func(minfo *minfo)) int { - c.mu.Lock() - m := c.counts[path] - if m == nil { - m = &minfo{} - c.counts[path] = m - } - // if we are checking this path for the first time check to make sure - // if it was already mounted on the system and make sure we have a correct ref - // count if it is mounted as it is in use. - if !m.check { - m.check = true - if c.checker.IsMounted(path) { - m.count++ - } - } - infoOp(m) - count := m.count - c.mu.Unlock() - return count -} diff --git a/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go b/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go deleted file mode 100644 index 1430c8859c..0000000000 --- a/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go +++ /dev/null @@ -1,236 +0,0 @@ -package devmapper - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "reflect" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -type directLVMConfig struct { - Device string - ThinpPercent uint64 - ThinpMetaPercent uint64 - AutoExtendPercent uint64 - AutoExtendThreshold uint64 -} - -var ( - errThinpPercentMissing = errors.New("must set both `dm.thinp_percent` and `dm.thinp_metapercent` if either is specified") - errThinpPercentTooBig = errors.New("combined `dm.thinp_percent` and `dm.thinp_metapercent` must not be greater than 100") - errMissingSetupDevice = errors.New("must provide device path in `dm.setup_device` in order to configure direct-lvm") -) - -func validateLVMConfig(cfg directLVMConfig) error { - if reflect.DeepEqual(cfg, directLVMConfig{}) { - return nil - } - if cfg.Device == "" { - return errMissingSetupDevice - } - if (cfg.ThinpPercent > 0 && cfg.ThinpMetaPercent == 0) || cfg.ThinpMetaPercent > 0 && cfg.ThinpPercent == 0 { - return errThinpPercentMissing - } - - if cfg.ThinpPercent+cfg.ThinpMetaPercent > 100 { - return errThinpPercentTooBig - } - return nil -} - -func checkDevAvailable(dev string) error { - lvmScan, err := exec.LookPath("lvmdiskscan") - if err != nil { - logrus.Debug("could not find lvmdiskscan") - return nil - } - - out, err := exec.Command(lvmScan).CombinedOutput() - if err != nil { - logrus.WithError(err).Error(string(out)) - return nil - } - - if !bytes.Contains(out, []byte(dev)) { - return errors.Errorf("%s is not available for use with devicemapper", dev) - } - return nil -} - -func checkDevInVG(dev string) error { - pvDisplay, err := exec.LookPath("pvdisplay") - if err != nil { - logrus.Debug("could not find pvdisplay") - return nil - } - - out, err := exec.Command(pvDisplay, dev).CombinedOutput() - if err != nil { - logrus.WithError(err).Error(string(out)) - return nil - } - - scanner := bufio.NewScanner(bytes.NewReader(bytes.TrimSpace(out))) - for scanner.Scan() { - fields := strings.SplitAfter(strings.TrimSpace(scanner.Text()), "VG Name") - if len(fields) > 1 { - // got "VG Name" line" - vg := strings.TrimSpace(fields[1]) - if len(vg) > 0 { - return errors.Errorf("%s is already part of a volume group %q: must remove this device from any volume group or provide a different device", dev, vg) - } - logrus.Error(fields) - break - } - } - return nil -} - -func checkDevHasFS(dev string) error { - blkid, err := exec.LookPath("blkid") - if err != nil { - logrus.Debug("could not find blkid") - return nil - } - - out, err := exec.Command(blkid, dev).CombinedOutput() - if err != nil { - logrus.WithError(err).Error(string(out)) - return nil - } - - fields := bytes.Fields(out) - for _, f := range fields { - kv := bytes.Split(f, []byte{'='}) - if bytes.Equal(kv[0], []byte("TYPE")) { - v := bytes.Trim(kv[1], "\"") - if len(v) > 0 { - return errors.Errorf("%s has a filesystem already, use dm.directlvm_device_force=true if you want to wipe the device", dev) - } - return nil - } - } - return nil -} - -func verifyBlockDevice(dev string, force bool) error { - if err := checkDevAvailable(dev); err != nil { - return err - } - if err := checkDevInVG(dev); err != nil { - return err - } - - if force { - return nil - } - - if err := checkDevHasFS(dev); err != nil { - return err - } - return nil -} - -func readLVMConfig(root string) (directLVMConfig, error) { - var cfg directLVMConfig - - p := filepath.Join(root, "setup-config.json") - b, err := ioutil.ReadFile(p) - if err != nil { - if os.IsNotExist(err) { - return cfg, nil - } - return cfg, errors.Wrap(err, "error reading existing setup config") - } - - // check if this is just an empty file, no need to produce a json error later if so - if len(b) == 0 { - return cfg, nil - } - - err = json.Unmarshal(b, &cfg) - return cfg, errors.Wrap(err, "error unmarshaling previous device setup config") -} - -func writeLVMConfig(root string, cfg directLVMConfig) error { - p := filepath.Join(root, "setup-config.json") - b, err := json.Marshal(cfg) - if err != nil { - return errors.Wrap(err, "error marshalling direct lvm config") - } - err = ioutil.WriteFile(p, b, 0600) - return errors.Wrap(err, "error writing direct lvm config to file") -} - -func setupDirectLVM(cfg directLVMConfig) error { - lvmProfileDir := "/etc/lvm/profile" - binaries := []string{"pvcreate", "vgcreate", "lvcreate", "lvconvert", "lvchange", "thin_check"} - - for _, bin := range binaries { - if _, err := exec.LookPath(bin); err != nil { - return errors.Wrap(err, "error looking up command `"+bin+"` while setting up direct lvm") - } - } - - err := os.MkdirAll(lvmProfileDir, 0755) - if err != nil { - return errors.Wrap(err, "error creating lvm profile directory") - } - - if cfg.AutoExtendPercent == 0 { - cfg.AutoExtendPercent = 20 - } - - if cfg.AutoExtendThreshold == 0 { - cfg.AutoExtendThreshold = 80 - } - - if cfg.ThinpPercent == 0 { - cfg.ThinpPercent = 95 - } - if cfg.ThinpMetaPercent == 0 { - cfg.ThinpMetaPercent = 1 - } - - out, err := exec.Command("pvcreate", "-f", cfg.Device).CombinedOutput() - if err != nil { - return errors.Wrap(err, string(out)) - } - - out, err = exec.Command("vgcreate", "storage", cfg.Device).CombinedOutput() - if err != nil { - return errors.Wrap(err, string(out)) - } - - out, err = exec.Command("lvcreate", "--wipesignatures", "y", "-n", "thinpool", "storage", "--extents", fmt.Sprintf("%d%%VG", cfg.ThinpPercent)).CombinedOutput() - if err != nil { - return errors.Wrap(err, string(out)) - } - out, err = exec.Command("lvcreate", "--wipesignatures", "y", "-n", "thinpoolmeta", "storage", "--extents", fmt.Sprintf("%d%%VG", cfg.ThinpMetaPercent)).CombinedOutput() - if err != nil { - return errors.Wrap(err, string(out)) - } - - out, err = exec.Command("lvconvert", "-y", "--zero", "n", "-c", "512K", "--thinpool", "storage/thinpool", "--poolmetadata", "storage/thinpoolmeta").CombinedOutput() - if err != nil { - return errors.Wrap(err, string(out)) - } - - profile := fmt.Sprintf("activation{\nthin_pool_autoextend_threshold=%d\nthin_pool_autoextend_percent=%d\n}", cfg.AutoExtendThreshold, cfg.AutoExtendPercent) - err = ioutil.WriteFile(lvmProfileDir+"/storage-thinpool.profile", []byte(profile), 0600) - if err != nil { - return errors.Wrap(err, "error writing storage thinp autoextend profile") - } - - out, err = exec.Command("lvchange", "--metadataprofile", "storage-thinpool", "storage/thinpool").CombinedOutput() - return errors.Wrap(err, string(out)) -} diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go deleted file mode 100644 index 6db7b2b2c9..0000000000 --- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go +++ /dev/null @@ -1,2825 +0,0 @@ -// +build linux - -package devmapper - -import ( - "bufio" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "reflect" - "strconv" - "strings" - "sync" - "time" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/devicemapper" - "github.com/containers/storage/pkg/dmesg" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/loopback" - "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/parsers" - "github.com/containers/storage/pkg/parsers/kernel" - units "github.com/docker/go-units" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -var ( - defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024 - defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024 - defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024 - defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors - defaultUdevSyncOverride = false - maxDeviceID = 0xffffff // 24 bit, pool limit - deviceIDMapSz = (maxDeviceID + 1) / 8 - driverDeferredRemovalSupport = false - enableDeferredRemoval = false - enableDeferredDeletion = false - userBaseSize = false - defaultMinFreeSpacePercent uint32 = 10 - lvmSetupConfigForce bool -) - -const deviceSetMetaFile string = "deviceset-metadata" -const transactionMetaFile string = "transaction-metadata" - -type transaction struct { - OpenTransactionID uint64 `json:"open_transaction_id"` - DeviceIDHash string `json:"device_hash"` - DeviceID int `json:"device_id"` -} - -type devInfo struct { - Hash string `json:"-"` - DeviceID int `json:"device_id"` - Size uint64 `json:"size"` - TransactionID uint64 `json:"transaction_id"` - Initialized bool `json:"initialized"` - Deleted bool `json:"deleted"` - devices *DeviceSet - - // The global DeviceSet lock guarantees that we serialize all - // the calls to libdevmapper (which is not threadsafe), but we - // sometimes release that lock while sleeping. In that case - // this per-device lock is still held, protecting against - // other accesses to the device that we're doing the wait on. - // - // WARNING: In order to avoid AB-BA deadlocks when releasing - // the global lock while holding the per-device locks all - // device locks must be acquired *before* the device lock, and - // multiple device locks should be acquired parent before child. - lock sync.Mutex -} - -type metaData struct { - Devices map[string]*devInfo `json:"Devices"` -} - -// DeviceSet holds information about list of devices -type DeviceSet struct { - metaData `json:"-"` - sync.Mutex `json:"-"` // Protects all fields of DeviceSet and serializes calls into libdevmapper - root string - devicePrefix string - TransactionID uint64 `json:"-"` - NextDeviceID int `json:"next_device_id"` - deviceIDMap []byte - - // Options - dataLoopbackSize int64 - metaDataLoopbackSize int64 - baseFsSize uint64 - filesystem string - mountOptions string - mkfsArgs []string - dataDevice string // block or loop dev - dataLoopFile string // loopback file, if used - metadataDevice string // block or loop dev - metadataLoopFile string // loopback file, if used - doBlkDiscard bool - thinpBlockSize uint32 - thinPoolDevice string - transaction `json:"-"` - overrideUdevSyncCheck bool - deferredRemove bool // use deferred removal - deferredDelete bool // use deferred deletion - BaseDeviceUUID string // save UUID of base device - BaseDeviceFilesystem string // save filesystem of base device - nrDeletedDevices uint // number of deleted devices - deletionWorkerTicker *time.Ticker - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - minFreeSpacePercent uint32 //min free space percentage in thinpool - xfsNospaceRetries string // max retries when xfs receives ENOSPC - lvmSetupConfig directLVMConfig -} - -// DiskUsage contains information about disk usage and is used when reporting Status of a device. -type DiskUsage struct { - // Used bytes on the disk. - Used uint64 - // Total bytes on the disk. - Total uint64 - // Available bytes on the disk. - Available uint64 -} - -// Status returns the information about the device. -type Status struct { - // PoolName is the name of the data pool. - PoolName string - // DataFile is the actual block device for data. - DataFile string - // DataLoopback loopback file, if used. - DataLoopback string - // MetadataFile is the actual block device for metadata. - MetadataFile string - // MetadataLoopback is the loopback file, if used. - MetadataLoopback string - // Data is the disk used for data. - Data DiskUsage - // Metadata is the disk used for meta data. - Metadata DiskUsage - // BaseDeviceSize is base size of container and image - BaseDeviceSize uint64 - // BaseDeviceFS is backing filesystem. - BaseDeviceFS string - // SectorSize size of the vector. - SectorSize uint64 - // UdevSyncSupported is true if sync is supported. - UdevSyncSupported bool - // DeferredRemoveEnabled is true then the device is not unmounted. - DeferredRemoveEnabled bool - // True if deferred deletion is enabled. This is different from - // deferred removal. "removal" means that device mapper device is - // deactivated. Thin device is still in thin pool and can be activated - // again. But "deletion" means that thin device will be deleted from - // thin pool and it can't be activated again. - DeferredDeleteEnabled bool - DeferredDeletedDeviceCount uint - MinFreeSpace uint64 -} - -// Structure used to export image/container metadata in inspect. -type deviceMetadata struct { - deviceID int - deviceSize uint64 // size in bytes - deviceName string // Device name as used during activation -} - -// DevStatus returns information about device mounted containing its id, size and sector information. -type DevStatus struct { - // DeviceID is the id of the device. - DeviceID int - // Size is the size of the filesystem. - Size uint64 - // TransactionID is a unique integer per device set used to identify an operation on the file system, this number is incremental. - TransactionID uint64 - // SizeInSectors indicates the size of the sectors allocated. - SizeInSectors uint64 - // MappedSectors indicates number of mapped sectors. - MappedSectors uint64 - // HighestMappedSector is the pointer to the highest mapped sector. - HighestMappedSector uint64 -} - -func getDevName(name string) string { - return "/dev/mapper/" + name -} - -func (info *devInfo) Name() string { - hash := info.Hash - if hash == "" { - hash = "base" - } - return fmt.Sprintf("%s-%s", info.devices.devicePrefix, hash) -} - -func (info *devInfo) DevName() string { - return getDevName(info.Name()) -} - -func (devices *DeviceSet) loopbackDir() string { - return path.Join(devices.root, "devicemapper") -} - -func (devices *DeviceSet) metadataDir() string { - return path.Join(devices.root, "metadata") -} - -func (devices *DeviceSet) metadataFile(info *devInfo) string { - file := info.Hash - if file == "" { - file = "base" - } - return path.Join(devices.metadataDir(), file) -} - -func (devices *DeviceSet) transactionMetaFile() string { - return path.Join(devices.metadataDir(), transactionMetaFile) -} - -func (devices *DeviceSet) deviceSetMetaFile() string { - return path.Join(devices.metadataDir(), deviceSetMetaFile) -} - -func (devices *DeviceSet) oldMetadataFile() string { - return path.Join(devices.loopbackDir(), "json") -} - -func (devices *DeviceSet) getPoolName() string { - if devices.thinPoolDevice == "" { - return devices.devicePrefix + "-pool" - } - return devices.thinPoolDevice -} - -func (devices *DeviceSet) getPoolDevName() string { - return getDevName(devices.getPoolName()) -} - -func (devices *DeviceSet) hasImage(name string) bool { - dirname := devices.loopbackDir() - filename := path.Join(dirname, name) - - _, err := os.Stat(filename) - return err == nil -} - -// ensureImage creates a sparse file of bytes at the path -// /devicemapper/. -// If the file already exists and new size is larger than its current size, it grows to the new size. -// Either way it returns the full path. -func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) { - dirname := devices.loopbackDir() - filename := path.Join(dirname, name) - - uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps) - if err != nil { - return "", err - } - if err := idtools.MkdirAllAs(dirname, 0700, uid, gid); err != nil && !os.IsExist(err) { - return "", err - } - - if fi, err := os.Stat(filename); err != nil { - if !os.IsNotExist(err) { - return "", err - } - logrus.Debugf("devmapper: Creating loopback file %s for device-manage use", filename) - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return "", err - } - defer file.Close() - - if err := file.Truncate(size); err != nil { - return "", err - } - } else { - if fi.Size() < size { - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return "", err - } - defer file.Close() - if err := file.Truncate(size); err != nil { - return "", fmt.Errorf("devmapper: Unable to grow loopback file %s: %v", filename, err) - } - } else if fi.Size() > size { - logrus.Warnf("devmapper: Can't shrink loopback file %s", filename) - } - } - return filename, nil -} - -func (devices *DeviceSet) allocateTransactionID() uint64 { - devices.OpenTransactionID = devices.TransactionID + 1 - return devices.OpenTransactionID -} - -func (devices *DeviceSet) updatePoolTransactionID() error { - if err := devicemapper.SetTransactionID(devices.getPoolDevName(), devices.TransactionID, devices.OpenTransactionID); err != nil { - return fmt.Errorf("devmapper: Error setting devmapper transaction ID: %s", err) - } - devices.TransactionID = devices.OpenTransactionID - return nil -} - -func (devices *DeviceSet) removeMetadata(info *devInfo) error { - if err := os.RemoveAll(devices.metadataFile(info)); err != nil { - return fmt.Errorf("devmapper: Error removing metadata file %s: %s", devices.metadataFile(info), err) - } - return nil -} - -// Given json data and file path, write it to disk -func (devices *DeviceSet) writeMetaFile(jsonData []byte, filePath string) error { - tmpFile, err := ioutil.TempFile(devices.metadataDir(), ".tmp") - if err != nil { - return fmt.Errorf("devmapper: Error creating metadata file: %s", err) - } - - n, err := tmpFile.Write(jsonData) - if err != nil { - return fmt.Errorf("devmapper: Error writing metadata to %s: %s", tmpFile.Name(), err) - } - if n < len(jsonData) { - return io.ErrShortWrite - } - if err := tmpFile.Sync(); err != nil { - return fmt.Errorf("devmapper: Error syncing metadata file %s: %s", tmpFile.Name(), err) - } - if err := tmpFile.Close(); err != nil { - return fmt.Errorf("devmapper: Error closing metadata file %s: %s", tmpFile.Name(), err) - } - if err := os.Rename(tmpFile.Name(), filePath); err != nil { - return fmt.Errorf("devmapper: Error committing metadata file %s: %s", tmpFile.Name(), err) - } - - return nil -} - -func (devices *DeviceSet) saveMetadata(info *devInfo) error { - jsonData, err := json.Marshal(info) - if err != nil { - return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) - } - if err := devices.writeMetaFile(jsonData, devices.metadataFile(info)); err != nil { - return err - } - return nil -} - -func (devices *DeviceSet) markDeviceIDUsed(deviceID int) { - var mask byte - i := deviceID % 8 - mask = 1 << uint(i) - devices.deviceIDMap[deviceID/8] = devices.deviceIDMap[deviceID/8] | mask -} - -func (devices *DeviceSet) markDeviceIDFree(deviceID int) { - var mask byte - i := deviceID % 8 - mask = ^(1 << uint(i)) - devices.deviceIDMap[deviceID/8] = devices.deviceIDMap[deviceID/8] & mask -} - -func (devices *DeviceSet) isDeviceIDFree(deviceID int) bool { - var mask byte - i := deviceID % 8 - mask = (1 << uint(i)) - return (devices.deviceIDMap[deviceID/8] & mask) == 0 -} - -// Should be called with devices.Lock() held. -func (devices *DeviceSet) lookupDevice(hash string) (*devInfo, error) { - info := devices.Devices[hash] - if info == nil { - info = devices.loadMetadata(hash) - if info == nil { - return nil, fmt.Errorf("devmapper: Unknown device %s", hash) - } - - devices.Devices[hash] = info - } - return info, nil -} - -func (devices *DeviceSet) lookupDeviceWithLock(hash string) (*devInfo, error) { - devices.Lock() - defer devices.Unlock() - info, err := devices.lookupDevice(hash) - return info, err -} - -// This function relies on that device hash map has been loaded in advance. -// Should be called with devices.Lock() held. -func (devices *DeviceSet) constructDeviceIDMap() { - logrus.Debug("devmapper: constructDeviceIDMap()") - defer logrus.Debug("devmapper: constructDeviceIDMap() END") - - for _, info := range devices.Devices { - devices.markDeviceIDUsed(info.DeviceID) - logrus.Debugf("devmapper: Added deviceId=%d to DeviceIdMap", info.DeviceID) - } -} - -func (devices *DeviceSet) deviceFileWalkFunction(path string, finfo os.FileInfo) error { - - // Skip some of the meta files which are not device files. - if strings.HasSuffix(finfo.Name(), ".migrated") { - logrus.Debugf("devmapper: Skipping file %s", path) - return nil - } - - if strings.HasPrefix(finfo.Name(), ".") { - logrus.Debugf("devmapper: Skipping file %s", path) - return nil - } - - if finfo.Name() == deviceSetMetaFile { - logrus.Debugf("devmapper: Skipping file %s", path) - return nil - } - - if finfo.Name() == transactionMetaFile { - logrus.Debugf("devmapper: Skipping file %s", path) - return nil - } - - logrus.Debugf("devmapper: Loading data for file %s", path) - - hash := finfo.Name() - if hash == "base" { - hash = "" - } - - // Include deleted devices also as cleanup delete device logic - // will go through it and see if there are any deleted devices. - if _, err := devices.lookupDevice(hash); err != nil { - return fmt.Errorf("devmapper: Error looking up device %s:%v", hash, err) - } - - return nil -} - -func (devices *DeviceSet) loadDeviceFilesOnStart() error { - logrus.Debug("devmapper: loadDeviceFilesOnStart()") - defer logrus.Debug("devmapper: loadDeviceFilesOnStart() END") - - var scan = func(path string, info os.FileInfo, err error) error { - if err != nil { - logrus.Debugf("devmapper: Can't walk the file %s", path) - return nil - } - - // Skip any directories - if info.IsDir() { - return nil - } - - return devices.deviceFileWalkFunction(path, info) - } - - return filepath.Walk(devices.metadataDir(), scan) -} - -// Should be called with devices.Lock() held. -func (devices *DeviceSet) unregisterDevice(hash string) error { - logrus.Debugf("devmapper: unregisterDevice(%v)", hash) - info := &devInfo{ - Hash: hash, - } - - delete(devices.Devices, hash) - - if err := devices.removeMetadata(info); err != nil { - logrus.Debugf("devmapper: Error removing metadata: %s", err) - return err - } - - return nil -} - -// Should be called with devices.Lock() held. -func (devices *DeviceSet) registerDevice(id int, hash string, size uint64, transactionID uint64) (*devInfo, error) { - logrus.Debugf("devmapper: registerDevice(%v, %v)", id, hash) - info := &devInfo{ - Hash: hash, - DeviceID: id, - Size: size, - TransactionID: transactionID, - Initialized: false, - devices: devices, - } - - devices.Devices[hash] = info - - if err := devices.saveMetadata(info); err != nil { - // Try to remove unused device - delete(devices.Devices, hash) - return nil, err - } - - return info, nil -} - -func (devices *DeviceSet) activateDeviceIfNeeded(info *devInfo, ignoreDeleted bool) error { - logrus.Debugf("devmapper: activateDeviceIfNeeded(%v)", info.Hash) - - if info.Deleted && !ignoreDeleted { - return fmt.Errorf("devmapper: Can't activate device %v as it is marked for deletion", info.Hash) - } - - // Make sure deferred removal on device is canceled, if one was - // scheduled. - if err := devices.cancelDeferredRemovalIfNeeded(info); err != nil { - return fmt.Errorf("devmapper: Device Deferred Removal Cancellation Failed: %s", err) - } - - if devinfo, _ := devicemapper.GetInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 { - return nil - } - - return devicemapper.ActivateDevice(devices.getPoolDevName(), info.Name(), info.DeviceID, info.Size) -} - -// xfsSupported checks if xfs is supported, returns nil if it is, otherwise an error -func xfsSupported() error { - // Make sure mkfs.xfs is available - if _, err := exec.LookPath("mkfs.xfs"); err != nil { - return err // error text is descriptive enough - } - - // Check if kernel supports xfs filesystem or not. - exec.Command("modprobe", "xfs").Run() - - f, err := os.Open("/proc/filesystems") - if err != nil { - return errors.Wrapf(err, "error checking for xfs support") - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - if strings.HasSuffix(s.Text(), "\txfs") { - return nil - } - } - - if err := s.Err(); err != nil { - return errors.Wrapf(err, "error checking for xfs support") - } - - return errors.New(`kernel does not support xfs, or "modprobe xfs" failed`) -} - -func determineDefaultFS() string { - err := xfsSupported() - if err == nil { - return "xfs" - } - - logrus.Warnf("devmapper: XFS is not supported in your system (%v). Defaulting to ext4 filesystem", err) - return "ext4" -} - -// mkfsOptions tries to figure out whether some additional mkfs options are required -func mkfsOptions(fs string) []string { - if fs == "xfs" && !kernel.CheckKernelVersion(3, 16, 0) { - // For kernels earlier than 3.16 (and newer xfsutils), - // some xfs features need to be explicitly disabled. - return []string{"-m", "crc=0,finobt=0"} - } - - return []string{} -} - -func (devices *DeviceSet) createFilesystem(info *devInfo) (err error) { - devname := info.DevName() - - if devices.filesystem == "" { - devices.filesystem = determineDefaultFS() - } - if err := devices.saveBaseDeviceFilesystem(devices.filesystem); err != nil { - return err - } - - args := mkfsOptions(devices.filesystem) - args = append(args, devices.mkfsArgs...) - args = append(args, devname) - - logrus.Infof("devmapper: Creating filesystem %s on device %s, mkfs args: %v", devices.filesystem, info.Name(), args) - defer func() { - if err != nil { - logrus.Infof("devmapper: Error while creating filesystem %s on device %s: %v", devices.filesystem, info.Name(), err) - } else { - logrus.Infof("devmapper: Successfully created filesystem %s on device %s", devices.filesystem, info.Name()) - } - }() - - switch devices.filesystem { - case "xfs": - err = exec.Command("mkfs.xfs", args...).Run() - case "ext4": - err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0"}, args...)...).Run() - if err != nil { - err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0"}, args...)...).Run() - } - if err != nil { - return err - } - err = exec.Command("tune2fs", append([]string{"-c", "-1", "-i", "0"}, devname)...).Run() - default: - err = fmt.Errorf("devmapper: Unsupported filesystem type %s", devices.filesystem) - } - return -} - -func (devices *DeviceSet) migrateOldMetaData() error { - // Migrate old metadata file - jsonData, err := ioutil.ReadFile(devices.oldMetadataFile()) - if err != nil && !os.IsNotExist(err) { - return err - } - - if jsonData != nil { - m := metaData{Devices: make(map[string]*devInfo)} - - if err := json.Unmarshal(jsonData, &m); err != nil { - return err - } - - for hash, info := range m.Devices { - info.Hash = hash - devices.saveMetadata(info) - } - if err := os.Rename(devices.oldMetadataFile(), devices.oldMetadataFile()+".migrated"); err != nil { - return err - } - - } - - return nil -} - -// Cleanup deleted devices. It assumes that all the devices have been -// loaded in the hash table. -func (devices *DeviceSet) cleanupDeletedDevices() error { - devices.Lock() - - // If there are no deleted devices, there is nothing to do. - if devices.nrDeletedDevices == 0 { - devices.Unlock() - return nil - } - - var deletedDevices []*devInfo - - for _, info := range devices.Devices { - if !info.Deleted { - continue - } - logrus.Debugf("devmapper: Found deleted device %s.", info.Hash) - deletedDevices = append(deletedDevices, info) - } - - // Delete the deleted devices. DeleteDevice() first takes the info lock - // and then devices.Lock(). So drop it to avoid deadlock. - devices.Unlock() - - for _, info := range deletedDevices { - // This will again try deferred deletion. - if err := devices.DeleteDevice(info.Hash, false); err != nil { - logrus.Warnf("devmapper: Deletion of device %s, device_id=%v failed:%v", info.Hash, info.DeviceID, err) - } - } - - return nil -} - -func (devices *DeviceSet) countDeletedDevices() { - for _, info := range devices.Devices { - if !info.Deleted { - continue - } - devices.nrDeletedDevices++ - } -} - -func (devices *DeviceSet) startDeviceDeletionWorker() { - // Deferred deletion is not enabled. Don't do anything. - if !devices.deferredDelete { - return - } - - logrus.Debug("devmapper: Worker to cleanup deleted devices started") - for range devices.deletionWorkerTicker.C { - devices.cleanupDeletedDevices() - } -} - -func (devices *DeviceSet) initMetaData() error { - devices.Lock() - defer devices.Unlock() - - if err := devices.migrateOldMetaData(); err != nil { - return err - } - - _, transactionID, _, _, _, _, err := devices.poolStatus() - if err != nil { - return err - } - - devices.TransactionID = transactionID - - if err := devices.loadDeviceFilesOnStart(); err != nil { - return fmt.Errorf("devmapper: Failed to load device files:%v", err) - } - - devices.constructDeviceIDMap() - devices.countDeletedDevices() - - if err := devices.processPendingTransaction(); err != nil { - return err - } - - // Start a goroutine to cleanup Deleted Devices - go devices.startDeviceDeletionWorker() - return nil -} - -func (devices *DeviceSet) incNextDeviceID() { - // IDs are 24bit, so wrap around - devices.NextDeviceID = (devices.NextDeviceID + 1) & maxDeviceID -} - -func (devices *DeviceSet) getNextFreeDeviceID() (int, error) { - devices.incNextDeviceID() - for i := 0; i <= maxDeviceID; i++ { - if devices.isDeviceIDFree(devices.NextDeviceID) { - devices.markDeviceIDUsed(devices.NextDeviceID) - return devices.NextDeviceID, nil - } - devices.incNextDeviceID() - } - - return 0, fmt.Errorf("devmapper: Unable to find a free device ID") -} - -func (devices *DeviceSet) poolHasFreeSpace() error { - if devices.minFreeSpacePercent == 0 { - return nil - } - - _, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus() - if err != nil { - return err - } - - minFreeData := (dataTotal * uint64(devices.minFreeSpacePercent)) / 100 - if minFreeData < 1 { - minFreeData = 1 - } - dataFree := dataTotal - dataUsed - if dataFree < minFreeData { - return fmt.Errorf("devmapper: Thin Pool has %v free data blocks which is less than minimum required %v free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior", (dataTotal - dataUsed), minFreeData) - } - - minFreeMetadata := (metadataTotal * uint64(devices.minFreeSpacePercent)) / 100 - if minFreeMetadata < 1 { - minFreeMetadata = 1 - } - - metadataFree := metadataTotal - metadataUsed - if metadataFree < minFreeMetadata { - return fmt.Errorf("devmapper: Thin Pool has %v free metadata blocks which is less than minimum required %v free metadata blocks. Create more free metadata space in thin pool or use dm.min_free_space option to change behavior", (metadataTotal - metadataUsed), minFreeMetadata) - } - - return nil -} - -func (devices *DeviceSet) createRegisterDevice(hash string) (*devInfo, error) { - devices.Lock() - defer devices.Unlock() - - deviceID, err := devices.getNextFreeDeviceID() - if err != nil { - return nil, err - } - - if err := devices.openTransaction(hash, deviceID); err != nil { - logrus.Debugf("devmapper: Error opening transaction hash = %s deviceID = %d", hash, deviceID) - devices.markDeviceIDFree(deviceID) - return nil, err - } - - for { - if err := devicemapper.CreateDevice(devices.getPoolDevName(), deviceID); err != nil { - if devicemapper.DeviceIDExists(err) { - // Device ID already exists. This should not - // happen. Now we have a mechanism to find - // a free device ID. So something is not right. - // Give a warning and continue. - logrus.Errorf("devmapper: Device ID %d exists in pool but it is supposed to be unused", deviceID) - deviceID, err = devices.getNextFreeDeviceID() - if err != nil { - return nil, err - } - // Save new device id into transaction - devices.refreshTransaction(deviceID) - continue - } - logrus.Debugf("devmapper: Error creating device: %s", err) - devices.markDeviceIDFree(deviceID) - return nil, err - } - break - } - - logrus.Debugf("devmapper: Registering device (id %v) with FS size %v", deviceID, devices.baseFsSize) - info, err := devices.registerDevice(deviceID, hash, devices.baseFsSize, devices.OpenTransactionID) - if err != nil { - _ = devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) - devices.markDeviceIDFree(deviceID) - return nil, err - } - - if err := devices.closeTransaction(); err != nil { - devices.unregisterDevice(hash) - devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) - devices.markDeviceIDFree(deviceID) - return nil, err - } - return info, nil -} - -func (devices *DeviceSet) takeSnapshot(hash string, baseInfo *devInfo, size uint64) error { - var ( - devinfo *devicemapper.Info - err error - ) - - if err = devices.poolHasFreeSpace(); err != nil { - return err - } - - if devices.deferredRemove { - devinfo, err = devicemapper.GetInfoWithDeferred(baseInfo.Name()) - if err != nil { - return err - } - if devinfo != nil && devinfo.DeferredRemove != 0 { - err = devices.cancelDeferredRemoval(baseInfo) - if err != nil { - // If Error is ErrEnxio. Device is probably already gone. Continue. - if errors.Cause(err) != devicemapper.ErrEnxio { - return err - } - devinfo = nil - } else { - defer devices.deactivateDevice(baseInfo) - } - } - } else { - devinfo, err = devicemapper.GetInfo(baseInfo.Name()) - if err != nil { - return err - } - } - - doSuspend := devinfo != nil && devinfo.Exists != 0 - - if doSuspend { - if err = devicemapper.SuspendDevice(baseInfo.Name()); err != nil { - return err - } - defer devicemapper.ResumeDevice(baseInfo.Name()) - } - - if err = devices.createRegisterSnapDevice(hash, baseInfo, size); err != nil { - return err - } - - return nil -} - -func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *devInfo, size uint64) error { - deviceID, err := devices.getNextFreeDeviceID() - if err != nil { - return err - } - - if err := devices.openTransaction(hash, deviceID); err != nil { - logrus.Debugf("devmapper: Error opening transaction hash = %s deviceID = %d", hash, deviceID) - devices.markDeviceIDFree(deviceID) - return err - } - - for { - if err := devicemapper.CreateSnapDeviceRaw(devices.getPoolDevName(), deviceID, baseInfo.DeviceID); err != nil { - if devicemapper.DeviceIDExists(err) { - // Device ID already exists. This should not - // happen. Now we have a mechanism to find - // a free device ID. So something is not right. - // Give a warning and continue. - logrus.Errorf("devmapper: Device ID %d exists in pool but it is supposed to be unused", deviceID) - deviceID, err = devices.getNextFreeDeviceID() - if err != nil { - return err - } - // Save new device id into transaction - devices.refreshTransaction(deviceID) - continue - } - logrus.Debugf("devmapper: Error creating snap device: %s", err) - devices.markDeviceIDFree(deviceID) - return err - } - break - } - - if _, err := devices.registerDevice(deviceID, hash, size, devices.OpenTransactionID); err != nil { - devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) - devices.markDeviceIDFree(deviceID) - logrus.Debugf("devmapper: Error registering device: %s", err) - return err - } - - if err := devices.closeTransaction(); err != nil { - devices.unregisterDevice(hash) - devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) - devices.markDeviceIDFree(deviceID) - return err - } - return nil -} - -func (devices *DeviceSet) loadMetadata(hash string) *devInfo { - info := &devInfo{Hash: hash, devices: devices} - - jsonData, err := ioutil.ReadFile(devices.metadataFile(info)) - if err != nil { - logrus.Debugf("devmapper: Failed to read %s with err: %v", devices.metadataFile(info), err) - return nil - } - - if err := json.Unmarshal(jsonData, &info); err != nil { - logrus.Debugf("devmapper: Failed to unmarshal devInfo from %s with err: %v", devices.metadataFile(info), err) - return nil - } - - if info.DeviceID > maxDeviceID { - logrus.Errorf("devmapper: Ignoring Invalid DeviceId=%d", info.DeviceID) - return nil - } - - return info -} - -func getDeviceUUID(device string) (string, error) { - out, err := exec.Command("blkid", "-s", "UUID", "-o", "value", device).Output() - if err != nil { - return "", fmt.Errorf("devmapper: Failed to find uuid for device %s:%v", device, err) - } - - uuid := strings.TrimSuffix(string(out), "\n") - uuid = strings.TrimSpace(uuid) - logrus.Debugf("devmapper: UUID for device: %s is:%s", device, uuid) - return uuid, nil -} - -func (devices *DeviceSet) getBaseDeviceSize() uint64 { - info, _ := devices.lookupDevice("") - if info == nil { - return 0 - } - return info.Size -} - -func (devices *DeviceSet) getBaseDeviceFS() string { - return devices.BaseDeviceFilesystem -} - -func (devices *DeviceSet) verifyBaseDeviceUUIDFS(baseInfo *devInfo) error { - devices.Lock() - defer devices.Unlock() - - if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil { - return err - } - defer devices.deactivateDevice(baseInfo) - - uuid, err := getDeviceUUID(baseInfo.DevName()) - if err != nil { - return err - } - - if devices.BaseDeviceUUID != uuid { - return fmt.Errorf("devmapper: Current Base Device UUID:%s does not match with stored UUID:%s. Possibly using a different thin pool than last invocation", uuid, devices.BaseDeviceUUID) - } - - if devices.BaseDeviceFilesystem == "" { - fsType, err := ProbeFsType(baseInfo.DevName()) - if err != nil { - return err - } - if err := devices.saveBaseDeviceFilesystem(fsType); err != nil { - return err - } - } - - // If user specified a filesystem using dm.fs option and current - // file system of base image is not same, warn user that dm.fs - // will be ignored. - if devices.BaseDeviceFilesystem != devices.filesystem { - logrus.Warnf("devmapper: Base device already exists and has filesystem %s on it. User specified filesystem %s will be ignored.", devices.BaseDeviceFilesystem, devices.filesystem) - devices.filesystem = devices.BaseDeviceFilesystem - } - return nil -} - -func (devices *DeviceSet) saveBaseDeviceFilesystem(fs string) error { - devices.BaseDeviceFilesystem = fs - return devices.saveDeviceSetMetaData() -} - -func (devices *DeviceSet) saveBaseDeviceUUID(baseInfo *devInfo) error { - devices.Lock() - defer devices.Unlock() - - if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil { - return err - } - defer devices.deactivateDevice(baseInfo) - - uuid, err := getDeviceUUID(baseInfo.DevName()) - if err != nil { - return err - } - - devices.BaseDeviceUUID = uuid - return devices.saveDeviceSetMetaData() -} - -func (devices *DeviceSet) createBaseImage() error { - logrus.Debug("devmapper: Initializing base device-mapper thin volume") - - // Create initial device - info, err := devices.createRegisterDevice("") - if err != nil { - return err - } - - logrus.Debug("devmapper: Creating filesystem on base device-mapper thin volume") - - if err := devices.activateDeviceIfNeeded(info, false); err != nil { - return err - } - - if err := devices.createFilesystem(info); err != nil { - return err - } - - info.Initialized = true - if err := devices.saveMetadata(info); err != nil { - info.Initialized = false - return err - } - - if err := devices.saveBaseDeviceUUID(info); err != nil { - return fmt.Errorf("devmapper: Could not query and save base device UUID:%v", err) - } - - return nil -} - -// Returns if thin pool device exists or not. If device exists, also makes -// sure it is a thin pool device and not some other type of device. -func (devices *DeviceSet) thinPoolExists(thinPoolDevice string) (bool, error) { - logrus.Debugf("devmapper: Checking for existence of the pool %s", thinPoolDevice) - - info, err := devicemapper.GetInfo(thinPoolDevice) - if err != nil { - return false, fmt.Errorf("devmapper: GetInfo() on device %s failed: %v", thinPoolDevice, err) - } - - // Device does not exist. - if info.Exists == 0 { - return false, nil - } - - _, _, deviceType, _, err := devicemapper.GetStatus(thinPoolDevice) - if err != nil { - return false, fmt.Errorf("devmapper: GetStatus() on device %s failed: %v", thinPoolDevice, err) - } - - if deviceType != "thin-pool" { - return false, fmt.Errorf("devmapper: Device %s is not a thin pool", thinPoolDevice) - } - - return true, nil -} - -func (devices *DeviceSet) checkThinPool() error { - _, transactionID, dataUsed, _, _, _, err := devices.poolStatus() - if err != nil { - return err - } - if dataUsed != 0 { - return fmt.Errorf("devmapper: Unable to take ownership of thin-pool (%s) that already has used data blocks", - devices.thinPoolDevice) - } - if transactionID != 0 { - return fmt.Errorf("devmapper: Unable to take ownership of thin-pool (%s) with non-zero transaction ID", - devices.thinPoolDevice) - } - return nil -} - -// Base image is initialized properly. Either save UUID for first time (for -// upgrade case or verify UUID. -func (devices *DeviceSet) setupVerifyBaseImageUUIDFS(baseInfo *devInfo) error { - // If BaseDeviceUUID is nil (upgrade case), save it and return success. - if devices.BaseDeviceUUID == "" { - if err := devices.saveBaseDeviceUUID(baseInfo); err != nil { - return fmt.Errorf("devmapper: Could not query and save base device UUID:%v", err) - } - return nil - } - - if err := devices.verifyBaseDeviceUUIDFS(baseInfo); err != nil { - return fmt.Errorf("devmapper: Base Device UUID and Filesystem verification failed: %v", err) - } - - return nil -} - -func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error { - - if !userBaseSize { - return nil - } - - if devices.baseFsSize < devices.getBaseDeviceSize() { - return fmt.Errorf("devmapper: Base device size cannot be smaller than %s", units.HumanSize(float64(devices.getBaseDeviceSize()))) - } - - if devices.baseFsSize == devices.getBaseDeviceSize() { - return nil - } - - info.lock.Lock() - defer info.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - info.Size = devices.baseFsSize - - if err := devices.saveMetadata(info); err != nil { - // Try to remove unused device - delete(devices.Devices, info.Hash) - return err - } - - return devices.growFS(info) -} - -func (devices *DeviceSet) growFS(info *devInfo) error { - if err := devices.activateDeviceIfNeeded(info, false); err != nil { - return fmt.Errorf("Error activating devmapper device: %s", err) - } - - defer devices.deactivateDevice(info) - - fsMountPoint := "/run/containers/storage/mnt" - if _, err := os.Stat(fsMountPoint); os.IsNotExist(err) { - if err := os.MkdirAll(fsMountPoint, 0700); err != nil { - return err - } - defer os.RemoveAll(fsMountPoint) - } - - options := "" - if devices.BaseDeviceFilesystem == "xfs" { - // XFS needs nouuid or it can't mount filesystems with the same fs - options = joinMountOptions(options, "nouuid") - } - options = joinMountOptions(options, devices.mountOptions) - - if err := mount.Mount(info.DevName(), fsMountPoint, devices.BaseDeviceFilesystem, options); err != nil { - return fmt.Errorf("Error mounting '%s' on '%s': %s\n%v", info.DevName(), fsMountPoint, err, string(dmesg.Dmesg(256))) - } - - defer unix.Unmount(fsMountPoint, unix.MNT_DETACH) - - switch devices.BaseDeviceFilesystem { - case "ext4": - if out, err := exec.Command("resize2fs", info.DevName()).CombinedOutput(); err != nil { - return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out)) - } - case "xfs": - if out, err := exec.Command("xfs_growfs", info.DevName()).CombinedOutput(); err != nil { - return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out)) - } - default: - return fmt.Errorf("Unsupported filesystem type %s", devices.BaseDeviceFilesystem) - } - return nil -} - -func (devices *DeviceSet) setupBaseImage() error { - oldInfo, _ := devices.lookupDeviceWithLock("") - - // base image already exists. If it is initialized properly, do UUID - // verification and return. Otherwise remove image and set it up - // fresh. - - if oldInfo != nil { - if oldInfo.Initialized && !oldInfo.Deleted { - if err := devices.setupVerifyBaseImageUUIDFS(oldInfo); err != nil { - return err - } - - if err := devices.checkGrowBaseDeviceFS(oldInfo); err != nil { - return err - } - - return nil - } - - logrus.Debug("devmapper: Removing uninitialized base image") - // If previous base device is in deferred delete state, - // that needs to be cleaned up first. So don't try - // deferred deletion. - if err := devices.DeleteDevice("", true); err != nil { - return err - } - } - - // If we are setting up base image for the first time, make sure - // thin pool is empty. - if devices.thinPoolDevice != "" && oldInfo == nil { - if err := devices.checkThinPool(); err != nil { - return err - } - } - - // Create new base image device - if err := devices.createBaseImage(); err != nil { - return err - } - - return nil -} - -func setCloseOnExec(name string) { - fileInfos, _ := ioutil.ReadDir("/proc/self/fd") - for _, i := range fileInfos { - link, _ := os.Readlink(filepath.Join("/proc/self/fd", i.Name())) - if link == name { - fd, err := strconv.Atoi(i.Name()) - if err == nil { - unix.CloseOnExec(fd) - } - } - } -} - -func major(device uint64) uint64 { - return (device >> 8) & 0xfff -} - -func minor(device uint64) uint64 { - return (device & 0xff) | ((device >> 12) & 0xfff00) -} - -// ResizePool increases the size of the pool. -func (devices *DeviceSet) ResizePool(size int64) error { - dirname := devices.loopbackDir() - datafilename := path.Join(dirname, "data") - if len(devices.dataDevice) > 0 { - datafilename = devices.dataDevice - } - metadatafilename := path.Join(dirname, "metadata") - if len(devices.metadataDevice) > 0 { - metadatafilename = devices.metadataDevice - } - - datafile, err := os.OpenFile(datafilename, os.O_RDWR, 0) - if datafile == nil { - return err - } - defer datafile.Close() - - fi, err := datafile.Stat() - if fi == nil { - return err - } - - if fi.Size() > size { - return fmt.Errorf("devmapper: Can't shrink file") - } - - dataloopback := loopback.FindLoopDeviceFor(datafile) - if dataloopback == nil { - return fmt.Errorf("devmapper: Unable to find loopback mount for: %s", datafilename) - } - defer dataloopback.Close() - - metadatafile, err := os.OpenFile(metadatafilename, os.O_RDWR, 0) - if metadatafile == nil { - return err - } - defer metadatafile.Close() - - metadataloopback := loopback.FindLoopDeviceFor(metadatafile) - if metadataloopback == nil { - return fmt.Errorf("devmapper: Unable to find loopback mount for: %s", metadatafilename) - } - defer metadataloopback.Close() - - // Grow loopback file - if err := datafile.Truncate(size); err != nil { - return fmt.Errorf("devmapper: Unable to grow loopback file: %s", err) - } - - // Reload size for loopback device - if err := loopback.SetCapacity(dataloopback); err != nil { - return fmt.Errorf("Unable to update loopback capacity: %s", err) - } - - // Suspend the pool - if err := devicemapper.SuspendDevice(devices.getPoolName()); err != nil { - return fmt.Errorf("devmapper: Unable to suspend pool: %s", err) - } - - // Reload with the new block sizes - if err := devicemapper.ReloadPool(devices.getPoolName(), dataloopback, metadataloopback, devices.thinpBlockSize); err != nil { - return fmt.Errorf("devmapper: Unable to reload pool: %s", err) - } - - // Resume the pool - if err := devicemapper.ResumeDevice(devices.getPoolName()); err != nil { - return fmt.Errorf("devmapper: Unable to resume pool: %s", err) - } - - return nil -} - -func (devices *DeviceSet) loadTransactionMetaData() error { - jsonData, err := ioutil.ReadFile(devices.transactionMetaFile()) - if err != nil { - // There is no active transaction. This will be the case - // during upgrade. - if os.IsNotExist(err) { - devices.OpenTransactionID = devices.TransactionID - return nil - } - return err - } - - json.Unmarshal(jsonData, &devices.transaction) - return nil -} - -func (devices *DeviceSet) saveTransactionMetaData() error { - jsonData, err := json.Marshal(&devices.transaction) - if err != nil { - return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) - } - - return devices.writeMetaFile(jsonData, devices.transactionMetaFile()) -} - -func (devices *DeviceSet) removeTransactionMetaData() error { - return os.RemoveAll(devices.transactionMetaFile()) -} - -func (devices *DeviceSet) rollbackTransaction() error { - logrus.Debugf("devmapper: Rolling back open transaction: TransactionID=%d hash=%s device_id=%d", devices.OpenTransactionID, devices.DeviceIDHash, devices.DeviceID) - - // A device id might have already been deleted before transaction - // closed. In that case this call will fail. Just leave a message - // in case of failure. - if err := devicemapper.DeleteDevice(devices.getPoolDevName(), devices.DeviceID); err != nil { - logrus.Errorf("devmapper: Unable to delete device: %s", err) - } - - dinfo := &devInfo{Hash: devices.DeviceIDHash} - if err := devices.removeMetadata(dinfo); err != nil { - logrus.Errorf("devmapper: Unable to remove metadata: %s", err) - } else { - devices.markDeviceIDFree(devices.DeviceID) - } - - if err := devices.removeTransactionMetaData(); err != nil { - logrus.Errorf("devmapper: Unable to remove transaction meta file %s: %s", devices.transactionMetaFile(), err) - } - - return nil -} - -func (devices *DeviceSet) processPendingTransaction() error { - if err := devices.loadTransactionMetaData(); err != nil { - return err - } - - // If there was open transaction but pool transaction ID is same - // as open transaction ID, nothing to roll back. - if devices.TransactionID == devices.OpenTransactionID { - return nil - } - - // If open transaction ID is less than pool transaction ID, something - // is wrong. Bail out. - if devices.OpenTransactionID < devices.TransactionID { - logrus.Errorf("devmapper: Open Transaction id %d is less than pool transaction id %d", devices.OpenTransactionID, devices.TransactionID) - return nil - } - - // Pool transaction ID is not same as open transaction. There is - // a transaction which was not completed. - if err := devices.rollbackTransaction(); err != nil { - return fmt.Errorf("devmapper: Rolling back open transaction failed: %s", err) - } - - devices.OpenTransactionID = devices.TransactionID - return nil -} - -func (devices *DeviceSet) loadDeviceSetMetaData() error { - jsonData, err := ioutil.ReadFile(devices.deviceSetMetaFile()) - if err != nil { - // For backward compatibility return success if file does - // not exist. - if os.IsNotExist(err) { - return nil - } - return err - } - - return json.Unmarshal(jsonData, devices) -} - -func (devices *DeviceSet) saveDeviceSetMetaData() error { - jsonData, err := json.Marshal(devices) - if err != nil { - return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) - } - - return devices.writeMetaFile(jsonData, devices.deviceSetMetaFile()) -} - -func (devices *DeviceSet) openTransaction(hash string, DeviceID int) error { - devices.allocateTransactionID() - devices.DeviceIDHash = hash - devices.DeviceID = DeviceID - if err := devices.saveTransactionMetaData(); err != nil { - return fmt.Errorf("devmapper: Error saving transaction metadata: %s", err) - } - return nil -} - -func (devices *DeviceSet) refreshTransaction(DeviceID int) error { - devices.DeviceID = DeviceID - if err := devices.saveTransactionMetaData(); err != nil { - return fmt.Errorf("devmapper: Error saving transaction metadata: %s", err) - } - return nil -} - -func (devices *DeviceSet) closeTransaction() error { - if err := devices.updatePoolTransactionID(); err != nil { - logrus.Debug("devmapper: Failed to close Transaction") - return err - } - return nil -} - -func determineDriverCapabilities(version string) error { - // Kernel driver version >= 4.27.0 support deferred removal - - logrus.Debugf("devicemapper: kernel dm driver version is %s", version) - - versionSplit := strings.Split(version, ".") - major, err := strconv.Atoi(versionSplit[0]) - if err != nil { - return errors.Wrapf(graphdriver.ErrNotSupported, "unable to parse driver major version %q as a number", versionSplit[0]) - } - - if major > 4 { - driverDeferredRemovalSupport = true - return nil - } - - if major < 4 { - return nil - } - - minor, err := strconv.Atoi(versionSplit[1]) - if err != nil { - return errors.Wrapf(graphdriver.ErrNotSupported, "unable to parse driver minor version %q as a number", versionSplit[1]) - } - - /* - * If major is 4 and minor is 27, then there is no need to - * check for patch level as it can not be less than 0. - */ - if minor >= 27 { - driverDeferredRemovalSupport = true - return nil - } - - return nil -} - -// Determine the major and minor number of loopback device -func getDeviceMajorMinor(file *os.File) (uint64, uint64, error) { - var stat unix.Stat_t - err := unix.Stat(file.Name(), &stat) - if err != nil { - return 0, 0, err - } - - dev := stat.Rdev - majorNum := major(dev) - minorNum := minor(dev) - - logrus.Debugf("devmapper: Major:Minor for device: %s is:%v:%v", file.Name(), majorNum, minorNum) - return majorNum, minorNum, nil -} - -// Given a file which is backing file of a loop back device, find the -// loopback device name and its major/minor number. -func getLoopFileDeviceMajMin(filename string) (string, uint64, uint64, error) { - file, err := os.Open(filename) - if err != nil { - logrus.Debugf("devmapper: Failed to open file %s", filename) - return "", 0, 0, err - } - - defer file.Close() - loopbackDevice := loopback.FindLoopDeviceFor(file) - if loopbackDevice == nil { - return "", 0, 0, fmt.Errorf("devmapper: Unable to find loopback mount for: %s", filename) - } - defer loopbackDevice.Close() - - Major, Minor, err := getDeviceMajorMinor(loopbackDevice) - if err != nil { - return "", 0, 0, err - } - return loopbackDevice.Name(), Major, Minor, nil -} - -// Get the major/minor numbers of thin pool data and metadata devices -func (devices *DeviceSet) getThinPoolDataMetaMajMin() (uint64, uint64, uint64, uint64, error) { - var params, poolDataMajMin, poolMetadataMajMin string - - _, _, _, params, err := devicemapper.GetTable(devices.getPoolName()) - if err != nil { - return 0, 0, 0, 0, err - } - - if _, err = fmt.Sscanf(params, "%s %s", &poolMetadataMajMin, &poolDataMajMin); err != nil { - return 0, 0, 0, 0, err - } - - logrus.Debugf("devmapper: poolDataMajMin=%s poolMetaMajMin=%s\n", poolDataMajMin, poolMetadataMajMin) - - poolDataMajMinorSplit := strings.Split(poolDataMajMin, ":") - poolDataMajor, err := strconv.ParseUint(poolDataMajMinorSplit[0], 10, 32) - if err != nil { - return 0, 0, 0, 0, err - } - - poolDataMinor, err := strconv.ParseUint(poolDataMajMinorSplit[1], 10, 32) - if err != nil { - return 0, 0, 0, 0, err - } - - poolMetadataMajMinorSplit := strings.Split(poolMetadataMajMin, ":") - poolMetadataMajor, err := strconv.ParseUint(poolMetadataMajMinorSplit[0], 10, 32) - if err != nil { - return 0, 0, 0, 0, err - } - - poolMetadataMinor, err := strconv.ParseUint(poolMetadataMajMinorSplit[1], 10, 32) - if err != nil { - return 0, 0, 0, 0, err - } - - return poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, nil -} - -func (devices *DeviceSet) loadThinPoolLoopBackInfo() error { - poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, err := devices.getThinPoolDataMetaMajMin() - if err != nil { - return err - } - - dirname := devices.loopbackDir() - - // data device has not been passed in. So there should be a data file - // which is being mounted as loop device. - if devices.dataDevice == "" { - datafilename := path.Join(dirname, "data") - dataLoopDevice, dataMajor, dataMinor, err := getLoopFileDeviceMajMin(datafilename) - if err != nil { - return err - } - - // Compare the two - if poolDataMajor == dataMajor && poolDataMinor == dataMinor { - devices.dataDevice = dataLoopDevice - devices.dataLoopFile = datafilename - } - - } - - // metadata device has not been passed in. So there should be a - // metadata file which is being mounted as loop device. - if devices.metadataDevice == "" { - metadatafilename := path.Join(dirname, "metadata") - metadataLoopDevice, metadataMajor, metadataMinor, err := getLoopFileDeviceMajMin(metadatafilename) - if err != nil { - return err - } - if poolMetadataMajor == metadataMajor && poolMetadataMinor == metadataMinor { - devices.metadataDevice = metadataLoopDevice - devices.metadataLoopFile = metadatafilename - } - } - - return nil -} - -func (devices *DeviceSet) enableDeferredRemovalDeletion() error { - - // If user asked for deferred removal then check both libdm library - // and kernel driver support deferred removal otherwise error out. - if enableDeferredRemoval { - if !driverDeferredRemovalSupport { - return fmt.Errorf("devmapper: Deferred removal can not be enabled as kernel does not support it") - } - if !devicemapper.LibraryDeferredRemovalSupport { - return fmt.Errorf("devmapper: Deferred removal can not be enabled as libdm does not support it") - } - logrus.Debug("devmapper: Deferred removal support enabled.") - devices.deferredRemove = true - } - - if enableDeferredDeletion { - if !devices.deferredRemove { - return fmt.Errorf("devmapper: Deferred deletion can not be enabled as deferred removal is not enabled. Enable deferred removal using --storage-opt dm.use_deferred_removal=true parameter") - } - logrus.Debug("devmapper: Deferred deletion support enabled.") - devices.deferredDelete = true - } - return nil -} - -func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) { - if err := devices.enableDeferredRemovalDeletion(); err != nil { - return err - } - - // https://github.com/docker/docker/issues/4036 - if supported := devicemapper.UdevSetSyncSupport(true); !supported { - logrus.Error("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options") - - if !devices.overrideUdevSyncCheck { - return graphdriver.ErrNotSupported - } - } - - //create the root dir of the devmapper driver ownership to match this - //daemon's remapped root uid/gid so containers can start properly - uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps) - if err != nil { - return err - } - if err := idtools.MkdirAs(devices.root, 0700, uid, gid); err != nil && !os.IsExist(err) { - return err - } - if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) { - return err - } - - prevSetupConfig, err := readLVMConfig(devices.root) - if err != nil { - return err - } - - if !reflect.DeepEqual(devices.lvmSetupConfig, directLVMConfig{}) { - if devices.thinPoolDevice != "" { - return errors.New("cannot setup direct-lvm when `dm.thinpooldev` is also specified") - } - - if !reflect.DeepEqual(prevSetupConfig, devices.lvmSetupConfig) { - if !reflect.DeepEqual(prevSetupConfig, directLVMConfig{}) { - return errors.New("changing direct-lvm config is not supported") - } - logrus.WithField("storage-driver", "devicemapper").WithField("direct-lvm-config", devices.lvmSetupConfig).Debugf("Setting up direct lvm mode") - if err := verifyBlockDevice(devices.lvmSetupConfig.Device, lvmSetupConfigForce); err != nil { - return err - } - if err := setupDirectLVM(devices.lvmSetupConfig); err != nil { - return err - } - if err := writeLVMConfig(devices.root, devices.lvmSetupConfig); err != nil { - return err - } - } - devices.thinPoolDevice = "storage-thinpool" - logrus.WithField("storage-driver", "devicemapper").Debugf("Setting dm.thinpooldev to %q", devices.thinPoolDevice) - } - - // Set the device prefix from the device id and inode of the storage root dir - var st unix.Stat_t - if err := unix.Stat(devices.root, &st); err != nil { - return fmt.Errorf("devmapper: Error looking up dir %s: %s", devices.root, err) - } - // "reg-" stands for "regular file". - // In the future we might use "dev-" for "device file", etc. - // container-maj,min[-inode] stands for: - // - Managed by container storage - // - The target of this device is at major and minor - // - If is defined, use that file inside the device as a loopback image. Otherwise use the device itself. - devices.devicePrefix = fmt.Sprintf("container-%d:%d-%d", major(st.Dev), minor(st.Dev), st.Ino) - logrus.Debugf("devmapper: Generated prefix: %s", devices.devicePrefix) - - // Check for the existence of the thin-pool device - poolExists, err := devices.thinPoolExists(devices.getPoolName()) - if err != nil { - return err - } - - // It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files - // that are not Close-on-exec, - // so we add this badhack to make sure it closes itself - setCloseOnExec("/dev/mapper/control") - - // Make sure the sparse images exist in /devicemapper/data and - // /devicemapper/metadata - - createdLoopback := false - - // If the pool doesn't exist, create it - if !poolExists && devices.thinPoolDevice == "" { - logrus.Debug("devmapper: Pool doesn't exist. Creating it.") - - var ( - dataFile *os.File - metadataFile *os.File - ) - - fsMagic, err := graphdriver.GetFSMagic(devices.loopbackDir()) - if err != nil { - return err - } - switch fsMagic { - case graphdriver.FsMagicAufs: - return errors.Errorf("devmapper: Loopback devices can not be created on AUFS filesystems") - } - - if devices.dataDevice == "" { - // Make sure the sparse images exist in /devicemapper/data - - hasData := devices.hasImage("data") - - if !doInit && !hasData { - return errors.New("loopback data file not found") - } - - if !hasData { - createdLoopback = true - } - - data, err := devices.ensureImage("data", devices.dataLoopbackSize) - if err != nil { - logrus.Debugf("devmapper: Error device ensureImage (data): %s", err) - return err - } - - dataFile, err = loopback.AttachLoopDevice(data) - if err != nil { - return err - } - devices.dataLoopFile = data - devices.dataDevice = dataFile.Name() - } else { - dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600) - if err != nil { - return err - } - } - defer dataFile.Close() - - if devices.metadataDevice == "" { - // Make sure the sparse images exist in /devicemapper/metadata - - hasMetadata := devices.hasImage("metadata") - - if !doInit && !hasMetadata { - return errors.New("loopback metadata file not found") - } - - if !hasMetadata { - createdLoopback = true - } - - metadata, err := devices.ensureImage("metadata", devices.metaDataLoopbackSize) - if err != nil { - logrus.Debugf("devmapper: Error device ensureImage (metadata): %s", err) - return err - } - - metadataFile, err = loopback.AttachLoopDevice(metadata) - if err != nil { - return err - } - devices.metadataLoopFile = metadata - devices.metadataDevice = metadataFile.Name() - } else { - metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0600) - if err != nil { - return err - } - } - defer metadataFile.Close() - - if err := devicemapper.CreatePool(devices.getPoolName(), dataFile, metadataFile, devices.thinpBlockSize); err != nil { - return err - } - defer func() { - if retErr != nil { - err = devices.deactivatePool() - if err != nil { - logrus.Warnf("devmapper: Failed to deactivatePool: %v", err) - } - } - }() - } - - // Pool already exists and caller did not pass us a pool. That means - // we probably created pool earlier and could not remove it as some - // containers were still using it. Detect some of the properties of - // pool, like is it using loop devices. - if poolExists && devices.thinPoolDevice == "" { - if err := devices.loadThinPoolLoopBackInfo(); err != nil { - logrus.Debugf("devmapper: Failed to load thin pool loopback device information:%v", err) - return err - } - } - - // If we didn't just create the data or metadata image, we need to - // load the transaction id and migrate old metadata - if !createdLoopback { - if err := devices.initMetaData(); err != nil { - return err - } - } - - if devices.thinPoolDevice == "" { - if devices.metadataLoopFile != "" || devices.dataLoopFile != "" { - logrus.Warn("devmapper: Usage of loopback devices is strongly discouraged for production use. Please use `--storage-opt dm.thinpooldev`.") - } - } - - // Right now this loads only NextDeviceID. If there is more metadata - // down the line, we might have to move it earlier. - if err := devices.loadDeviceSetMetaData(); err != nil { - return err - } - - // Setup the base image - if doInit { - if err := devices.setupBaseImage(); err != nil { - logrus.Debugf("devmapper: Error device setupBaseImage: %s", err) - return err - } - } - - return nil -} - -// AddDevice adds a device and registers in the hash. -func (devices *DeviceSet) AddDevice(hash, baseHash string, storageOpt map[string]string) error { - logrus.Debugf("devmapper: AddDevice START(hash=%s basehash=%s)", hash, baseHash) - defer logrus.Debugf("devmapper: AddDevice END(hash=%s basehash=%s)", hash, baseHash) - - // If a deleted device exists, return error. - baseInfo, err := devices.lookupDeviceWithLock(baseHash) - if err != nil { - return err - } - - if baseInfo.Deleted { - return fmt.Errorf("devmapper: Base device %v has been marked for deferred deletion", baseInfo.Hash) - } - - baseInfo.lock.Lock() - defer baseInfo.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - // Also include deleted devices in case hash of new device is - // same as one of the deleted devices. - if info, _ := devices.lookupDevice(hash); info != nil { - return fmt.Errorf("devmapper: device %s already exists. Deleted=%v", hash, info.Deleted) - } - - size, err := devices.parseStorageOpt(storageOpt) - if err != nil { - return err - } - - if size == 0 { - size = baseInfo.Size - } - - if size < baseInfo.Size { - return fmt.Errorf("devmapper: Container size cannot be smaller than %s", units.HumanSize(float64(baseInfo.Size))) - } - - if err := devices.takeSnapshot(hash, baseInfo, size); err != nil { - return err - } - - // Grow the container rootfs. - if size > baseInfo.Size { - info, err := devices.lookupDevice(hash) - if err != nil { - return err - } - - if err := devices.growFS(info); err != nil { - return err - } - } - - return nil -} - -func (devices *DeviceSet) parseStorageOpt(storageOpt map[string]string) (uint64, error) { - - // Read size to change the block device size per container. - for key, val := range storageOpt { - key := strings.ToLower(key) - switch key { - case "size": - size, err := units.RAMInBytes(val) - if err != nil { - return 0, err - } - return uint64(size), nil - default: - return 0, fmt.Errorf("Unknown option %s", key) - } - } - - return 0, nil -} - -func (devices *DeviceSet) markForDeferredDeletion(info *devInfo) error { - // If device is already in deleted state, there is nothing to be done. - if info.Deleted { - return nil - } - - logrus.Debugf("devmapper: Marking device %s for deferred deletion.", info.Hash) - - info.Deleted = true - - // save device metadata to reflect deleted state. - if err := devices.saveMetadata(info); err != nil { - info.Deleted = false - return err - } - - devices.nrDeletedDevices++ - return nil -} - -// Should be called with devices.Lock() held. -func (devices *DeviceSet) deleteTransaction(info *devInfo, syncDelete bool) error { - if err := devices.openTransaction(info.Hash, info.DeviceID); err != nil { - logrus.Debugf("devmapper: Error opening transaction hash = %s deviceId = %d", "", info.DeviceID) - return err - } - - defer devices.closeTransaction() - - err := devicemapper.DeleteDevice(devices.getPoolDevName(), info.DeviceID) - if err != nil { - // If syncDelete is true, we want to return error. If deferred - // deletion is not enabled, we return an error. If error is - // something other then EBUSY, return an error. - if syncDelete || !devices.deferredDelete || errors.Cause(err) != devicemapper.ErrBusy { - logrus.Debugf("devmapper: Error deleting device: %s", err) - return err - } - } - - if err == nil { - if err := devices.unregisterDevice(info.Hash); err != nil { - return err - } - // If device was already in deferred delete state that means - // deletion was being tried again later. Reduce the deleted - // device count. - if info.Deleted { - devices.nrDeletedDevices-- - } - devices.markDeviceIDFree(info.DeviceID) - } else { - if err := devices.markForDeferredDeletion(info); err != nil { - return err - } - } - - return nil -} - -// Issue discard only if device open count is zero. -func (devices *DeviceSet) issueDiscard(info *devInfo) error { - logrus.Debugf("devmapper: issueDiscard START(device: %s).", info.Hash) - defer logrus.Debugf("devmapper: issueDiscard END(device: %s).", info.Hash) - // This is a workaround for the kernel not discarding block so - // on the thin pool when we remove a thinp device, so we do it - // manually. - // Even if device is deferred deleted, activate it and issue - // discards. - if err := devices.activateDeviceIfNeeded(info, true); err != nil { - return err - } - - devinfo, err := devicemapper.GetInfo(info.Name()) - if err != nil { - return err - } - - if devinfo.OpenCount != 0 { - logrus.Debugf("devmapper: Device: %s is in use. OpenCount=%d. Not issuing discards.", info.Hash, devinfo.OpenCount) - return nil - } - - if err := devicemapper.BlockDeviceDiscard(info.DevName()); err != nil { - logrus.Debugf("devmapper: Error discarding block on device: %s (ignoring)", err) - } - return nil -} - -// Should be called with devices.Lock() held. -func (devices *DeviceSet) deleteDevice(info *devInfo, syncDelete bool) error { - if devices.doBlkDiscard { - devices.issueDiscard(info) - } - - // Try to deactivate device in case it is active. - // If deferred removal is enabled and deferred deletion is disabled - // then make sure device is removed synchronously. There have been - // some cases of device being busy for short duration and we would - // rather busy wait for device removal to take care of these cases. - deferredRemove := devices.deferredRemove - if !devices.deferredDelete { - deferredRemove = false - } - - if err := devices.deactivateDeviceMode(info, deferredRemove); err != nil { - logrus.Debugf("devmapper: Error deactivating device: %s", err) - return err - } - - if err := devices.deleteTransaction(info, syncDelete); err != nil { - return err - } - - return nil -} - -// DeleteDevice will return success if device has been marked for deferred -// removal. If one wants to override that and want DeleteDevice() to fail if -// device was busy and could not be deleted, set syncDelete=true. -func (devices *DeviceSet) DeleteDevice(hash string, syncDelete bool) error { - logrus.Debugf("devmapper: DeleteDevice START(hash=%v syncDelete=%v)", hash, syncDelete) - defer logrus.Debugf("devmapper: DeleteDevice END(hash=%v syncDelete=%v)", hash, syncDelete) - info, err := devices.lookupDeviceWithLock(hash) - if err != nil { - return err - } - - info.lock.Lock() - defer info.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - return devices.deleteDevice(info, syncDelete) -} - -func (devices *DeviceSet) deactivatePool() error { - logrus.Debug("devmapper: deactivatePool() START") - defer logrus.Debug("devmapper: deactivatePool() END") - devname := devices.getPoolDevName() - - devinfo, err := devicemapper.GetInfo(devname) - if err != nil { - return err - } - - if devinfo.Exists == 0 { - return nil - } - if err := devicemapper.RemoveDevice(devname); err != nil { - return err - } - - if d, err := devicemapper.GetDeps(devname); err == nil { - logrus.Warnf("devmapper: device %s still has %d active dependents", devname, d.Count) - } - - return nil -} - -func (devices *DeviceSet) deactivateDevice(info *devInfo) error { - return devices.deactivateDeviceMode(info, devices.deferredRemove) -} - -func (devices *DeviceSet) deactivateDeviceMode(info *devInfo, deferredRemove bool) error { - var err error - logrus.Debugf("devmapper: deactivateDevice START(%s)", info.Hash) - defer logrus.Debugf("devmapper: deactivateDevice END(%s)", info.Hash) - - devinfo, err := devicemapper.GetInfo(info.Name()) - if err != nil { - return err - } - - if devinfo.Exists == 0 { - return nil - } - - if deferredRemove { - err = devicemapper.RemoveDeviceDeferred(info.Name()) - } else { - err = devices.removeDevice(info.Name()) - } - - // This function's semantics is such that it does not return an - // error if device does not exist. So if device went away by - // the time we actually tried to remove it, do not return error. - if errors.Cause(err) != devicemapper.ErrEnxio { - return err - } - return nil -} - -// Issues the underlying dm remove operation. -func (devices *DeviceSet) removeDevice(devname string) error { - var err error - - logrus.Debugf("devmapper: removeDevice START(%s)", devname) - defer logrus.Debugf("devmapper: removeDevice END(%s)", devname) - - for i := 0; i < 200; i++ { - err = devicemapper.RemoveDevice(devname) - if err == nil { - break - } - if errors.Cause(err) != devicemapper.ErrBusy { - return err - } - - // If we see EBUSY it may be a transient error, - // sleep a bit a retry a few times. - devices.Unlock() - time.Sleep(100 * time.Millisecond) - devices.Lock() - } - - return err -} - -func (devices *DeviceSet) cancelDeferredRemovalIfNeeded(info *devInfo) error { - if !devices.deferredRemove { - return nil - } - - logrus.Debugf("devmapper: cancelDeferredRemovalIfNeeded START(%s)", info.Name()) - defer logrus.Debugf("devmapper: cancelDeferredRemovalIfNeeded END(%s)", info.Name()) - - devinfo, err := devicemapper.GetInfoWithDeferred(info.Name()) - if err != nil { - return err - } - - if devinfo != nil && devinfo.DeferredRemove == 0 { - return nil - } - - // Cancel deferred remove - if err := devices.cancelDeferredRemoval(info); err != nil { - // If Error is ErrEnxio. Device is probably already gone. Continue. - if errors.Cause(err) != devicemapper.ErrBusy { - return err - } - } - return nil -} - -func (devices *DeviceSet) cancelDeferredRemoval(info *devInfo) error { - logrus.Debugf("devmapper: cancelDeferredRemoval START(%s)", info.Name()) - defer logrus.Debugf("devmapper: cancelDeferredRemoval END(%s)", info.Name()) - - var err error - - // Cancel deferred remove - for i := 0; i < 100; i++ { - err = devicemapper.CancelDeferredRemove(info.Name()) - if err != nil { - if errors.Cause(err) != devicemapper.ErrBusy { - // If we see EBUSY it may be a transient error, - // sleep a bit a retry a few times. - devices.Unlock() - time.Sleep(100 * time.Millisecond) - devices.Lock() - continue - } - } - break - } - return err -} - -// Shutdown shuts down the device by unmounting the root. -func (devices *DeviceSet) Shutdown(home string) error { - logrus.Debugf("devmapper: [deviceset %s] Shutdown()", devices.devicePrefix) - logrus.Debugf("devmapper: Shutting down DeviceSet: %s", devices.root) - defer logrus.Debugf("devmapper: [deviceset %s] Shutdown() END", devices.devicePrefix) - - // Stop deletion worker. This should start delivering new events to - // ticker channel. That means no new instance of cleanupDeletedDevice() - // will run after this call. If one instance is already running at - // the time of the call, it must be holding devices.Lock() and - // we will block on this lock till cleanup function exits. - devices.deletionWorkerTicker.Stop() - - devices.Lock() - // Save DeviceSet Metadata first. Docker kills all threads if they - // don't finish in certain time. It is possible that Shutdown() - // routine does not finish in time as we loop trying to deactivate - // some devices while these are busy. In that case shutdown() routine - // will be killed and we will not get a chance to save deviceset - // metadata. Hence save this early before trying to deactivate devices. - devices.saveDeviceSetMetaData() - - // ignore the error since it's just a best effort to not try to unmount something that's mounted - mounts, _ := mount.GetMounts() - mounted := make(map[string]bool, len(mounts)) - for _, mnt := range mounts { - mounted[mnt.Mountpoint] = true - } - - if err := filepath.Walk(path.Join(home, "mnt"), func(p string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - return nil - } - - if mounted[p] { - // We use MNT_DETACH here in case it is still busy in some running - // container. This means it'll go away from the global scope directly, - // and the device will be released when that container dies. - if err := unix.Unmount(p, unix.MNT_DETACH); err != nil { - logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", p, err) - } - } - - if devInfo, err := devices.lookupDevice(path.Base(p)); err != nil { - logrus.Debugf("devmapper: Shutdown lookup device %s, error: %s", path.Base(p), err) - } else { - if err := devices.deactivateDevice(devInfo); err != nil { - logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", devInfo.Hash, err) - } - } - - return nil - }); err != nil && !os.IsNotExist(err) { - devices.Unlock() - return err - } - - devices.Unlock() - - info, _ := devices.lookupDeviceWithLock("") - if info != nil { - info.lock.Lock() - devices.Lock() - if err := devices.deactivateDevice(info); err != nil { - logrus.Debugf("devmapper: Shutdown deactivate base , error: %s", err) - } - devices.Unlock() - info.lock.Unlock() - } - - devices.Lock() - if devices.thinPoolDevice == "" { - if err := devices.deactivatePool(); err != nil { - logrus.Debugf("devmapper: Shutdown deactivate pool , error: %s", err) - } - } - devices.Unlock() - - return nil -} - -// Recent XFS changes allow changing behavior of filesystem in case of errors. -// When thin pool gets full and XFS gets ENOSPC error, currently it tries -// IO infinitely and sometimes it can block the container process -// and process can't be killWith 0 value, XFS will not retry upon error -// and instead will shutdown filesystem. - -func (devices *DeviceSet) xfsSetNospaceRetries(info *devInfo) error { - dmDevicePath, err := os.Readlink(info.DevName()) - if err != nil { - return fmt.Errorf("devmapper: readlink failed for device %v:%v", info.DevName(), err) - } - - dmDeviceName := path.Base(dmDevicePath) - filePath := "/sys/fs/xfs/" + dmDeviceName + "/error/metadata/ENOSPC/max_retries" - maxRetriesFile, err := os.OpenFile(filePath, os.O_WRONLY, 0) - if err != nil { - return fmt.Errorf("devmapper: user specified daemon option dm.xfs_nospace_max_retries but it does not seem to be supported on this system :%v", err) - } - defer maxRetriesFile.Close() - - // Set max retries to 0 - _, err = maxRetriesFile.WriteString(devices.xfsNospaceRetries) - if err != nil { - return fmt.Errorf("devmapper: Failed to write string %v to file %v:%v", devices.xfsNospaceRetries, filePath, err) - } - return nil -} - -// MountDevice mounts the device if not already mounted. -func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { - info, err := devices.lookupDeviceWithLock(hash) - if err != nil { - return err - } - - if info.Deleted { - return fmt.Errorf("devmapper: Can't mount device %v as it has been marked for deferred deletion", info.Hash) - } - - info.lock.Lock() - defer info.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - if err := devices.activateDeviceIfNeeded(info, false); err != nil { - return fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err) - } - - fstype, err := ProbeFsType(info.DevName()) - if err != nil { - return err - } - - options := "" - - if fstype == "xfs" { - // XFS needs nouuid or it can't mount filesystems with the same fs - options = joinMountOptions(options, "nouuid") - } - - options = joinMountOptions(options, devices.mountOptions) - options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) - - if err := mount.Mount(info.DevName(), path, fstype, options); err != nil { - return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s\n%v", info.DevName(), path, err, string(dmesg.Dmesg(256))) - } - - if fstype == "xfs" && devices.xfsNospaceRetries != "" { - if err := devices.xfsSetNospaceRetries(info); err != nil { - unix.Unmount(path, unix.MNT_DETACH) - devices.deactivateDevice(info) - return err - } - } - - return nil -} - -// UnmountDevice unmounts the device and removes it from hash. -func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { - logrus.Debugf("devmapper: UnmountDevice START(hash=%s)", hash) - defer logrus.Debugf("devmapper: UnmountDevice END(hash=%s)", hash) - - info, err := devices.lookupDeviceWithLock(hash) - if err != nil { - return err - } - - info.lock.Lock() - defer info.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - logrus.Debugf("devmapper: Unmount(%s)", mountPath) - if err := unix.Unmount(mountPath, unix.MNT_DETACH); err != nil { - return err - } - logrus.Debug("devmapper: Unmount done") - - return devices.deactivateDevice(info) -} - -// HasDevice returns true if the device metadata exists. -func (devices *DeviceSet) HasDevice(hash string) bool { - info, _ := devices.lookupDeviceWithLock(hash) - return info != nil -} - -// List returns a list of device ids. -func (devices *DeviceSet) List() []string { - devices.Lock() - defer devices.Unlock() - - ids := make([]string, len(devices.Devices)) - i := 0 - for k := range devices.Devices { - ids[i] = k - i++ - } - return ids -} - -func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) { - var params string - _, sizeInSectors, _, params, err = devicemapper.GetStatus(devName) - if err != nil { - return - } - if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil { - return - } - return -} - -// GetDeviceStatus provides size, mapped sectors -func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) { - info, err := devices.lookupDeviceWithLock(hash) - if err != nil { - return nil, err - } - - info.lock.Lock() - defer info.lock.Unlock() - - devices.Lock() - defer devices.Unlock() - - status := &DevStatus{ - DeviceID: info.DeviceID, - Size: info.Size, - TransactionID: info.TransactionID, - } - - if err := devices.activateDeviceIfNeeded(info, false); err != nil { - return nil, fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err) - } - - sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()) - - if err != nil { - return nil, err - } - - status.SizeInSectors = sizeInSectors - status.MappedSectors = mappedSectors - status.HighestMappedSector = highestMappedSector - - return status, nil -} - -func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionID, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) { - var params string - if _, totalSizeInSectors, _, params, err = devicemapper.GetStatus(devices.getPoolName()); err == nil { - _, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionID, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal) - } - return -} - -// DataDevicePath returns the path to the data storage for this deviceset, -// regardless of loopback or block device -func (devices *DeviceSet) DataDevicePath() string { - return devices.dataDevice -} - -// MetadataDevicePath returns the path to the metadata storage for this deviceset, -// regardless of loopback or block device -func (devices *DeviceSet) MetadataDevicePath() string { - return devices.metadataDevice -} - -func (devices *DeviceSet) getUnderlyingAvailableSpace(loopFile string) (uint64, error) { - buf := new(unix.Statfs_t) - if err := unix.Statfs(loopFile, buf); err != nil { - logrus.Warnf("devmapper: Couldn't stat loopfile filesystem %v: %v", loopFile, err) - return 0, err - } - return buf.Bfree * uint64(buf.Bsize), nil -} - -func (devices *DeviceSet) isRealFile(loopFile string) (bool, error) { - if loopFile != "" { - fi, err := os.Stat(loopFile) - if err != nil { - logrus.Warnf("devmapper: Couldn't stat loopfile %v: %v", loopFile, err) - return false, err - } - return fi.Mode().IsRegular(), nil - } - return false, nil -} - -// Status returns the current status of this deviceset -func (devices *DeviceSet) Status() *Status { - devices.Lock() - defer devices.Unlock() - - status := &Status{} - - status.PoolName = devices.getPoolName() - status.DataFile = devices.DataDevicePath() - status.DataLoopback = devices.dataLoopFile - status.MetadataFile = devices.MetadataDevicePath() - status.MetadataLoopback = devices.metadataLoopFile - status.UdevSyncSupported = devicemapper.UdevSyncSupported() - status.DeferredRemoveEnabled = devices.deferredRemove - status.DeferredDeleteEnabled = devices.deferredDelete - status.DeferredDeletedDeviceCount = devices.nrDeletedDevices - status.BaseDeviceSize = devices.getBaseDeviceSize() - status.BaseDeviceFS = devices.getBaseDeviceFS() - - totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus() - if err == nil { - // Convert from blocks to bytes - blockSizeInSectors := totalSizeInSectors / dataTotal - - status.Data.Used = dataUsed * blockSizeInSectors * 512 - status.Data.Total = dataTotal * blockSizeInSectors * 512 - status.Data.Available = status.Data.Total - status.Data.Used - - // metadata blocks are always 4k - status.Metadata.Used = metadataUsed * 4096 - status.Metadata.Total = metadataTotal * 4096 - status.Metadata.Available = status.Metadata.Total - status.Metadata.Used - - status.SectorSize = blockSizeInSectors * 512 - - if check, _ := devices.isRealFile(devices.dataLoopFile); check { - actualSpace, err := devices.getUnderlyingAvailableSpace(devices.dataLoopFile) - if err == nil && actualSpace < status.Data.Available { - status.Data.Available = actualSpace - } - } - - if check, _ := devices.isRealFile(devices.metadataLoopFile); check { - actualSpace, err := devices.getUnderlyingAvailableSpace(devices.metadataLoopFile) - if err == nil && actualSpace < status.Metadata.Available { - status.Metadata.Available = actualSpace - } - } - - minFreeData := (dataTotal * uint64(devices.minFreeSpacePercent)) / 100 - status.MinFreeSpace = minFreeData * blockSizeInSectors * 512 - } - - return status -} - -// Status returns the current status of this deviceset -func (devices *DeviceSet) exportDeviceMetadata(hash string) (*deviceMetadata, error) { - info, err := devices.lookupDeviceWithLock(hash) - if err != nil { - return nil, err - } - - info.lock.Lock() - defer info.lock.Unlock() - - metadata := &deviceMetadata{info.DeviceID, info.Size, info.Name()} - return metadata, nil -} - -// NewDeviceSet creates the device set based on the options provided. -func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps []idtools.IDMap) (*DeviceSet, error) { - devicemapper.SetDevDir("/dev") - - devices := &DeviceSet{ - root: root, - metaData: metaData{Devices: make(map[string]*devInfo)}, - dataLoopbackSize: defaultDataLoopbackSize, - metaDataLoopbackSize: defaultMetaDataLoopbackSize, - baseFsSize: defaultBaseFsSize, - overrideUdevSyncCheck: defaultUdevSyncOverride, - doBlkDiscard: true, - thinpBlockSize: defaultThinpBlockSize, - deviceIDMap: make([]byte, deviceIDMapSz), - deletionWorkerTicker: time.NewTicker(time.Second * 30), - uidMaps: uidMaps, - gidMaps: gidMaps, - minFreeSpacePercent: defaultMinFreeSpacePercent, - } - - version, err := devicemapper.GetDriverVersion() - if err != nil { - // Can't even get driver version, assume not supported - return nil, graphdriver.ErrNotSupported - } - - if err := determineDriverCapabilities(version); err != nil { - return nil, graphdriver.ErrNotSupported - } - - if driverDeferredRemovalSupport && devicemapper.LibraryDeferredRemovalSupport { - // enable deferred stuff by default - enableDeferredDeletion = true - enableDeferredRemoval = true - } - - foundBlkDiscard := false - var lvmSetupConfig directLVMConfig - for _, option := range options { - key, val, err := parsers.ParseKeyValueOpt(option) - if err != nil { - return nil, err - } - key = strings.ToLower(key) - switch key { - case "dm.basesize": - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - userBaseSize = true - devices.baseFsSize = uint64(size) - case "dm.loopdatasize": - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - devices.dataLoopbackSize = size - case "dm.loopmetadatasize": - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - devices.metaDataLoopbackSize = size - case "dm.fs": - if val != "ext4" && val != "xfs" { - return nil, fmt.Errorf("devmapper: Unsupported filesystem %s", val) - } - devices.filesystem = val - case "dm.mkfsarg": - devices.mkfsArgs = append(devices.mkfsArgs, val) - case "dm.mountopt": - devices.mountOptions = joinMountOptions(devices.mountOptions, val) - case "dm.metadatadev": - devices.metadataDevice = val - case "dm.datadev": - devices.dataDevice = val - case "dm.thinpooldev": - devices.thinPoolDevice = strings.TrimPrefix(val, "/dev/mapper/") - case "dm.blkdiscard": - foundBlkDiscard = true - devices.doBlkDiscard, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - case "dm.blocksize": - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - // convert to 512b sectors - devices.thinpBlockSize = uint32(size) >> 9 - case "dm.override_udev_sync_check": - devices.overrideUdevSyncCheck, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - - case "dm.use_deferred_removal": - enableDeferredRemoval, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - - case "dm.use_deferred_deletion": - enableDeferredDeletion, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - - case "dm.min_free_space": - if !strings.HasSuffix(val, "%") { - return nil, fmt.Errorf("devmapper: Option dm.min_free_space requires %% suffix") - } - - valstring := strings.TrimSuffix(val, "%") - minFreeSpacePercent, err := strconv.ParseUint(valstring, 10, 32) - if err != nil { - return nil, err - } - - if minFreeSpacePercent >= 100 { - return nil, fmt.Errorf("devmapper: Invalid value %v for option dm.min_free_space", val) - } - - devices.minFreeSpacePercent = uint32(minFreeSpacePercent) - case "dm.xfs_nospace_max_retries": - _, err := strconv.ParseUint(val, 10, 64) - if err != nil { - return nil, err - } - devices.xfsNospaceRetries = val - case "dm.directlvm_device": - lvmSetupConfig.Device = val - case "dm.directlvm_device_force": - lvmSetupConfigForce, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - case "dm.thinp_percent": - per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "could not parse `dm.thinp_percent=%s`", val) - } - if per >= 100 { - return nil, errors.New("dm.thinp_percent must be greater than 0 and less than 100") - } - lvmSetupConfig.ThinpPercent = per - case "dm.thinp_metapercent": - per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "could not parse `dm.thinp_metapercent=%s`", val) - } - if per >= 100 { - return nil, errors.New("dm.thinp_metapercent must be greater than 0 and less than 100") - } - lvmSetupConfig.ThinpMetaPercent = per - case "dm.thinp_autoextend_percent": - per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "could not parse `dm.thinp_autoextend_percent=%s`", val) - } - if per > 100 { - return nil, errors.New("dm.thinp_autoextend_percent must be greater than 0 and less than 100") - } - lvmSetupConfig.AutoExtendPercent = per - case "dm.thinp_autoextend_threshold": - per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "could not parse `dm.thinp_autoextend_threshold=%s`", val) - } - if per > 100 { - return nil, errors.New("dm.thinp_autoextend_threshold must be greater than 0 and less than 100") - } - lvmSetupConfig.AutoExtendThreshold = per - case "dm.libdm_log_level": - level, err := strconv.ParseInt(val, 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "could not parse `dm.libdm_log_level=%s`", val) - } - if level < devicemapper.LogLevelFatal || level > devicemapper.LogLevelDebug { - return nil, errors.Errorf("dm.libdm_log_level must be in range [%d,%d]", devicemapper.LogLevelFatal, devicemapper.LogLevelDebug) - } - // Register a new logging callback with the specified level. - devicemapper.LogInit(devicemapper.DefaultLogger{ - Level: int(level), - }) - default: - return nil, fmt.Errorf("devmapper: Unknown option %s", key) - } - } - - if err := validateLVMConfig(lvmSetupConfig); err != nil { - return nil, err - } - - devices.lvmSetupConfig = lvmSetupConfig - - // By default, don't do blk discard hack on raw devices, its rarely useful and is expensive - if !foundBlkDiscard && (devices.dataDevice != "" || devices.thinPoolDevice != "") { - devices.doBlkDiscard = false - } - - if err := devices.initDevmapper(doInit); err != nil { - return nil, err - } - - return devices, nil -} diff --git a/vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go b/vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go deleted file mode 100644 index 9ab3e4f864..0000000000 --- a/vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go +++ /dev/null @@ -1,106 +0,0 @@ -package devmapper - -// Definition of struct dm_task and sub structures (from lvm2) -// -// struct dm_ioctl { -// /* -// * The version number is made up of three parts: -// * major - no backward or forward compatibility, -// * minor - only backwards compatible, -// * patch - both backwards and forwards compatible. -// * -// * All clients of the ioctl interface should fill in the -// * version number of the interface that they were -// * compiled with. -// * -// * All recognized ioctl commands (ie. those that don't -// * return -ENOTTY) fill out this field, even if the -// * command failed. -// */ -// uint32_t version[3]; /* in/out */ -// uint32_t data_size; /* total size of data passed in -// * including this struct */ - -// uint32_t data_start; /* offset to start of data -// * relative to start of this struct */ - -// uint32_t target_count; /* in/out */ -// int32_t open_count; /* out */ -// uint32_t flags; /* in/out */ - -// /* -// * event_nr holds either the event number (input and output) or the -// * udev cookie value (input only). -// * The DM_DEV_WAIT ioctl takes an event number as input. -// * The DM_SUSPEND, DM_DEV_REMOVE and DM_DEV_RENAME ioctls -// * use the field as a cookie to return in the DM_COOKIE -// * variable with the uevents they issue. -// * For output, the ioctls return the event number, not the cookie. -// */ -// uint32_t event_nr; /* in/out */ -// uint32_t padding; - -// uint64_t dev; /* in/out */ - -// char name[DM_NAME_LEN]; /* device name */ -// char uuid[DM_UUID_LEN]; /* unique identifier for -// * the block device */ -// char data[7]; /* padding or data */ -// }; - -// struct target { -// uint64_t start; -// uint64_t length; -// char *type; -// char *params; - -// struct target *next; -// }; - -// typedef enum { -// DM_ADD_NODE_ON_RESUME, /* add /dev/mapper node with dmsetup resume */ -// DM_ADD_NODE_ON_CREATE /* add /dev/mapper node with dmsetup create */ -// } dm_add_node_t; - -// struct dm_task { -// int type; -// char *dev_name; -// char *mangled_dev_name; - -// struct target *head, *tail; - -// int read_only; -// uint32_t event_nr; -// int major; -// int minor; -// int allow_default_major_fallback; -// uid_t uid; -// gid_t gid; -// mode_t mode; -// uint32_t read_ahead; -// uint32_t read_ahead_flags; -// union { -// struct dm_ioctl *v4; -// } dmi; -// char *newname; -// char *message; -// char *geometry; -// uint64_t sector; -// int no_flush; -// int no_open_count; -// int skip_lockfs; -// int query_inactive_table; -// int suppress_identical_reload; -// dm_add_node_t add_node; -// uint64_t existing_table_size; -// int cookie_set; -// int new_uuid; -// int secure_data; -// int retry_remove; -// int enable_checks; -// int expected_errno; - -// char *uuid; -// char *mangled_uuid; -// }; -// diff --git a/vendor/github.com/containers/storage/drivers/devmapper/driver.go b/vendor/github.com/containers/storage/drivers/devmapper/driver.go deleted file mode 100644 index d68fb66cc8..0000000000 --- a/vendor/github.com/containers/storage/drivers/devmapper/driver.go +++ /dev/null @@ -1,240 +0,0 @@ -// +build linux - -package devmapper - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "strconv" - - "github.com/sirupsen/logrus" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/devicemapper" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/locker" - "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/system" - units "github.com/docker/go-units" -) - -func init() { - graphdriver.Register("devicemapper", Init) -} - -// Driver contains the device set mounted and the home directory -type Driver struct { - *DeviceSet - home string - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - ctr *graphdriver.RefCounter - locker *locker.Locker -} - -// Init creates a driver with the given home and the set of options. -func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps) - if err != nil { - return nil, err - } - - if err := mount.MakePrivate(home); err != nil { - return nil, err - } - - d := &Driver{ - DeviceSet: deviceSet, - home: home, - uidMaps: uidMaps, - gidMaps: gidMaps, - ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), - locker: locker.New(), - } - - return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil -} - -func (d *Driver) String() string { - return "devicemapper" -} - -// Status returns the status about the driver in a printable format. -// Information returned contains Pool Name, Data File, Metadata file, disk usage by -// the data and metadata, etc. -func (d *Driver) Status() [][2]string { - s := d.DeviceSet.Status() - - status := [][2]string{ - {"Pool Name", s.PoolName}, - {"Pool Blocksize", units.HumanSize(float64(s.SectorSize))}, - {"Base Device Size", units.HumanSize(float64(s.BaseDeviceSize))}, - {"Backing Filesystem", s.BaseDeviceFS}, - {"Data file", s.DataFile}, - {"Metadata file", s.MetadataFile}, - {"Data Space Used", units.HumanSize(float64(s.Data.Used))}, - {"Data Space Total", units.HumanSize(float64(s.Data.Total))}, - {"Data Space Available", units.HumanSize(float64(s.Data.Available))}, - {"Metadata Space Used", units.HumanSize(float64(s.Metadata.Used))}, - {"Metadata Space Total", units.HumanSize(float64(s.Metadata.Total))}, - {"Metadata Space Available", units.HumanSize(float64(s.Metadata.Available))}, - {"Thin Pool Minimum Free Space", units.HumanSize(float64(s.MinFreeSpace))}, - {"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)}, - {"Deferred Removal Enabled", fmt.Sprintf("%v", s.DeferredRemoveEnabled)}, - {"Deferred Deletion Enabled", fmt.Sprintf("%v", s.DeferredDeleteEnabled)}, - {"Deferred Deleted Device Count", fmt.Sprintf("%v", s.DeferredDeletedDeviceCount)}, - } - if len(s.DataLoopback) > 0 { - status = append(status, [2]string{"Data loop file", s.DataLoopback}) - } - if len(s.MetadataLoopback) > 0 { - status = append(status, [2]string{"Metadata loop file", s.MetadataLoopback}) - } - if vStr, err := devicemapper.GetLibraryVersion(); err == nil { - status = append(status, [2]string{"Library Version", vStr}) - } - return status -} - -// Metadata returns a map of information about the device. -func (d *Driver) Metadata(id string) (map[string]string, error) { - m, err := d.DeviceSet.exportDeviceMetadata(id) - - if err != nil { - return nil, err - } - - metadata := make(map[string]string) - metadata["DeviceId"] = strconv.Itoa(m.deviceID) - metadata["DeviceSize"] = strconv.FormatUint(m.deviceSize, 10) - metadata["DeviceName"] = m.deviceName - return metadata, nil -} - -// Cleanup unmounts a device. -func (d *Driver) Cleanup() error { - err := d.DeviceSet.Shutdown(d.home) - - if err2 := mount.Unmount(d.home); err == nil { - err = err2 - } - - return err -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - return d.Create(id, parent, opts) -} - -// Create adds a device with a given id and the parent. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - var storageOpt map[string]string - if opts != nil { - storageOpt = opts.StorageOpt - } - - if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil { - return err - } - - return nil -} - -// Remove removes a device with a given id, unmounts the filesystem. -func (d *Driver) Remove(id string) error { - d.locker.Lock(id) - defer d.locker.Unlock(id) - if !d.DeviceSet.HasDevice(id) { - // Consider removing a non-existing device a no-op - // This is useful to be able to progress on container removal - // if the underlying device has gone away due to earlier errors - return nil - } - - // This assumes the device has been properly Get/Put:ed and thus is unmounted - if err := d.DeviceSet.DeleteDevice(id, false); err != nil { - return fmt.Errorf("failed to remove device %s: %v", id, err) - } - return system.EnsureRemoveAll(path.Join(d.home, "mnt", id)) -} - -// Get mounts a device with given id into the root filesystem -func (d *Driver) Get(id, mountLabel string) (string, error) { - d.locker.Lock(id) - defer d.locker.Unlock(id) - mp := path.Join(d.home, "mnt", id) - rootFs := path.Join(mp, "rootfs") - if count := d.ctr.Increment(mp); count > 1 { - return rootFs, nil - } - - uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - d.ctr.Decrement(mp) - return "", err - } - - // Create the target directories if they don't exist - if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) { - d.ctr.Decrement(mp) - return "", err - } - if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) { - d.ctr.Decrement(mp) - return "", err - } - - // Mount the device - if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil { - d.ctr.Decrement(mp) - return "", err - } - - if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) { - d.ctr.Decrement(mp) - d.DeviceSet.UnmountDevice(id, mp) - return "", err - } - - idFile := path.Join(mp, "id") - if _, err := os.Stat(idFile); err != nil && os.IsNotExist(err) { - // Create an "id" file with the container/image id in it to help reconstruct this in case - // of later problems - if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil { - d.ctr.Decrement(mp) - d.DeviceSet.UnmountDevice(id, mp) - return "", err - } - } - - return rootFs, nil -} - -// Put unmounts a device and removes it. -func (d *Driver) Put(id string) error { - d.locker.Lock(id) - defer d.locker.Unlock(id) - mp := path.Join(d.home, "mnt", id) - if count := d.ctr.Decrement(mp); count > 0 { - return nil - } - err := d.DeviceSet.UnmountDevice(id, mp) - if err != nil { - logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err) - } - return err -} - -// Exists checks to see if the device exists. -func (d *Driver) Exists(id string) bool { - return d.DeviceSet.HasDevice(id) -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/devmapper/mount.go b/vendor/github.com/containers/storage/drivers/devmapper/mount.go deleted file mode 100644 index 1dc3262d27..0000000000 --- a/vendor/github.com/containers/storage/drivers/devmapper/mount.go +++ /dev/null @@ -1,88 +0,0 @@ -// +build linux - -package devmapper - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - - "golang.org/x/sys/unix" -) - -// FIXME: this is copy-pasted from the aufs driver. -// It should be moved into the core. - -// Mounted returns true if a mount point exists. -func Mounted(mountpoint string) (bool, error) { - var mntpointSt unix.Stat_t - if err := unix.Stat(mountpoint, &mntpointSt); err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - var parentSt unix.Stat_t - if err := unix.Stat(filepath.Join(mountpoint, ".."), &parentSt); err != nil { - return false, err - } - return mntpointSt.Dev != parentSt.Dev, nil -} - -type probeData struct { - fsName string - magic string - offset uint64 -} - -// ProbeFsType returns the filesystem name for the given device id. -func ProbeFsType(device string) (string, error) { - probes := []probeData{ - {"btrfs", "_BHRfS_M", 0x10040}, - {"ext4", "\123\357", 0x438}, - {"xfs", "XFSB", 0}, - } - - maxLen := uint64(0) - for _, p := range probes { - l := p.offset + uint64(len(p.magic)) - if l > maxLen { - maxLen = l - } - } - - file, err := os.Open(device) - if err != nil { - return "", err - } - defer file.Close() - - buffer := make([]byte, maxLen) - l, err := file.Read(buffer) - if err != nil { - return "", err - } - - if uint64(l) != maxLen { - return "", fmt.Errorf("devmapper: unable to detect filesystem type of %s, short read", device) - } - - for _, p := range probes { - if bytes.Equal([]byte(p.magic), buffer[p.offset:p.offset+uint64(len(p.magic))]) { - return p.fsName, nil - } - } - - return "", fmt.Errorf("devmapper: Unknown filesystem type on %s", device) -} - -func joinMountOptions(a, b string) string { - if a == "" { - return b - } - if b == "" { - return a - } - return a + "," + b -} diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go deleted file mode 100644 index 615d93be5f..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver.go +++ /dev/null @@ -1,285 +0,0 @@ -package graphdriver - -import ( - "fmt" - "io" - "os" - "path/filepath" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/vbatts/tar-split/tar/storage" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/idtools" -) - -// FsMagic unsigned id of the filesystem in use. -type FsMagic uint32 - -const ( - // FsMagicUnsupported is a predefined constant value other than a valid filesystem id. - FsMagicUnsupported = FsMagic(0x00000000) -) - -var ( - // All registered drivers - drivers map[string]InitFunc - - // ErrNotSupported returned when driver is not supported. - ErrNotSupported = errors.New("driver not supported") - // ErrPrerequisites returned when driver does not meet prerequisites. - ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)") - // ErrIncompatibleFS returned when file system is not supported. - ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver") -) - -//CreateOpts contains optional arguments for Create() and CreateReadWrite() -// methods. -type CreateOpts struct { - MountLabel string - StorageOpt map[string]string -} - -// InitFunc initializes the storage driver. -type InitFunc func(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) - -// ProtoDriver defines the basic capabilities of a driver. -// This interface exists solely to be a minimum set of methods -// for client code which choose not to implement the entire Driver -// interface and use the NaiveDiffDriver wrapper constructor. -// -// Use of ProtoDriver directly by client code is not recommended. -type ProtoDriver interface { - // String returns a string representation of this driver. - String() string - // CreateReadWrite creates a new, empty filesystem layer that is ready - // to be used as the storage for a container. Additional options can - // be passed in opts. parent may be "" and opts may be nil. - CreateReadWrite(id, parent string, opts *CreateOpts) error - // Create creates a new, empty, filesystem layer with the - // specified id and parent and options passed in opts. Parent - // may be "" and opts may be nil. - Create(id, parent string, opts *CreateOpts) error - // Remove attempts to remove the filesystem layer with this id. - Remove(id string) error - // Get returns the mountpoint for the layered filesystem referred - // to by this id. You can optionally specify a mountLabel or "". - // Returns the absolute path to the mounted layered filesystem. - Get(id, mountLabel string) (dir string, err error) - // Put releases the system resources for the specified id, - // e.g, unmounting layered filesystem. - Put(id string) error - // Exists returns whether a filesystem layer with the specified - // ID exists on this driver. - Exists(id string) bool - // Status returns a set of key-value pairs which give low - // level diagnostic status about this driver. - Status() [][2]string - // Returns a set of key-value pairs which give low level information - // about the image/container driver is managing. - Metadata(id string) (map[string]string, error) - // Cleanup performs necessary tasks to release resources - // held by the driver, e.g., unmounting all layered filesystems - // known to this driver. - Cleanup() error - // AdditionalImageStores returns additional image stores supported by the driver - AdditionalImageStores() []string -} - -// DiffDriver is the interface to use to implement graph diffs -type DiffDriver interface { - // Diff produces an archive of the changes between the specified - // layer and its parent layer which may be "". - Diff(id, parent, mountLabel string) (io.ReadCloser, error) - // Changes produces a list of changes between the specified layer - // and its parent layer. If parent is "", then all changes will be ADD changes. - Changes(id, parent, mountLabel string) ([]archive.Change, error) - // ApplyDiff extracts the changeset from the given diff into the - // layer with the specified id and parent, returning the size of the - // new layer in bytes. - // The io.Reader must be an uncompressed stream. - ApplyDiff(id, parent, mountLabel string, diff io.Reader) (size int64, err error) - // DiffSize calculates the changes between the specified id - // and its parent and returns the size in bytes of the changes - // relative to its base filesystem directory. - DiffSize(id, parent, mountLabel string) (size int64, err error) -} - -// Driver is the interface for layered/snapshot file system drivers. -type Driver interface { - ProtoDriver - DiffDriver -} - -// Capabilities defines a list of capabilities a driver may implement. -// These capabilities are not required; however, they do determine how a -// graphdriver can be used. -type Capabilities struct { - // Flags that this driver is capable of reproducing exactly equivalent - // diffs for read-only layers. If set, clients can rely on the driver - // for consistent tar streams, and avoid extra processing to account - // for potential differences (eg: the layer store's use of tar-split). - ReproducesExactDiffs bool -} - -// CapabilityDriver is the interface for layered file system drivers that -// can report on their Capabilities. -type CapabilityDriver interface { - Capabilities() Capabilities -} - -// DiffGetterDriver is the interface for layered file system drivers that -// provide a specialized function for getting file contents for tar-split. -type DiffGetterDriver interface { - Driver - // DiffGetter returns an interface to efficiently retrieve the contents - // of files in a layer. - DiffGetter(id string) (FileGetCloser, error) -} - -// FileGetCloser extends the storage.FileGetter interface with a Close method -// for cleaning up. -type FileGetCloser interface { - storage.FileGetter - // Close cleans up any resources associated with the FileGetCloser. - Close() error -} - -// Checker makes checks on specified filesystems. -type Checker interface { - // IsMounted returns true if the provided path is mounted for the specific checker - IsMounted(path string) bool -} - -func init() { - drivers = make(map[string]InitFunc) -} - -// Register registers an InitFunc for the driver. -func Register(name string, initFunc InitFunc) error { - if _, exists := drivers[name]; exists { - return fmt.Errorf("Name already registered %s", name) - } - drivers[name] = initFunc - - return nil -} - -// GetDriver initializes and returns the registered driver -func GetDriver(name string, config Options) (Driver, error) { - if initFunc, exists := drivers[name]; exists { - return initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) - } - - logrus.Errorf("Failed to GetDriver graph %s %s", name, config.Root) - return nil, errors.Wrapf(ErrNotSupported, "failed to GetDriver graph %s %s", name, config.Root) -} - -// getBuiltinDriver initializes and returns the registered driver, but does not try to load from plugins -func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) { - if initFunc, exists := drivers[name]; exists { - return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps) - } - logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home) - return nil, errors.Wrapf(ErrNotSupported, "failed to built-in GetDriver graph %s %s", name, home) -} - -// Options is used to initialize a graphdriver -type Options struct { - Root string - DriverOptions []string - UIDMaps []idtools.IDMap - GIDMaps []idtools.IDMap - ExperimentalEnabled bool -} - -// New creates the driver and initializes it at the specified root. -func New(name string, config Options) (Driver, error) { - if name != "" { - logrus.Debugf("[graphdriver] trying provided driver %q", name) // so the logs show specified driver - return GetDriver(name, config) - } - - // Guess for prior driver - driversMap := scanPriorDrivers(config.Root) - for _, name := range priority { - if name == "vfs" { - // don't use vfs even if there is state present. - continue - } - if _, prior := driversMap[name]; prior { - // of the state found from prior drivers, check in order of our priority - // which we would prefer - driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps) - if err != nil { - // unlike below, we will return error here, because there is prior - // state, and now it is no longer supported/prereq/compatible, so - // something changed and needs attention. Otherwise the daemon's - // images would just "disappear". - logrus.Errorf("[graphdriver] prior storage driver %s failed: %s", name, err) - return nil, err - } - - // abort starting when there are other prior configured drivers - // to ensure the user explicitly selects the driver to load - if len(driversMap)-1 > 0 { - var driversSlice []string - for name := range driversMap { - driversSlice = append(driversSlice, name) - } - - return nil, fmt.Errorf("%s contains several valid graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s )", config.Root, strings.Join(driversSlice, ", ")) - } - - logrus.Infof("[graphdriver] using prior storage driver: %s", name) - return driver, nil - } - } - - // Check for priority drivers first - for _, name := range priority { - driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps) - if err != nil { - if isDriverNotSupported(err) { - continue - } - return nil, err - } - return driver, nil - } - - // Check all registered drivers if no priority driver is found - for name, initFunc := range drivers { - driver, err := initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) - if err != nil { - if isDriverNotSupported(err) { - continue - } - return nil, err - } - return driver, nil - } - return nil, fmt.Errorf("No supported storage backend found") -} - -// isDriverNotSupported returns true if the error initializing -// the graph driver is a non-supported error. -func isDriverNotSupported(err error) bool { - cause := errors.Cause(err) - return cause == ErrNotSupported || cause == ErrPrerequisites || cause == ErrIncompatibleFS -} - -// scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers -func scanPriorDrivers(root string) map[string]bool { - driversMap := make(map[string]bool) - - for driver := range drivers { - p := filepath.Join(root, driver) - if _, err := os.Stat(p); err == nil && driver != "vfs" { - driversMap[driver] = true - } - } - return driversMap -} diff --git a/vendor/github.com/containers/storage/drivers/driver_freebsd.go b/vendor/github.com/containers/storage/drivers/driver_freebsd.go deleted file mode 100644 index 53394b738d..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver_freebsd.go +++ /dev/null @@ -1,23 +0,0 @@ -package graphdriver - -import ( - "syscall" - - "golang.org/x/sys/unix" -) - -var ( - // Slice of drivers that should be used in an order - priority = []string{ - "zfs", - } -) - -// Mounted checks if the given path is mounted as the fs type -func Mounted(fsType FsMagic, mountPath string) (bool, error) { - var buf unix.Statfs_t - if err := syscall.Statfs(mountPath, &buf); err != nil { - return false, err - } - return FsMagic(buf.Type) == fsType, nil -} diff --git a/vendor/github.com/containers/storage/drivers/driver_linux.go b/vendor/github.com/containers/storage/drivers/driver_linux.go deleted file mode 100644 index 94f7270eae..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver_linux.go +++ /dev/null @@ -1,135 +0,0 @@ -// +build linux - -package graphdriver - -import ( - "path/filepath" - - "github.com/containers/storage/pkg/mount" - "golang.org/x/sys/unix" -) - -const ( - // FsMagicAufs filesystem id for Aufs - FsMagicAufs = FsMagic(0x61756673) - // FsMagicBtrfs filesystem id for Btrfs - FsMagicBtrfs = FsMagic(0x9123683E) - // FsMagicCramfs filesystem id for Cramfs - FsMagicCramfs = FsMagic(0x28cd3d45) - // FsMagicEcryptfs filesystem id for eCryptfs - FsMagicEcryptfs = FsMagic(0xf15f) - // FsMagicExtfs filesystem id for Extfs - FsMagicExtfs = FsMagic(0x0000EF53) - // FsMagicF2fs filesystem id for F2fs - FsMagicF2fs = FsMagic(0xF2F52010) - // FsMagicGPFS filesystem id for GPFS - FsMagicGPFS = FsMagic(0x47504653) - // FsMagicJffs2Fs filesystem if for Jffs2Fs - FsMagicJffs2Fs = FsMagic(0x000072b6) - // FsMagicJfs filesystem id for Jfs - FsMagicJfs = FsMagic(0x3153464a) - // FsMagicNfsFs filesystem id for NfsFs - FsMagicNfsFs = FsMagic(0x00006969) - // FsMagicRAMFs filesystem id for RamFs - FsMagicRAMFs = FsMagic(0x858458f6) - // FsMagicReiserFs filesystem id for ReiserFs - FsMagicReiserFs = FsMagic(0x52654973) - // FsMagicSmbFs filesystem id for SmbFs - FsMagicSmbFs = FsMagic(0x0000517B) - // FsMagicSquashFs filesystem id for SquashFs - FsMagicSquashFs = FsMagic(0x73717368) - // FsMagicTmpFs filesystem id for TmpFs - FsMagicTmpFs = FsMagic(0x01021994) - // FsMagicVxFS filesystem id for VxFs - FsMagicVxFS = FsMagic(0xa501fcf5) - // FsMagicXfs filesystem id for Xfs - FsMagicXfs = FsMagic(0x58465342) - // FsMagicZfs filesystem id for Zfs - FsMagicZfs = FsMagic(0x2fc12fc1) - // FsMagicOverlay filesystem id for overlay - FsMagicOverlay = FsMagic(0x794C7630) -) - -var ( - // Slice of drivers that should be used in an order - priority = []string{ - "overlay", - "devicemapper", - "aufs", - "btrfs", - "zfs", - "vfs", - } - - // FsNames maps filesystem id to name of the filesystem. - FsNames = map[FsMagic]string{ - FsMagicAufs: "aufs", - FsMagicBtrfs: "btrfs", - FsMagicCramfs: "cramfs", - FsMagicEcryptfs: "ecryptfs", - FsMagicExtfs: "extfs", - FsMagicF2fs: "f2fs", - FsMagicGPFS: "gpfs", - FsMagicJffs2Fs: "jffs2", - FsMagicJfs: "jfs", - FsMagicNfsFs: "nfs", - FsMagicOverlay: "overlayfs", - FsMagicRAMFs: "ramfs", - FsMagicReiserFs: "reiserfs", - FsMagicSmbFs: "smb", - FsMagicSquashFs: "squashfs", - FsMagicTmpFs: "tmpfs", - FsMagicUnsupported: "unsupported", - FsMagicVxFS: "vxfs", - FsMagicXfs: "xfs", - FsMagicZfs: "zfs", - } -) - -// GetFSMagic returns the filesystem id given the path. -func GetFSMagic(rootpath string) (FsMagic, error) { - var buf unix.Statfs_t - if err := unix.Statfs(filepath.Dir(rootpath), &buf); err != nil { - return 0, err - } - return FsMagic(buf.Type), nil -} - -// NewFsChecker returns a checker configured for the provided FsMagic -func NewFsChecker(t FsMagic) Checker { - return &fsChecker{ - t: t, - } -} - -type fsChecker struct { - t FsMagic -} - -func (c *fsChecker) IsMounted(path string) bool { - m, _ := Mounted(c.t, path) - return m -} - -// NewDefaultChecker returns a check that parses /proc/mountinfo to check -// if the specified path is mounted. -func NewDefaultChecker() Checker { - return &defaultChecker{} -} - -type defaultChecker struct { -} - -func (c *defaultChecker) IsMounted(path string) bool { - m, _ := mount.Mounted(path) - return m -} - -// Mounted checks if the given path is mounted as the fs type -func Mounted(fsType FsMagic, mountPath string) (bool, error) { - var buf unix.Statfs_t - if err := unix.Statfs(mountPath, &buf); err != nil { - return false, err - } - return FsMagic(buf.Type) == fsType, nil -} diff --git a/vendor/github.com/containers/storage/drivers/driver_solaris.go b/vendor/github.com/containers/storage/drivers/driver_solaris.go deleted file mode 100644 index 174fa9670b..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver_solaris.go +++ /dev/null @@ -1,96 +0,0 @@ -// +build solaris,cgo - -package graphdriver - -/* -#include -#include - -static inline struct statvfs *getstatfs(char *s) { - struct statvfs *buf; - int err; - buf = (struct statvfs *)malloc(sizeof(struct statvfs)); - err = statvfs(s, buf); - return buf; -} -*/ -import "C" -import ( - "path/filepath" - "unsafe" - - "github.com/containers/storage/pkg/mount" - "github.com/sirupsen/logrus" -) - -const ( - // FsMagicZfs filesystem id for Zfs - FsMagicZfs = FsMagic(0x2fc12fc1) -) - -var ( - // Slice of drivers that should be used in an order - priority = []string{ - "zfs", - } - - // FsNames maps filesystem id to name of the filesystem. - FsNames = map[FsMagic]string{ - FsMagicZfs: "zfs", - } -) - -// GetFSMagic returns the filesystem id given the path. -func GetFSMagic(rootpath string) (FsMagic, error) { - return 0, nil -} - -type fsChecker struct { - t FsMagic -} - -func (c *fsChecker) IsMounted(path string) bool { - m, _ := Mounted(c.t, path) - return m -} - -// NewFsChecker returns a checker configured for the provided FsMagic -func NewFsChecker(t FsMagic) Checker { - return &fsChecker{ - t: t, - } -} - -// NewDefaultChecker returns a check that parses /proc/mountinfo to check -// if the specified path is mounted. -// No-op on Solaris. -func NewDefaultChecker() Checker { - return &defaultChecker{} -} - -type defaultChecker struct { -} - -func (c *defaultChecker) IsMounted(path string) bool { - m, _ := mount.Mounted(path) - return m -} - -// Mounted checks if the given path is mounted as the fs type -//Solaris supports only ZFS for now -func Mounted(fsType FsMagic, mountPath string) (bool, error) { - - cs := C.CString(filepath.Dir(mountPath)) - defer C.free(unsafe.Pointer(cs)) - buf := C.getstatfs(cs) - defer C.free(unsafe.Pointer(buf)) - - // on Solaris buf.f_basetype contains ['z', 'f', 's', 0 ... ] - if (buf.f_basetype[0] != 122) || (buf.f_basetype[1] != 102) || (buf.f_basetype[2] != 115) || - (buf.f_basetype[3] != 0) { - logrus.Debugf("[zfs] no zfs dataset found for rootdir '%s'", mountPath) - return false, ErrPrerequisites - } - - return true, nil -} diff --git a/vendor/github.com/containers/storage/drivers/driver_unsupported.go b/vendor/github.com/containers/storage/drivers/driver_unsupported.go deleted file mode 100644 index 4a875608b0..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver_unsupported.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !linux,!windows,!freebsd,!solaris - -package graphdriver - -var ( - // Slice of drivers that should be used in an order - priority = []string{ - "unsupported", - } -) - -// GetFSMagic returns the filesystem id given the path. -func GetFSMagic(rootpath string) (FsMagic, error) { - return FsMagicUnsupported, nil -} diff --git a/vendor/github.com/containers/storage/drivers/driver_windows.go b/vendor/github.com/containers/storage/drivers/driver_windows.go deleted file mode 100644 index ffd30c2950..0000000000 --- a/vendor/github.com/containers/storage/drivers/driver_windows.go +++ /dev/null @@ -1,14 +0,0 @@ -package graphdriver - -var ( - // Slice of drivers that should be used in order - priority = []string{ - "windowsfilter", - } -) - -// GetFSMagic returns the filesystem id given the path. -func GetFSMagic(rootpath string) (FsMagic, error) { - // Note it is OK to return FsMagicUnsupported on Windows. - return FsMagicUnsupported, nil -} diff --git a/vendor/github.com/containers/storage/drivers/fsdiff.go b/vendor/github.com/containers/storage/drivers/fsdiff.go deleted file mode 100644 index f74239cb93..0000000000 --- a/vendor/github.com/containers/storage/drivers/fsdiff.go +++ /dev/null @@ -1,169 +0,0 @@ -package graphdriver - -import ( - "io" - "time" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/ioutils" - "github.com/sirupsen/logrus" -) - -var ( - // ApplyUncompressedLayer defines the unpack method used by the graph - // driver. - ApplyUncompressedLayer = chrootarchive.ApplyUncompressedLayer -) - -// NaiveDiffDriver takes a ProtoDriver and adds the -// capability of the Diffing methods which it may or may not -// support on its own. See the comment on the exported -// NewNaiveDiffDriver function below. -// Notably, the AUFS driver doesn't need to be wrapped like this. -type NaiveDiffDriver struct { - ProtoDriver - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap -} - -// NewNaiveDiffDriver returns a fully functional driver that wraps the -// given ProtoDriver and adds the capability of the following methods which -// it may or may not support on its own: -// Diff(id, parent, mountLabel string) (io.ReadCloser, error) -// Changes(id, parent, mountLabel string) ([]archive.Change, error) -// ApplyDiff(id, parent, mountLabel string, diff io.Reader) (size int64, err error) -// DiffSize(id, parent, mountLabel string) (size int64, err error) -func NewNaiveDiffDriver(driver ProtoDriver, uidMaps, gidMaps []idtools.IDMap) Driver { - return &NaiveDiffDriver{ProtoDriver: driver, - uidMaps: uidMaps, - gidMaps: gidMaps} -} - -// Diff produces an archive of the changes between the specified -// layer and its parent layer which may be "". -func (gdw *NaiveDiffDriver) Diff(id, parent, mountLabel string) (arch io.ReadCloser, err error) { - startTime := time.Now() - driver := gdw.ProtoDriver - - layerFs, err := driver.Get(id, mountLabel) - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - driver.Put(id) - } - }() - - if parent == "" { - archive, err := archive.Tar(layerFs, archive.Uncompressed) - if err != nil { - return nil, err - } - return ioutils.NewReadCloserWrapper(archive, func() error { - err := archive.Close() - driver.Put(id) - return err - }), nil - } - - parentFs, err := driver.Get(parent, mountLabel) - if err != nil { - return nil, err - } - defer driver.Put(parent) - - changes, err := archive.ChangesDirs(layerFs, parentFs) - if err != nil { - return nil, err - } - - archive, err := archive.ExportChanges(layerFs, changes, gdw.uidMaps, gdw.gidMaps) - if err != nil { - return nil, err - } - - return ioutils.NewReadCloserWrapper(archive, func() error { - err := archive.Close() - driver.Put(id) - - // NaiveDiffDriver compares file metadata with parent layers. Parent layers - // are extracted from tar's with full second precision on modified time. - // We need this hack here to make sure calls within same second receive - // correct result. - time.Sleep(startTime.Truncate(time.Second).Add(time.Second).Sub(time.Now())) - return err - }), nil -} - -// Changes produces a list of changes between the specified layer -// and its parent layer. If parent is "", then all changes will be ADD changes. -func (gdw *NaiveDiffDriver) Changes(id, parent, mountLabel string) ([]archive.Change, error) { - driver := gdw.ProtoDriver - - layerFs, err := driver.Get(id, mountLabel) - if err != nil { - return nil, err - } - defer driver.Put(id) - - parentFs := "" - - if parent != "" { - parentFs, err = driver.Get(parent, mountLabel) - if err != nil { - return nil, err - } - defer driver.Put(parent) - } - - return archive.ChangesDirs(layerFs, parentFs) -} - -// ApplyDiff extracts the changeset from the given diff into the -// layer with the specified id and parent, returning the size of the -// new layer in bytes. -func (gdw *NaiveDiffDriver) ApplyDiff(id, parent, mountLabel string, diff io.Reader) (size int64, err error) { - driver := gdw.ProtoDriver - - // Mount the root filesystem so we can apply the diff/layer. - layerFs, err := driver.Get(id, mountLabel) - if err != nil { - return - } - defer driver.Put(id) - - options := &archive.TarOptions{UIDMaps: gdw.uidMaps, - GIDMaps: gdw.gidMaps} - start := time.Now().UTC() - logrus.Debug("Start untar layer") - if size, err = ApplyUncompressedLayer(layerFs, diff, options); err != nil { - return - } - logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) - - return -} - -// DiffSize calculates the changes between the specified layer -// and its parent and returns the size in bytes of the changes -// relative to its base filesystem directory. -func (gdw *NaiveDiffDriver) DiffSize(id, parent, mountLabel string) (size int64, err error) { - driver := gdw.ProtoDriver - - changes, err := gdw.Changes(id, parent, mountLabel) - if err != nil { - return - } - - layerFs, err := driver.Get(id, mountLabel) - if err != nil { - return - } - defer driver.Put(id) - - return archive.ChangesSize(layerFs, changes), nil -} diff --git a/vendor/github.com/containers/storage/drivers/overlay/check.go b/vendor/github.com/containers/storage/drivers/overlay/check.go deleted file mode 100644 index 2a096edf6f..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlay/check.go +++ /dev/null @@ -1,102 +0,0 @@ -// +build linux - -package overlay - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "syscall" - - "github.com/containers/storage/pkg/system" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// doesSupportNativeDiff checks whether the filesystem has a bug -// which copies up the opaque flag when copying up an opaque -// directory or the kernel enable CONFIG_OVERLAY_FS_REDIRECT_DIR. -// When these exist naive diff should be used. -func doesSupportNativeDiff(d string) error { - td, err := ioutil.TempDir(d, "opaque-bug-check") - if err != nil { - return err - } - defer func() { - if err := os.RemoveAll(td); err != nil { - logrus.Warnf("Failed to remove check directory %v: %v", td, err) - } - }() - - // Make directories l1/d, l1/d1, l2/d, l3, work, merged - if err := os.MkdirAll(filepath.Join(td, "l1", "d"), 0755); err != nil { - return err - } - if err := os.MkdirAll(filepath.Join(td, "l1", "d1"), 0755); err != nil { - return err - } - if err := os.MkdirAll(filepath.Join(td, "l2", "d"), 0755); err != nil { - return err - } - if err := os.Mkdir(filepath.Join(td, "l3"), 0755); err != nil { - return err - } - if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { - return err - } - if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { - return err - } - - // Mark l2/d as opaque - if err := system.Lsetxattr(filepath.Join(td, "l2", "d"), "trusted.overlay.opaque", []byte("y"), 0); err != nil { - return errors.Wrap(err, "failed to set opaque flag on middle layer") - } - - opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "l2"), path.Join(td, "l1"), path.Join(td, "l3"), path.Join(td, "work")) - if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { - return errors.Wrap(err, "failed to mount overlay") - } - defer func() { - if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil { - logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err) - } - }() - - // Touch file in d to force copy up of opaque directory "d" from "l2" to "l3" - if err := ioutil.WriteFile(filepath.Join(td, "merged", "d", "f"), []byte{}, 0644); err != nil { - return errors.Wrap(err, "failed to write to merged directory") - } - - // Check l3/d does not have opaque flag - xattrOpaque, err := system.Lgetxattr(filepath.Join(td, "l3", "d"), "trusted.overlay.opaque") - if err != nil { - return errors.Wrap(err, "failed to read opaque flag on upper layer") - } - if string(xattrOpaque) == "y" { - return errors.New("opaque flag erroneously copied up, consider update to kernel 4.8 or later to fix") - } - - // rename "d1" to "d2" - if err := os.Rename(filepath.Join(td, "merged", "d1"), filepath.Join(td, "merged", "d2")); err != nil { - // if rename failed with syscall.EXDEV, the kernel doesn't have CONFIG_OVERLAY_FS_REDIRECT_DIR enabled - if err.(*os.LinkError).Err == syscall.EXDEV { - return nil - } - return errors.Wrap(err, "failed to rename dir in merged directory") - } - // get the xattr of "d2" - xattrRedirect, err := system.Lgetxattr(filepath.Join(td, "l3", "d2"), "trusted.overlay.redirect") - if err != nil { - return errors.Wrap(err, "failed to read redirect flag on upper layer") - } - - if string(xattrRedirect) == "d1" { - return errors.New("kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled") - } - - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/overlay/mount.go b/vendor/github.com/containers/storage/drivers/overlay/mount.go deleted file mode 100644 index feb0395924..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlay/mount.go +++ /dev/null @@ -1,89 +0,0 @@ -// +build linux - -package overlay - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "os" - "runtime" - - "github.com/containers/storage/pkg/reexec" - "golang.org/x/sys/unix" -) - -func init() { - reexec.Register("storage-mountfrom", mountFromMain) -} - -func fatal(err error) { - fmt.Fprint(os.Stderr, err) - os.Exit(1) -} - -type mountOptions struct { - Device string - Target string - Type string - Label string - Flag uint32 -} - -func mountFrom(dir, device, target, mType string, flags uintptr, label string) error { - options := &mountOptions{ - Device: device, - Target: target, - Type: mType, - Flag: uint32(flags), - Label: label, - } - - cmd := reexec.Command("storage-mountfrom", dir) - w, err := cmd.StdinPipe() - if err != nil { - return fmt.Errorf("mountfrom error on pipe creation: %v", err) - } - - output := bytes.NewBuffer(nil) - cmd.Stdout = output - cmd.Stderr = output - if err := cmd.Start(); err != nil { - w.Close() - return fmt.Errorf("mountfrom error on re-exec cmd: %v", err) - } - //write the options to the pipe for the untar exec to read - if err := json.NewEncoder(w).Encode(options); err != nil { - w.Close() - return fmt.Errorf("mountfrom json encode to pipe failed: %v", err) - } - w.Close() - - if err := cmd.Wait(); err != nil { - return fmt.Errorf("mountfrom re-exec error: %v: output: %v", err, output) - } - return nil -} - -// mountfromMain is the entry-point for storage-mountfrom on re-exec. -func mountFromMain() { - runtime.LockOSThread() - flag.Parse() - - var options *mountOptions - - if err := json.NewDecoder(os.Stdin).Decode(&options); err != nil { - fatal(err) - } - - if err := os.Chdir(flag.Arg(0)); err != nil { - fatal(err) - } - - if err := unix.Mount(options.Device, options.Target, options.Type, uintptr(options.Flag), options.Label); err != nil { - fatal(err) - } - - os.Exit(0) -} diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go deleted file mode 100644 index 4458b679ab..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ /dev/null @@ -1,773 +0,0 @@ -// +build linux - -package overlay - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "strconv" - "strings" - "sync" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/drivers/overlayutils" - "github.com/containers/storage/drivers/quota" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/directory" - "github.com/containers/storage/pkg/fsutils" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/locker" - "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/parsers" - "github.com/containers/storage/pkg/system" - units "github.com/docker/go-units" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -var ( - // untar defines the untar method - untar = chrootarchive.UntarUncompressed -) - -// This backend uses the overlay union filesystem for containers -// with diff directories for each layer. - -// This version of the overlay driver requires at least kernel -// 4.0.0 in order to support mounting multiple diff directories. - -// Each container/image has at least a "diff" directory and "link" file. -// If there is also a "lower" file when there are diff layers -// below as well as "merged" and "work" directories. The "diff" directory -// has the upper layer of the overlay and is used to capture any -// changes to the layer. The "lower" file contains all the lower layer -// mounts separated by ":" and ordered from uppermost to lowermost -// layers. The overlay itself is mounted in the "merged" directory, -// and the "work" dir is needed for overlay to work. - -// The "link" file for each layer contains a unique string for the layer. -// Under the "l" directory at the root there will be a symbolic link -// with that unique string pointing the "diff" directory for the layer. -// The symbolic links are used to reference lower layers in the "lower" -// file and on mount. The links are used to shorten the total length -// of a layer reference without requiring changes to the layer identifier -// or root directory. Mounts are always done relative to root and -// referencing the symbolic links in order to ensure the number of -// lower directories can fit in a single page for making the mount -// syscall. A hard upper limit of 128 lower layers is enforced to ensure -// that mounts do not fail due to length. - -const ( - linkDir = "l" - lowerFile = "lower" - maxDepth = 128 - - // idLength represents the number of random characters - // which can be used to create the unique link identifer - // for every layer. If this value is too long then the - // page size limit for the mount command may be exceeded. - // The idLength should be selected such that following equation - // is true (512 is a buffer for label metadata). - // ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512) - idLength = 26 -) - -type overlayOptions struct { - overrideKernelCheck bool - imageStores []string - quota quota.Quota -} - -// Driver contains information about the home directory and the list of active mounts that are created using this driver. -type Driver struct { - name string - home string - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - ctr *graphdriver.RefCounter - quotaCtl *quota.Control - options overlayOptions - naiveDiff graphdriver.DiffDriver - supportsDType bool - locker *locker.Locker -} - -var ( - backingFs = "" - projectQuotaSupported = false - - useNaiveDiffLock sync.Once - useNaiveDiffOnly bool -) - -func init() { - graphdriver.Register("overlay", Init) - graphdriver.Register("overlay2", Init) -} - -// Init returns the a native diff driver for overlay filesystem. -// If overlay filesystem is not supported on the host, graphdriver.ErrNotSupported is returned as error. -// If an overlay filesystem is not supported over an existing filesystem then error graphdriver.ErrIncompatibleFS is returned. -func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - opts, err := parseOptions(options) - if err != nil { - return nil, err - } - - fsMagic, err := graphdriver.GetFSMagic(home) - if err != nil { - return nil, err - } - if fsName, ok := graphdriver.FsNames[fsMagic]; ok { - backingFs = fsName - } - - // check if they are running over btrfs, aufs, zfs, overlay, or ecryptfs - switch fsMagic { - case graphdriver.FsMagicAufs, graphdriver.FsMagicZfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicEcryptfs: - logrus.Errorf("'overlay' is not supported over %s", backingFs) - return nil, errors.Wrapf(graphdriver.ErrIncompatibleFS, "'overlay' is not supported over %s", backingFs) - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, err - } - - // Create the driver home dir - if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { - return nil, err - } - - supportsDType, err := supportsOverlay(home, fsMagic, rootUID, rootGID) - if err != nil { - os.Remove(filepath.Join(home, linkDir)) - os.Remove(home) - return nil, errors.Wrap(graphdriver.ErrNotSupported, "kernel does not support overlay fs") - } - - if err := mount.MakePrivate(home); err != nil { - return nil, err - } - - d := &Driver{ - name: "overlay", - home: home, - uidMaps: uidMaps, - gidMaps: gidMaps, - ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)), - supportsDType: supportsDType, - locker: locker.New(), - options: *opts, - } - - d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps) - - if backingFs == "xfs" { - // Try to enable project quota support over xfs. - if d.quotaCtl, err = quota.NewControl(home); err == nil { - projectQuotaSupported = true - } else if opts.quota.Size > 0 { - return nil, fmt.Errorf("Storage option overlay.size not supported. Filesystem does not support Project Quota: %v", err) - } - } else if opts.quota.Size > 0 { - // if xfs is not the backing fs then error out if the storage-opt overlay.size is used. - return nil, fmt.Errorf("Storage option overlay.size only supported for backingFS XFS. Found %v", backingFs) - } - - logrus.Debugf("backingFs=%s, projectQuotaSupported=%v, useNativeDiff=%v", backingFs, projectQuotaSupported, !useNaiveDiff(home)) - - return d, nil -} - -func parseOptions(options []string) (*overlayOptions, error) { - o := &overlayOptions{} - for _, option := range options { - key, val, err := parsers.ParseKeyValueOpt(option) - if err != nil { - return nil, err - } - key = strings.ToLower(key) - switch key { - case ".override_kernel_check", "overlay.override_kernel_check", "overlay2.override_kernel_check": - logrus.Debugf("overlay: override_kernelcheck=%s", val) - o.overrideKernelCheck, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } - case ".size", "overlay.size", "overlay2.size": - logrus.Debugf("overlay: size=%s", val) - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - o.quota.Size = uint64(size) - case ".imagestore", "overlay.imagestore", "overlay2.imagestore": - logrus.Debugf("overlay: imagestore=%s", val) - // Additional read only image stores to use for lower paths - for _, store := range strings.Split(val, ",") { - store = filepath.Clean(store) - if !filepath.IsAbs(store) { - return nil, fmt.Errorf("overlay: image path %q is not absolute. Can not be relative", store) - } - st, err := os.Stat(store) - if err != nil { - return nil, fmt.Errorf("overlay: can't stat imageStore dir %s: %v", store, err) - } - if !st.IsDir() { - return nil, fmt.Errorf("overlay: image path %q must be a directory", store) - } - o.imageStores = append(o.imageStores, store) - } - default: - return nil, fmt.Errorf("overlay: Unknown option %s", key) - } - } - return o, nil -} - -func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGID int) (supportsDType bool, err error) { - // We can try to modprobe overlay first - exec.Command("modprobe", "overlay").Run() - - layerDir, err := ioutil.TempDir(home, "compat") - if err == nil { - // Check if reading the directory's contents populates the d_type field, which is required - // for proper operation of the overlay filesystem. - supportsDType, err = fsutils.SupportsDType(layerDir) - if err != nil { - return false, err - } - if !supportsDType { - return false, overlayutils.ErrDTypeNotSupported("overlay", backingFs) - } - - // Try a test mount in the specific location we're looking at using. - mergedDir := filepath.Join(layerDir, "merged") - lower1Dir := filepath.Join(layerDir, "lower1") - lower2Dir := filepath.Join(layerDir, "lower2") - defer func() { - // Permitted to fail, since the various subdirectories - // can be empty or not even there, and the home might - // legitimately be not empty - _ = unix.Unmount(mergedDir, unix.MNT_DETACH) - _ = os.RemoveAll(layerDir) - _ = os.Remove(home) - }() - _ = idtools.MkdirAs(mergedDir, 0700, rootUID, rootGID) - _ = idtools.MkdirAs(lower1Dir, 0700, rootUID, rootGID) - _ = idtools.MkdirAs(lower2Dir, 0700, rootUID, rootGID) - flags := fmt.Sprintf("lowerdir=%s:%s", lower1Dir, lower2Dir) - if len(flags) < unix.Getpagesize() { - if mountFrom(filepath.Dir(home), "overlay", mergedDir, "overlay", 0, flags) == nil { - logrus.Debugf("overlay test mount with multiple lowers succeeded") - return supportsDType, nil - } - } - flags = fmt.Sprintf("lowerdir=%s", lower1Dir) - if len(flags) < unix.Getpagesize() { - if mountFrom(filepath.Dir(home), "overlay", mergedDir, "overlay", 0, flags) == nil { - logrus.Errorf("overlay test mount with multiple lowers failed, but succeeded with a single lower") - return supportsDType, errors.Wrap(graphdriver.ErrNotSupported, "kernel too old to provide multiple lowers feature for overlay") - } - } - logrus.Errorf("'overlay' is not supported over %s at %q", backingFs, home) - return supportsDType, errors.Wrapf(graphdriver.ErrIncompatibleFS, "'overlay' is not supported over %s at %q", backingFs, home) - } - - logrus.Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.") - return supportsDType, errors.Wrap(graphdriver.ErrNotSupported, "'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.") -} - -func useNaiveDiff(home string) bool { - useNaiveDiffLock.Do(func() { - if err := doesSupportNativeDiff(home); err != nil { - logrus.Warnf("Not using native diff for overlay, this may cause degraded performance for building images: %v", err) - useNaiveDiffOnly = true - } - }) - return useNaiveDiffOnly -} - -func (d *Driver) String() string { - return d.name -} - -// Status returns current driver information in a two dimensional string array. -// Output contains "Backing Filesystem" used in this implementation. -func (d *Driver) Status() [][2]string { - return [][2]string{ - {"Backing Filesystem", backingFs}, - {"Supports d_type", strconv.FormatBool(d.supportsDType)}, - {"Native Overlay Diff", strconv.FormatBool(!useNaiveDiff(d.home))}, - } -} - -// Metadata returns meta data about the overlay driver such as -// LowerDir, UpperDir, WorkDir and MergeDir used to store data. -func (d *Driver) Metadata(id string) (map[string]string, error) { - dir := d.dir(id) - if _, err := os.Stat(dir); err != nil { - return nil, err - } - - metadata := map[string]string{ - "WorkDir": path.Join(dir, "work"), - "MergedDir": path.Join(dir, "merged"), - "UpperDir": path.Join(dir, "diff"), - } - - lowerDirs, err := d.getLowerDirs(id) - if err != nil { - return nil, err - } - if len(lowerDirs) > 0 { - metadata["LowerDir"] = strings.Join(lowerDirs, ":") - } - - return metadata, nil -} - -// Cleanup any state created by overlay which should be cleaned when daemon -// is being shutdown. For now, we just have to unmount the bind mounted -// we had created. -func (d *Driver) Cleanup() error { - return mount.Unmount(d.home) -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - if opts != nil && len(opts.StorageOpt) != 0 && !projectQuotaSupported { - return fmt.Errorf("--storage-opt is supported only for overlay over xfs with 'pquota' mount option") - } - - if opts == nil { - opts = &graphdriver.CreateOpts{ - StorageOpt: map[string]string{}, - } - } - - if _, ok := opts.StorageOpt["size"]; !ok { - if opts.StorageOpt == nil { - opts.StorageOpt = map[string]string{} - } - opts.StorageOpt["size"] = strconv.FormatUint(d.options.quota.Size, 10) - } - - return d.create(id, parent, opts) -} - -// Create is used to create the upper, lower, and merge directories required for overlay fs for a given id. -// The parent filesystem is used to configure these directories for the overlay. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) { - if opts != nil && len(opts.StorageOpt) != 0 { - if _, ok := opts.StorageOpt["size"]; ok { - return fmt.Errorf("--storage-opt size is only supported for ReadWrite Layers") - } - } - return d.create(id, parent, opts) -} - -func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) { - dir := d.dir(id) - - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - return err - } - if err := idtools.MkdirAllAs(path.Dir(dir), 0700, rootUID, rootGID); err != nil { - return err - } - if err := idtools.MkdirAs(dir, 0700, rootUID, rootGID); err != nil { - return err - } - - defer func() { - // Clean up on failure - if retErr != nil { - os.RemoveAll(dir) - } - }() - - if opts != nil && len(opts.StorageOpt) > 0 { - driver := &Driver{} - if err := d.parseStorageOpt(opts.StorageOpt, driver); err != nil { - return err - } - - if driver.options.quota.Size > 0 { - // Set container disk quota limit - if err := d.quotaCtl.SetQuota(dir, driver.options.quota); err != nil { - return err - } - } - } - - if err := idtools.MkdirAs(path.Join(dir, "diff"), 0755, rootUID, rootGID); err != nil { - return err - } - - lid := generateID(idLength) - if err := os.Symlink(path.Join("..", id, "diff"), path.Join(d.home, linkDir, lid)); err != nil { - return err - } - - // Write link id to link file - if err := ioutil.WriteFile(path.Join(dir, "link"), []byte(lid), 0644); err != nil { - return err - } - - if err := idtools.MkdirAs(path.Join(dir, "work"), 0700, rootUID, rootGID); err != nil { - return err - } - if err := idtools.MkdirAs(path.Join(dir, "merged"), 0700, rootUID, rootGID); err != nil { - return err - } - - // if no parent directory, create a dummy lower directory and skip writing a "lowers" file - if parent == "" { - return idtools.MkdirAs(path.Join(dir, "empty"), 0700, rootUID, rootGID) - } - - lower, err := d.getLower(parent) - if err != nil { - return err - } - if lower != "" { - if err := ioutil.WriteFile(path.Join(dir, lowerFile), []byte(lower), 0666); err != nil { - return err - } - } - - return nil -} - -// Parse overlay storage options -func (d *Driver) parseStorageOpt(storageOpt map[string]string, driver *Driver) error { - // Read size to set the disk project quota per container - for key, val := range storageOpt { - key := strings.ToLower(key) - switch key { - case "size": - size, err := units.RAMInBytes(val) - if err != nil { - return err - } - driver.options.quota.Size = uint64(size) - default: - return fmt.Errorf("Unknown option %s", key) - } - } - - return nil -} - -func (d *Driver) getLower(parent string) (string, error) { - parentDir := d.dir(parent) - - // Ensure parent exists - if _, err := os.Lstat(parentDir); err != nil { - return "", err - } - - // Read Parent link fileA - parentLink, err := ioutil.ReadFile(path.Join(parentDir, "link")) - if err != nil { - return "", err - } - lowers := []string{path.Join(linkDir, string(parentLink))} - - parentLower, err := ioutil.ReadFile(path.Join(parentDir, lowerFile)) - if err == nil { - parentLowers := strings.Split(string(parentLower), ":") - lowers = append(lowers, parentLowers...) - } - if len(lowers) > maxDepth { - return "", errors.New("max depth exceeded") - } - return strings.Join(lowers, ":"), nil -} - -func (d *Driver) dir(id string) string { - newpath := path.Join(d.home, id) - if _, err := os.Stat(newpath); err != nil { - for _, p := range d.AdditionalImageStores() { - l := path.Join(p, d.name, id) - _, err = os.Stat(l) - if err == nil { - return l - } - } - } - return newpath -} - -func (d *Driver) getLowerDirs(id string) ([]string, error) { - var lowersArray []string - lowers, err := ioutil.ReadFile(path.Join(d.dir(id), lowerFile)) - if err == nil { - for _, s := range strings.Split(string(lowers), ":") { - lower := d.dir(s) - lp, err := os.Readlink(lower) - if err != nil { - return nil, err - } - lowersArray = append(lowersArray, path.Clean(d.dir(path.Join("link", lp)))) - } - } else if !os.IsNotExist(err) { - return nil, err - } - return lowersArray, nil -} - -// Remove cleans the directories that are created for this id. -func (d *Driver) Remove(id string) error { - d.locker.Lock(id) - defer d.locker.Unlock(id) - dir := d.dir(id) - lid, err := ioutil.ReadFile(path.Join(dir, "link")) - if err == nil { - if err := os.RemoveAll(path.Join(d.home, linkDir, string(lid))); err != nil { - logrus.Debugf("Failed to remove link: %v", err) - } - } - - if err := system.EnsureRemoveAll(dir); err != nil && !os.IsNotExist(err) { - return err - } - return nil -} - -// Get creates and mounts the required file system for the given id and returns the mount path. -func (d *Driver) Get(id, mountLabel string) (_ string, retErr error) { - d.locker.Lock(id) - defer d.locker.Unlock(id) - dir := d.dir(id) - if _, err := os.Stat(dir); err != nil { - return "", err - } - - diffDir := path.Join(dir, "diff") - lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile)) - if err != nil && !os.IsNotExist(err) { - return "", err - } - - newlowers := "" - for _, l := range strings.Split(string(lowers), ":") { - lower := "" - newpath := path.Join(d.home, l) - if _, err := os.Stat(newpath); err != nil { - for _, p := range d.AdditionalImageStores() { - lower = path.Join(p, d.name, l) - if _, err2 := os.Stat(lower); err2 == nil { - break - } - lower = "" - } - if lower == "" { - return "", fmt.Errorf("Can't stat lower layer %q: %v", newpath, err) - } - } else { - lower = newpath - } - if newlowers == "" { - newlowers = lower - } else { - newlowers = newlowers + ":" + lower - } - } - if len(lowers) == 0 { - newlowers = path.Join(dir, "empty") - lowers = []byte(newlowers) - } - - mergedDir := path.Join(dir, "merged") - if count := d.ctr.Increment(mergedDir); count > 1 { - return mergedDir, nil - } - defer func() { - if retErr != nil { - if c := d.ctr.Decrement(mergedDir); c <= 0 { - if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil { - logrus.Errorf("error unmounting %v: %v", mergedDir, mntErr) - } - } - } - }() - - workDir := path.Join(dir, "work") - opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", newlowers, diffDir, workDir) - mountData := label.FormatMountLabel(opts, mountLabel) - mount := unix.Mount - mountTarget := mergedDir - - pageSize := unix.Getpagesize() - - // Use relative paths and mountFrom when the mount data has exceeded - // the page size. The mount syscall fails if the mount data cannot - // fit within a page and relative links make the mount data much - // smaller at the expense of requiring a fork exec to chroot. - if len(mountData) > pageSize { - //FIXME: We need to figure out to get this to work with additional stores - opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work")) - mountData = label.FormatMountLabel(opts, mountLabel) - if len(mountData) > pageSize { - return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData)) - } - - mount = func(source string, target string, mType string, flags uintptr, label string) error { - return mountFrom(d.home, source, target, mType, flags, label) - } - mountTarget = path.Join(id, "merged") - } - if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil { - return "", fmt.Errorf("error creating overlay mount to %s: %v", mountTarget, err) - } - - // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a - // user namespace requires this to move a directory from lower to upper. - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - return "", err - } - - if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { - return "", err - } - - return mergedDir, nil -} - -// Put unmounts the mount path created for the give id. -func (d *Driver) Put(id string) error { - d.locker.Lock(id) - defer d.locker.Unlock(id) - dir := d.dir(id) - if _, err := os.Stat(dir); err != nil { - return err - } - mountpoint := path.Join(d.dir(id), "merged") - if count := d.ctr.Decrement(mountpoint); count > 0 { - return nil - } - if _, err := ioutil.ReadFile(path.Join(dir, lowerFile)); err != nil && !os.IsNotExist(err) { - return err - } - if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil { - logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err) - } - return nil -} - -// Exists checks to see if the id is already mounted. -func (d *Driver) Exists(id string) bool { - _, err := os.Stat(d.dir(id)) - return err == nil -} - -// isParent returns if the passed in parent is the direct parent of the passed in layer -func (d *Driver) isParent(id, parent string) bool { - lowers, err := d.getLowerDirs(id) - if err != nil { - return false - } - if parent == "" && len(lowers) > 0 { - return false - } - - parentDir := d.dir(parent) - var ld string - if len(lowers) > 0 { - ld = filepath.Dir(lowers[0]) - } - if ld == "" && parent == "" { - return true - } - return ld == parentDir -} - -// ApplyDiff applies the new layer into a root -func (d *Driver) ApplyDiff(id, parent, mountLabel string, diff io.Reader) (size int64, err error) { - if !d.isParent(id, parent) { - return d.naiveDiff.ApplyDiff(id, parent, mountLabel, diff) - } - - applyDir := d.getDiffPath(id) - - logrus.Debugf("Applying tar in %s", applyDir) - // Overlay doesn't need the parent id to apply the diff - if err := untar(diff, applyDir, &archive.TarOptions{ - UIDMaps: d.uidMaps, - GIDMaps: d.gidMaps, - WhiteoutFormat: archive.OverlayWhiteoutFormat, - }); err != nil { - return 0, err - } - - return directory.Size(applyDir) -} - -func (d *Driver) getDiffPath(id string) string { - dir := d.dir(id) - - return path.Join(dir, "diff") -} - -// DiffSize calculates the changes between the specified id -// and its parent and returns the size in bytes of the changes -// relative to its base filesystem directory. -func (d *Driver) DiffSize(id, parent, mountLabel string) (size int64, err error) { - if useNaiveDiff(d.home) || !d.isParent(id, parent) { - return d.naiveDiff.DiffSize(id, parent, mountLabel) - } - return directory.Size(d.getDiffPath(id)) -} - -// Diff produces an archive of the changes between the specified -// layer and its parent layer which may be "". -func (d *Driver) Diff(id, parent, mountLabel string) (io.ReadCloser, error) { - if useNaiveDiff(d.home) || !d.isParent(id, parent) { - return d.naiveDiff.Diff(id, parent, mountLabel) - } - - diffPath := d.getDiffPath(id) - logrus.Debugf("Tar with options on %s", diffPath) - return archive.TarWithOptions(diffPath, &archive.TarOptions{ - Compression: archive.Uncompressed, - UIDMaps: d.uidMaps, - GIDMaps: d.gidMaps, - WhiteoutFormat: archive.OverlayWhiteoutFormat, - }) -} - -// Changes produces a list of changes between the specified layer -// and its parent layer. If parent is "", then all changes will be ADD changes. -func (d *Driver) Changes(id, parent, mountLabel string) ([]archive.Change, error) { - if useNaiveDiff(d.home) || !d.isParent(id, parent) { - return d.naiveDiff.Changes(id, parent, mountLabel) - } - // Overlay doesn't have snapshots, so we need to get changes from all parent - // layers. - diffPath := d.getDiffPath(id) - layers, err := d.getLowerDirs(id) - if err != nil { - return nil, err - } - - return archive.OverlayChanges(layers, diffPath) -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - return d.options.imageStores -} diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay_unsupported.go b/vendor/github.com/containers/storage/drivers/overlay/overlay_unsupported.go deleted file mode 100644 index 3dbb4de44e..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay_unsupported.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build !linux - -package overlay diff --git a/vendor/github.com/containers/storage/drivers/overlay/randomid.go b/vendor/github.com/containers/storage/drivers/overlay/randomid.go deleted file mode 100644 index fc565ef0ba..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlay/randomid.go +++ /dev/null @@ -1,81 +0,0 @@ -// +build linux - -package overlay - -import ( - "crypto/rand" - "encoding/base32" - "fmt" - "io" - "os" - "syscall" - "time" - - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// generateID creates a new random string identifier with the given length -func generateID(l int) string { - const ( - // ensures we backoff for less than 450ms total. Use the following to - // select new value, in units of 10ms: - // n*(n+1)/2 = d -> n^2 + n - 2d -> n = (sqrt(8d + 1) - 1)/2 - maxretries = 9 - backoff = time.Millisecond * 10 - ) - - var ( - totalBackoff time.Duration - count int - retries int - size = (l*5 + 7) / 8 - u = make([]byte, size) - ) - // TODO: Include time component, counter component, random component - - for { - // This should never block but the read may fail. Because of this, - // we just try to read the random number generator until we get - // something. This is a very rare condition but may happen. - b := time.Duration(retries) * backoff - time.Sleep(b) - totalBackoff += b - - n, err := io.ReadFull(rand.Reader, u[count:]) - if err != nil { - if retryOnError(err) && retries < maxretries { - count += n - retries++ - logrus.Errorf("error generating version 4 uuid, retrying: %v", err) - continue - } - - // Any other errors represent a system problem. What did someone - // do to /dev/urandom? - panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff.String(), err)) - } - - break - } - - s := base32.StdEncoding.EncodeToString(u) - - return s[:l] -} - -// retryOnError tries to detect whether or not retrying would be fruitful. -func retryOnError(err error) bool { - switch err := err.(type) { - case *os.PathError: - return retryOnError(err.Err) // unpack the target error - case syscall.Errno: - if err == unix.EPERM { - // EPERM represents an entropy pool exhaustion, a condition under - // which we backoff and retry. - return true - } - } - - return false -} diff --git a/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go b/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go deleted file mode 100644 index 467733647c..0000000000 --- a/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build linux - -package overlayutils - -import ( - "errors" - "fmt" -) - -// ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type. -func ErrDTypeNotSupported(driver, backingFs string) error { - msg := fmt.Sprintf("%s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.", driver, backingFs) - if backingFs == "xfs" { - msg += " Reformat the filesystem with ftype=1 to enable d_type support." - } - msg += " Running without d_type is not supported." - return errors.New(msg) -} diff --git a/vendor/github.com/containers/storage/drivers/quota/projectquota.go b/vendor/github.com/containers/storage/drivers/quota/projectquota.go deleted file mode 100644 index 93e7443713..0000000000 --- a/vendor/github.com/containers/storage/drivers/quota/projectquota.go +++ /dev/null @@ -1,337 +0,0 @@ -// +build linux - -// -// projectquota.go - implements XFS project quota controls -// for setting quota limits on a newly created directory. -// It currently supports the legacy XFS specific ioctls. -// -// TODO: use generic quota control ioctl FS_IOC_FS{GET,SET}XATTR -// for both xfs/ext4 for kernel version >= v4.5 -// - -package quota - -/* -#include -#include -#include -#include -#include - -#ifndef FS_XFLAG_PROJINHERIT -struct fsxattr { - __u32 fsx_xflags; - __u32 fsx_extsize; - __u32 fsx_nextents; - __u32 fsx_projid; - unsigned char fsx_pad[12]; -}; -#define FS_XFLAG_PROJINHERIT 0x00000200 -#endif -#ifndef FS_IOC_FSGETXATTR -#define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) -#endif -#ifndef FS_IOC_FSSETXATTR -#define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) -#endif - -#ifndef PRJQUOTA -#define PRJQUOTA 2 -#endif -#ifndef XFS_PROJ_QUOTA -#define XFS_PROJ_QUOTA 2 -#endif -#ifndef Q_XSETPQLIM -#define Q_XSETPQLIM QCMD(Q_XSETQLIM, PRJQUOTA) -#endif -#ifndef Q_XGETPQUOTA -#define Q_XGETPQUOTA QCMD(Q_XGETQUOTA, PRJQUOTA) -#endif -*/ -import "C" -import ( - "fmt" - "io/ioutil" - "path" - "path/filepath" - "unsafe" - - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// Quota limit params - currently we only control blocks hard limit -type Quota struct { - Size uint64 -} - -// Control - Context to be used by storage driver (e.g. overlay) -// who wants to apply project quotas to container dirs -type Control struct { - backingFsBlockDev string - nextProjectID uint32 - quotas map[string]uint32 -} - -// NewControl - initialize project quota support. -// Test to make sure that quota can be set on a test dir and find -// the first project id to be used for the next container create. -// -// Returns nil (and error) if project quota is not supported. -// -// First get the project id of the home directory. -// This test will fail if the backing fs is not xfs. -// -// xfs_quota tool can be used to assign a project id to the driver home directory, e.g.: -// echo 999:/var/lib/containers/storage/overlay >> /etc/projects -// echo storage:999 >> /etc/projid -// xfs_quota -x -c 'project -s storage' / -// -// In that case, the home directory project id will be used as a "start offset" -// and all containers will be assigned larger project ids (e.g. >= 1000). -// This is a way to prevent xfs_quota management from conflicting with containers/storage. -// -// Then try to create a test directory with the next project id and set a quota -// on it. If that works, continue to scan existing containers to map allocated -// project ids. -// -func NewControl(basePath string) (*Control, error) { - // - // Get project id of parent dir as minimal id to be used by driver - // - minProjectID, err := getProjectID(basePath) - if err != nil { - return nil, err - } - minProjectID++ - - // - // create backing filesystem device node - // - backingFsBlockDev, err := makeBackingFsDev(basePath) - if err != nil { - return nil, err - } - - // - // Test if filesystem supports project quotas by trying to set - // a quota on the first available project id - // - quota := Quota{ - Size: 0, - } - if err := setProjectQuota(backingFsBlockDev, minProjectID, quota); err != nil { - return nil, err - } - - q := Control{ - backingFsBlockDev: backingFsBlockDev, - nextProjectID: minProjectID + 1, - quotas: make(map[string]uint32), - } - - // - // get first project id to be used for next container - // - err = q.findNextProjectID(basePath) - if err != nil { - return nil, err - } - - logrus.Debugf("NewControl(%s): nextProjectID = %d", basePath, q.nextProjectID) - return &q, nil -} - -// SetQuota - assign a unique project id to directory and set the quota limits -// for that project id -func (q *Control) SetQuota(targetPath string, quota Quota) error { - - projectID, ok := q.quotas[targetPath] - if !ok { - projectID = q.nextProjectID - - // - // assign project id to new container directory - // - err := setProjectID(targetPath, projectID) - if err != nil { - return err - } - - q.quotas[targetPath] = projectID - q.nextProjectID++ - } - - // - // set the quota limit for the container's project id - // - logrus.Debugf("SetQuota(%s, %d): projectID=%d", targetPath, quota.Size, projectID) - return setProjectQuota(q.backingFsBlockDev, projectID, quota) -} - -// setProjectQuota - set the quota for project id on xfs block device -func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) error { - var d C.fs_disk_quota_t - d.d_version = C.FS_DQUOT_VERSION - d.d_id = C.__u32(projectID) - d.d_flags = C.XFS_PROJ_QUOTA - - d.d_fieldmask = C.FS_DQ_BHARD | C.FS_DQ_BSOFT - d.d_blk_hardlimit = C.__u64(quota.Size / 512) - d.d_blk_softlimit = d.d_blk_hardlimit - - var cs = C.CString(backingFsBlockDev) - defer C.free(unsafe.Pointer(cs)) - - _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XSETPQLIM, - uintptr(unsafe.Pointer(cs)), uintptr(d.d_id), - uintptr(unsafe.Pointer(&d)), 0, 0) - if errno != 0 { - return fmt.Errorf("Failed to set quota limit for projid %d on %s: %v", - projectID, backingFsBlockDev, errno.Error()) - } - - return nil -} - -// GetQuota - get the quota limits of a directory that was configured with SetQuota -func (q *Control) GetQuota(targetPath string, quota *Quota) error { - - projectID, ok := q.quotas[targetPath] - if !ok { - return fmt.Errorf("quota not found for path : %s", targetPath) - } - - // - // get the quota limit for the container's project id - // - var d C.fs_disk_quota_t - - var cs = C.CString(q.backingFsBlockDev) - defer C.free(unsafe.Pointer(cs)) - - _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XGETPQUOTA, - uintptr(unsafe.Pointer(cs)), uintptr(C.__u32(projectID)), - uintptr(unsafe.Pointer(&d)), 0, 0) - if errno != 0 { - return fmt.Errorf("Failed to get quota limit for projid %d on %s: %v", - projectID, q.backingFsBlockDev, errno.Error()) - } - quota.Size = uint64(d.d_blk_hardlimit) * 512 - - return nil -} - -// getProjectID - get the project id of path on xfs -func getProjectID(targetPath string) (uint32, error) { - dir, err := openDir(targetPath) - if err != nil { - return 0, err - } - defer closeDir(dir) - - var fsx C.struct_fsxattr - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.FS_IOC_FSGETXATTR, - uintptr(unsafe.Pointer(&fsx))) - if errno != 0 { - return 0, fmt.Errorf("Failed to get projid for %s: %v", targetPath, errno.Error()) - } - - return uint32(fsx.fsx_projid), nil -} - -// setProjectID - set the project id of path on xfs -func setProjectID(targetPath string, projectID uint32) error { - dir, err := openDir(targetPath) - if err != nil { - return err - } - defer closeDir(dir) - - var fsx C.struct_fsxattr - _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.FS_IOC_FSGETXATTR, - uintptr(unsafe.Pointer(&fsx))) - if errno != 0 { - return fmt.Errorf("Failed to get projid for %s: %v", targetPath, errno.Error()) - } - fsx.fsx_projid = C.__u32(projectID) - fsx.fsx_xflags |= C.FS_XFLAG_PROJINHERIT - _, _, errno = unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.FS_IOC_FSSETXATTR, - uintptr(unsafe.Pointer(&fsx))) - if errno != 0 { - return fmt.Errorf("Failed to set projid for %s: %v", targetPath, errno.Error()) - } - - return nil -} - -// findNextProjectID - find the next project id to be used for containers -// by scanning driver home directory to find used project ids -func (q *Control) findNextProjectID(home string) error { - files, err := ioutil.ReadDir(home) - if err != nil { - return fmt.Errorf("read directory failed : %s", home) - } - for _, file := range files { - if !file.IsDir() { - continue - } - path := filepath.Join(home, file.Name()) - projid, err := getProjectID(path) - if err != nil { - return err - } - if projid > 0 { - q.quotas[path] = projid - } - if q.nextProjectID <= projid { - q.nextProjectID = projid + 1 - } - } - - return nil -} - -func free(p *C.char) { - C.free(unsafe.Pointer(p)) -} - -func openDir(path string) (*C.DIR, error) { - Cpath := C.CString(path) - defer free(Cpath) - - dir := C.opendir(Cpath) - if dir == nil { - return nil, fmt.Errorf("Can't open dir") - } - return dir, nil -} - -func closeDir(dir *C.DIR) { - if dir != nil { - C.closedir(dir) - } -} - -func getDirFd(dir *C.DIR) uintptr { - return uintptr(C.dirfd(dir)) -} - -// Get the backing block device of the driver home directory -// and create a block device node under the home directory -// to be used by quotactl commands -func makeBackingFsDev(home string) (string, error) { - var stat unix.Stat_t - if err := unix.Stat(home, &stat); err != nil { - return "", err - } - - backingFsBlockDev := path.Join(home, "backingFsBlockDev") - // Re-create just in case someone copied the home directory over to a new device - unix.Unlink(backingFsBlockDev) - if err := unix.Mknod(backingFsBlockDev, unix.S_IFBLK|0600, int(stat.Dev)); err != nil { - return "", fmt.Errorf("Failed to mknod %s: %v", backingFsBlockDev, err) - } - - return backingFsBlockDev, nil -} diff --git a/vendor/github.com/containers/storage/drivers/register/register_aufs.go b/vendor/github.com/containers/storage/drivers/register/register_aufs.go deleted file mode 100644 index 7743dcedbd..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_aufs.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_aufs,linux - -package register - -import ( - // register the aufs graphdriver - _ "github.com/containers/storage/drivers/aufs" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_btrfs.go b/vendor/github.com/containers/storage/drivers/register/register_btrfs.go deleted file mode 100644 index 40ff1cdd0d..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_btrfs.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_btrfs,linux - -package register - -import ( - // register the btrfs graphdriver - _ "github.com/containers/storage/drivers/btrfs" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_devicemapper.go b/vendor/github.com/containers/storage/drivers/register/register_devicemapper.go deleted file mode 100644 index 08ac984b05..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_devicemapper.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_devicemapper,linux - -package register - -import ( - // register the devmapper graphdriver - _ "github.com/containers/storage/drivers/devmapper" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_overlay.go b/vendor/github.com/containers/storage/drivers/register/register_overlay.go deleted file mode 100644 index 2d61219bbb..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_overlay.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_overlay,linux - -package register - -import ( - // register the overlay graphdriver - _ "github.com/containers/storage/drivers/overlay" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_vfs.go b/vendor/github.com/containers/storage/drivers/register/register_vfs.go deleted file mode 100644 index 691ce85929..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_vfs.go +++ /dev/null @@ -1,6 +0,0 @@ -package register - -import ( - // register vfs - _ "github.com/containers/storage/drivers/vfs" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_windows.go b/vendor/github.com/containers/storage/drivers/register/register_windows.go deleted file mode 100644 index 048b27097d..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package register - -import ( - // register the windows graph driver - _ "github.com/containers/storage/drivers/windows" -) diff --git a/vendor/github.com/containers/storage/drivers/register/register_zfs.go b/vendor/github.com/containers/storage/drivers/register/register_zfs.go deleted file mode 100644 index c748468e5c..0000000000 --- a/vendor/github.com/containers/storage/drivers/register/register_zfs.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !exclude_graphdriver_zfs,linux !exclude_graphdriver_zfs,freebsd, solaris - -package register - -import ( - // register the zfs driver - _ "github.com/containers/storage/drivers/zfs" -) diff --git a/vendor/github.com/containers/storage/drivers/vfs/driver.go b/vendor/github.com/containers/storage/drivers/vfs/driver.go deleted file mode 100644 index ae62207d17..0000000000 --- a/vendor/github.com/containers/storage/drivers/vfs/driver.go +++ /dev/null @@ -1,160 +0,0 @@ -package vfs - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/system" - "github.com/opencontainers/selinux/go-selinux/label" -) - -var ( - // CopyWithTar defines the copy method to use. - CopyWithTar = chrootarchive.NewArchiver(nil).CopyWithTar -) - -func init() { - graphdriver.Register("vfs", Init) -} - -// Init returns a new VFS driver. -// This sets the home directory for the driver and returns NaiveDiffDriver. -func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - d := &Driver{ - homes: []string{home}, - idMappings: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), - } - rootIDs := d.idMappings.RootPair() - if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil { - return nil, err - } - for _, option := range options { - if strings.HasPrefix(option, "vfs.imagestore=") { - d.homes = append(d.homes, strings.Split(option[15:], ",")...) - continue - } - if strings.HasPrefix(option, ".imagestore=") { - d.homes = append(d.homes, strings.Split(option[12:], ",")...) - continue - } - } - return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil -} - -// Driver holds information about the driver, home directory of the driver. -// Driver implements graphdriver.ProtoDriver. It uses only basic vfs operations. -// In order to support layering, files are copied from the parent layer into the new layer. There is no copy-on-write support. -// Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver -type Driver struct { - homes []string - idMappings *idtools.IDMappings -} - -func (d *Driver) String() string { - return "vfs" -} - -// Status is used for implementing the graphdriver.ProtoDriver interface. VFS does not currently have any status information. -func (d *Driver) Status() [][2]string { - return nil -} - -// Metadata is used for implementing the graphdriver.ProtoDriver interface. VFS does not currently have any meta data. -func (d *Driver) Metadata(id string) (map[string]string, error) { - return nil, nil -} - -// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver. -func (d *Driver) Cleanup() error { - return nil -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - return d.Create(id, parent, opts) -} - -// Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - if opts != nil && len(opts.StorageOpt) != 0 { - return fmt.Errorf("--storage-opt is not supported for vfs") - } - - dir := d.dir(id) - rootIDs := d.idMappings.RootPair() - if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil { - return err - } - if err := idtools.MkdirAndChown(dir, 0755, rootIDs); err != nil { - return err - } - labelOpts := []string{"level:s0"} - if _, mountLabel, err := label.InitLabels(labelOpts); err == nil { - label.SetFileLabel(dir, mountLabel) - } - if parent == "" { - return nil - } - parentDir, err := d.Get(parent, "") - if err != nil { - return fmt.Errorf("%s: %s", parent, err) - } - return CopyWithTar(parentDir, dir) -} - -func (d *Driver) dir(id string) string { - for i, home := range d.homes { - if i > 0 { - home = filepath.Join(home, d.String()) - } - candidate := filepath.Join(home, "dir", filepath.Base(id)) - fi, err := os.Stat(candidate) - if err == nil && fi.IsDir() { - return candidate - } - } - return filepath.Join(d.homes[0], "dir", filepath.Base(id)) -} - -// Remove deletes the content from the directory for a given id. -func (d *Driver) Remove(id string) error { - return system.EnsureRemoveAll(d.dir(id)) -} - -// Get returns the directory for the given id. -func (d *Driver) Get(id, mountLabel string) (string, error) { - dir := d.dir(id) - if st, err := os.Stat(dir); err != nil { - return "", err - } else if !st.IsDir() { - return "", fmt.Errorf("%s: not a directory", dir) - } - return dir, nil -} - -// Put is a noop for vfs that return nil for the error, since this driver has no runtime resources to clean up. -func (d *Driver) Put(id string) error { - // The vfs driver has no runtime resources (e.g. mounts) - // to clean up, so we don't need anything here - return nil -} - -// Exists checks to see if the directory exists for the given id. -func (d *Driver) Exists(id string) bool { - _, err := os.Stat(d.dir(id)) - return err == nil -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - if len(d.homes) > 1 { - return d.homes[1:] - } - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/windows/windows.go b/vendor/github.com/containers/storage/drivers/windows/windows.go deleted file mode 100644 index e9e9f5c65a..0000000000 --- a/vendor/github.com/containers/storage/drivers/windows/windows.go +++ /dev/null @@ -1,965 +0,0 @@ -//+build windows - -package windows - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "sync" - "syscall" - "time" - "unsafe" - - "github.com/Microsoft/go-winio" - "github.com/Microsoft/go-winio/archive/tar" - "github.com/Microsoft/go-winio/backuptar" - "github.com/Microsoft/hcsshim" - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/longpath" - "github.com/containers/storage/pkg/reexec" - "github.com/containers/storage/pkg/system" - units "github.com/docker/go-units" - "github.com/sirupsen/logrus" - "golang.org/x/sys/windows" -) - -// filterDriver is an HCSShim driver type for the Windows Filter driver. -const filterDriver = 1 - -var ( - // mutatedFiles is a list of files that are mutated by the import process - // and must be backed up and restored. - mutatedFiles = map[string]string{ - "UtilityVM/Files/EFI/Microsoft/Boot/BCD": "bcd.bak", - "UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG": "bcd.log.bak", - "UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak", - "UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak", - } - noreexec = false -) - -// init registers the windows graph drivers to the register. -func init() { - graphdriver.Register("windowsfilter", InitFilter) - // DOCKER_WINDOWSFILTER_NOREEXEC allows for inline processing which makes - // debugging issues in the re-exec codepath significantly easier. - if os.Getenv("DOCKER_WINDOWSFILTER_NOREEXEC") != "" { - logrus.Warnf("WindowsGraphDriver is set to not re-exec. This is intended for debugging purposes only.") - noreexec = true - } else { - reexec.Register("docker-windows-write-layer", writeLayerReexec) - } -} - -type checker struct { -} - -func (c *checker) IsMounted(path string) bool { - return false -} - -// Driver represents a windows graph driver. -type Driver struct { - // info stores the shim driver information - info hcsshim.DriverInfo - ctr *graphdriver.RefCounter - // it is safe for windows to use a cache here because it does not support - // restoring containers when the daemon dies. - cacheMu sync.Mutex - cache map[string]string -} - -// InitFilter returns a new Windows storage filter driver. -func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - logrus.Debugf("WindowsGraphDriver InitFilter at %s", home) - - fsType, err := getFileSystemType(string(home[0])) - if err != nil { - return nil, err - } - if strings.ToLower(fsType) == "refs" { - return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home) - } - - if err := idtools.MkdirAllAs(home, 0700, 0, 0); err != nil { - return nil, fmt.Errorf("windowsfilter failed to create '%s': %v", home, err) - } - - d := &Driver{ - info: hcsshim.DriverInfo{ - HomeDir: home, - Flavour: filterDriver, - }, - cache: make(map[string]string), - ctr: graphdriver.NewRefCounter(&checker{}), - } - return d, nil -} - -// win32FromHresult is a helper function to get the win32 error code from an HRESULT -func win32FromHresult(hr uintptr) uintptr { - if hr&0x1fff0000 == 0x00070000 { - return hr & 0xffff - } - return hr -} - -// getFileSystemType obtains the type of a file system through GetVolumeInformation -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx -func getFileSystemType(drive string) (fsType string, hr error) { - var ( - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW") - buf = make([]uint16, 255) - size = windows.MAX_PATH + 1 - ) - if len(drive) != 1 { - hr = errors.New("getFileSystemType must be called with a drive letter") - return - } - drive += `:\` - n := uintptr(unsafe.Pointer(nil)) - r0, _, _ := syscall.Syscall9(procGetVolumeInformation.Addr(), 8, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(drive))), n, n, n, n, n, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0) - if int32(r0) < 0 { - hr = syscall.Errno(win32FromHresult(r0)) - } - fsType = windows.UTF16ToString(buf) - return -} - -// String returns the string representation of a driver. This should match -// the name the graph driver has been registered with. -func (d *Driver) String() string { - return "windowsfilter" -} - -// Status returns the status of the driver. -func (d *Driver) Status() [][2]string { - return [][2]string{ - {"Windows", ""}, - } -} - -// panicIfUsedByLcow does exactly what it says. -// TODO @jhowardmsft - this is a temporary measure for the bring-up of -// Linux containers on Windows. It is a failsafe to ensure that the right -// graphdriver is used. -func panicIfUsedByLcow() { - if system.LCOWSupported() { - panic("inconsistency - windowsfilter graphdriver should not be used when in LCOW mode") - } -} - -// Exists returns true if the given id is registered with this driver. -func (d *Driver) Exists(id string) bool { - panicIfUsedByLcow() - rID, err := d.resolveID(id) - if err != nil { - return false - } - result, err := hcsshim.LayerExists(d.info, rID) - if err != nil { - return false - } - return result -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - panicIfUsedByLcow() - if opts != nil { - return d.create(id, parent, opts.MountLabel, false, opts.StorageOpt) - } - return d.create(id, parent, "", false, nil) -} - -// Create creates a new read-only layer with the given id. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - panicIfUsedByLcow() - if opts != nil { - return d.create(id, parent, opts.MountLabel, true, opts.StorageOpt) - } - return d.create(id, parent, "", true, nil) -} - -func (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error { - rPId, err := d.resolveID(parent) - if err != nil { - return err - } - - parentChain, err := d.getLayerChain(rPId) - if err != nil { - return err - } - - var layerChain []string - - if rPId != "" { - parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) - if err != nil { - return err - } - if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil { - // This is a legitimate parent layer (not the empty "-init" layer), - // so include it in the layer chain. - layerChain = []string{parentPath} - } - } - - layerChain = append(layerChain, parentChain...) - - if readOnly { - if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil { - return err - } - } else { - var parentPath string - if len(layerChain) != 0 { - parentPath = layerChain[0] - } - - if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil { - return err - } - - storageOptions, err := parseStorageOpt(storageOpt) - if err != nil { - return fmt.Errorf("Failed to parse storage options - %s", err) - } - - if storageOptions.size != 0 { - if err := hcsshim.ExpandSandboxSize(d.info, id, storageOptions.size); err != nil { - return err - } - } - } - - if _, err := os.Lstat(d.dir(parent)); err != nil { - if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { - logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) - } - return fmt.Errorf("Cannot create layer with missing parent %s: %s", parent, err) - } - - if err := d.setLayerChain(id, layerChain); err != nil { - if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { - logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) - } - return err - } - - return nil -} - -// dir returns the absolute path to the layer. -func (d *Driver) dir(id string) string { - return filepath.Join(d.info.HomeDir, filepath.Base(id)) -} - -// Remove unmounts and removes the dir information. -func (d *Driver) Remove(id string) error { - panicIfUsedByLcow() - rID, err := d.resolveID(id) - if err != nil { - return err - } - - // This retry loop is due to a bug in Windows (Internal bug #9432268) - // if GetContainers fails with ErrVmcomputeOperationInvalidState - // it is a transient error. Retry until it succeeds. - var computeSystems []hcsshim.ContainerProperties - retryCount := 0 - osv := system.GetOSVersion() - for { - // Get and terminate any template VMs that are currently using the layer. - // Note: It is unfortunate that we end up in the graphdrivers Remove() call - // for both containers and images, but the logic for template VMs is only - // needed for images - specifically we are looking to see if a base layer - // is in use by a template VM as a result of having started a Hyper-V - // container at some point. - // - // We have a retry loop for ErrVmcomputeOperationInvalidState and - // ErrVmcomputeOperationAccessIsDenied as there is a race condition - // in RS1 and RS2 building during enumeration when a silo is going away - // for example under it, in HCS. AccessIsDenied added to fix 30278. - // - // TODO @jhowardmsft - For RS3, we can remove the retries. Also consider - // using platform APIs (if available) to get this more succinctly. Also - // consider enhancing the Remove() interface to have context of why - // the remove is being called - that could improve efficiency by not - // enumerating compute systems during a remove of a container as it's - // not required. - computeSystems, err = hcsshim.GetContainers(hcsshim.ComputeSystemQuery{}) - if err != nil { - if (osv.Build < 15139) && - ((err == hcsshim.ErrVmcomputeOperationInvalidState) || (err == hcsshim.ErrVmcomputeOperationAccessIsDenied)) { - if retryCount >= 500 { - break - } - retryCount++ - time.Sleep(10 * time.Millisecond) - continue - } - return err - } - break - } - - for _, computeSystem := range computeSystems { - if strings.Contains(computeSystem.RuntimeImagePath, id) && computeSystem.IsRuntimeTemplate { - container, err := hcsshim.OpenContainer(computeSystem.ID) - if err != nil { - return err - } - defer container.Close() - err = container.Terminate() - if hcsshim.IsPending(err) { - err = container.Wait() - } else if hcsshim.IsAlreadyStopped(err) { - err = nil - } - - if err != nil { - return err - } - } - } - - layerPath := filepath.Join(d.info.HomeDir, rID) - tmpID := fmt.Sprintf("%s-removing", rID) - tmpLayerPath := filepath.Join(d.info.HomeDir, tmpID) - if err := os.Rename(layerPath, tmpLayerPath); err != nil && !os.IsNotExist(err) { - return err - } - if err := hcsshim.DestroyLayer(d.info, tmpID); err != nil { - logrus.Errorf("Failed to DestroyLayer %s: %s", id, err) - } - - return nil -} - -// Get returns the rootfs path for the id. This will mount the dir at its given path. -func (d *Driver) Get(id, mountLabel string) (string, error) { - panicIfUsedByLcow() - logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel) - var dir string - - rID, err := d.resolveID(id) - if err != nil { - return "", err - } - if count := d.ctr.Increment(rID); count > 1 { - return d.cache[rID], nil - } - - // Getting the layer paths must be done outside of the lock. - layerChain, err := d.getLayerChain(rID) - if err != nil { - d.ctr.Decrement(rID) - return "", err - } - - if err := hcsshim.ActivateLayer(d.info, rID); err != nil { - d.ctr.Decrement(rID) - return "", err - } - if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { - d.ctr.Decrement(rID) - if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { - logrus.Warnf("Failed to Deactivate %s: %s", id, err) - } - return "", err - } - - mountPath, err := hcsshim.GetLayerMountPath(d.info, rID) - if err != nil { - d.ctr.Decrement(rID) - if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { - logrus.Warnf("Failed to Unprepare %s: %s", id, err) - } - if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { - logrus.Warnf("Failed to Deactivate %s: %s", id, err) - } - return "", err - } - d.cacheMu.Lock() - d.cache[rID] = mountPath - d.cacheMu.Unlock() - - // If the layer has a mount path, use that. Otherwise, use the - // folder path. - if mountPath != "" { - dir = mountPath - } else { - dir = d.dir(id) - } - - return dir, nil -} - -// Put adds a new layer to the driver. -func (d *Driver) Put(id string) error { - panicIfUsedByLcow() - logrus.Debugf("WindowsGraphDriver Put() id %s", id) - - rID, err := d.resolveID(id) - if err != nil { - return err - } - if count := d.ctr.Decrement(rID); count > 0 { - return nil - } - d.cacheMu.Lock() - _, exists := d.cache[rID] - delete(d.cache, rID) - d.cacheMu.Unlock() - - // If the cache was not populated, then the layer was left unprepared and deactivated - if !exists { - return nil - } - - if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { - return err - } - return hcsshim.DeactivateLayer(d.info, rID) -} - -// Cleanup ensures the information the driver stores is properly removed. -// We use this opportunity to cleanup any -removing folders which may be -// still left if the daemon was killed while it was removing a layer. -func (d *Driver) Cleanup() error { - items, err := ioutil.ReadDir(d.info.HomeDir) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - // Note we don't return an error below - it's possible the files - // are locked. However, next time around after the daemon exits, - // we likely will be able to to cleanup successfully. Instead we log - // warnings if there are errors. - for _, item := range items { - if item.IsDir() && strings.HasSuffix(item.Name(), "-removing") { - if err := hcsshim.DestroyLayer(d.info, item.Name()); err != nil { - logrus.Warnf("Failed to cleanup %s: %s", item.Name(), err) - } else { - logrus.Infof("Cleaned up %s", item.Name()) - } - } - } - - return nil -} - -// Diff produces an archive of the changes between the specified -// layer and its parent layer which may be "". -// The layer should be mounted when calling this function -func (d *Driver) Diff(id, parent, mountLabel string) (_ io.ReadCloser, err error) { - panicIfUsedByLcow() - rID, err := d.resolveID(id) - if err != nil { - return - } - - layerChain, err := d.getLayerChain(rID) - if err != nil { - return - } - - // this is assuming that the layer is unmounted - if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { - return nil, err - } - prepare := func() { - if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { - logrus.Warnf("Failed to Deactivate %s: %s", rID, err) - } - } - - arch, err := d.exportLayer(rID, layerChain) - if err != nil { - prepare() - return - } - return ioutils.NewReadCloserWrapper(arch, func() error { - err := arch.Close() - prepare() - return err - }), nil -} - -// Changes produces a list of changes between the specified layer -// and its parent layer. If parent is "", then all changes will be ADD changes. -// The layer should not be mounted when calling this function. -func (d *Driver) Changes(id, parent, mountLabel string) ([]archive.Change, error) { - panicIfUsedByLcow() - rID, err := d.resolveID(id) - if err != nil { - return nil, err - } - parentChain, err := d.getLayerChain(rID) - if err != nil { - return nil, err - } - - if err := hcsshim.ActivateLayer(d.info, rID); err != nil { - return nil, err - } - defer func() { - if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { - logrus.Errorf("changes() failed to DeactivateLayer %s %s: %s", id, rID, err2) - } - }() - - var changes []archive.Change - err = winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error { - r, err := hcsshim.NewLayerReader(d.info, id, parentChain) - if err != nil { - return err - } - defer r.Close() - - for { - name, _, fileInfo, err := r.Next() - if err == io.EOF { - return nil - } - if err != nil { - return err - } - name = filepath.ToSlash(name) - if fileInfo == nil { - changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeDelete}) - } else { - // Currently there is no way to tell between an add and a modify. - changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeModify}) - } - } - }) - if err != nil { - return nil, err - } - - return changes, nil -} - -// ApplyDiff extracts the changeset from the given diff into the -// layer with the specified id and parent, returning the size of the -// new layer in bytes. -// The layer should not be mounted when calling this function -func (d *Driver) ApplyDiff(id, parent, mountLabel string, diff io.Reader) (int64, error) { - panicIfUsedByLcow() - var layerChain []string - if parent != "" { - rPId, err := d.resolveID(parent) - if err != nil { - return 0, err - } - parentChain, err := d.getLayerChain(rPId) - if err != nil { - return 0, err - } - parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) - if err != nil { - return 0, err - } - layerChain = append(layerChain, parentPath) - layerChain = append(layerChain, parentChain...) - } - - size, err := d.importLayer(id, diff, layerChain) - if err != nil { - return 0, err - } - - if err = d.setLayerChain(id, layerChain); err != nil { - return 0, err - } - - return size, nil -} - -// DiffSize calculates the changes between the specified layer -// and its parent and returns the size in bytes of the changes -// relative to its base filesystem directory. -func (d *Driver) DiffSize(id, parent, mountLabel string) (size int64, err error) { - panicIfUsedByLcow() - rPId, err := d.resolveID(parent) - if err != nil { - return - } - - changes, err := d.Changes(id, rPId, mountLabel) - if err != nil { - return - } - - layerFs, err := d.Get(id, "") - if err != nil { - return - } - defer d.Put(id) - - return archive.ChangesSize(layerFs, changes), nil -} - -// Metadata returns custom driver information. -func (d *Driver) Metadata(id string) (map[string]string, error) { - panicIfUsedByLcow() - m := make(map[string]string) - m["dir"] = d.dir(id) - return m, nil -} - -func writeTarFromLayer(r hcsshim.LayerReader, w io.Writer) error { - t := tar.NewWriter(w) - for { - name, size, fileInfo, err := r.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - if fileInfo == nil { - // Write a whiteout file. - hdr := &tar.Header{ - Name: filepath.ToSlash(filepath.Join(filepath.Dir(name), archive.WhiteoutPrefix+filepath.Base(name))), - } - err := t.WriteHeader(hdr) - if err != nil { - return err - } - } else { - err = backuptar.WriteTarFileFromBackupStream(t, r, name, size, fileInfo) - if err != nil { - return err - } - } - } - return t.Close() -} - -// exportLayer generates an archive from a layer based on the given ID. -func (d *Driver) exportLayer(id string, parentLayerPaths []string) (io.ReadCloser, error) { - archive, w := io.Pipe() - go func() { - err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error { - r, err := hcsshim.NewLayerReader(d.info, id, parentLayerPaths) - if err != nil { - return err - } - - err = writeTarFromLayer(r, w) - cerr := r.Close() - if err == nil { - err = cerr - } - return err - }) - w.CloseWithError(err) - }() - - return archive, nil -} - -// writeBackupStreamFromTarAndSaveMutatedFiles reads data from a tar stream and -// writes it to a backup stream, and also saves any files that will be mutated -// by the import layer process to a backup location. -func writeBackupStreamFromTarAndSaveMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) { - var bcdBackup *os.File - var bcdBackupWriter *winio.BackupFileWriter - if backupPath, ok := mutatedFiles[hdr.Name]; ok { - bcdBackup, err = os.Create(filepath.Join(root, backupPath)) - if err != nil { - return nil, err - } - defer func() { - cerr := bcdBackup.Close() - if err == nil { - err = cerr - } - }() - - bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false) - defer func() { - cerr := bcdBackupWriter.Close() - if err == nil { - err = cerr - } - }() - - buf.Reset(io.MultiWriter(w, bcdBackupWriter)) - } else { - buf.Reset(w) - } - - defer func() { - ferr := buf.Flush() - if err == nil { - err = ferr - } - }() - - return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr) -} - -func writeLayerFromTar(r io.Reader, w hcsshim.LayerWriter, root string) (int64, error) { - t := tar.NewReader(r) - hdr, err := t.Next() - totalSize := int64(0) - buf := bufio.NewWriter(nil) - for err == nil { - base := path.Base(hdr.Name) - if strings.HasPrefix(base, archive.WhiteoutPrefix) { - name := path.Join(path.Dir(hdr.Name), base[len(archive.WhiteoutPrefix):]) - err = w.Remove(filepath.FromSlash(name)) - if err != nil { - return 0, err - } - hdr, err = t.Next() - } else if hdr.Typeflag == tar.TypeLink { - err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname)) - if err != nil { - return 0, err - } - hdr, err = t.Next() - } else { - var ( - name string - size int64 - fileInfo *winio.FileBasicInfo - ) - name, size, fileInfo, err = backuptar.FileInfoFromHeader(hdr) - if err != nil { - return 0, err - } - err = w.Add(filepath.FromSlash(name), fileInfo) - if err != nil { - return 0, err - } - hdr, err = writeBackupStreamFromTarAndSaveMutatedFiles(buf, w, t, hdr, root) - totalSize += size - } - } - if err != io.EOF { - return 0, err - } - return totalSize, nil -} - -// importLayer adds a new layer to the tag and graph store based on the given data. -func (d *Driver) importLayer(id string, layerData io.Reader, parentLayerPaths []string) (size int64, err error) { - if !noreexec { - cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...) - output := bytes.NewBuffer(nil) - cmd.Stdin = layerData - cmd.Stdout = output - cmd.Stderr = output - - if err = cmd.Start(); err != nil { - return - } - - if err = cmd.Wait(); err != nil { - return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output) - } - - return strconv.ParseInt(output.String(), 10, 64) - } - return writeLayer(layerData, d.info.HomeDir, id, parentLayerPaths...) -} - -// writeLayerReexec is the re-exec entry point for writing a layer from a tar file -func writeLayerReexec() { - size, err := writeLayer(os.Stdin, os.Args[1], os.Args[2], os.Args[3:]...) - if err != nil { - fmt.Fprint(os.Stderr, err) - os.Exit(1) - } - fmt.Fprint(os.Stdout, size) -} - -// writeLayer writes a layer from a tar file. -func writeLayer(layerData io.Reader, home string, id string, parentLayerPaths ...string) (int64, error) { - err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}) - if err != nil { - return 0, err - } - if noreexec { - defer func() { - if err := winio.DisableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}); err != nil { - // This should never happen, but just in case when in debugging mode. - // See https://github.com/docker/docker/pull/28002#discussion_r86259241 for rationale. - panic("Failed to disabled process privileges while in non re-exec mode") - } - }() - } - - info := hcsshim.DriverInfo{ - Flavour: filterDriver, - HomeDir: home, - } - - w, err := hcsshim.NewLayerWriter(info, id, parentLayerPaths) - if err != nil { - return 0, err - } - - size, err := writeLayerFromTar(layerData, w, filepath.Join(home, id)) - if err != nil { - return 0, err - } - - err = w.Close() - if err != nil { - return 0, err - } - - return size, nil -} - -// resolveID computes the layerID information based on the given id. -func (d *Driver) resolveID(id string) (string, error) { - content, err := ioutil.ReadFile(filepath.Join(d.dir(id), "layerID")) - if os.IsNotExist(err) { - return id, nil - } else if err != nil { - return "", err - } - return string(content), nil -} - -// setID stores the layerId in disk. -func (d *Driver) setID(id, altID string) error { - return ioutil.WriteFile(filepath.Join(d.dir(id), "layerId"), []byte(altID), 0600) -} - -// getLayerChain returns the layer chain information. -func (d *Driver) getLayerChain(id string) ([]string, error) { - jPath := filepath.Join(d.dir(id), "layerchain.json") - content, err := ioutil.ReadFile(jPath) - if os.IsNotExist(err) { - return nil, nil - } else if err != nil { - return nil, fmt.Errorf("Unable to read layerchain file - %s", err) - } - - var layerChain []string - err = json.Unmarshal(content, &layerChain) - if err != nil { - return nil, fmt.Errorf("Failed to unmarshall layerchain json - %s", err) - } - - return layerChain, nil -} - -// setLayerChain stores the layer chain information in disk. -func (d *Driver) setLayerChain(id string, chain []string) error { - content, err := json.Marshal(&chain) - if err != nil { - return fmt.Errorf("Failed to marshall layerchain json - %s", err) - } - - jPath := filepath.Join(d.dir(id), "layerchain.json") - err = ioutil.WriteFile(jPath, content, 0600) - if err != nil { - return fmt.Errorf("Unable to write layerchain file - %s", err) - } - - return nil -} - -type fileGetCloserWithBackupPrivileges struct { - path string -} - -func (fg *fileGetCloserWithBackupPrivileges) Get(filename string) (io.ReadCloser, error) { - if backupPath, ok := mutatedFiles[filename]; ok { - return os.Open(filepath.Join(fg.path, backupPath)) - } - - var f *os.File - // Open the file while holding the Windows backup privilege. This ensures that the - // file can be opened even if the caller does not actually have access to it according - // to the security descriptor. Also use sequential file access to avoid depleting the - // standby list - Microsoft VSO Bug Tracker #9900466 - err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error { - path := longpath.AddPrefix(filepath.Join(fg.path, filename)) - p, err := windows.UTF16FromString(path) - if err != nil { - return err - } - const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN - h, err := windows.CreateFile(&p[0], windows.GENERIC_READ, windows.FILE_SHARE_READ, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_BACKUP_SEMANTICS|fileFlagSequentialScan, 0) - if err != nil { - return &os.PathError{Op: "open", Path: path, Err: err} - } - f = os.NewFile(uintptr(h), path) - return nil - }) - return f, err -} - -func (fg *fileGetCloserWithBackupPrivileges) Close() error { - return nil -} - -// DiffGetter returns a FileGetCloser that can read files from the directory that -// contains files for the layer differences. Used for direct access for tar-split. -func (d *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) { - panicIfUsedByLcow() - id, err := d.resolveID(id) - if err != nil { - return nil, err - } - - return &fileGetCloserWithBackupPrivileges{d.dir(id)}, nil -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - return nil -} - -type storageOptions struct { - size uint64 -} - -func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) { - options := storageOptions{} - - // Read size to change the block device size per container. - for key, val := range storageOpt { - key := strings.ToLower(key) - switch key { - case "size": - size, err := units.RAMInBytes(val) - if err != nil { - return nil, err - } - options.size = uint64(size) - default: - return nil, fmt.Errorf("Unknown storage option: %s", key) - } - } - return &options, nil -} diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go deleted file mode 100644 index 8c8e7d6718..0000000000 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go +++ /dev/null @@ -1,426 +0,0 @@ -// +build linux freebsd solaris - -package zfs - -import ( - "fmt" - "os" - "os/exec" - "path" - "strconv" - "strings" - "sync" - "time" - - "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/parsers" - zfs "github.com/mistifyio/go-zfs" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -type zfsOptions struct { - fsName string - mountPath string -} - -func init() { - graphdriver.Register("zfs", Init) -} - -// Logger returns a zfs logger implementation. -type Logger struct{} - -// Log wraps log message from ZFS driver with a prefix '[zfs]'. -func (*Logger) Log(cmd []string) { - logrus.Debugf("[zfs] %s", strings.Join(cmd, " ")) -} - -// Init returns a new ZFS driver. -// It takes base mount path and an array of options which are represented as key value pairs. -// Each option is in the for key=value. 'zfs.fsname' is expected to be a valid key in the options. -func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - var err error - - if _, err := exec.LookPath("zfs"); err != nil { - logrus.Debugf("[zfs] zfs command is not available: %v", err) - return nil, errors.Wrap(graphdriver.ErrPrerequisites, "the 'zfs' command is not available") - } - - file, err := os.OpenFile("/dev/zfs", os.O_RDWR, 600) - if err != nil { - logrus.Debugf("[zfs] cannot open /dev/zfs: %v", err) - return nil, errors.Wrapf(graphdriver.ErrPrerequisites, "could not open /dev/zfs: %v", err) - } - defer file.Close() - - options, err := parseOptions(opt) - if err != nil { - return nil, err - } - options.mountPath = base - - rootdir := path.Dir(base) - - if options.fsName == "" { - err = checkRootdirFs(rootdir) - if err != nil { - return nil, err - } - } - - if options.fsName == "" { - options.fsName, err = lookupZfsDataset(rootdir) - if err != nil { - return nil, err - } - } - - zfs.SetLogger(new(Logger)) - - filesystems, err := zfs.Filesystems(options.fsName) - if err != nil { - return nil, fmt.Errorf("Cannot find root filesystem %s: %v", options.fsName, err) - } - - filesystemsCache := make(map[string]bool, len(filesystems)) - var rootDataset *zfs.Dataset - for _, fs := range filesystems { - if fs.Name == options.fsName { - rootDataset = fs - } - filesystemsCache[fs.Name] = true - } - - if rootDataset == nil { - return nil, fmt.Errorf("BUG: zfs get all -t filesystem -rHp '%s' should contain '%s'", options.fsName, options.fsName) - } - - rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) - if err != nil { - return nil, fmt.Errorf("Failed to get root uid/guid: %v", err) - } - if err := idtools.MkdirAllAs(base, 0700, rootUID, rootGID); err != nil { - return nil, fmt.Errorf("Failed to create '%s': %v", base, err) - } - - if err := mount.MakePrivate(base); err != nil { - return nil, err - } - d := &Driver{ - dataset: rootDataset, - options: options, - filesystemsCache: filesystemsCache, - uidMaps: uidMaps, - gidMaps: gidMaps, - ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), - } - return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil -} - -func parseOptions(opt []string) (zfsOptions, error) { - var options zfsOptions - options.fsName = "" - for _, option := range opt { - key, val, err := parsers.ParseKeyValueOpt(option) - if err != nil { - return options, err - } - key = strings.ToLower(key) - switch key { - case "zfs.fsname": - options.fsName = val - default: - return options, fmt.Errorf("Unknown option %s", key) - } - } - return options, nil -} - -func lookupZfsDataset(rootdir string) (string, error) { - var stat unix.Stat_t - if err := unix.Stat(rootdir, &stat); err != nil { - return "", fmt.Errorf("Failed to access '%s': %s", rootdir, err) - } - wantedDev := stat.Dev - - mounts, err := mount.GetMounts() - if err != nil { - return "", err - } - for _, m := range mounts { - if err := unix.Stat(m.Mountpoint, &stat); err != nil { - logrus.Debugf("[zfs] failed to stat '%s' while scanning for zfs mount: %v", m.Mountpoint, err) - continue // may fail on fuse file systems - } - - if stat.Dev == wantedDev && m.Fstype == "zfs" { - return m.Source, nil - } - } - - return "", fmt.Errorf("Failed to find zfs dataset mounted on '%s' in /proc/mounts", rootdir) -} - -// Driver holds information about the driver, such as zfs dataset, options and cache. -type Driver struct { - dataset *zfs.Dataset - options zfsOptions - sync.Mutex // protects filesystem cache against concurrent access - filesystemsCache map[string]bool - uidMaps []idtools.IDMap - gidMaps []idtools.IDMap - ctr *graphdriver.RefCounter -} - -func (d *Driver) String() string { - return "zfs" -} - -// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver. -func (d *Driver) Cleanup() error { - return nil -} - -// Status returns information about the ZFS filesystem. It returns a two dimensional array of information -// such as pool name, dataset name, disk usage, parent quota and compression used. -// Currently it return 'Zpool', 'Zpool Health', 'Parent Dataset', 'Space Used By Parent', -// 'Space Available', 'Parent Quota' and 'Compression'. -func (d *Driver) Status() [][2]string { - parts := strings.Split(d.dataset.Name, "/") - pool, err := zfs.GetZpool(parts[0]) - - var poolName, poolHealth string - if err == nil { - poolName = pool.Name - poolHealth = pool.Health - } else { - poolName = fmt.Sprintf("error while getting pool information %v", err) - poolHealth = "not available" - } - - quota := "no" - if d.dataset.Quota != 0 { - quota = strconv.FormatUint(d.dataset.Quota, 10) - } - - return [][2]string{ - {"Zpool", poolName}, - {"Zpool Health", poolHealth}, - {"Parent Dataset", d.dataset.Name}, - {"Space Used By Parent", strconv.FormatUint(d.dataset.Used, 10)}, - {"Space Available", strconv.FormatUint(d.dataset.Avail, 10)}, - {"Parent Quota", quota}, - {"Compression", d.dataset.Compression}, - } -} - -// Metadata returns image/container metadata related to graph driver -func (d *Driver) Metadata(id string) (map[string]string, error) { - return map[string]string{ - "Mountpoint": d.mountPath(id), - "Dataset": d.zfsPath(id), - }, nil -} - -func (d *Driver) cloneFilesystem(name, parentName string) error { - snapshotName := fmt.Sprintf("%d", time.Now().Nanosecond()) - parentDataset := zfs.Dataset{Name: parentName} - snapshot, err := parentDataset.Snapshot(snapshotName /*recursive */, false) - if err != nil { - return err - } - - _, err = snapshot.Clone(name, map[string]string{"mountpoint": "legacy"}) - if err == nil { - d.Lock() - d.filesystemsCache[name] = true - d.Unlock() - } - - if err != nil { - snapshot.Destroy(zfs.DestroyDeferDeletion) - return err - } - return snapshot.Destroy(zfs.DestroyDeferDeletion) -} - -func (d *Driver) zfsPath(id string) string { - return d.options.fsName + "/" + id -} - -func (d *Driver) mountPath(id string) string { - return path.Join(d.options.mountPath, "graph", getMountpoint(id)) -} - -// CreateReadWrite creates a layer that is writable for use as a container -// file system. -func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { - return d.Create(id, parent, opts) -} - -// Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent. -func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { - var storageOpt map[string]string - if opts != nil { - storageOpt = opts.StorageOpt - } - - err := d.create(id, parent, storageOpt) - if err == nil { - return nil - } - if zfsError, ok := err.(*zfs.Error); ok { - if !strings.HasSuffix(zfsError.Stderr, "dataset already exists\n") { - return err - } - // aborted build -> cleanup - } else { - return err - } - - dataset := zfs.Dataset{Name: d.zfsPath(id)} - if err := dataset.Destroy(zfs.DestroyRecursiveClones); err != nil { - return err - } - - // retry - return d.create(id, parent, storageOpt) -} - -func (d *Driver) create(id, parent string, storageOpt map[string]string) error { - name := d.zfsPath(id) - quota, err := parseStorageOpt(storageOpt) - if err != nil { - return err - } - if parent == "" { - mountoptions := map[string]string{"mountpoint": "legacy"} - fs, err := zfs.CreateFilesystem(name, mountoptions) - if err == nil { - err = setQuota(name, quota) - if err == nil { - d.Lock() - d.filesystemsCache[fs.Name] = true - d.Unlock() - } - } - return err - } - err = d.cloneFilesystem(name, d.zfsPath(parent)) - if err == nil { - err = setQuota(name, quota) - } - return err -} - -func parseStorageOpt(storageOpt map[string]string) (string, error) { - // Read size to change the disk quota per container - for k, v := range storageOpt { - key := strings.ToLower(k) - switch key { - case "size": - return v, nil - default: - return "0", fmt.Errorf("Unknown option %s", key) - } - } - return "0", nil -} - -func setQuota(name string, quota string) error { - if quota == "0" { - return nil - } - fs, err := zfs.GetDataset(name) - if err != nil { - return err - } - return fs.SetProperty("quota", quota) -} - -// Remove deletes the dataset, filesystem and the cache for the given id. -func (d *Driver) Remove(id string) error { - name := d.zfsPath(id) - dataset := zfs.Dataset{Name: name} - err := dataset.Destroy(zfs.DestroyRecursive) - if err == nil { - d.Lock() - delete(d.filesystemsCache, name) - d.Unlock() - } - return err -} - -// Get returns the mountpoint for the given id after creating the target directories if necessary. -func (d *Driver) Get(id, mountLabel string) (string, error) { - mountpoint := d.mountPath(id) - if count := d.ctr.Increment(mountpoint); count > 1 { - return mountpoint, nil - } - - filesystem := d.zfsPath(id) - options := label.FormatMountLabel("", mountLabel) - logrus.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options) - - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - d.ctr.Decrement(mountpoint) - return "", err - } - // Create the target directories if they don't exist - if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil { - d.ctr.Decrement(mountpoint) - return "", err - } - - if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil { - d.ctr.Decrement(mountpoint) - return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err) - } - - // this could be our first mount after creation of the filesystem, and the root dir may still have root - // permissions instead of the remapped root uid:gid (if user namespaces are enabled): - if err := os.Chown(mountpoint, rootUID, rootGID); err != nil { - mount.Unmount(mountpoint) - d.ctr.Decrement(mountpoint) - return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) - } - - return mountpoint, nil -} - -// Put removes the existing mountpoint for the given id if it exists. -func (d *Driver) Put(id string) error { - mountpoint := d.mountPath(id) - if count := d.ctr.Decrement(mountpoint); count > 0 { - return nil - } - mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint) - if err != nil || !mounted { - return err - } - - logrus.Debugf(`[zfs] unmount("%s")`, mountpoint) - - if err := mount.Unmount(mountpoint); err != nil { - return fmt.Errorf("error unmounting to %s: %v", mountpoint, err) - } - return nil -} - -// Exists checks to see if the cache entry exists for the given id. -func (d *Driver) Exists(id string) bool { - d.Lock() - defer d.Unlock() - return d.filesystemsCache[d.zfsPath(id)] -} - -// AdditionalImageStores returns additional image stores supported by the driver -func (d *Driver) AdditionalImageStores() []string { - return nil -} diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs_freebsd.go b/vendor/github.com/containers/storage/drivers/zfs/zfs_freebsd.go deleted file mode 100644 index 69c0448d34..0000000000 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs_freebsd.go +++ /dev/null @@ -1,39 +0,0 @@ -package zfs - -import ( - "fmt" - "strings" - - "github.com/containers/storage/drivers" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -func checkRootdirFs(rootdir string) error { - var buf unix.Statfs_t - if err := unix.Statfs(rootdir, &buf); err != nil { - return fmt.Errorf("Failed to access '%s': %s", rootdir, err) - } - - // on FreeBSD buf.Fstypename contains ['z', 'f', 's', 0 ... ] - if (buf.Fstypename[0] != 122) || (buf.Fstypename[1] != 102) || (buf.Fstypename[2] != 115) || (buf.Fstypename[3] != 0) { - logrus.Debugf("[zfs] no zfs dataset found for rootdir '%s'", rootdir) - return errors.Wrapf(graphdriver.ErrPrerequisites, "no zfs dataset found for rootdir '%s'", rootdir) - } - - return nil -} - -func getMountpoint(id string) string { - maxlen := 12 - - // we need to preserve filesystem suffix - suffix := strings.SplitN(id, "-", 2) - - if len(suffix) > 1 { - return id[:maxlen] + "-" + suffix[1] - } - - return id[:maxlen] -} diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go b/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go deleted file mode 100644 index da298047d5..0000000000 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go +++ /dev/null @@ -1,28 +0,0 @@ -package zfs - -import ( - "fmt" - - "github.com/containers/storage/drivers" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -func checkRootdirFs(rootdir string) error { - var buf unix.Statfs_t - if err := unix.Statfs(rootdir, &buf); err != nil { - return fmt.Errorf("Failed to access '%s': %s", rootdir, err) - } - - if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicZfs { - logrus.Debugf("[zfs] no zfs dataset found for rootdir '%s'", rootdir) - return errors.Wrapf(graphdriver.ErrPrerequisites, "no zfs dataset found for rootdir '%s'", rootdir) - } - - return nil -} - -func getMountpoint(id string) string { - return id -} diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs_solaris.go b/vendor/github.com/containers/storage/drivers/zfs/zfs_solaris.go deleted file mode 100644 index 2383bf3bf3..0000000000 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs_solaris.go +++ /dev/null @@ -1,59 +0,0 @@ -// +build solaris,cgo - -package zfs - -/* -#include -#include - -static inline struct statvfs *getstatfs(char *s) { - struct statvfs *buf; - int err; - buf = (struct statvfs *)malloc(sizeof(struct statvfs)); - err = statvfs(s, buf); - return buf; -} -*/ -import "C" -import ( - "path/filepath" - "strings" - "unsafe" - - "github.com/containers/storage/drivers" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -func checkRootdirFs(rootdir string) error { - - cs := C.CString(filepath.Dir(rootdir)) - defer C.free(unsafe.Pointer(cs)) - buf := C.getstatfs(cs) - defer C.free(unsafe.Pointer(buf)) - - // on Solaris buf.f_basetype contains ['z', 'f', 's', 0 ... ] - if (buf.f_basetype[0] != 122) || (buf.f_basetype[1] != 102) || (buf.f_basetype[2] != 115) || - (buf.f_basetype[3] != 0) { - logrus.Debugf("[zfs] no zfs dataset found for rootdir '%s'", rootdir) - return errors.Wrapf(graphdriver.ErrPrerequisites, "no zfs dataset found for rootdir '%s'", rootdir) - } - - return nil -} - -/* rootfs is introduced to comply with the OCI spec -which states that root filesystem must be mounted at /rootfs/ instead of / -*/ -func getMountpoint(id string) string { - maxlen := 12 - - // we need to preserve filesystem suffix - suffix := strings.SplitN(id, "-", 2) - - if len(suffix) > 1 { - return filepath.Join(id[:maxlen]+"-"+suffix[1], "rootfs", "root") - } - - return filepath.Join(id[:maxlen], "rootfs", "root") -} diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs_unsupported.go b/vendor/github.com/containers/storage/drivers/zfs/zfs_unsupported.go deleted file mode 100644 index ce8daadaf6..0000000000 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs_unsupported.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !linux,!freebsd,!solaris - -package zfs - -func checkRootdirFs(rootdir string) error { - return nil -} - -func getMountpoint(id string) string { - return id -} diff --git a/vendor/github.com/containers/storage/errors.go b/vendor/github.com/containers/storage/errors.go deleted file mode 100644 index bed6f8cdc7..0000000000 --- a/vendor/github.com/containers/storage/errors.go +++ /dev/null @@ -1,56 +0,0 @@ -package storage - -import ( - "errors" -) - -var ( - // ErrContainerUnknown indicates that there was no container with the specified name or ID. - ErrContainerUnknown = errors.New("container not known") - // ErrImageUnknown indicates that there was no image with the specified name or ID. - ErrImageUnknown = errors.New("image not known") - // ErrParentUnknown indicates that we didn't record the ID of the parent of the specified layer. - ErrParentUnknown = errors.New("parent of layer not known") - // ErrLayerUnknown indicates that there was no layer with the specified name or ID. - ErrLayerUnknown = errors.New("layer not known") - // ErrLoadError indicates that there was an initialization error. - ErrLoadError = errors.New("error loading storage metadata") - // ErrDuplicateID indicates that an ID which is to be assigned to a new item is already being used. - ErrDuplicateID = errors.New("that ID is already in use") - // ErrDuplicateName indicates that a name which is to be assigned to a new item is already being used. - ErrDuplicateName = errors.New("that name is already in use") - // ErrParentIsContainer is returned when a caller attempts to create a layer as a child of a container's layer. - ErrParentIsContainer = errors.New("would-be parent layer is a container") - // ErrNotAContainer is returned when the caller attempts to delete a container that isn't a container. - ErrNotAContainer = errors.New("identifier is not a container") - // ErrNotAnImage is returned when the caller attempts to delete an image that isn't an image. - ErrNotAnImage = errors.New("identifier is not an image") - // ErrNotALayer is returned when the caller attempts to delete a layer that isn't a layer. - ErrNotALayer = errors.New("identifier is not a layer") - // ErrNotAnID is returned when the caller attempts to read or write metadata from an item that doesn't exist. - ErrNotAnID = errors.New("identifier is not a layer, image, or container") - // ErrLayerHasChildren is returned when the caller attempts to delete a layer that has children. - ErrLayerHasChildren = errors.New("layer has children") - // ErrLayerUsedByImage is returned when the caller attempts to delete a layer that is an image's top layer. - ErrLayerUsedByImage = errors.New("layer is in use by an image") - // ErrLayerUsedByContainer is returned when the caller attempts to delete a layer that is a container's layer. - ErrLayerUsedByContainer = errors.New("layer is in use by a container") - // ErrImageUsedByContainer is returned when the caller attempts to delete an image that is a container's image. - ErrImageUsedByContainer = errors.New("image is in use by a container") - // ErrIncompleteOptions is returned when the caller attempts to initialize a Store without providing required information. - ErrIncompleteOptions = errors.New("missing necessary StoreOptions") - // ErrSizeUnknown is returned when the caller asks for the size of a big data item, but the Store couldn't determine the answer. - ErrSizeUnknown = errors.New("size is not known") - // ErrStoreIsReadOnly is returned when the caller makes a call to a read-only store that would require modifying its contents. - ErrStoreIsReadOnly = errors.New("called a write method on a read-only store") - // ErrLockReadOnly indicates that the caller only took a read-only lock, and is not allowed to write. - ErrLockReadOnly = errors.New("lock is not a read-write lock") - // ErrDuplicateImageNames indicates that the read-only store uses the same name for multiple images. - ErrDuplicateImageNames = errors.New("read-only image store assigns the same name to multiple images") - // ErrDuplicateLayerNames indicates that the read-only store uses the same name for multiple layers. - ErrDuplicateLayerNames = errors.New("read-only layer store assigns the same name to multiple layers") - // ErrInvalidBigDataName indicates that the name for a big data item is not acceptable; it may be empty. - ErrInvalidBigDataName = errors.New("not a valid name for a big data item") - // ErrDigestUnknown indicates that we were unable to compute the digest of a specified item. - ErrDigestUnknown = errors.New("could not compute digest of item") -) diff --git a/vendor/github.com/containers/storage/hack/generate-authors.sh b/vendor/github.com/containers/storage/hack/generate-authors.sh deleted file mode 100755 index e78a97f962..0000000000 --- a/vendor/github.com/containers/storage/hack/generate-authors.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -set -e - -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.." - -# see also ".mailmap" for how email addresses and names are deduplicated - -{ - cat <<-'EOH' - # This file lists all individuals having contributed content to the repository. - # For how it is generated, see `hack/generate-authors.sh`. - EOH - echo - git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf -} > AUTHORS diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go deleted file mode 100644 index 962e1bb760..0000000000 --- a/vendor/github.com/containers/storage/images.go +++ /dev/null @@ -1,673 +0,0 @@ -package storage - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "time" - - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/stringid" - "github.com/containers/storage/pkg/truncindex" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -const ( - // ImageDigestBigDataKey is the name of the big data item whose - // contents we consider useful for computing a "digest" of the - // image, by which we can locate the image later. - ImageDigestBigDataKey = "manifest" -) - -// An Image is a reference to a layer and an associated metadata string. -type Image struct { - // ID is either one which was specified at create-time, or a random - // value which was generated by the library. - ID string `json:"id"` - - // Digest is a digest value that we can use to locate the image. - Digest digest.Digest `json:"digest,omitempty"` - - // Names is an optional set of user-defined convenience values. The - // image can be referred to by its ID or any of its names. Names are - // unique among images. - Names []string `json:"names,omitempty"` - - // TopLayer is the ID of the topmost layer of the image itself, if the - // image contains one or more layers. Multiple images can refer to the - // same top layer. - TopLayer string `json:"layer,omitempty"` - - // Metadata is data we keep for the convenience of the caller. It is not - // expected to be large, since it is kept in memory. - Metadata string `json:"metadata,omitempty"` - - // BigDataNames is a list of names of data items that we keep for the - // convenience of the caller. They can be large, and are only in - // memory when being read from or written to disk. - BigDataNames []string `json:"big-data-names,omitempty"` - - // BigDataSizes maps the names in BigDataNames to the sizes of the data - // that has been stored, if they're known. - BigDataSizes map[string]int64 `json:"big-data-sizes,omitempty"` - - // BigDataDigests maps the names in BigDataNames to the digests of the - // data that has been stored, if they're known. - BigDataDigests map[string]digest.Digest `json:"big-data-digests,omitempty"` - - // Created is the datestamp for when this image was created. Older - // versions of the library did not track this information, so callers - // will likely want to use the IsZero() method to verify that a value - // is set before using it. - Created time.Time `json:"created,omitempty"` - - Flags map[string]interface{} `json:"flags,omitempty"` -} - -// ROImageStore provides bookkeeping for information about Images. -type ROImageStore interface { - ROFileBasedStore - ROMetadataStore - ROBigDataStore - - // Exists checks if there is an image with the given ID or name. - Exists(id string) bool - - // Get retrieves information about an image given an ID or name. - Get(id string) (*Image, error) - - // Lookup attempts to translate a name to an ID. Most methods do this - // implicitly. - Lookup(name string) (string, error) - - // Images returns a slice enumerating the known images. - Images() ([]Image, error) - - // Images returns a slice enumerating the images which have a big data - // item with the name ImageDigestBigDataKey and the specified digest. - ByDigest(d digest.Digest) ([]*Image, error) -} - -// ImageStore provides bookkeeping for information about Images. -type ImageStore interface { - ROImageStore - RWFileBasedStore - RWMetadataStore - RWBigDataStore - FlaggableStore - - // Create creates an image that has a specified ID (or a random one) and - // optional names, using the specified layer as its topmost (hopefully - // read-only) layer. That layer can be referenced by multiple images. - Create(id string, names []string, layer, metadata string, created time.Time, searchableDigest digest.Digest) (*Image, error) - - // SetNames replaces the list of names associated with an image with the - // supplied values. - SetNames(id string, names []string) error - - // Delete removes the record of the image. - Delete(id string) error - - // Wipe removes records of all images. - Wipe() error -} - -type imageStore struct { - lockfile Locker - dir string - images []*Image - idindex *truncindex.TruncIndex - byid map[string]*Image - byname map[string]*Image - bydigest map[digest.Digest][]*Image -} - -func (r *imageStore) Images() ([]Image, error) { - images := make([]Image, len(r.images)) - for i := range r.images { - images[i] = *(r.images[i]) - } - return images, nil -} - -func (r *imageStore) imagespath() string { - return filepath.Join(r.dir, "images.json") -} - -func (r *imageStore) datadir(id string) string { - return filepath.Join(r.dir, id) -} - -func (r *imageStore) datapath(id, key string) string { - return filepath.Join(r.datadir(id), makeBigDataBaseName(key)) -} - -func (r *imageStore) Load() error { - shouldSave := false - rpath := r.imagespath() - data, err := ioutil.ReadFile(rpath) - if err != nil && !os.IsNotExist(err) { - return err - } - images := []*Image{} - idlist := []string{} - ids := make(map[string]*Image) - names := make(map[string]*Image) - digests := make(map[digest.Digest][]*Image) - if err = json.Unmarshal(data, &images); len(data) == 0 || err == nil { - idlist = make([]string, 0, len(images)) - for n, image := range images { - ids[image.ID] = images[n] - idlist = append(idlist, image.ID) - for _, name := range image.Names { - if conflict, ok := names[name]; ok { - r.removeName(conflict, name) - shouldSave = true - } - names[name] = images[n] - } - // Implicit digest - if digest, ok := image.BigDataDigests[ImageDigestBigDataKey]; ok { - digests[digest] = append(digests[digest], images[n]) - } - // Explicit digest - if image.Digest == "" { - image.Digest = image.BigDataDigests[ImageDigestBigDataKey] - } else if image.Digest != image.BigDataDigests[ImageDigestBigDataKey] { - digests[image.Digest] = append(digests[image.Digest], images[n]) - } - } - } - if shouldSave && !r.IsReadWrite() { - return ErrDuplicateImageNames - } - r.images = images - r.idindex = truncindex.NewTruncIndex(idlist) - r.byid = ids - r.byname = names - r.bydigest = digests - if shouldSave { - return r.Save() - } - return nil -} - -func (r *imageStore) Save() error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the image store at %q", r.imagespath()) - } - rpath := r.imagespath() - if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { - return err - } - jdata, err := json.Marshal(&r.images) - if err != nil { - return err - } - defer r.Touch() - return ioutils.AtomicWriteFile(rpath, jdata, 0600) -} - -func newImageStore(dir string) (ImageStore, error) { - if err := os.MkdirAll(dir, 0700); err != nil { - return nil, err - } - lockfile, err := GetLockfile(filepath.Join(dir, "images.lock")) - if err != nil { - return nil, err - } - lockfile.Lock() - defer lockfile.Unlock() - istore := imageStore{ - lockfile: lockfile, - dir: dir, - images: []*Image{}, - byid: make(map[string]*Image), - byname: make(map[string]*Image), - bydigest: make(map[digest.Digest][]*Image), - } - if err := istore.Load(); err != nil { - return nil, err - } - return &istore, nil -} - -func newROImageStore(dir string) (ROImageStore, error) { - lockfile, err := GetROLockfile(filepath.Join(dir, "images.lock")) - if err != nil { - return nil, err - } - lockfile.Lock() - defer lockfile.Unlock() - istore := imageStore{ - lockfile: lockfile, - dir: dir, - images: []*Image{}, - byid: make(map[string]*Image), - byname: make(map[string]*Image), - bydigest: make(map[digest.Digest][]*Image), - } - if err := istore.Load(); err != nil { - return nil, err - } - return &istore, nil -} - -func (r *imageStore) lookup(id string) (*Image, bool) { - if image, ok := r.byid[id]; ok { - return image, ok - } else if image, ok := r.byname[id]; ok { - return image, ok - } else if longid, err := r.idindex.Get(id); err == nil { - image, ok := r.byid[longid] - return image, ok - } - return nil, false -} - -func (r *imageStore) ClearFlag(id string, flag string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to clear flags on images at %q", r.imagespath()) - } - image, ok := r.lookup(id) - if !ok { - return ErrImageUnknown - } - delete(image.Flags, flag) - return r.Save() -} - -func (r *imageStore) SetFlag(id string, flag string, value interface{}) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to set flags on images at %q", r.imagespath()) - } - image, ok := r.lookup(id) - if !ok { - return ErrImageUnknown - } - if image.Flags == nil { - image.Flags = make(map[string]interface{}) - } - image.Flags[flag] = value - return r.Save() -} - -func (r *imageStore) Create(id string, names []string, layer, metadata string, created time.Time, searchableDigest digest.Digest) (image *Image, err error) { - if !r.IsReadWrite() { - return nil, errors.Wrapf(ErrStoreIsReadOnly, "not allowed to create new images at %q", r.imagespath()) - } - if id == "" { - id = stringid.GenerateRandomID() - _, idInUse := r.byid[id] - for idInUse { - id = stringid.GenerateRandomID() - _, idInUse = r.byid[id] - } - } - if _, idInUse := r.byid[id]; idInUse { - return nil, ErrDuplicateID - } - names = dedupeNames(names) - for _, name := range names { - if _, nameInUse := r.byname[name]; nameInUse { - return nil, ErrDuplicateName - } - } - if created.IsZero() { - created = time.Now().UTC() - } - if err == nil { - image = &Image{ - ID: id, - Digest: searchableDigest, - Names: names, - TopLayer: layer, - Metadata: metadata, - BigDataNames: []string{}, - BigDataSizes: make(map[string]int64), - BigDataDigests: make(map[string]digest.Digest), - Created: created, - Flags: make(map[string]interface{}), - } - r.images = append(r.images, image) - r.idindex.Add(id) - r.byid[id] = image - if searchableDigest != "" { - list := r.bydigest[searchableDigest] - r.bydigest[searchableDigest] = append(list, image) - } - for _, name := range names { - r.byname[name] = image - } - err = r.Save() - } - return image, err -} - -func (r *imageStore) Metadata(id string) (string, error) { - if image, ok := r.lookup(id); ok { - return image.Metadata, nil - } - return "", ErrImageUnknown -} - -func (r *imageStore) SetMetadata(id, metadata string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify image metadata at %q", r.imagespath()) - } - if image, ok := r.lookup(id); ok { - image.Metadata = metadata - return r.Save() - } - return ErrImageUnknown -} - -func (r *imageStore) removeName(image *Image, name string) { - image.Names = stringSliceWithoutValue(image.Names, name) -} - -func (r *imageStore) SetNames(id string, names []string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change image name assignments at %q", r.imagespath()) - } - names = dedupeNames(names) - if image, ok := r.lookup(id); ok { - for _, name := range image.Names { - delete(r.byname, name) - } - for _, name := range names { - if otherImage, ok := r.byname[name]; ok { - r.removeName(otherImage, name) - } - r.byname[name] = image - } - image.Names = names - return r.Save() - } - return ErrImageUnknown -} - -func (r *imageStore) Delete(id string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete images at %q", r.imagespath()) - } - image, ok := r.lookup(id) - if !ok { - return ErrImageUnknown - } - id = image.ID - toDeleteIndex := -1 - for i, candidate := range r.images { - if candidate.ID == id { - toDeleteIndex = i - } - } - delete(r.byid, id) - r.idindex.Delete(id) - for _, name := range image.Names { - delete(r.byname, name) - } - if toDeleteIndex != -1 { - // delete the image at toDeleteIndex - if toDeleteIndex == len(r.images)-1 { - r.images = r.images[:len(r.images)-1] - } else { - r.images = append(r.images[:toDeleteIndex], r.images[toDeleteIndex+1:]...) - } - } - if digest, ok := image.BigDataDigests[ImageDigestBigDataKey]; ok { - // remove the image from the digest-based index - if list, ok := r.bydigest[digest]; ok { - prunedList := imageSliceWithoutValue(list, image) - if len(prunedList) == 0 { - delete(r.bydigest, digest) - } else { - r.bydigest[digest] = prunedList - } - } - } - if image.Digest != "" { - // remove the image's hard-coded digest from the digest-based index - if list, ok := r.bydigest[image.Digest]; ok { - prunedList := imageSliceWithoutValue(list, image) - if len(prunedList) == 0 { - delete(r.bydigest, image.Digest) - } else { - r.bydigest[image.Digest] = prunedList - } - } - } - if err := r.Save(); err != nil { - return err - } - if err := os.RemoveAll(r.datadir(id)); err != nil { - return err - } - return nil -} - -func (r *imageStore) Get(id string) (*Image, error) { - if image, ok := r.lookup(id); ok { - return image, nil - } - return nil, ErrImageUnknown -} - -func (r *imageStore) Lookup(name string) (id string, err error) { - if image, ok := r.lookup(name); ok { - return image.ID, nil - } - return "", ErrImageUnknown -} - -func (r *imageStore) Exists(id string) bool { - _, ok := r.lookup(id) - return ok -} - -func (r *imageStore) ByDigest(d digest.Digest) ([]*Image, error) { - if images, ok := r.bydigest[d]; ok { - return images, nil - } - return nil, ErrImageUnknown -} - -func (r *imageStore) BigData(id, key string) ([]byte, error) { - if key == "" { - return nil, errors.Wrapf(ErrInvalidBigDataName, "can't retrieve image big data value for empty name") - } - image, ok := r.lookup(id) - if !ok { - return nil, ErrImageUnknown - } - return ioutil.ReadFile(r.datapath(image.ID, key)) -} - -func (r *imageStore) BigDataSize(id, key string) (int64, error) { - if key == "" { - return -1, errors.Wrapf(ErrInvalidBigDataName, "can't retrieve size of image big data with empty name") - } - image, ok := r.lookup(id) - if !ok { - return -1, ErrImageUnknown - } - if image.BigDataSizes == nil { - image.BigDataSizes = make(map[string]int64) - } - if size, ok := image.BigDataSizes[key]; ok { - return size, nil - } - if data, err := r.BigData(id, key); err == nil && data != nil { - if r.SetBigData(id, key, data) == nil { - image, ok := r.lookup(id) - if !ok { - return -1, ErrImageUnknown - } - if size, ok := image.BigDataSizes[key]; ok { - return size, nil - } - } - } - return -1, ErrSizeUnknown -} - -func (r *imageStore) BigDataDigest(id, key string) (digest.Digest, error) { - if key == "" { - return "", errors.Wrapf(ErrInvalidBigDataName, "can't retrieve digest of image big data value with empty name") - } - image, ok := r.lookup(id) - if !ok { - return "", ErrImageUnknown - } - if image.BigDataDigests == nil { - image.BigDataDigests = make(map[string]digest.Digest) - } - if d, ok := image.BigDataDigests[key]; ok { - return d, nil - } - if data, err := r.BigData(id, key); err == nil && data != nil { - if r.SetBigData(id, key, data) == nil { - image, ok := r.lookup(id) - if !ok { - return "", ErrImageUnknown - } - if d, ok := image.BigDataDigests[key]; ok { - return d, nil - } - } - } - return "", ErrDigestUnknown -} - -func (r *imageStore) BigDataNames(id string) ([]string, error) { - image, ok := r.lookup(id) - if !ok { - return nil, ErrImageUnknown - } - return image.BigDataNames, nil -} - -func imageSliceWithoutValue(slice []*Image, value *Image) []*Image { - modified := make([]*Image, 0, len(slice)) - for _, v := range slice { - if v == value { - continue - } - modified = append(modified, v) - } - return modified -} - -func (r *imageStore) SetBigData(id, key string, data []byte) error { - if key == "" { - return errors.Wrapf(ErrInvalidBigDataName, "can't set empty name for image big data item") - } - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to save data items associated with images at %q", r.imagespath()) - } - image, ok := r.lookup(id) - if !ok { - return ErrImageUnknown - } - if err := os.MkdirAll(r.datadir(image.ID), 0700); err != nil { - return err - } - err := ioutils.AtomicWriteFile(r.datapath(image.ID, key), data, 0600) - if err == nil { - save := false - if image.BigDataSizes == nil { - image.BigDataSizes = make(map[string]int64) - } - oldSize, sizeOk := image.BigDataSizes[key] - image.BigDataSizes[key] = int64(len(data)) - if image.BigDataDigests == nil { - image.BigDataDigests = make(map[string]digest.Digest) - } - oldDigest, digestOk := image.BigDataDigests[key] - newDigest := digest.Canonical.FromBytes(data) - image.BigDataDigests[key] = newDigest - if !sizeOk || oldSize != image.BigDataSizes[key] || !digestOk || oldDigest != newDigest { - save = true - } - addName := true - for _, name := range image.BigDataNames { - if name == key { - addName = false - break - } - } - if addName { - image.BigDataNames = append(image.BigDataNames, key) - save = true - } - if key == ImageDigestBigDataKey { - if oldDigest != "" && oldDigest != newDigest && oldDigest != image.Digest { - // remove the image from the list of images in the digest-based - // index which corresponds to the old digest for this item, unless - // it's also the hard-coded digest - if list, ok := r.bydigest[oldDigest]; ok { - prunedList := imageSliceWithoutValue(list, image) - if len(prunedList) == 0 { - delete(r.bydigest, oldDigest) - } else { - r.bydigest[oldDigest] = prunedList - } - } - } - // add the image to the list of images in the digest-based index which - // corresponds to the new digest for this item, unless it's already there - list := r.bydigest[newDigest] - if len(list) == len(imageSliceWithoutValue(list, image)) { - // the list isn't shortened by trying to prune this image from it, - // so it's not in there yet - r.bydigest[newDigest] = append(list, image) - } - } - if save { - err = r.Save() - } - } - return err -} - -func (r *imageStore) Wipe() error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete images at %q", r.imagespath()) - } - ids := make([]string, 0, len(r.byid)) - for id := range r.byid { - ids = append(ids, id) - } - for _, id := range ids { - if err := r.Delete(id); err != nil { - return err - } - } - return nil -} - -func (r *imageStore) Lock() { - r.lockfile.Lock() -} - -func (r *imageStore) Unlock() { - r.lockfile.Unlock() -} - -func (r *imageStore) Touch() error { - return r.lockfile.Touch() -} - -func (r *imageStore) Modified() (bool, error) { - return r.lockfile.Modified() -} - -func (r *imageStore) IsReadWrite() bool { - return r.lockfile.IsReadWrite() -} - -func (r *imageStore) TouchedSince(when time.Time) bool { - return r.lockfile.TouchedSince(when) -} diff --git a/vendor/github.com/containers/storage/images_ffjson.go b/vendor/github.com/containers/storage/images_ffjson.go deleted file mode 100644 index f6a8b0650e..0000000000 --- a/vendor/github.com/containers/storage/images_ffjson.go +++ /dev/null @@ -1,1202 +0,0 @@ -// Code generated by ffjson . DO NOT EDIT. -// source: images.go - -package storage - -import ( - "bytes" - "encoding/json" - "fmt" - "github.com/opencontainers/go-digest" - fflib "github.com/pquerna/ffjson/fflib/v1" -) - -// MarshalJSON marshal bytes to json - template -func (j *Image) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *Image) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{ "id":`) - fflib.WriteJsonString(buf, string(j.ID)) - buf.WriteByte(',') - if len(j.Digest) != 0 { - buf.WriteString(`"digest":`) - fflib.WriteJsonString(buf, string(j.Digest)) - buf.WriteByte(',') - } - if len(j.Names) != 0 { - buf.WriteString(`"names":`) - if j.Names != nil { - buf.WriteString(`[`) - for i, v := range j.Names { - if i != 0 { - buf.WriteString(`,`) - } - fflib.WriteJsonString(buf, string(v)) - } - buf.WriteString(`]`) - } else { - buf.WriteString(`null`) - } - buf.WriteByte(',') - } - if len(j.TopLayer) != 0 { - buf.WriteString(`"layer":`) - fflib.WriteJsonString(buf, string(j.TopLayer)) - buf.WriteByte(',') - } - if len(j.Metadata) != 0 { - buf.WriteString(`"metadata":`) - fflib.WriteJsonString(buf, string(j.Metadata)) - buf.WriteByte(',') - } - if len(j.BigDataNames) != 0 { - buf.WriteString(`"big-data-names":`) - if j.BigDataNames != nil { - buf.WriteString(`[`) - for i, v := range j.BigDataNames { - if i != 0 { - buf.WriteString(`,`) - } - fflib.WriteJsonString(buf, string(v)) - } - buf.WriteString(`]`) - } else { - buf.WriteString(`null`) - } - buf.WriteByte(',') - } - if len(j.BigDataSizes) != 0 { - if j.BigDataSizes == nil { - buf.WriteString(`"big-data-sizes":null`) - } else { - buf.WriteString(`"big-data-sizes":{ `) - for key, value := range j.BigDataSizes { - fflib.WriteJsonString(buf, key) - buf.WriteString(`:`) - fflib.FormatBits2(buf, uint64(value), 10, value < 0) - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - } - buf.WriteByte(',') - } - if len(j.BigDataDigests) != 0 { - if j.BigDataDigests == nil { - buf.WriteString(`"big-data-digests":null`) - } else { - buf.WriteString(`"big-data-digests":{ `) - for key, value := range j.BigDataDigests { - fflib.WriteJsonString(buf, key) - buf.WriteString(`:`) - fflib.WriteJsonString(buf, string(value)) - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - } - buf.WriteByte(',') - } - if true { - buf.WriteString(`"created":`) - - { - - obj, err = j.Created.MarshalJSON() - if err != nil { - return err - } - buf.Write(obj) - - } - buf.WriteByte(',') - } - if len(j.Flags) != 0 { - buf.WriteString(`"flags":`) - /* Falling back. type=map[string]interface {} kind=map */ - err = buf.Encode(j.Flags) - if err != nil { - return err - } - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - return nil -} - -const ( - ffjtImagebase = iota - ffjtImagenosuchkey - - ffjtImageID - - ffjtImageDigest - - ffjtImageNames - - ffjtImageTopLayer - - ffjtImageMetadata - - ffjtImageBigDataNames - - ffjtImageBigDataSizes - - ffjtImageBigDataDigests - - ffjtImageCreated - - ffjtImageFlags -) - -var ffjKeyImageID = []byte("id") - -var ffjKeyImageDigest = []byte("digest") - -var ffjKeyImageNames = []byte("names") - -var ffjKeyImageTopLayer = []byte("layer") - -var ffjKeyImageMetadata = []byte("metadata") - -var ffjKeyImageBigDataNames = []byte("big-data-names") - -var ffjKeyImageBigDataSizes = []byte("big-data-sizes") - -var ffjKeyImageBigDataDigests = []byte("big-data-digests") - -var ffjKeyImageCreated = []byte("created") - -var ffjKeyImageFlags = []byte("flags") - -// UnmarshalJSON umarshall json - template of ffjson -func (j *Image) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *Image) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtImagebase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtImagenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - case 'b': - - if bytes.Equal(ffjKeyImageBigDataNames, kn) { - currentKey = ffjtImageBigDataNames - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyImageBigDataSizes, kn) { - currentKey = ffjtImageBigDataSizes - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyImageBigDataDigests, kn) { - currentKey = ffjtImageBigDataDigests - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'c': - - if bytes.Equal(ffjKeyImageCreated, kn) { - currentKey = ffjtImageCreated - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'd': - - if bytes.Equal(ffjKeyImageDigest, kn) { - currentKey = ffjtImageDigest - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'f': - - if bytes.Equal(ffjKeyImageFlags, kn) { - currentKey = ffjtImageFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'i': - - if bytes.Equal(ffjKeyImageID, kn) { - currentKey = ffjtImageID - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'l': - - if bytes.Equal(ffjKeyImageTopLayer, kn) { - currentKey = ffjtImageTopLayer - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'm': - - if bytes.Equal(ffjKeyImageMetadata, kn) { - currentKey = ffjtImageMetadata - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'n': - - if bytes.Equal(ffjKeyImageNames, kn) { - currentKey = ffjtImageNames - state = fflib.FFParse_want_colon - goto mainparse - } - - } - - if fflib.EqualFoldRight(ffjKeyImageFlags, kn) { - currentKey = ffjtImageFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyImageCreated, kn) { - currentKey = ffjtImageCreated - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyImageBigDataDigests, kn) { - currentKey = ffjtImageBigDataDigests - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyImageBigDataSizes, kn) { - currentKey = ffjtImageBigDataSizes - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyImageBigDataNames, kn) { - currentKey = ffjtImageBigDataNames - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyImageMetadata, kn) { - currentKey = ffjtImageMetadata - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyImageTopLayer, kn) { - currentKey = ffjtImageTopLayer - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyImageNames, kn) { - currentKey = ffjtImageNames - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyImageDigest, kn) { - currentKey = ffjtImageDigest - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyImageID, kn) { - currentKey = ffjtImageID - state = fflib.FFParse_want_colon - goto mainparse - } - - currentKey = ffjtImagenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtImageID: - goto handle_ID - - case ffjtImageDigest: - goto handle_Digest - - case ffjtImageNames: - goto handle_Names - - case ffjtImageTopLayer: - goto handle_TopLayer - - case ffjtImageMetadata: - goto handle_Metadata - - case ffjtImageBigDataNames: - goto handle_BigDataNames - - case ffjtImageBigDataSizes: - goto handle_BigDataSizes - - case ffjtImageBigDataDigests: - goto handle_BigDataDigests - - case ffjtImageCreated: - goto handle_Created - - case ffjtImageFlags: - goto handle_Flags - - case ffjtImagenosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -handle_ID: - - /* handler: j.ID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.ID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Digest: - - /* handler: j.Digest type=digest.Digest kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.Digest = digest.Digest(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Names: - - /* handler: j.Names type=[]string kind=slice quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Names = nil - } else { - - j.Names = []string{} - - wantVal := true - - for { - - var tmpJNames string - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_brace { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: tmpJNames type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJNames = string(string(outBuf)) - - } - } - - j.Names = append(j.Names, tmpJNames) - - wantVal = false - } - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_TopLayer: - - /* handler: j.TopLayer type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.TopLayer = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Metadata: - - /* handler: j.Metadata type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.Metadata = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataNames: - - /* handler: j.BigDataNames type=[]string kind=slice quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataNames = nil - } else { - - j.BigDataNames = []string{} - - wantVal := true - - for { - - var tmpJBigDataNames string - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_brace { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: tmpJBigDataNames type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJBigDataNames = string(string(outBuf)) - - } - } - - j.BigDataNames = append(j.BigDataNames, tmpJBigDataNames) - - wantVal = false - } - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataSizes: - - /* handler: j.BigDataSizes type=map[string]int64 kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataSizes = nil - } else { - - j.BigDataSizes = make(map[string]int64, 0) - - wantVal := true - - for { - - var k string - - var tmpJBigDataSizes int64 - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJBigDataSizes type=int64 kind=int64 quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - tmpJBigDataSizes = int64(tval) - - } - } - - j.BigDataSizes[k] = tmpJBigDataSizes - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_BigDataDigests: - - /* handler: j.BigDataDigests type=map[string]digest.Digest kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.BigDataDigests = nil - } else { - - j.BigDataDigests = make(map[string]digest.Digest, 0) - - wantVal := true - - for { - - var k string - - var tmpJBigDataDigests digest.Digest - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJBigDataDigests type=digest.Digest kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJBigDataDigests = digest.Digest(string(outBuf)) - - } - } - - j.BigDataDigests[k] = tmpJBigDataDigests - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Created: - - /* handler: j.Created type=time.Time kind=struct quoted=false*/ - - { - if tok == fflib.FFTok_null { - - } else { - - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = j.Created.UnmarshalJSON(tbuf) - if err != nil { - return fs.WrapErr(err) - } - } - state = fflib.FFParse_after_value - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Flags: - - /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Flags = nil - } else { - - j.Flags = make(map[string]interface{}, 0) - - wantVal := true - - for { - - var k string - - var tmpJFlags interface{} - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/ - - { - /* Falling back. type=interface {} kind=interface */ - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = json.Unmarshal(tbuf, &tmpJFlags) - if err != nil { - return fs.WrapErr(err) - } - } - - j.Flags[k] = tmpJFlags - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *imageStore) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *imageStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{}`) - return nil -} - -const ( - ffjtimageStorebase = iota - ffjtimageStorenosuchkey -) - -// UnmarshalJSON umarshall json - template of ffjson -func (j *imageStore) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *imageStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtimageStorebase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtimageStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - } - - currentKey = ffjtimageStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtimageStorenosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go deleted file mode 100644 index a1be6eee77..0000000000 --- a/vendor/github.com/containers/storage/layers.go +++ /dev/null @@ -1,1041 +0,0 @@ -package storage - -import ( - "bytes" - "compress/gzip" - "encoding/json" - "io" - "io/ioutil" - "os" - "path/filepath" - "time" - - drivers "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/stringid" - "github.com/containers/storage/pkg/truncindex" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/vbatts/tar-split/tar/asm" - "github.com/vbatts/tar-split/tar/storage" -) - -const ( - tarSplitSuffix = ".tar-split.gz" - incompleteFlag = "incomplete" - compressionFlag = "diff-compression" -) - -// A Layer is a record of a copy-on-write layer that's stored by the lower -// level graph driver. -type Layer struct { - // ID is either one which was specified at create-time, or a random - // value which was generated by the library. - ID string `json:"id"` - - // Names is an optional set of user-defined convenience values. The - // layer can be referred to by its ID or any of its names. Names are - // unique among layers. - Names []string `json:"names,omitempty"` - - // Parent is the ID of a layer from which this layer inherits data. - Parent string `json:"parent,omitempty"` - - // Metadata is data we keep for the convenience of the caller. It is not - // expected to be large, since it is kept in memory. - Metadata string `json:"metadata,omitempty"` - - // MountLabel is an SELinux label which should be used when attempting to mount - // the layer. - MountLabel string `json:"mountlabel,omitempty"` - - // MountPoint is the path where the layer is mounted, or where it was most - // recently mounted. This can change between subsequent Unmount() and - // Mount() calls, so the caller should consult this value after Mount() - // succeeds to find the location of the container's root filesystem. - MountPoint string `json:"-"` - - // MountCount is used as a reference count for the container's layer being - // mounted at the mount point. - MountCount int `json:"-"` - - // Created is the datestamp for when this layer was created. Older - // versions of the library did not track this information, so callers - // will likely want to use the IsZero() method to verify that a value - // is set before using it. - Created time.Time `json:"created,omitempty"` - - // CompressedDigest is the digest of the blob that was last passed to - // ApplyDiff() or Put(), as it was presented to us. - CompressedDigest digest.Digest `json:"compressed-diff-digest,omitempty"` - - // CompressedSize is the length of the blob that was last passed to - // ApplyDiff() or Put(), as it was presented to us. If - // CompressedDigest is not set, this should be treated as if it were an - // uninitialized value. - CompressedSize int64 `json:"compressed-size,omitempty"` - - // UncompressedDigest is the digest of the blob that was last passed to - // ApplyDiff() or Put(), after we decompressed it. Often referred to - // as a DiffID. - UncompressedDigest digest.Digest `json:"diff-digest,omitempty"` - - // UncompressedSize is the length of the blob that was last passed to - // ApplyDiff() or Put(), after we decompressed it. If - // UncompressedDigest is not set, this should be treated as if it were - // an uninitialized value. - UncompressedSize int64 `json:"diff-size,omitempty"` - - // CompressionType is the type of compression which we detected on the blob - // that was last passed to ApplyDiff() or Put(). - CompressionType archive.Compression `json:"compression,omitempty"` - - // Flags is arbitrary data about the layer. - Flags map[string]interface{} `json:"flags,omitempty"` -} - -type layerMountPoint struct { - ID string `json:"id"` - MountPoint string `json:"path"` - MountCount int `json:"count"` -} - -// DiffOptions override the default behavior of Diff() methods. -type DiffOptions struct { - // Compression, if set overrides the default compressor when generating a diff. - Compression *archive.Compression -} - -// ROLayerStore wraps a graph driver, adding the ability to refer to layers by -// name, and keeping track of parent-child relationships, along with a list of -// all known layers. -type ROLayerStore interface { - ROFileBasedStore - ROMetadataStore - - // Exists checks if a layer with the specified name or ID is known. - Exists(id string) bool - - // Get retrieves information about a layer given an ID or name. - Get(id string) (*Layer, error) - - // Status returns an slice of key-value pairs, suitable for human consumption, - // relaying whatever status information the underlying driver can share. - Status() ([][2]string, error) - - // Changes returns a slice of Change structures, which contain a pathname - // (Path) and a description of what sort of change (Kind) was made by the - // layer (either ChangeModify, ChangeAdd, or ChangeDelete), relative to a - // specified layer. By default, the layer's parent is used as a reference. - Changes(from, to string) ([]archive.Change, error) - - // Diff produces a tarstream which can be applied to a layer with the contents - // of the first layer to produce a layer with the contents of the second layer. - // By default, the parent of the second layer is used as the first - // layer, so it need not be specified. Options can be used to override - // default behavior, but are also not required. - Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) - - // DiffSize produces an estimate of the length of the tarstream which would be - // produced by Diff. - DiffSize(from, to string) (int64, error) - - // Size produces a cached value for the uncompressed size of the layer, - // if one is known, or -1 if it is not known. If the layer can not be - // found, it returns an error. - Size(name string) (int64, error) - - // Lookup attempts to translate a name to an ID. Most methods do this - // implicitly. - Lookup(name string) (string, error) - - // LayersByCompressedDigest returns a slice of the layers with the - // specified compressed digest value recorded for them. - LayersByCompressedDigest(d digest.Digest) ([]Layer, error) - - // LayersByUncompressedDigest returns a slice of the layers with the - // specified uncompressed digest value recorded for them. - LayersByUncompressedDigest(d digest.Digest) ([]Layer, error) - - // Layers returns a slice of the known layers. - Layers() ([]Layer, error) -} - -// LayerStore wraps a graph driver, adding the ability to refer to layers by -// name, and keeping track of parent-child relationships, along with a list of -// all known layers. -type LayerStore interface { - ROLayerStore - RWFileBasedStore - RWMetadataStore - FlaggableStore - - // Create creates a new layer, optionally giving it a specified ID rather than - // a randomly-generated one, either inheriting data from another specified - // layer or the empty base layer. The new layer can optionally be given names - // and have an SELinux label specified for use when mounting it. Some - // underlying drivers can accept a "size" option. At this time, most - // underlying drivers do not themselves distinguish between writeable - // and read-only layers. - Create(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool) (*Layer, error) - - // CreateWithFlags combines the functions of Create and SetFlag. - CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error) - - // Put combines the functions of CreateWithFlags and ApplyDiff. - Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff io.Reader) (*Layer, int64, error) - - // SetNames replaces the list of names associated with a layer with the - // supplied values. - SetNames(id string, names []string) error - - // Delete deletes a layer with the specified name or ID. - Delete(id string) error - - // Wipe deletes all layers. - Wipe() error - - // Mount mounts a layer for use. If the specified layer is the parent of other - // layers, it should not be written to. An SELinux label to be applied to the - // mount can be specified to override the one configured for the layer. - Mount(id, mountLabel string) (string, error) - - // Unmount unmounts a layer when it is no longer in use. - Unmount(id string) error - - // ApplyDiff reads a tarstream which was created by a previous call to Diff and - // applies its changes to a specified layer. - ApplyDiff(to string, diff io.Reader) (int64, error) -} - -type layerStore struct { - lockfile Locker - rundir string - driver drivers.Driver - layerdir string - layers []*Layer - idindex *truncindex.TruncIndex - byid map[string]*Layer - byname map[string]*Layer - bymount map[string]*Layer - bycompressedsum map[digest.Digest][]string - byuncompressedsum map[digest.Digest][]string -} - -func (r *layerStore) Layers() ([]Layer, error) { - layers := make([]Layer, len(r.layers)) - for i := range r.layers { - layers[i] = *(r.layers[i]) - } - return layers, nil -} - -func (r *layerStore) mountspath() string { - return filepath.Join(r.rundir, "mountpoints.json") -} - -func (r *layerStore) layerspath() string { - return filepath.Join(r.layerdir, "layers.json") -} - -func (r *layerStore) Load() error { - shouldSave := false - rpath := r.layerspath() - data, err := ioutil.ReadFile(rpath) - if err != nil && !os.IsNotExist(err) { - return err - } - layers := []*Layer{} - idlist := []string{} - ids := make(map[string]*Layer) - names := make(map[string]*Layer) - mounts := make(map[string]*Layer) - compressedsums := make(map[digest.Digest][]string) - uncompressedsums := make(map[digest.Digest][]string) - if err = json.Unmarshal(data, &layers); len(data) == 0 || err == nil { - idlist = make([]string, 0, len(layers)) - for n, layer := range layers { - ids[layer.ID] = layers[n] - idlist = append(idlist, layer.ID) - for _, name := range layer.Names { - if conflict, ok := names[name]; ok { - r.removeName(conflict, name) - shouldSave = true - } - names[name] = layers[n] - } - if layer.CompressedDigest != "" { - compressedsums[layer.CompressedDigest] = append(compressedsums[layer.CompressedDigest], layer.ID) - } - if layer.UncompressedDigest != "" { - uncompressedsums[layer.UncompressedDigest] = append(uncompressedsums[layer.UncompressedDigest], layer.ID) - } - } - } - if shouldSave && !r.IsReadWrite() { - return ErrDuplicateLayerNames - } - mpath := r.mountspath() - data, err = ioutil.ReadFile(mpath) - if err != nil && !os.IsNotExist(err) { - return err - } - layerMounts := []layerMountPoint{} - if err = json.Unmarshal(data, &layerMounts); len(data) == 0 || err == nil { - for _, mount := range layerMounts { - if mount.MountPoint != "" { - if layer, ok := ids[mount.ID]; ok { - mounts[mount.MountPoint] = layer - layer.MountPoint = mount.MountPoint - layer.MountCount = mount.MountCount - } - } - } - } - r.layers = layers - r.idindex = truncindex.NewTruncIndex(idlist) - r.byid = ids - r.byname = names - r.bymount = mounts - r.bycompressedsum = compressedsums - r.byuncompressedsum = uncompressedsums - err = nil - // Last step: if we're writable, try to remove anything that a previous - // user of this storage area marked for deletion but didn't manage to - // actually delete. - if r.IsReadWrite() { - for _, layer := range r.layers { - if layer.Flags == nil { - layer.Flags = make(map[string]interface{}) - } - if cleanup, ok := layer.Flags[incompleteFlag]; ok { - if b, ok := cleanup.(bool); ok && b { - err = r.Delete(layer.ID) - if err != nil { - break - } - shouldSave = true - } - } - } - if shouldSave { - return r.Save() - } - } - return err -} - -func (r *layerStore) Save() error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the layer store at %q", r.layerspath()) - } - rpath := r.layerspath() - if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { - return err - } - jldata, err := json.Marshal(&r.layers) - if err != nil { - return err - } - mpath := r.mountspath() - if err := os.MkdirAll(filepath.Dir(mpath), 0700); err != nil { - return err - } - mounts := make([]layerMountPoint, 0, len(r.layers)) - for _, layer := range r.layers { - if layer.MountPoint != "" && layer.MountCount > 0 { - mounts = append(mounts, layerMountPoint{ - ID: layer.ID, - MountPoint: layer.MountPoint, - MountCount: layer.MountCount, - }) - } - } - jmdata, err := json.Marshal(&mounts) - if err != nil { - return err - } - if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil { - return err - } - defer r.Touch() - return ioutils.AtomicWriteFile(mpath, jmdata, 0600) -} - -func newLayerStore(rundir string, layerdir string, driver drivers.Driver) (LayerStore, error) { - if err := os.MkdirAll(rundir, 0700); err != nil { - return nil, err - } - if err := os.MkdirAll(layerdir, 0700); err != nil { - return nil, err - } - lockfile, err := GetLockfile(filepath.Join(layerdir, "layers.lock")) - if err != nil { - return nil, err - } - lockfile.Lock() - defer lockfile.Unlock() - rlstore := layerStore{ - lockfile: lockfile, - driver: driver, - rundir: rundir, - layerdir: layerdir, - byid: make(map[string]*Layer), - bymount: make(map[string]*Layer), - byname: make(map[string]*Layer), - } - if err := rlstore.Load(); err != nil { - return nil, err - } - return &rlstore, nil -} - -func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (ROLayerStore, error) { - lockfile, err := GetROLockfile(filepath.Join(layerdir, "layers.lock")) - if err != nil { - return nil, err - } - lockfile.Lock() - defer lockfile.Unlock() - rlstore := layerStore{ - lockfile: lockfile, - driver: driver, - rundir: rundir, - layerdir: layerdir, - byid: make(map[string]*Layer), - bymount: make(map[string]*Layer), - byname: make(map[string]*Layer), - } - if err := rlstore.Load(); err != nil { - return nil, err - } - return &rlstore, nil -} - -func (r *layerStore) lookup(id string) (*Layer, bool) { - if layer, ok := r.byid[id]; ok { - return layer, ok - } else if layer, ok := r.byname[id]; ok { - return layer, ok - } else if longid, err := r.idindex.Get(id); err == nil { - layer, ok := r.byid[longid] - return layer, ok - } - return nil, false -} - -func (r *layerStore) Size(name string) (int64, error) { - layer, ok := r.lookup(name) - if !ok { - return -1, ErrLayerUnknown - } - // We use the presence of a non-empty digest as an indicator that the size value was intentionally set, and that - // a zero value is not just present because it was never set to anything else (which can happen if the layer was - // created by a version of this library that didn't keep track of digest and size information). - if layer.UncompressedDigest != "" { - return layer.UncompressedSize, nil - } - return -1, nil -} - -func (r *layerStore) ClearFlag(id string, flag string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to clear flags on layers at %q", r.layerspath()) - } - layer, ok := r.lookup(id) - if !ok { - return ErrLayerUnknown - } - delete(layer.Flags, flag) - return r.Save() -} - -func (r *layerStore) SetFlag(id string, flag string, value interface{}) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to set flags on layers at %q", r.layerspath()) - } - layer, ok := r.lookup(id) - if !ok { - return ErrLayerUnknown - } - if layer.Flags == nil { - layer.Flags = make(map[string]interface{}) - } - layer.Flags[flag] = value - return r.Save() -} - -func (r *layerStore) Status() ([][2]string, error) { - return r.driver.Status(), nil -} - -func (r *layerStore) Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff io.Reader) (layer *Layer, size int64, err error) { - if !r.IsReadWrite() { - return nil, -1, errors.Wrapf(ErrStoreIsReadOnly, "not allowed to create new layers at %q", r.layerspath()) - } - size = -1 - if err := os.MkdirAll(r.rundir, 0700); err != nil { - return nil, -1, err - } - if err := os.MkdirAll(r.layerdir, 0700); err != nil { - return nil, -1, err - } - if parent != "" { - if parentLayer, ok := r.lookup(parent); ok { - parent = parentLayer.ID - } - } - if id == "" { - id = stringid.GenerateRandomID() - _, idInUse := r.byid[id] - for idInUse { - id = stringid.GenerateRandomID() - _, idInUse = r.byid[id] - } - } - if _, idInUse := r.byid[id]; idInUse { - return nil, -1, ErrDuplicateID - } - names = dedupeNames(names) - for _, name := range names { - if _, nameInUse := r.byname[name]; nameInUse { - return nil, -1, ErrDuplicateName - } - } - opts := drivers.CreateOpts{ - MountLabel: mountLabel, - StorageOpt: options, - } - if writeable { - err = r.driver.CreateReadWrite(id, parent, &opts) - } else { - err = r.driver.Create(id, parent, &opts) - } - if err == nil { - layer = &Layer{ - ID: id, - Parent: parent, - Names: names, - MountLabel: mountLabel, - Created: time.Now().UTC(), - Flags: make(map[string]interface{}), - } - r.layers = append(r.layers, layer) - r.idindex.Add(id) - r.byid[id] = layer - for _, name := range names { - r.byname[name] = layer - } - for flag, value := range flags { - layer.Flags[flag] = value - } - if diff != nil { - layer.Flags[incompleteFlag] = true - err = r.Save() - if err != nil { - // We don't have a record of this layer, but at least - // try to clean it up underneath us. - r.driver.Remove(id) - return nil, -1, err - } - size, err = r.ApplyDiff(layer.ID, diff) - if err != nil { - if r.Delete(layer.ID) != nil { - // Either a driver error or an error saving. - // We now have a layer that's been marked for - // deletion but which we failed to remove. - } - return nil, -1, err - } - delete(layer.Flags, incompleteFlag) - } - err = r.Save() - if err != nil { - // We don't have a record of this layer, but at least - // try to clean it up underneath us. - r.driver.Remove(id) - return nil, -1, err - } - } - return layer, size, err -} - -func (r *layerStore) CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error) { - layer, _, err = r.Put(id, parent, names, mountLabel, options, writeable, flags, nil) - return layer, err -} - -func (r *layerStore) Create(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool) (layer *Layer, err error) { - return r.CreateWithFlags(id, parent, names, mountLabel, options, writeable, nil) -} - -func (r *layerStore) Mount(id, mountLabel string) (string, error) { - if !r.IsReadWrite() { - return "", errors.Wrapf(ErrStoreIsReadOnly, "not allowed to update mount locations for layers at %q", r.mountspath()) - } - layer, ok := r.lookup(id) - if !ok { - return "", ErrLayerUnknown - } - if layer.MountCount > 0 { - layer.MountCount++ - return layer.MountPoint, r.Save() - } - if mountLabel == "" { - mountLabel = layer.MountLabel - } - mountpoint, err := r.driver.Get(id, mountLabel) - if mountpoint != "" && err == nil { - if layer.MountPoint != "" { - delete(r.bymount, layer.MountPoint) - } - layer.MountPoint = filepath.Clean(mountpoint) - layer.MountCount++ - r.bymount[layer.MountPoint] = layer - err = r.Save() - } - return mountpoint, err -} - -func (r *layerStore) Unmount(id string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to update mount locations for layers at %q", r.mountspath()) - } - layer, ok := r.lookup(id) - if !ok { - layerByMount, ok := r.bymount[filepath.Clean(id)] - if !ok { - return ErrLayerUnknown - } - layer = layerByMount - } - if layer.MountCount > 1 { - layer.MountCount-- - return r.Save() - } - err := r.driver.Put(id) - if err == nil || os.IsNotExist(err) { - if layer.MountPoint != "" { - delete(r.bymount, layer.MountPoint) - } - layer.MountCount-- - layer.MountPoint = "" - err = r.Save() - } - return err -} - -func (r *layerStore) removeName(layer *Layer, name string) { - layer.Names = stringSliceWithoutValue(layer.Names, name) -} - -func (r *layerStore) SetNames(id string, names []string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change layer name assignments at %q", r.layerspath()) - } - names = dedupeNames(names) - if layer, ok := r.lookup(id); ok { - for _, name := range layer.Names { - delete(r.byname, name) - } - for _, name := range names { - if otherLayer, ok := r.byname[name]; ok { - r.removeName(otherLayer, name) - } - r.byname[name] = layer - } - layer.Names = names - return r.Save() - } - return ErrLayerUnknown -} - -func (r *layerStore) Metadata(id string) (string, error) { - if layer, ok := r.lookup(id); ok { - return layer.Metadata, nil - } - return "", ErrLayerUnknown -} - -func (r *layerStore) SetMetadata(id, metadata string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify layer metadata at %q", r.layerspath()) - } - if layer, ok := r.lookup(id); ok { - layer.Metadata = metadata - return r.Save() - } - return ErrLayerUnknown -} - -func (r *layerStore) tspath(id string) string { - return filepath.Join(r.layerdir, id+tarSplitSuffix) -} - -func (r *layerStore) Delete(id string) error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete layers at %q", r.layerspath()) - } - layer, ok := r.lookup(id) - if !ok { - return ErrLayerUnknown - } - id = layer.ID - for layer.MountCount > 0 { - if err := r.Unmount(id); err != nil { - return err - } - } - err := r.driver.Remove(id) - if err == nil { - os.Remove(r.tspath(id)) - delete(r.byid, id) - r.idindex.Delete(id) - if layer.MountPoint != "" { - delete(r.bymount, layer.MountPoint) - } - toDeleteIndex := -1 - for i, candidate := range r.layers { - if candidate.ID == id { - toDeleteIndex = i - break - } - } - if toDeleteIndex != -1 { - // delete the layer at toDeleteIndex - if toDeleteIndex == len(r.layers)-1 { - r.layers = r.layers[:len(r.layers)-1] - } else { - r.layers = append(r.layers[:toDeleteIndex], r.layers[toDeleteIndex+1:]...) - } - } - if err = r.Save(); err != nil { - return err - } - } - return err -} - -func (r *layerStore) Lookup(name string) (id string, err error) { - if layer, ok := r.lookup(name); ok { - return layer.ID, nil - } - return "", ErrLayerUnknown -} - -func (r *layerStore) Exists(id string) bool { - _, ok := r.lookup(id) - return ok -} - -func (r *layerStore) Get(id string) (*Layer, error) { - if layer, ok := r.lookup(id); ok { - return layer, nil - } - return nil, ErrLayerUnknown -} - -func (r *layerStore) Wipe() error { - if !r.IsReadWrite() { - return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete layers at %q", r.layerspath()) - } - ids := make([]string, 0, len(r.byid)) - for id := range r.byid { - ids = append(ids, id) - } - for _, id := range ids { - if err := r.Delete(id); err != nil { - return err - } - } - return nil -} - -func (r *layerStore) findParentAndLayer(from, to string) (fromID string, toID string, toLayer *Layer, err error) { - var ok bool - var fromLayer *Layer - toLayer, ok = r.lookup(to) - if !ok { - return "", "", nil, ErrLayerUnknown - } - to = toLayer.ID - if from == "" { - from = toLayer.Parent - } - if from != "" { - fromLayer, ok = r.lookup(from) - if ok { - from = fromLayer.ID - } else { - fromLayer, ok = r.lookup(toLayer.Parent) - if ok { - from = fromLayer.ID - } - } - } - return from, to, toLayer, nil -} - -func (r *layerStore) Changes(from, to string) ([]archive.Change, error) { - from, to, toLayer, err := r.findParentAndLayer(from, to) - if err != nil { - return nil, ErrLayerUnknown - } - return r.driver.Changes(to, from, toLayer.MountLabel) -} - -type simpleGetCloser struct { - r *layerStore - path string - id string -} - -func (s *simpleGetCloser) Get(path string) (io.ReadCloser, error) { - return os.Open(filepath.Join(s.path, path)) -} - -func (s *simpleGetCloser) Close() error { - return s.r.Unmount(s.id) -} - -func (r *layerStore) newFileGetter(id string) (drivers.FileGetCloser, error) { - if getter, ok := r.driver.(drivers.DiffGetterDriver); ok { - return getter.DiffGetter(id) - } - path, err := r.Mount(id, "") - if err != nil { - return nil, err - } - return &simpleGetCloser{ - r: r, - path: path, - id: id, - }, nil -} - -func (r *layerStore) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) { - var metadata storage.Unpacker - - from, to, toLayer, err := r.findParentAndLayer(from, to) - if err != nil { - return nil, ErrLayerUnknown - } - // Default to applying the type of compression that we noted was used - // for the layerdiff when it was applied. - compression := toLayer.CompressionType - // If a particular compression type (or no compression) was selected, - // use that instead. - if options != nil && options.Compression != nil { - compression = *options.Compression - } - maybeCompressReadCloser := func(rc io.ReadCloser) (io.ReadCloser, error) { - // Depending on whether or not compression is desired, return either the - // passed-in ReadCloser, or a new one that provides its readers with a - // compressed version of the data that the original would have provided - // to its readers. - if compression == archive.Uncompressed { - return rc, nil - } - preader, pwriter := io.Pipe() - compressor, err := archive.CompressStream(pwriter, compression) - if err != nil { - rc.Close() - pwriter.Close() - preader.Close() - return nil, err - } - go func() { - defer pwriter.Close() - defer compressor.Close() - defer rc.Close() - io.Copy(compressor, rc) - }() - return preader, nil - } - - if from != toLayer.Parent { - diff, err := r.driver.Diff(to, from, toLayer.MountLabel) - if err != nil { - return nil, err - } - return maybeCompressReadCloser(diff) - } - - tsfile, err := os.Open(r.tspath(to)) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } - diff, err := r.driver.Diff(to, from, toLayer.MountLabel) - if err != nil { - return nil, err - } - return maybeCompressReadCloser(diff) - } - defer tsfile.Close() - - decompressor, err := gzip.NewReader(tsfile) - if err != nil { - return nil, err - } - defer decompressor.Close() - - tsbytes, err := ioutil.ReadAll(decompressor) - if err != nil { - return nil, err - } - - metadata = storage.NewJSONUnpacker(bytes.NewBuffer(tsbytes)) - - fgetter, err := r.newFileGetter(to) - if err != nil { - return nil, err - } - - tarstream := asm.NewOutputTarStream(fgetter, metadata) - rc := ioutils.NewReadCloserWrapper(tarstream, func() error { - err1 := tarstream.Close() - err2 := fgetter.Close() - if err2 == nil { - return err1 - } - return err2 - }) - return maybeCompressReadCloser(rc) -} - -func (r *layerStore) DiffSize(from, to string) (size int64, err error) { - var toLayer *Layer - from, to, toLayer, err = r.findParentAndLayer(from, to) - if err != nil { - return -1, ErrLayerUnknown - } - return r.driver.DiffSize(to, from, toLayer.MountLabel) -} - -func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error) { - if !r.IsReadWrite() { - return -1, errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify layer contents at %q", r.layerspath()) - } - - layer, ok := r.lookup(to) - if !ok { - return -1, ErrLayerUnknown - } - - header := make([]byte, 10240) - n, err := diff.Read(header) - if err != nil && err != io.EOF { - return -1, err - } - - compression := archive.DetectCompression(header[:n]) - compressedDigest := digest.Canonical.Digester() - compressedCounter := ioutils.NewWriteCounter(compressedDigest.Hash()) - defragmented := io.TeeReader(io.MultiReader(bytes.NewBuffer(header[:n]), diff), compressedCounter) - - tsdata := bytes.Buffer{} - compressor, err := gzip.NewWriterLevel(&tsdata, gzip.BestSpeed) - if err != nil { - compressor = gzip.NewWriter(&tsdata) - } - metadata := storage.NewJSONPacker(compressor) - uncompressed, err := archive.DecompressStream(defragmented) - if err != nil { - return -1, err - } - uncompressedDigest := digest.Canonical.Digester() - uncompressedCounter := ioutils.NewWriteCounter(uncompressedDigest.Hash()) - payload, err := asm.NewInputTarStream(io.TeeReader(uncompressed, uncompressedCounter), metadata, storage.NewDiscardFilePutter()) - if err != nil { - return -1, err - } - size, err = r.driver.ApplyDiff(layer.ID, layer.Parent, layer.MountLabel, payload) - if err != nil { - return -1, err - } - compressor.Close() - if err == nil { - if err := os.MkdirAll(filepath.Dir(r.tspath(layer.ID)), 0700); err != nil { - return -1, err - } - if err := ioutils.AtomicWriteFile(r.tspath(layer.ID), tsdata.Bytes(), 0600); err != nil { - return -1, err - } - } - - updateDigestMap := func(m *map[digest.Digest][]string, oldvalue, newvalue digest.Digest, id string) { - var newList []string - if oldvalue != "" { - for _, value := range (*m)[oldvalue] { - if value != id { - newList = append(newList, value) - } - } - if len(newList) > 0 { - (*m)[oldvalue] = newList - } else { - delete(*m, oldvalue) - } - } - if newvalue != "" { - (*m)[newvalue] = append((*m)[newvalue], id) - } - } - updateDigestMap(&r.bycompressedsum, layer.CompressedDigest, compressedDigest.Digest(), layer.ID) - layer.CompressedDigest = compressedDigest.Digest() - layer.CompressedSize = compressedCounter.Count - updateDigestMap(&r.byuncompressedsum, layer.UncompressedDigest, uncompressedDigest.Digest(), layer.ID) - layer.UncompressedDigest = uncompressedDigest.Digest() - layer.UncompressedSize = uncompressedCounter.Count - layer.CompressionType = compression - - err = r.Save() - - return size, err -} - -func (r *layerStore) layersByDigestMap(m map[digest.Digest][]string, d digest.Digest) ([]Layer, error) { - var layers []Layer - for _, layerID := range m[d] { - layer, ok := r.lookup(layerID) - if !ok { - return nil, ErrLayerUnknown - } - layers = append(layers, *layer) - } - return layers, nil -} - -func (r *layerStore) LayersByCompressedDigest(d digest.Digest) ([]Layer, error) { - return r.layersByDigestMap(r.bycompressedsum, d) -} - -func (r *layerStore) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error) { - return r.layersByDigestMap(r.byuncompressedsum, d) -} - -func (r *layerStore) Lock() { - r.lockfile.Lock() -} - -func (r *layerStore) Unlock() { - r.lockfile.Unlock() -} - -func (r *layerStore) Touch() error { - return r.lockfile.Touch() -} - -func (r *layerStore) Modified() (bool, error) { - return r.lockfile.Modified() -} - -func (r *layerStore) IsReadWrite() bool { - return r.lockfile.IsReadWrite() -} - -func (r *layerStore) TouchedSince(when time.Time) bool { - return r.lockfile.TouchedSince(when) -} diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go deleted file mode 100644 index 1d494e9d43..0000000000 --- a/vendor/github.com/containers/storage/layers_ffjson.go +++ /dev/null @@ -1,1713 +0,0 @@ -// Code generated by ffjson . DO NOT EDIT. -// source: layers.go. Hack to make this work on github.com - -package storage - -import ( - "bytes" - "encoding/json" - "fmt" - "github.com/containers/storage/pkg/archive" - "github.com/opencontainers/go-digest" - fflib "github.com/pquerna/ffjson/fflib/v1" -) - -// MarshalJSON marshal bytes to json - template -func (j *DiffOptions) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *DiffOptions) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - if j.Compression != nil { - buf.WriteString(`{"Compression":`) - fflib.FormatBits2(buf, uint64(*j.Compression), 10, *j.Compression < 0) - } else { - buf.WriteString(`{"Compression":null`) - } - buf.WriteByte('}') - return nil -} - -const ( - ffjtDiffOptionsbase = iota - ffjtDiffOptionsnosuchkey - - ffjtDiffOptionsCompression -) - -var ffjKeyDiffOptionsCompression = []byte("Compression") - -// UnmarshalJSON umarshall json - template of ffjson -func (j *DiffOptions) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *DiffOptions) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtDiffOptionsbase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtDiffOptionsnosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - case 'C': - - if bytes.Equal(ffjKeyDiffOptionsCompression, kn) { - currentKey = ffjtDiffOptionsCompression - state = fflib.FFParse_want_colon - goto mainparse - } - - } - - if fflib.EqualFoldRight(ffjKeyDiffOptionsCompression, kn) { - currentKey = ffjtDiffOptionsCompression - state = fflib.FFParse_want_colon - goto mainparse - } - - currentKey = ffjtDiffOptionsnosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtDiffOptionsCompression: - goto handle_Compression - - case ffjtDiffOptionsnosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -handle_Compression: - - /* handler: j.Compression type=archive.Compression kind=int quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - j.Compression = nil - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - ttypval := archive.Compression(tval) - j.Compression = &ttypval - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *Layer) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *Layer) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{ "id":`) - fflib.WriteJsonString(buf, string(j.ID)) - buf.WriteByte(',') - if len(j.Names) != 0 { - buf.WriteString(`"names":`) - if j.Names != nil { - buf.WriteString(`[`) - for i, v := range j.Names { - if i != 0 { - buf.WriteString(`,`) - } - fflib.WriteJsonString(buf, string(v)) - } - buf.WriteString(`]`) - } else { - buf.WriteString(`null`) - } - buf.WriteByte(',') - } - if len(j.Parent) != 0 { - buf.WriteString(`"parent":`) - fflib.WriteJsonString(buf, string(j.Parent)) - buf.WriteByte(',') - } - if len(j.Metadata) != 0 { - buf.WriteString(`"metadata":`) - fflib.WriteJsonString(buf, string(j.Metadata)) - buf.WriteByte(',') - } - if len(j.MountLabel) != 0 { - buf.WriteString(`"mountlabel":`) - fflib.WriteJsonString(buf, string(j.MountLabel)) - buf.WriteByte(',') - } - if true { - buf.WriteString(`"created":`) - - { - - obj, err = j.Created.MarshalJSON() - if err != nil { - return err - } - buf.Write(obj) - - } - buf.WriteByte(',') - } - if len(j.CompressedDigest) != 0 { - buf.WriteString(`"compressed-diff-digest":`) - fflib.WriteJsonString(buf, string(j.CompressedDigest)) - buf.WriteByte(',') - } - if j.CompressedSize != 0 { - buf.WriteString(`"compressed-size":`) - fflib.FormatBits2(buf, uint64(j.CompressedSize), 10, j.CompressedSize < 0) - buf.WriteByte(',') - } - if len(j.UncompressedDigest) != 0 { - buf.WriteString(`"diff-digest":`) - fflib.WriteJsonString(buf, string(j.UncompressedDigest)) - buf.WriteByte(',') - } - if j.UncompressedSize != 0 { - buf.WriteString(`"diff-size":`) - fflib.FormatBits2(buf, uint64(j.UncompressedSize), 10, j.UncompressedSize < 0) - buf.WriteByte(',') - } - if j.CompressionType != 0 { - buf.WriteString(`"compression":`) - fflib.FormatBits2(buf, uint64(j.CompressionType), 10, j.CompressionType < 0) - buf.WriteByte(',') - } - if len(j.Flags) != 0 { - buf.WriteString(`"flags":`) - /* Falling back. type=map[string]interface {} kind=map */ - err = buf.Encode(j.Flags) - if err != nil { - return err - } - buf.WriteByte(',') - } - buf.Rewind(1) - buf.WriteByte('}') - return nil -} - -const ( - ffjtLayerbase = iota - ffjtLayernosuchkey - - ffjtLayerID - - ffjtLayerNames - - ffjtLayerParent - - ffjtLayerMetadata - - ffjtLayerMountLabel - - ffjtLayerCreated - - ffjtLayerCompressedDigest - - ffjtLayerCompressedSize - - ffjtLayerUncompressedDigest - - ffjtLayerUncompressedSize - - ffjtLayerCompressionType - - ffjtLayerFlags -) - -var ffjKeyLayerID = []byte("id") - -var ffjKeyLayerNames = []byte("names") - -var ffjKeyLayerParent = []byte("parent") - -var ffjKeyLayerMetadata = []byte("metadata") - -var ffjKeyLayerMountLabel = []byte("mountlabel") - -var ffjKeyLayerCreated = []byte("created") - -var ffjKeyLayerCompressedDigest = []byte("compressed-diff-digest") - -var ffjKeyLayerCompressedSize = []byte("compressed-size") - -var ffjKeyLayerUncompressedDigest = []byte("diff-digest") - -var ffjKeyLayerUncompressedSize = []byte("diff-size") - -var ffjKeyLayerCompressionType = []byte("compression") - -var ffjKeyLayerFlags = []byte("flags") - -// UnmarshalJSON umarshall json - template of ffjson -func (j *Layer) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *Layer) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtLayerbase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtLayernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - case 'c': - - if bytes.Equal(ffjKeyLayerCreated, kn) { - currentKey = ffjtLayerCreated - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyLayerCompressedDigest, kn) { - currentKey = ffjtLayerCompressedDigest - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyLayerCompressedSize, kn) { - currentKey = ffjtLayerCompressedSize - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyLayerCompressionType, kn) { - currentKey = ffjtLayerCompressionType - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'd': - - if bytes.Equal(ffjKeyLayerUncompressedDigest, kn) { - currentKey = ffjtLayerUncompressedDigest - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyLayerUncompressedSize, kn) { - currentKey = ffjtLayerUncompressedSize - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'f': - - if bytes.Equal(ffjKeyLayerFlags, kn) { - currentKey = ffjtLayerFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'i': - - if bytes.Equal(ffjKeyLayerID, kn) { - currentKey = ffjtLayerID - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'm': - - if bytes.Equal(ffjKeyLayerMetadata, kn) { - currentKey = ffjtLayerMetadata - state = fflib.FFParse_want_colon - goto mainparse - - } else if bytes.Equal(ffjKeyLayerMountLabel, kn) { - currentKey = ffjtLayerMountLabel - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'n': - - if bytes.Equal(ffjKeyLayerNames, kn) { - currentKey = ffjtLayerNames - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'p': - - if bytes.Equal(ffjKeyLayerParent, kn) { - currentKey = ffjtLayerParent - state = fflib.FFParse_want_colon - goto mainparse - } - - } - - if fflib.EqualFoldRight(ffjKeyLayerFlags, kn) { - currentKey = ffjtLayerFlags - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerCompressionType, kn) { - currentKey = ffjtLayerCompressionType - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerUncompressedSize, kn) { - currentKey = ffjtLayerUncompressedSize - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerUncompressedDigest, kn) { - currentKey = ffjtLayerUncompressedDigest - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerCompressedSize, kn) { - currentKey = ffjtLayerCompressedSize - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerCompressedDigest, kn) { - currentKey = ffjtLayerCompressedDigest - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyLayerCreated, kn) { - currentKey = ffjtLayerCreated - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyLayerMountLabel, kn) { - currentKey = ffjtLayerMountLabel - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyLayerMetadata, kn) { - currentKey = ffjtLayerMetadata - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyLayerParent, kn) { - currentKey = ffjtLayerParent - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.EqualFoldRight(ffjKeyLayerNames, kn) { - currentKey = ffjtLayerNames - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeyLayerID, kn) { - currentKey = ffjtLayerID - state = fflib.FFParse_want_colon - goto mainparse - } - - currentKey = ffjtLayernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtLayerID: - goto handle_ID - - case ffjtLayerNames: - goto handle_Names - - case ffjtLayerParent: - goto handle_Parent - - case ffjtLayerMetadata: - goto handle_Metadata - - case ffjtLayerMountLabel: - goto handle_MountLabel - - case ffjtLayerCreated: - goto handle_Created - - case ffjtLayerCompressedDigest: - goto handle_CompressedDigest - - case ffjtLayerCompressedSize: - goto handle_CompressedSize - - case ffjtLayerUncompressedDigest: - goto handle_UncompressedDigest - - case ffjtLayerUncompressedSize: - goto handle_UncompressedSize - - case ffjtLayerCompressionType: - goto handle_CompressionType - - case ffjtLayerFlags: - goto handle_Flags - - case ffjtLayernosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -handle_ID: - - /* handler: j.ID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.ID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Names: - - /* handler: j.Names type=[]string kind=slice quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Names = nil - } else { - - j.Names = []string{} - - wantVal := true - - for { - - var tmpJNames string - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_brace { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: tmpJNames type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - tmpJNames = string(string(outBuf)) - - } - } - - j.Names = append(j.Names, tmpJNames) - - wantVal = false - } - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Parent: - - /* handler: j.Parent type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.Parent = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Metadata: - - /* handler: j.Metadata type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.Metadata = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_MountLabel: - - /* handler: j.MountLabel type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.MountLabel = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Created: - - /* handler: j.Created type=time.Time kind=struct quoted=false*/ - - { - if tok == fflib.FFTok_null { - - } else { - - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = j.Created.UnmarshalJSON(tbuf) - if err != nil { - return fs.WrapErr(err) - } - } - state = fflib.FFParse_after_value - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_CompressedDigest: - - /* handler: j.CompressedDigest type=digest.Digest kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.CompressedDigest = digest.Digest(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_CompressedSize: - - /* handler: j.CompressedSize type=int64 kind=int64 quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - j.CompressedSize = int64(tval) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_UncompressedDigest: - - /* handler: j.UncompressedDigest type=digest.Digest kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.UncompressedDigest = digest.Digest(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_UncompressedSize: - - /* handler: j.UncompressedSize type=int64 kind=int64 quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - j.UncompressedSize = int64(tval) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_CompressionType: - - /* handler: j.CompressionType type=archive.Compression kind=int quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - j.CompressionType = archive.Compression(tval) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_Flags: - - /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/ - - { - - { - if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) - } - } - - if tok == fflib.FFTok_null { - j.Flags = nil - } else { - - j.Flags = make(map[string]interface{}, 0) - - wantVal := true - - for { - - var k string - - var tmpJFlags interface{} - - tok = fs.Scan() - if tok == fflib.FFTok_error { - goto tokerror - } - if tok == fflib.FFTok_right_bracket { - break - } - - if tok == fflib.FFTok_comma { - if wantVal == true { - // TODO(pquerna): this isn't an ideal error message, this handles - // things like [,,,] as an array value. - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) - } - continue - } else { - wantVal = true - } - - /* handler: k type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - k = string(string(outBuf)) - - } - } - - // Expect ':' after key - tok = fs.Scan() - if tok != fflib.FFTok_colon { - return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) - } - - tok = fs.Scan() - /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/ - - { - /* Falling back. type=interface {} kind=interface */ - tbuf, err := fs.CaptureField(tok) - if err != nil { - return fs.WrapErr(err) - } - - err = json.Unmarshal(tbuf, &tmpJFlags) - if err != nil { - return fs.WrapErr(err) - } - } - - j.Flags[k] = tmpJFlags - - wantVal = false - } - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *layerMountPoint) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *layerMountPoint) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{"id":`) - fflib.WriteJsonString(buf, string(j.ID)) - buf.WriteString(`,"path":`) - fflib.WriteJsonString(buf, string(j.MountPoint)) - buf.WriteString(`,"count":`) - fflib.FormatBits2(buf, uint64(j.MountCount), 10, j.MountCount < 0) - buf.WriteByte('}') - return nil -} - -const ( - ffjtlayerMountPointbase = iota - ffjtlayerMountPointnosuchkey - - ffjtlayerMountPointID - - ffjtlayerMountPointMountPoint - - ffjtlayerMountPointMountCount -) - -var ffjKeylayerMountPointID = []byte("id") - -var ffjKeylayerMountPointMountPoint = []byte("path") - -var ffjKeylayerMountPointMountCount = []byte("count") - -// UnmarshalJSON umarshall json - template of ffjson -func (j *layerMountPoint) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *layerMountPoint) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtlayerMountPointbase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtlayerMountPointnosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - case 'c': - - if bytes.Equal(ffjKeylayerMountPointMountCount, kn) { - currentKey = ffjtlayerMountPointMountCount - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'i': - - if bytes.Equal(ffjKeylayerMountPointID, kn) { - currentKey = ffjtlayerMountPointID - state = fflib.FFParse_want_colon - goto mainparse - } - - case 'p': - - if bytes.Equal(ffjKeylayerMountPointMountPoint, kn) { - currentKey = ffjtlayerMountPointMountPoint - state = fflib.FFParse_want_colon - goto mainparse - } - - } - - if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountCount, kn) { - currentKey = ffjtlayerMountPointMountCount - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountPoint, kn) { - currentKey = ffjtlayerMountPointMountPoint - state = fflib.FFParse_want_colon - goto mainparse - } - - if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointID, kn) { - currentKey = ffjtlayerMountPointID - state = fflib.FFParse_want_colon - goto mainparse - } - - currentKey = ffjtlayerMountPointnosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtlayerMountPointID: - goto handle_ID - - case ffjtlayerMountPointMountPoint: - goto handle_MountPoint - - case ffjtlayerMountPointMountCount: - goto handle_MountCount - - case ffjtlayerMountPointnosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -handle_ID: - - /* handler: j.ID type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.ID = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_MountPoint: - - /* handler: j.MountPoint type=string kind=string quoted=false*/ - - { - - { - if tok != fflib.FFTok_string && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) - } - } - - if tok == fflib.FFTok_null { - - } else { - - outBuf := fs.Output.Bytes() - - j.MountPoint = string(string(outBuf)) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -handle_MountCount: - - /* handler: j.MountCount type=int kind=int quoted=false*/ - - { - if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { - return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) - } - } - - { - - if tok == fflib.FFTok_null { - - } else { - - tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) - - if err != nil { - return fs.WrapErr(err) - } - - j.MountCount = int(tval) - - } - } - - state = fflib.FFParse_after_value - goto mainparse - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *layerStore) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *layerStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{}`) - return nil -} - -const ( - ffjtlayerStorebase = iota - ffjtlayerStorenosuchkey -) - -// UnmarshalJSON umarshall json - template of ffjson -func (j *layerStore) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *layerStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtlayerStorebase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtlayerStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - } - - currentKey = ffjtlayerStorenosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtlayerStorenosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} - -// MarshalJSON marshal bytes to json - template -func (j *simpleGetCloser) MarshalJSON() ([]byte, error) { - var buf fflib.Buffer - if j == nil { - buf.WriteString("null") - return buf.Bytes(), nil - } - err := j.MarshalJSONBuf(&buf) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalJSONBuf marshal buff to json - template -func (j *simpleGetCloser) MarshalJSONBuf(buf fflib.EncodingBuffer) error { - if j == nil { - buf.WriteString("null") - return nil - } - var err error - var obj []byte - _ = obj - _ = err - buf.WriteString(`{}`) - return nil -} - -const ( - ffjtsimpleGetCloserbase = iota - ffjtsimpleGetClosernosuchkey -) - -// UnmarshalJSON umarshall json - template of ffjson -func (j *simpleGetCloser) UnmarshalJSON(input []byte) error { - fs := fflib.NewFFLexer(input) - return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) -} - -// UnmarshalJSONFFLexer fast json unmarshall - template ffjson -func (j *simpleGetCloser) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { - var err error - currentKey := ffjtsimpleGetCloserbase - _ = currentKey - tok := fflib.FFTok_init - wantedTok := fflib.FFTok_init - -mainparse: - for { - tok = fs.Scan() - // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) - if tok == fflib.FFTok_error { - goto tokerror - } - - switch state { - - case fflib.FFParse_map_start: - if tok != fflib.FFTok_left_bracket { - wantedTok = fflib.FFTok_left_bracket - goto wrongtokenerror - } - state = fflib.FFParse_want_key - continue - - case fflib.FFParse_after_value: - if tok == fflib.FFTok_comma { - state = fflib.FFParse_want_key - } else if tok == fflib.FFTok_right_bracket { - goto done - } else { - wantedTok = fflib.FFTok_comma - goto wrongtokenerror - } - - case fflib.FFParse_want_key: - // json {} ended. goto exit. woo. - if tok == fflib.FFTok_right_bracket { - goto done - } - if tok != fflib.FFTok_string { - wantedTok = fflib.FFTok_string - goto wrongtokenerror - } - - kn := fs.Output.Bytes() - if len(kn) <= 0 { - // "" case. hrm. - currentKey = ffjtsimpleGetClosernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } else { - switch kn[0] { - - } - - currentKey = ffjtsimpleGetClosernosuchkey - state = fflib.FFParse_want_colon - goto mainparse - } - - case fflib.FFParse_want_colon: - if tok != fflib.FFTok_colon { - wantedTok = fflib.FFTok_colon - goto wrongtokenerror - } - state = fflib.FFParse_want_value - continue - case fflib.FFParse_want_value: - - if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { - switch currentKey { - - case ffjtsimpleGetClosernosuchkey: - err = fs.SkipField(tok) - if err != nil { - return fs.WrapErr(err) - } - state = fflib.FFParse_after_value - goto mainparse - } - } else { - goto wantedvalue - } - } - } - -wantedvalue: - return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) -wrongtokenerror: - return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) -tokerror: - if fs.BigError != nil { - return fs.WrapErr(fs.BigError) - } - err = fs.Error.ToError() - if err != nil { - return fs.WrapErr(err) - } - panic("ffjson-generated: unreachable, please report bug.") -done: - - return nil -} diff --git a/vendor/github.com/containers/storage/lockfile.go b/vendor/github.com/containers/storage/lockfile.go deleted file mode 100644 index c1aa482f85..0000000000 --- a/vendor/github.com/containers/storage/lockfile.go +++ /dev/null @@ -1,82 +0,0 @@ -package storage - -import ( - "fmt" - "path/filepath" - "sync" - "time" - - "github.com/pkg/errors" -) - -// A Locker represents a file lock where the file is used to cache an -// identifier of the last party that made changes to whatever's being protected -// by the lock. -type Locker interface { - sync.Locker - - // Touch records, for others sharing the lock, that the caller was the - // last writer. It should only be called with the lock held. - Touch() error - - // Modified() checks if the most recent writer was a party other than the - // last recorded writer. It should only be called with the lock held. - Modified() (bool, error) - - // TouchedSince() checks if the most recent writer modified the file (likely using Touch()) after the specified time. - TouchedSince(when time.Time) bool - - // IsReadWrite() checks if the lock file is read-write - IsReadWrite() bool -} - -var ( - lockfiles map[string]Locker - lockfilesLock sync.Mutex -) - -// GetLockfile opens a read-write lock file, creating it if necessary. The -// Locker object it returns will be returned unlocked. -func GetLockfile(path string) (Locker, error) { - lockfilesLock.Lock() - defer lockfilesLock.Unlock() - if lockfiles == nil { - lockfiles = make(map[string]Locker) - } - cleanPath := filepath.Clean(path) - if locker, ok := lockfiles[cleanPath]; ok { - if !locker.IsReadWrite() { - return nil, errors.Wrapf(ErrLockReadOnly, "lock %q is a read-only lock", cleanPath) - } - return locker, nil - } - locker, err := getLockFile(path, false) // platform dependent locker - if err != nil { - return nil, err - } - lockfiles[filepath.Clean(path)] = locker - return locker, nil -} - -// GetROLockfile opens a read-only lock file. The Locker object it returns -// will be returned unlocked. -func GetROLockfile(path string) (Locker, error) { - lockfilesLock.Lock() - defer lockfilesLock.Unlock() - if lockfiles == nil { - lockfiles = make(map[string]Locker) - } - cleanPath := filepath.Clean(path) - if locker, ok := lockfiles[cleanPath]; ok { - if locker.IsReadWrite() { - return nil, fmt.Errorf("lock %q is a read-write lock", cleanPath) - } - return locker, nil - } - locker, err := getLockFile(path, true) // platform dependent locker - if err != nil { - return nil, err - } - lockfiles[filepath.Clean(path)] = locker - return locker, nil -} diff --git a/vendor/github.com/containers/storage/lockfile_darwin.go b/vendor/github.com/containers/storage/lockfile_darwin.go deleted file mode 100644 index 041d54c057..0000000000 --- a/vendor/github.com/containers/storage/lockfile_darwin.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build darwin freebsd - -package storage - -import ( - "time" - - "golang.org/x/sys/unix" -) - -func (l *lockfile) TouchedSince(when time.Time) bool { - st := unix.Stat_t{} - err := unix.Fstat(int(l.fd), &st) - if err != nil { - return true - } - touched := time.Unix(st.Mtimespec.Unix()) - return when.Before(touched) -} diff --git a/vendor/github.com/containers/storage/lockfile_linux.go b/vendor/github.com/containers/storage/lockfile_linux.go deleted file mode 100644 index 903387c661..0000000000 --- a/vendor/github.com/containers/storage/lockfile_linux.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build linux solaris - -package storage - -import ( - "time" - - "golang.org/x/sys/unix" -) - -// TouchedSince indicates if the lock file has been touched since the specified time -func (l *lockfile) TouchedSince(when time.Time) bool { - st := unix.Stat_t{} - err := unix.Fstat(int(l.fd), &st) - if err != nil { - return true - } - touched := time.Unix(st.Mtim.Unix()) - return when.Before(touched) -} diff --git a/vendor/github.com/containers/storage/lockfile_unix.go b/vendor/github.com/containers/storage/lockfile_unix.go deleted file mode 100644 index 6792592344..0000000000 --- a/vendor/github.com/containers/storage/lockfile_unix.go +++ /dev/null @@ -1,115 +0,0 @@ -// +build linux solaris darwin freebsd - -package storage - -import ( - "os" - "sync" - "time" - - "github.com/containers/storage/pkg/stringid" - "github.com/pkg/errors" - "golang.org/x/sys/unix" -) - -func getLockFile(path string, ro bool) (Locker, error) { - var fd int - var err error - if ro { - fd, err = unix.Open(path, os.O_RDONLY, 0) - } else { - fd, err = unix.Open(path, os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR) - } - if err != nil { - return nil, errors.Wrapf(err, "error opening %q", path) - } - unix.CloseOnExec(fd) - if ro { - return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_RDLCK}, nil - } - return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_WRLCK}, nil -} - -type lockfile struct { - mu sync.Mutex - file string - fd uintptr - lw string - locktype int16 -} - -// Lock locks the lock file -func (l *lockfile) Lock() { - lk := unix.Flock_t{ - Type: l.locktype, - Whence: int16(os.SEEK_SET), - Start: 0, - Len: 0, - Pid: int32(os.Getpid()), - } - l.mu.Lock() - for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { - time.Sleep(10 * time.Millisecond) - } -} - -// Unlock unlocks the lock file -func (l *lockfile) Unlock() { - lk := unix.Flock_t{ - Type: unix.F_UNLCK, - Whence: int16(os.SEEK_SET), - Start: 0, - Len: 0, - Pid: int32(os.Getpid()), - } - for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { - time.Sleep(10 * time.Millisecond) - } - l.mu.Unlock() -} - -// Touch updates the lock file with the UID of the user -func (l *lockfile) Touch() error { - l.lw = stringid.GenerateRandomID() - id := []byte(l.lw) - _, err := unix.Seek(int(l.fd), 0, os.SEEK_SET) - if err != nil { - return err - } - n, err := unix.Write(int(l.fd), id) - if err != nil { - return err - } - if n != len(id) { - return unix.ENOSPC - } - err = unix.Fsync(int(l.fd)) - if err != nil { - return err - } - return nil -} - -// Modified indicates if the lock file has been updated since the last time it was loaded -func (l *lockfile) Modified() (bool, error) { - id := []byte(l.lw) - _, err := unix.Seek(int(l.fd), 0, os.SEEK_SET) - if err != nil { - return true, err - } - n, err := unix.Read(int(l.fd), id) - if err != nil { - return true, err - } - if n != len(id) { - return true, unix.ENOSPC - } - lw := l.lw - l.lw = string(id) - return l.lw != lw, nil -} - -// IsRWLock indicates if the lock file is a read-write lock -func (l *lockfile) IsReadWrite() bool { - return (l.locktype == unix.F_WRLCK) -} diff --git a/vendor/github.com/containers/storage/lockfile_windows.go b/vendor/github.com/containers/storage/lockfile_windows.go deleted file mode 100644 index ed6c5c4b2b..0000000000 --- a/vendor/github.com/containers/storage/lockfile_windows.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build windows - -package storage - -import ( - "os" - "sync" - "time" -) - -func getLockFile(path string, ro bool) (Locker, error) { - return &lockfile{}, nil -} - -type lockfile struct { - mu sync.Mutex - file string -} - -func (l *lockfile) Lock() { -} -func (l *lockfile) Unlock() { -} -func (l *lockfile) Modified() (bool, error) { - return false, nil -} -func (l *lockfile) Touch() error { - return nil -} -func (l *lockfile) IsReadWrite() bool { - return false -} - -func (l *lockfile) TouchedSince(when time.Time) bool { - stat, err := os.Stat(l.file) - if err != nil { - return true - } - return when.Before(stat.ModTime()) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go deleted file mode 100644 index abee36f7e4..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ /dev/null @@ -1,1251 +0,0 @@ -package archive - -import ( - "archive/tar" - "bufio" - "bytes" - "compress/bzip2" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "syscall" - - "github.com/containers/storage/pkg/fileutils" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/pools" - "github.com/containers/storage/pkg/promise" - "github.com/containers/storage/pkg/system" - "github.com/sirupsen/logrus" -) - -type ( - // Compression is the state represents if compressed or not. - Compression int - // WhiteoutFormat is the format of whiteouts unpacked - WhiteoutFormat int - - // TarOptions wraps the tar options. - TarOptions struct { - IncludeFiles []string - ExcludePatterns []string - Compression Compression - NoLchown bool - UIDMaps []idtools.IDMap - GIDMaps []idtools.IDMap - ChownOpts *idtools.IDPair - IncludeSourceDir bool - // WhiteoutFormat is the expected on disk format for whiteout files. - // This format will be converted to the standard format on pack - // and from the standard format on unpack. - WhiteoutFormat WhiteoutFormat - // When unpacking, specifies whether overwriting a directory with a - // non-directory is allowed and vice versa. - NoOverwriteDirNonDir bool - // For each include when creating an archive, the included name will be - // replaced with the matching name from this map. - RebaseNames map[string]string - InUserNS bool - } -) - -// Archiver allows the reuse of most utility functions of this package -// with a pluggable Untar function. Also, to facilitate the passing of -// specific id mappings for untar, an archiver can be created with maps -// which will then be passed to Untar operations -type Archiver struct { - Untar func(io.Reader, string, *TarOptions) error - IDMappings *idtools.IDMappings -} - -// NewDefaultArchiver returns a new Archiver without any IDMappings -func NewDefaultArchiver() *Archiver { - return &Archiver{Untar: Untar, IDMappings: &idtools.IDMappings{}} -} - -// breakoutError is used to differentiate errors related to breaking out -// When testing archive breakout in the unit tests, this error is expected -// in order for the test to pass. -type breakoutError error - -const ( - // Uncompressed represents the uncompressed. - Uncompressed Compression = iota - // Bzip2 is bzip2 compression algorithm. - Bzip2 - // Gzip is gzip compression algorithm. - Gzip - // Xz is xz compression algorithm. - Xz -) - -const ( - // AUFSWhiteoutFormat is the default format for whiteouts - AUFSWhiteoutFormat WhiteoutFormat = iota - // OverlayWhiteoutFormat formats whiteout according to the overlay - // standard. - OverlayWhiteoutFormat -) - -const ( - modeISDIR = 040000 // Directory - modeISFIFO = 010000 // FIFO - modeISREG = 0100000 // Regular file - modeISLNK = 0120000 // Symbolic link - modeISBLK = 060000 // Block special file - modeISCHR = 020000 // Character special file - modeISSOCK = 0140000 // Socket -) - -// IsArchivePath checks if the (possibly compressed) file at the given path -// starts with a tar file header. -func IsArchivePath(path string) bool { - file, err := os.Open(path) - if err != nil { - return false - } - defer file.Close() - rdr, err := DecompressStream(file) - if err != nil { - return false - } - r := tar.NewReader(rdr) - _, err = r.Next() - return err == nil -} - -// DetectCompression detects the compression algorithm of the source. -func DetectCompression(source []byte) Compression { - for compression, m := range map[Compression][]byte{ - Bzip2: {0x42, 0x5A, 0x68}, - Gzip: {0x1F, 0x8B, 0x08}, - Xz: {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, - } { - if len(source) < len(m) { - logrus.Debug("Len too short") - continue - } - if bytes.Equal(m, source[:len(m)]) { - return compression - } - } - return Uncompressed -} - -func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) { - args := []string{"xz", "-d", "-c", "-q"} - - return cmdStream(exec.Command(args[0], args[1:]...), archive) -} - -// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. -func DecompressStream(archive io.Reader) (io.ReadCloser, error) { - p := pools.BufioReader32KPool - buf := p.Get(archive) - bs, err := buf.Peek(10) - if err != nil && err != io.EOF { - // Note: we'll ignore any io.EOF error because there are some odd - // cases where the layer.tar file will be empty (zero bytes) and - // that results in an io.EOF from the Peek() call. So, in those - // cases we'll just treat it as a non-compressed stream and - // that means just create an empty layer. - // See Issue 18170 - return nil, err - } - - compression := DetectCompression(bs) - switch compression { - case Uncompressed: - readBufWrapper := p.NewReadCloserWrapper(buf, buf) - return readBufWrapper, nil - case Gzip: - gzReader, err := gzip.NewReader(buf) - if err != nil { - return nil, err - } - readBufWrapper := p.NewReadCloserWrapper(buf, gzReader) - return readBufWrapper, nil - case Bzip2: - bz2Reader := bzip2.NewReader(buf) - readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader) - return readBufWrapper, nil - case Xz: - xzReader, chdone, err := xzDecompress(buf) - if err != nil { - return nil, err - } - readBufWrapper := p.NewReadCloserWrapper(buf, xzReader) - return ioutils.NewReadCloserWrapper(readBufWrapper, func() error { - <-chdone - return readBufWrapper.Close() - }), nil - default: - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - } -} - -// CompressStream compresses the dest with specified compression algorithm. -func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { - p := pools.BufioWriter32KPool - buf := p.Get(dest) - switch compression { - case Uncompressed: - writeBufWrapper := p.NewWriteCloserWrapper(buf, buf) - return writeBufWrapper, nil - case Gzip: - gzWriter := gzip.NewWriter(dest) - writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter) - return writeBufWrapper, nil - case Bzip2, Xz: - // archive/bzip2 does not support writing, and there is no xz support at all - // However, this is not a problem as docker only currently generates gzipped tars - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - default: - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - } -} - -// TarModifierFunc is a function that can be passed to ReplaceFileTarWrapper to -// modify the contents or header of an entry in the archive. If the file already -// exists in the archive the TarModifierFunc will be called with the Header and -// a reader which will return the files content. If the file does not exist both -// header and content will be nil. -type TarModifierFunc func(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) - -// ReplaceFileTarWrapper converts inputTarStream to a new tar stream. Files in the -// tar stream are modified if they match any of the keys in mods. -func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModifierFunc) io.ReadCloser { - pipeReader, pipeWriter := io.Pipe() - - go func() { - tarReader := tar.NewReader(inputTarStream) - tarWriter := tar.NewWriter(pipeWriter) - defer inputTarStream.Close() - defer tarWriter.Close() - - modify := func(name string, original *tar.Header, modifier TarModifierFunc, tarReader io.Reader) error { - header, data, err := modifier(name, original, tarReader) - switch { - case err != nil: - return err - case header == nil: - return nil - } - - header.Name = name - header.Size = int64(len(data)) - if err := tarWriter.WriteHeader(header); err != nil { - return err - } - if len(data) != 0 { - if _, err := tarWriter.Write(data); err != nil { - return err - } - } - return nil - } - - var err error - var originalHeader *tar.Header - for { - originalHeader, err = tarReader.Next() - if err == io.EOF { - break - } - if err != nil { - pipeWriter.CloseWithError(err) - return - } - - modifier, ok := mods[originalHeader.Name] - if !ok { - // No modifiers for this file, copy the header and data - if err := tarWriter.WriteHeader(originalHeader); err != nil { - pipeWriter.CloseWithError(err) - return - } - if _, err := pools.Copy(tarWriter, tarReader); err != nil { - pipeWriter.CloseWithError(err) - return - } - continue - } - delete(mods, originalHeader.Name) - - if err := modify(originalHeader.Name, originalHeader, modifier, tarReader); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - - // Apply the modifiers that haven't matched any files in the archive - for name, modifier := range mods { - if err := modify(name, nil, modifier, nil); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - - pipeWriter.Close() - - }() - return pipeReader -} - -// Extension returns the extension of a file that uses the specified compression algorithm. -func (compression *Compression) Extension() string { - switch *compression { - case Uncompressed: - return "tar" - case Bzip2: - return "tar.bz2" - case Gzip: - return "tar.gz" - case Xz: - return "tar.xz" - } - return "" -} - -// FileInfoHeader creates a populated Header from fi. -// Compared to archive pkg this function fills in more information. -// Also, regardless of Go version, this function fills file type bits (e.g. hdr.Mode |= modeISDIR), -// which have been deleted since Go 1.9 archive/tar. -func FileInfoHeader(name string, fi os.FileInfo, link string) (*tar.Header, error) { - hdr, err := tar.FileInfoHeader(fi, link) - if err != nil { - return nil, err - } - hdr.Mode = fillGo18FileTypeBits(int64(chmodTarEntry(os.FileMode(hdr.Mode))), fi) - name, err = canonicalTarName(name, fi.IsDir()) - if err != nil { - return nil, fmt.Errorf("tar: cannot canonicalize path: %v", err) - } - hdr.Name = name - if err := setHeaderForSpecialDevice(hdr, name, fi.Sys()); err != nil { - return nil, err - } - return hdr, nil -} - -// fillGo18FileTypeBits fills type bits which have been removed on Go 1.9 archive/tar -// https://github.com/golang/go/commit/66b5a2f -func fillGo18FileTypeBits(mode int64, fi os.FileInfo) int64 { - fm := fi.Mode() - switch { - case fm.IsRegular(): - mode |= modeISREG - case fi.IsDir(): - mode |= modeISDIR - case fm&os.ModeSymlink != 0: - mode |= modeISLNK - case fm&os.ModeDevice != 0: - if fm&os.ModeCharDevice != 0 { - mode |= modeISCHR - } else { - mode |= modeISBLK - } - case fm&os.ModeNamedPipe != 0: - mode |= modeISFIFO - case fm&os.ModeSocket != 0: - mode |= modeISSOCK - } - return mode -} - -// ReadSecurityXattrToTarHeader reads security.capability xattr from filesystem -// to a tar header -func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { - capability, _ := system.Lgetxattr(path, "security.capability") - if capability != nil { - hdr.Xattrs = make(map[string]string) - hdr.Xattrs["security.capability"] = string(capability) - } - return nil -} - -type tarWhiteoutConverter interface { - ConvertWrite(*tar.Header, string, os.FileInfo) (*tar.Header, error) - ConvertRead(*tar.Header, string) (bool, error) -} - -type tarAppender struct { - TarWriter *tar.Writer - Buffer *bufio.Writer - - // for hardlink mapping - SeenFiles map[uint64]string - IDMappings *idtools.IDMappings - ChownOpts *idtools.IDPair - - // For packing and unpacking whiteout files in the - // non standard format. The whiteout files defined - // by the AUFS standard are used as the tar whiteout - // standard. - WhiteoutConverter tarWhiteoutConverter -} - -func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender { - return &tarAppender{ - SeenFiles: make(map[uint64]string), - TarWriter: tar.NewWriter(writer), - Buffer: pools.BufioWriter32KPool.Get(nil), - IDMappings: idMapping, - ChownOpts: chownOpts, - } -} - -// canonicalTarName provides a platform-independent and consistent posix-style -//path for files and directories to be archived regardless of the platform. -func canonicalTarName(name string, isDir bool) (string, error) { - name, err := CanonicalTarNameForPath(name) - if err != nil { - return "", err - } - - // suffix with '/' for directories - if isDir && !strings.HasSuffix(name, "/") { - name += "/" - } - return name, nil -} - -// addTarFile adds to the tar archive a file from `path` as `name` -func (ta *tarAppender) addTarFile(path, name string) error { - fi, err := os.Lstat(path) - if err != nil { - return err - } - - var link string - if fi.Mode()&os.ModeSymlink != 0 { - var err error - link, err = os.Readlink(path) - if err != nil { - return err - } - } - - hdr, err := FileInfoHeader(name, fi, link) - if err != nil { - return err - } - if err := ReadSecurityXattrToTarHeader(path, hdr); err != nil { - return err - } - - // if it's not a directory and has more than 1 link, - // it's hard linked, so set the type flag accordingly - if !fi.IsDir() && hasHardlinks(fi) { - inode, err := getInodeFromStat(fi.Sys()) - if err != nil { - return err - } - // a link should have a name that it links too - // and that linked name should be first in the tar archive - if oldpath, ok := ta.SeenFiles[inode]; ok { - hdr.Typeflag = tar.TypeLink - hdr.Linkname = oldpath - hdr.Size = 0 // This Must be here for the writer math to add up! - } else { - ta.SeenFiles[inode] = name - } - } - - //handle re-mapping container ID mappings back to host ID mappings before - //writing tar headers/files. We skip whiteout files because they were written - //by the kernel and already have proper ownership relative to the host - if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() { - fileIDPair, err := getFileUIDGID(fi.Sys()) - if err != nil { - return err - } - hdr.Uid, hdr.Gid, err = ta.IDMappings.ToContainer(fileIDPair) - if err != nil { - return err - } - } - - // explicitly override with ChownOpts - if ta.ChownOpts != nil { - hdr.Uid = ta.ChownOpts.UID - hdr.Gid = ta.ChownOpts.GID - } - - if ta.WhiteoutConverter != nil { - wo, err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi) - if err != nil { - return err - } - - // If a new whiteout file exists, write original hdr, then - // replace hdr with wo to be written after. Whiteouts should - // always be written after the original. Note the original - // hdr may have been updated to be a whiteout with returning - // a whiteout header - if wo != nil { - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - return err - } - if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { - return fmt.Errorf("tar: cannot use whiteout for non-empty file") - } - hdr = wo - } - } - - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - return err - } - - if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { - // We use system.OpenSequential to ensure we use sequential file - // access on Windows to avoid depleting the standby list. - // On Linux, this equates to a regular os.Open. - file, err := system.OpenSequential(path) - if err != nil { - return err - } - - ta.Buffer.Reset(ta.TarWriter) - defer ta.Buffer.Reset(nil) - _, err = io.Copy(ta.Buffer, file) - file.Close() - if err != nil { - return err - } - err = ta.Buffer.Flush() - if err != nil { - return err - } - } - - return nil -} - -func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns bool) error { - // hdr.Mode is in linux format, which we can use for sycalls, - // but for os.Foo() calls we need the mode converted to os.FileMode, - // so use hdrInfo.Mode() (they differ for e.g. setuid bits) - hdrInfo := hdr.FileInfo() - - switch hdr.Typeflag { - case tar.TypeDir: - // Create directory unless it exists as a directory already. - // In that case we just want to merge the two - if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { - if err := os.Mkdir(path, hdrInfo.Mode()); err != nil { - return err - } - } - - case tar.TypeReg, tar.TypeRegA: - // Source is regular file. We use system.OpenFileSequential to use sequential - // file access to avoid depleting the standby list on Windows. - // On Linux, this equates to a regular os.OpenFile - file, err := system.OpenFileSequential(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode()) - if err != nil { - return err - } - if _, err := io.Copy(file, reader); err != nil { - file.Close() - return err - } - file.Close() - - case tar.TypeBlock, tar.TypeChar: - if inUserns { // cannot create devices in a userns - return nil - } - // Handle this is an OS-specific way - if err := handleTarTypeBlockCharFifo(hdr, path); err != nil { - return err - } - - case tar.TypeFifo: - // Handle this is an OS-specific way - if err := handleTarTypeBlockCharFifo(hdr, path); err != nil { - return err - } - - case tar.TypeLink: - targetPath := filepath.Join(extractDir, hdr.Linkname) - // check for hardlink breakout - if !strings.HasPrefix(targetPath, extractDir) { - return breakoutError(fmt.Errorf("invalid hardlink %q -> %q", targetPath, hdr.Linkname)) - } - if err := os.Link(targetPath, path); err != nil { - return err - } - - case tar.TypeSymlink: - // path -> hdr.Linkname = targetPath - // e.g. /extractDir/path/to/symlink -> ../2/file = /extractDir/path/2/file - targetPath := filepath.Join(filepath.Dir(path), hdr.Linkname) - - // the reason we don't need to check symlinks in the path (with FollowSymlinkInScope) is because - // that symlink would first have to be created, which would be caught earlier, at this very check: - if !strings.HasPrefix(targetPath, extractDir) { - return breakoutError(fmt.Errorf("invalid symlink %q -> %q", path, hdr.Linkname)) - } - if err := os.Symlink(hdr.Linkname, path); err != nil { - return err - } - - case tar.TypeXGlobalHeader: - logrus.Debug("PAX Global Extended Headers found and ignored") - return nil - - default: - return fmt.Errorf("unhandled tar header type %d", hdr.Typeflag) - } - - // Lchown is not supported on Windows. - if Lchown && runtime.GOOS != "windows" { - if chownOpts == nil { - chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} - } - if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil { - return err - } - } - - var errors []string - for key, value := range hdr.Xattrs { - if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil { - if err == syscall.ENOTSUP { - // We ignore errors here because not all graphdrivers support - // xattrs *cough* old versions of AUFS *cough*. However only - // ENOTSUP should be emitted in that case, otherwise we still - // bail. - errors = append(errors, err.Error()) - continue - } - return err - } - - } - - if len(errors) > 0 { - logrus.WithFields(logrus.Fields{ - "errors": errors, - }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them") - } - - // There is no LChmod, so ignore mode for symlink. Also, this - // must happen after chown, as that can modify the file mode - if err := handleLChmod(hdr, path, hdrInfo); err != nil { - return err - } - - aTime := hdr.AccessTime - if aTime.Before(hdr.ModTime) { - // Last access time should never be before last modified time. - aTime = hdr.ModTime - } - - // system.Chtimes doesn't support a NOFOLLOW flag atm - if hdr.Typeflag == tar.TypeLink { - if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { - return err - } - } - } else if hdr.Typeflag != tar.TypeSymlink { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { - return err - } - } else { - ts := []syscall.Timespec{timeToTimespec(aTime), timeToTimespec(hdr.ModTime)} - if err := system.LUtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform { - return err - } - } - return nil -} - -// Tar creates an archive from the directory at `path`, and returns it as a -// stream of bytes. -func Tar(path string, compression Compression) (io.ReadCloser, error) { - return TarWithOptions(path, &TarOptions{Compression: compression}) -} - -// TarWithOptions creates an archive from the directory at `path`, only including files whose relative -// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`. -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) - - pm, err := fileutils.NewPatternMatcher(options.ExcludePatterns) - if err != nil { - return nil, err - } - - pipeReader, pipeWriter := io.Pipe() - - compressWriter, err := CompressStream(pipeWriter, options.Compression) - if err != nil { - return nil, err - } - - go func() { - ta := newTarAppender( - idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), - compressWriter, - options.ChownOpts, - ) - ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat) - - defer func() { - // Make sure to check the error on Close. - if err := ta.TarWriter.Close(); err != nil { - logrus.Errorf("Can't close tar writer: %s", err) - } - if err := compressWriter.Close(); err != nil { - logrus.Errorf("Can't close compress writer: %s", err) - } - if err := pipeWriter.Close(); err != nil { - logrus.Errorf("Can't close pipe writer: %s", err) - } - }() - - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - - // In general we log errors here but ignore them because - // during e.g. a diff operation the container can continue - // mutating the filesystem and we can see transient errors - // from this - - stat, err := os.Lstat(srcPath) - if err != nil { - return - } - - if !stat.IsDir() { - // We can't later join a non-dir with any includes because the - // 'walk' will error if "file/." is stat-ed and "file" is not a - // directory. So, we must split the source path and use the - // basename as the include. - if len(options.IncludeFiles) > 0 { - logrus.Warn("Tar: Can't archive a file with includes") - } - - dir, base := SplitPathDirEntry(srcPath) - srcPath = dir - options.IncludeFiles = []string{base} - } - - if len(options.IncludeFiles) == 0 { - options.IncludeFiles = []string{"."} - } - - seen := make(map[string]bool) - - for _, include := range options.IncludeFiles { - rebaseName := options.RebaseNames[include] - - walkRoot := getWalkRoot(srcPath, include) - filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error { - if err != nil { - logrus.Errorf("Tar: Can't stat file %s to tar: %s", srcPath, err) - return nil - } - - relFilePath, err := filepath.Rel(srcPath, filePath) - if err != nil || (!options.IncludeSourceDir && relFilePath == "." && f.IsDir()) { - // Error getting relative path OR we are looking - // at the source directory path. Skip in both situations. - return nil - } - - if options.IncludeSourceDir && include == "." && relFilePath != "." { - relFilePath = strings.Join([]string{".", relFilePath}, string(filepath.Separator)) - } - - skip := false - - // If "include" is an exact match for the current file - // then even if there's an "excludePatterns" pattern that - // matches it, don't skip it. IOW, assume an explicit 'include' - // is asking for that file no matter what - which is true - // for some files, like .dockerignore and Dockerfile (sometimes) - if include != relFilePath { - skip, err = pm.Matches(relFilePath) - if err != nil { - logrus.Errorf("Error matching %s: %v", relFilePath, err) - return err - } - } - - if skip { - // If we want to skip this file and its a directory - // then we should first check to see if there's an - // excludes pattern (e.g. !dir/file) that starts with this - // dir. If so then we can't skip this dir. - - // Its not a dir then so we can just return/skip. - if !f.IsDir() { - return nil - } - - // No exceptions (!...) in patterns so just skip dir - if !pm.Exclusions() { - return filepath.SkipDir - } - - dirSlash := relFilePath + string(filepath.Separator) - - for _, pat := range pm.Patterns() { - if !pat.Exclusion() { - continue - } - if strings.HasPrefix(pat.String()+string(filepath.Separator), dirSlash) { - // found a match - so can't skip this dir - return nil - } - } - - // No matching exclusion dir so just skip dir - return filepath.SkipDir - } - - if seen[relFilePath] { - return nil - } - seen[relFilePath] = true - - // Rename the base resource. - if rebaseName != "" { - var replacement string - if rebaseName != string(filepath.Separator) { - // Special case the root directory to replace with an - // empty string instead so that we don't end up with - // double slashes in the paths. - replacement = rebaseName - } - - relFilePath = strings.Replace(relFilePath, include, replacement, 1) - } - - if err := ta.addTarFile(filePath, relFilePath); err != nil { - logrus.Errorf("Can't add file %s to tar: %s", filePath, err) - // if pipe is broken, stop writing tar stream to it - if err == io.ErrClosedPipe { - return err - } - } - return nil - }) - } - }() - - return pipeReader, nil -} - -// Unpack unpacks the decompressedArchive to dest with options. -func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error { - tr := tar.NewReader(decompressedArchive) - trBuf := pools.BufioReader32KPool.Get(nil) - defer pools.BufioReader32KPool.Put(trBuf) - - var dirs []*tar.Header - idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) - rootIDs := idMappings.RootPair() - whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat) - - // Iterate through the files in the archive. -loop: - for { - hdr, err := tr.Next() - if err == io.EOF { - // end of tar archive - break - } - if err != nil { - return err - } - - // Normalize name, for safety and for a simple is-root check - // This keeps "../" as-is, but normalizes "/../" to "/". Or Windows: - // This keeps "..\" as-is, but normalizes "\..\" to "\". - hdr.Name = filepath.Clean(hdr.Name) - - for _, exclude := range options.ExcludePatterns { - if strings.HasPrefix(hdr.Name, exclude) { - continue loop - } - } - - // After calling filepath.Clean(hdr.Name) above, hdr.Name will now be in - // the filepath format for the OS on which the daemon is running. Hence - // the check for a slash-suffix MUST be done in an OS-agnostic way. - if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) { - // Not the root directory, ensure that the parent directory exists - parent := filepath.Dir(hdr.Name) - parentPath := filepath.Join(dest, parent) - if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { - err = idtools.MkdirAllAndChownNew(parentPath, 0777, rootIDs) - if err != nil { - return err - } - } - } - - path := filepath.Join(dest, hdr.Name) - rel, err := filepath.Rel(dest, path) - if err != nil { - return err - } - if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { - return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) - } - - // If path exits we almost always just want to remove and replace it - // The only exception is when it is a directory *and* the file from - // the layer is also a directory. Then we want to merge them (i.e. - // just apply the metadata from the layer). - if fi, err := os.Lstat(path); err == nil { - if options.NoOverwriteDirNonDir && fi.IsDir() && hdr.Typeflag != tar.TypeDir { - // If NoOverwriteDirNonDir is true then we cannot replace - // an existing directory with a non-directory from the archive. - return fmt.Errorf("cannot overwrite directory %q with non-directory %q", path, dest) - } - - if options.NoOverwriteDirNonDir && !fi.IsDir() && hdr.Typeflag == tar.TypeDir { - // If NoOverwriteDirNonDir is true then we cannot replace - // an existing non-directory with a directory from the archive. - return fmt.Errorf("cannot overwrite non-directory %q with directory %q", path, dest) - } - - if fi.IsDir() && hdr.Name == "." { - continue - } - - if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) { - if err := os.RemoveAll(path); err != nil { - return err - } - } - } - trBuf.Reset(tr) - - if err := remapIDs(idMappings, hdr); err != nil { - return err - } - - if whiteoutConverter != nil { - writeFile, err := whiteoutConverter.ConvertRead(hdr, path) - if err != nil { - return err - } - if !writeFile { - continue - } - } - - if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts, options.InUserNS); err != nil { - return err - } - - // Directory mtimes must be handled at the end to avoid further - // file creation in them to modify the directory mtime - if hdr.Typeflag == tar.TypeDir { - dirs = append(dirs, hdr) - } - } - - for _, hdr := range dirs { - path := filepath.Join(dest, hdr.Name) - - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { - return err - } - } - return nil -} - -// Untar reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive may be compressed with one of the following algorithms: -// identity (uncompressed), gzip, bzip2, xz. -// FIXME: specify behavior when target path exists vs. doesn't exist. -func Untar(tarArchive io.Reader, dest string, options *TarOptions) error { - return untarHandler(tarArchive, dest, options, true) -} - -// UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive must be an uncompressed stream. -func UntarUncompressed(tarArchive io.Reader, dest string, options *TarOptions) error { - return untarHandler(tarArchive, dest, options, false) -} - -// Handler for teasing out the automatic decompression -func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decompress bool) error { - if tarArchive == nil { - return fmt.Errorf("Empty archive") - } - dest = filepath.Clean(dest) - if options == nil { - options = &TarOptions{} - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - - r := tarArchive - if decompress { - decompressedArchive, err := DecompressStream(tarArchive) - if err != nil { - return err - } - defer decompressedArchive.Close() - r = decompressedArchive - } - - return Unpack(r, dest, options) -} - -// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. -// If either Tar or Untar fails, TarUntar aborts and returns the error. -func (archiver *Archiver) TarUntar(src, dst string) error { - logrus.Debugf("TarUntar(%s %s)", src, dst) - archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed}) - if err != nil { - return err - } - defer archive.Close() - options := &TarOptions{ - UIDMaps: archiver.IDMappings.UIDs(), - GIDMaps: archiver.IDMappings.GIDs(), - } - return archiver.Untar(archive, dst, options) -} - -// UntarPath untar a file from path to a destination, src is the source tar file path. -func (archiver *Archiver) UntarPath(src, dst string) error { - archive, err := os.Open(src) - if err != nil { - return err - } - defer archive.Close() - options := &TarOptions{ - UIDMaps: archiver.IDMappings.UIDs(), - GIDMaps: archiver.IDMappings.GIDs(), - } - return archiver.Untar(archive, dst, options) -} - -// CopyWithTar creates a tar archive of filesystem path `src`, and -// unpacks it at filesystem path `dst`. -// The archive is streamed directly with fixed buffering and no -// intermediary disk IO. -func (archiver *Archiver) CopyWithTar(src, dst string) error { - srcSt, err := os.Stat(src) - if err != nil { - return err - } - if !srcSt.IsDir() { - return archiver.CopyFileWithTar(src, dst) - } - - // if this archiver is set up with ID mapping we need to create - // the new destination directory with the remapped root UID/GID pair - // as owner - rootIDs := archiver.IDMappings.RootPair() - // Create dst, copy src's content into it - logrus.Debugf("Creating dest directory: %s", dst) - if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil { - return err - } - logrus.Debugf("Calling TarUntar(%s, %s)", src, dst) - return archiver.TarUntar(src, dst) -} - -// CopyFileWithTar emulates the behavior of the 'cp' command-line -// for a single file. It copies a regular file from path `src` to -// path `dst`, and preserves all its metadata. -func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { - logrus.Debugf("CopyFileWithTar(%s, %s)", src, dst) - srcSt, err := os.Stat(src) - if err != nil { - return err - } - - if srcSt.IsDir() { - return fmt.Errorf("Can't copy a directory") - } - - // Clean up the trailing slash. This must be done in an operating - // system specific manner. - if dst[len(dst)-1] == os.PathSeparator { - dst = filepath.Join(dst, filepath.Base(src)) - } - // Create the holding directory if necessary - if err := system.MkdirAll(filepath.Dir(dst), 0700, ""); err != nil { - return err - } - - r, w := io.Pipe() - errC := promise.Go(func() error { - defer w.Close() - - srcF, err := os.Open(src) - if err != nil { - return err - } - defer srcF.Close() - - hdr, err := tar.FileInfoHeader(srcSt, "") - if err != nil { - return err - } - hdr.Name = filepath.Base(dst) - hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode))) - - if err := remapIDs(archiver.IDMappings, hdr); err != nil { - return err - } - - tw := tar.NewWriter(w) - defer tw.Close() - if err := tw.WriteHeader(hdr); err != nil { - return err - } - if _, err := io.Copy(tw, srcF); err != nil { - return err - } - return nil - }) - defer func() { - if er := <-errC; err == nil && er != nil { - err = er - } - }() - - err = archiver.Untar(r, filepath.Dir(dst), nil) - if err != nil { - r.CloseWithError(err) - } - return err -} - -func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error { - ids, err := idMappings.ToHost(idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid}) - hdr.Uid, hdr.Gid = ids.UID, ids.GID - return err -} - -// cmdStream executes a command, and returns its stdout as a stream. -// If the command fails to run or doesn't complete successfully, an error -// will be returned, including anything written on stderr. -func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) { - chdone := make(chan struct{}) - cmd.Stdin = input - pipeR, pipeW := io.Pipe() - cmd.Stdout = pipeW - var errBuf bytes.Buffer - cmd.Stderr = &errBuf - - // Run the command and return the pipe - if err := cmd.Start(); err != nil { - return nil, nil, err - } - - // Copy stdout to the returned pipe - go func() { - if err := cmd.Wait(); err != nil { - pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String())) - } else { - pipeW.Close() - } - close(chdone) - }() - - return pipeR, chdone, nil -} - -// NewTempArchive reads the content of src into a temporary file, and returns the contents -// of that file as an archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -func NewTempArchive(src io.Reader, dir string) (*TempArchive, error) { - f, err := ioutil.TempFile(dir, "") - if err != nil { - return nil, err - } - if _, err := io.Copy(f, src); err != nil { - return nil, err - } - if _, err := f.Seek(0, 0); err != nil { - return nil, err - } - st, err := f.Stat() - if err != nil { - return nil, err - } - size := st.Size() - return &TempArchive{File: f, Size: size}, nil -} - -// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -type TempArchive struct { - *os.File - Size int64 // Pre-computed from Stat().Size() as a convenience - read int64 - closed bool -} - -// Close closes the underlying file if it's still open, or does a no-op -// to allow callers to try to close the TempArchive multiple times safely. -func (archive *TempArchive) Close() error { - if archive.closed { - return nil - } - - archive.closed = true - - return archive.File.Close() -} - -func (archive *TempArchive) Read(data []byte) (int, error) { - n, err := archive.File.Read(data) - archive.read += int64(n) - if err != nil || archive.read == archive.Size { - archive.Close() - os.Remove(archive.File.Name()) - } - return n, err -} - -// IsArchive checks for the magic bytes of a tar or any supported compression -// algorithm. -func IsArchive(header []byte) bool { - compression := DetectCompression(header) - if compression != Uncompressed { - return true - } - r := tar.NewReader(bytes.NewBuffer(header)) - _, err := r.Next() - return err == nil -} - -// UntarPath is a convenience function which looks for an archive -// at filesystem path `src`, and unpacks it at `dst`. -func UntarPath(src, dst string) error { - return NewDefaultArchiver().UntarPath(src, dst) -} - -const ( - // HeaderSize is the size in bytes of a tar header - HeaderSize = 512 -) diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_linux.go b/vendor/github.com/containers/storage/pkg/archive/archive_linux.go deleted file mode 100644 index 5a14eb91a9..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/archive_linux.go +++ /dev/null @@ -1,92 +0,0 @@ -package archive - -import ( - "archive/tar" - "os" - "path/filepath" - "strings" - - "github.com/containers/storage/pkg/system" - "golang.org/x/sys/unix" -) - -func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { - if format == OverlayWhiteoutFormat { - return overlayWhiteoutConverter{} - } - return nil -} - -type overlayWhiteoutConverter struct{} - -func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) { - // convert whiteouts to AUFS format - if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 { - // we just rename the file and make it normal - dir, filename := filepath.Split(hdr.Name) - hdr.Name = filepath.Join(dir, WhiteoutPrefix+filename) - hdr.Mode = 0600 - hdr.Typeflag = tar.TypeReg - hdr.Size = 0 - } - - if fi.Mode()&os.ModeDir != 0 { - // convert opaque dirs to AUFS format by writing an empty file with the prefix - opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") - if err != nil { - return nil, err - } - if len(opaque) == 1 && opaque[0] == 'y' { - if hdr.Xattrs != nil { - delete(hdr.Xattrs, "trusted.overlay.opaque") - } - - // create a header for the whiteout file - // it should inherit some properties from the parent, but be a regular file - wo = &tar.Header{ - Typeflag: tar.TypeReg, - Mode: hdr.Mode & int64(os.ModePerm), - Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir), - Size: 0, - Uid: hdr.Uid, - Uname: hdr.Uname, - Gid: hdr.Gid, - Gname: hdr.Gname, - AccessTime: hdr.AccessTime, - ChangeTime: hdr.ChangeTime, - } - } - } - - return -} - -func (overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) { - base := filepath.Base(path) - dir := filepath.Dir(path) - - // if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay - if base == WhiteoutOpaqueDir { - err := unix.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0) - // don't write the file itself - return false, err - } - - // if a file was deleted and we are using overlay, we need to create a character device - if strings.HasPrefix(base, WhiteoutPrefix) { - originalBase := base[len(WhiteoutPrefix):] - originalPath := filepath.Join(dir, originalBase) - - if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil { - return false, err - } - if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil { - return false, err - } - - // don't write the file itself - return false, nil - } - - return true, nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_other.go b/vendor/github.com/containers/storage/pkg/archive/archive_other.go deleted file mode 100644 index 54acbf2856..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/archive_other.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !linux - -package archive - -func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_unix.go b/vendor/github.com/containers/storage/pkg/archive/archive_unix.go deleted file mode 100644 index bdc1a3d794..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/archive_unix.go +++ /dev/null @@ -1,122 +0,0 @@ -// +build !windows - -package archive - -import ( - "archive/tar" - "errors" - "os" - "path/filepath" - "syscall" - - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/system" - rsystem "github.com/opencontainers/runc/libcontainer/system" - "golang.org/x/sys/unix" -) - -// 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 separate 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 -// to canonical posix-style path for tar archival. p is relative -// path. -func CanonicalTarNameForPath(p string) (string, error) { - return p, nil // already unix-style -} - -// chmodTarEntry is used to adjust the file permissions used in tar header based -// on the platform the archival is done. - -func chmodTarEntry(perm os.FileMode) os.FileMode { - return perm // noop for unix as golang APIs provide perm bits correctly -} - -func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) { - s, ok := stat.(*syscall.Stat_t) - - if ok { - // Currently go does not fill in the major/minors - if s.Mode&unix.S_IFBLK != 0 || - s.Mode&unix.S_IFCHR != 0 { - hdr.Devmajor = int64(major(uint64(s.Rdev))) // nolint: unconvert - hdr.Devminor = int64(minor(uint64(s.Rdev))) // nolint: unconvert - } - } - - return -} - -func getInodeFromStat(stat interface{}) (inode uint64, err error) { - s, ok := stat.(*syscall.Stat_t) - - if ok { - inode = s.Ino - } - - return -} - -func getFileUIDGID(stat interface{}) (idtools.IDPair, error) { - s, ok := stat.(*syscall.Stat_t) - - if !ok { - return idtools.IDPair{}, errors.New("cannot convert stat value to syscall.Stat_t") - } - return idtools.IDPair{UID: int(s.Uid), GID: int(s.Gid)}, nil -} - -func major(device uint64) uint64 { - return (device >> 8) & 0xfff -} - -func minor(device uint64) uint64 { - return (device & 0xff) | ((device >> 12) & 0xfff00) -} - -// handleTarTypeBlockCharFifo is an OS-specific helper function used by -// createTarFile to handle the following types of header: Block; Char; Fifo -func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { - if rsystem.RunningInUserNS() { - // cannot create a device if running in user namespace - return nil - } - - mode := uint32(hdr.Mode & 07777) - switch hdr.Typeflag { - case tar.TypeBlock: - mode |= unix.S_IFBLK - case tar.TypeChar: - mode |= unix.S_IFCHR - case tar.TypeFifo: - mode |= unix.S_IFIFO - } - - return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))) -} - -func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { - if hdr.Typeflag == tar.TypeLink { - if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := os.Chmod(path, hdrInfo.Mode()); err != nil { - return err - } - } - } else if hdr.Typeflag != tar.TypeSymlink { - if err := os.Chmod(path, hdrInfo.Mode()); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_windows.go b/vendor/github.com/containers/storage/pkg/archive/archive_windows.go deleted file mode 100644 index 0bcbb925d2..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/archive_windows.go +++ /dev/null @@ -1,79 +0,0 @@ -// +build windows - -package archive - -import ( - "archive/tar" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/longpath" -) - -// 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 longpath.AddPrefix(srcPath) -} - -// getWalkRoot calculates the root path when performing a TarWithOptions. -// We use a separate function as this is platform specific. -func getWalkRoot(srcPath string, include string) string { - return filepath.Join(srcPath, include) -} - -// CanonicalTarNameForPath returns platform-specific filepath -// to canonical posix-style path for tar archival. p is relative -// path. -func CanonicalTarNameForPath(p string) (string, error) { - // windows: convert windows style relative path with backslashes - // into forward slashes. Since windows does not allow '/' or '\' - // in file names, it is mostly safe to replace however we must - // check just in case - if strings.Contains(p, "/") { - return "", fmt.Errorf("Windows path contains forward slash: %s", p) - } - return strings.Replace(p, string(os.PathSeparator), "/", -1), nil - -} - -// chmodTarEntry is used to adjust the file permissions used in tar header based -// on the platform the archival is done. -func chmodTarEntry(perm os.FileMode) os.FileMode { - //perm &= 0755 // this 0-ed out tar flags (like link, regular file, directory marker etc.) - permPart := perm & os.ModePerm - noPermPart := perm &^ os.ModePerm - // Add the x bit: make everything +x from windows - permPart |= 0111 - permPart &= 0755 - - return noPermPart | permPart -} - -func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) { - // do nothing. no notion of Rdev, Nlink in stat on Windows - return -} - -func getInodeFromStat(stat interface{}) (inode uint64, err error) { - // do nothing. no notion of Inode in stat on Windows - return -} - -// handleTarTypeBlockCharFifo is an OS-specific helper function used by -// createTarFile to handle the following types of header: Block; Char; Fifo -func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { - return nil -} - -func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { - return nil -} - -func getFileUIDGID(stat interface{}) (idtools.IDPair, error) { - // no notion of file ownership mapping yet on Windows - return idtools.IDPair{0, 0}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/changes.go b/vendor/github.com/containers/storage/pkg/archive/changes.go deleted file mode 100644 index 6ba4b8ec6f..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/changes.go +++ /dev/null @@ -1,441 +0,0 @@ -package archive - -import ( - "archive/tar" - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - "syscall" - "time" - - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/pools" - "github.com/containers/storage/pkg/system" - "github.com/sirupsen/logrus" -) - -// ChangeType represents the change type. -type ChangeType int - -const ( - // ChangeModify represents the modify operation. - ChangeModify = iota - // ChangeAdd represents the add operation. - ChangeAdd - // ChangeDelete represents the delete operation. - ChangeDelete -) - -func (c ChangeType) String() string { - switch c { - case ChangeModify: - return "C" - case ChangeAdd: - return "A" - case ChangeDelete: - return "D" - } - return "" -} - -// Change represents a change, it wraps the change type and path. -// It describes changes of the files in the path respect to the -// parent layers. The change could be modify, add, delete. -// This is used for layer diff. -type Change struct { - Path string - Kind ChangeType -} - -func (change *Change) String() string { - return fmt.Sprintf("%s %s", change.Kind, change.Path) -} - -// for sort.Sort -type changesByPath []Change - -func (c changesByPath) Less(i, j int) bool { return c[i].Path < c[j].Path } -func (c changesByPath) Len() int { return len(c) } -func (c changesByPath) Swap(i, j int) { c[j], c[i] = c[i], c[j] } - -// Gnu tar and the go tar writer don't have sub-second mtime -// precision, which is problematic when we apply changes via tar -// files, we handle this by comparing for exact times, *or* same -// second count and either a or b having exactly 0 nanoseconds -func sameFsTime(a, b time.Time) bool { - return a == b || - (a.Unix() == b.Unix() && - (a.Nanosecond() == 0 || b.Nanosecond() == 0)) -} - -func sameFsTimeSpec(a, b syscall.Timespec) bool { - return a.Sec == b.Sec && - (a.Nsec == b.Nsec || a.Nsec == 0 || b.Nsec == 0) -} - -// Changes walks the path rw and determines changes for the files in the path, -// with respect to the parent layers -func Changes(layers []string, rw string) ([]Change, error) { - return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip) -} - -func aufsMetadataSkip(path string) (skip bool, err error) { - skip, err = filepath.Match(string(os.PathSeparator)+WhiteoutMetaPrefix+"*", path) - if err != nil { - skip = true - } - return -} - -func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) { - f := filepath.Base(path) - - // If there is a whiteout, then the file was removed - if strings.HasPrefix(f, WhiteoutPrefix) { - originalFile := f[len(WhiteoutPrefix):] - return filepath.Join(filepath.Dir(path), originalFile), nil - } - - return "", nil -} - -type skipChange func(string) (bool, error) -type deleteChange func(string, string, os.FileInfo) (string, error) - -func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) { - var ( - changes []Change - changedDirs = make(map[string]struct{}) - ) - - err := filepath.Walk(rw, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - - // Rebase path - path, err = filepath.Rel(rw, path) - if err != nil { - return err - } - - // As this runs on the daemon side, file paths are OS specific. - path = filepath.Join(string(os.PathSeparator), path) - - // Skip root - if path == string(os.PathSeparator) { - return nil - } - - if sc != nil { - if skip, err := sc(path); skip { - return err - } - } - - change := Change{ - Path: path, - } - - deletedFile, err := dc(rw, path, f) - if err != nil { - return err - } - - // Find out what kind of modification happened - if deletedFile != "" { - change.Path = deletedFile - change.Kind = ChangeDelete - } else { - // Otherwise, the file was added - change.Kind = ChangeAdd - - // ...Unless it already existed in a top layer, in which case, it's a modification - for _, layer := range layers { - stat, err := os.Stat(filepath.Join(layer, path)) - if err != nil && !os.IsNotExist(err) { - return err - } - if err == nil { - // The file existed in the top layer, so that's a modification - - // However, if it's a directory, maybe it wasn't actually modified. - // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar - if stat.IsDir() && f.IsDir() { - if f.Size() == stat.Size() && f.Mode() == stat.Mode() && sameFsTime(f.ModTime(), stat.ModTime()) { - // Both directories are the same, don't record the change - return nil - } - } - change.Kind = ChangeModify - break - } - } - } - - // If /foo/bar/file.txt is modified, then /foo/bar must be part of the changed files. - // This block is here to ensure the change is recorded even if the - // modify time, mode and size of the parent directory in the rw and ro layers are all equal. - // Check https://github.com/docker/docker/pull/13590 for details. - if f.IsDir() { - changedDirs[path] = struct{}{} - } - if change.Kind == ChangeAdd || change.Kind == ChangeDelete { - parent := filepath.Dir(path) - if _, ok := changedDirs[parent]; !ok && parent != "/" { - changes = append(changes, Change{Path: parent, Kind: ChangeModify}) - changedDirs[parent] = struct{}{} - } - } - - // Record change - changes = append(changes, change) - return nil - }) - if err != nil && !os.IsNotExist(err) { - return nil, err - } - return changes, nil -} - -// FileInfo describes the information of a file. -type FileInfo struct { - parent *FileInfo - name string - stat *system.StatT - children map[string]*FileInfo - capability []byte - added bool -} - -// LookUp looks up the file information of a file. -func (info *FileInfo) LookUp(path string) *FileInfo { - // As this runs on the daemon side, file paths are OS specific. - parent := info - if path == string(os.PathSeparator) { - return info - } - - pathElements := strings.Split(path, string(os.PathSeparator)) - for _, elem := range pathElements { - if elem != "" { - child := parent.children[elem] - if child == nil { - return nil - } - parent = child - } - } - return parent -} - -func (info *FileInfo) path() string { - if info.parent == nil { - // As this runs on the daemon side, file paths are OS specific. - return string(os.PathSeparator) - } - return filepath.Join(info.parent.path(), info.name) -} - -func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) { - - sizeAtEntry := len(*changes) - - if oldInfo == nil { - // add - change := Change{ - Path: info.path(), - Kind: ChangeAdd, - } - *changes = append(*changes, change) - info.added = true - } - - // We make a copy so we can modify it to detect additions - // also, we only recurse on the old dir if the new info is a directory - // otherwise any previous delete/change is considered recursive - oldChildren := make(map[string]*FileInfo) - if oldInfo != nil && info.isDir() { - for k, v := range oldInfo.children { - oldChildren[k] = v - } - } - - for name, newChild := range info.children { - oldChild := oldChildren[name] - if oldChild != nil { - // change? - oldStat := oldChild.stat - newStat := newChild.stat - // Note: We can't compare inode or ctime or blocksize here, because these change - // when copying a file into a container. However, that is not generally a problem - // because any content change will change mtime, and any status change should - // be visible when actually comparing the stat fields. The only time this - // breaks down is if some code intentionally hides a change by setting - // back mtime - if statDifferent(oldStat, newStat) || - !bytes.Equal(oldChild.capability, newChild.capability) { - change := Change{ - Path: newChild.path(), - Kind: ChangeModify, - } - *changes = append(*changes, change) - newChild.added = true - } - - // Remove from copy so we can detect deletions - delete(oldChildren, name) - } - - newChild.addChanges(oldChild, changes) - } - for _, oldChild := range oldChildren { - // delete - change := Change{ - Path: oldChild.path(), - Kind: ChangeDelete, - } - *changes = append(*changes, change) - } - - // If there were changes inside this directory, we need to add it, even if the directory - // itself wasn't changed. This is needed to properly save and restore filesystem permissions. - // As this runs on the daemon side, file paths are OS specific. - if len(*changes) > sizeAtEntry && info.isDir() && !info.added && info.path() != string(os.PathSeparator) { - change := Change{ - Path: info.path(), - Kind: ChangeModify, - } - // Let's insert the directory entry before the recently added entries located inside this dir - *changes = append(*changes, change) // just to resize the slice, will be overwritten - copy((*changes)[sizeAtEntry+1:], (*changes)[sizeAtEntry:]) - (*changes)[sizeAtEntry] = change - } - -} - -// Changes add changes to file information. -func (info *FileInfo) Changes(oldInfo *FileInfo) []Change { - var changes []Change - - info.addChanges(oldInfo, &changes) - - return changes -} - -func newRootFileInfo() *FileInfo { - // As this runs on the daemon side, file paths are OS specific. - root := &FileInfo{ - name: string(os.PathSeparator), - children: make(map[string]*FileInfo), - } - return root -} - -// ChangesDirs compares two directories and generates an array of Change objects describing the changes. -// If oldDir is "", then all files in newDir will be Add-Changes. -func ChangesDirs(newDir, oldDir string) ([]Change, error) { - var ( - oldRoot, newRoot *FileInfo - ) - if oldDir == "" { - emptyDir, err := ioutil.TempDir("", "empty") - if err != nil { - return nil, err - } - defer os.Remove(emptyDir) - oldDir = emptyDir - } - oldRoot, newRoot, err := collectFileInfoForChanges(oldDir, newDir) - if err != nil { - return nil, err - } - - return newRoot.Changes(oldRoot), nil -} - -// ChangesSize calculates the size in bytes of the provided changes, based on newDir. -func ChangesSize(newDir string, changes []Change) int64 { - var ( - size int64 - sf = make(map[uint64]struct{}) - ) - for _, change := range changes { - if change.Kind == ChangeModify || change.Kind == ChangeAdd { - file := filepath.Join(newDir, change.Path) - fileInfo, err := os.Lstat(file) - if err != nil { - logrus.Errorf("Can not stat %q: %s", file, err) - continue - } - - if fileInfo != nil && !fileInfo.IsDir() { - if hasHardlinks(fileInfo) { - inode := getIno(fileInfo) - if _, ok := sf[inode]; !ok { - size += fileInfo.Size() - sf[inode] = struct{}{} - } - } else { - size += fileInfo.Size() - } - } - } - } - return size -} - -// ExportChanges produces an Archive from the provided changes, relative to dir. -func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) { - reader, writer := io.Pipe() - go func() { - ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil) - - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - - sort.Sort(changesByPath(changes)) - - // In general we log errors here but ignore them because - // during e.g. a diff operation the container can continue - // mutating the filesystem and we can see transient errors - // from this - for _, change := range changes { - if change.Kind == ChangeDelete { - whiteOutDir := filepath.Dir(change.Path) - whiteOutBase := filepath.Base(change.Path) - whiteOut := filepath.Join(whiteOutDir, WhiteoutPrefix+whiteOutBase) - timestamp := time.Now() - hdr := &tar.Header{ - Name: whiteOut[1:], - Size: 0, - ModTime: timestamp, - AccessTime: timestamp, - ChangeTime: timestamp, - } - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - logrus.Debugf("Can't write whiteout header: %s", err) - } - } else { - path := filepath.Join(dir, change.Path) - if err := ta.addTarFile(path, change.Path[1:]); err != nil { - logrus.Debugf("Can't add file %s to tar: %s", path, err) - } - } - } - - // Make sure to check the error on Close. - if err := ta.TarWriter.Close(); err != nil { - logrus.Debugf("Can't close layer: %s", err) - } - if err := writer.Close(); err != nil { - logrus.Debugf("failed close Changes writer: %s", err) - } - }() - return reader, nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_linux.go b/vendor/github.com/containers/storage/pkg/archive/changes_linux.go deleted file mode 100644 index 90c9a627e5..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/changes_linux.go +++ /dev/null @@ -1,313 +0,0 @@ -package archive - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "sort" - "syscall" - "unsafe" - - "github.com/containers/storage/pkg/system" - "golang.org/x/sys/unix" -) - -// walker is used to implement collectFileInfoForChanges on linux. Where this -// method in general returns the entire contents of two directory trees, we -// optimize some FS calls out on linux. In particular, we take advantage of the -// fact that getdents(2) returns the inode of each file in the directory being -// walked, which, when walking two trees in parallel to generate a list of -// changes, can be used to prune subtrees without ever having to lstat(2) them -// directly. Eliminating stat calls in this way can save up to seconds on large -// images. -type walker struct { - dir1 string - dir2 string - root1 *FileInfo - root2 *FileInfo -} - -// collectFileInfoForChanges returns a complete representation of the trees -// rooted at dir1 and dir2, with one important exception: any subtree or -// leaf where the inode and device numbers are an exact match between dir1 -// and dir2 will be pruned from the results. This method is *only* to be used -// to generating a list of changes between the two directories, as it does not -// reflect the full contents. -func collectFileInfoForChanges(dir1, dir2 string) (*FileInfo, *FileInfo, error) { - w := &walker{ - dir1: dir1, - dir2: dir2, - root1: newRootFileInfo(), - root2: newRootFileInfo(), - } - - i1, err := os.Lstat(w.dir1) - if err != nil { - return nil, nil, err - } - i2, err := os.Lstat(w.dir2) - if err != nil { - return nil, nil, err - } - - if err := w.walk("/", i1, i2); err != nil { - return nil, nil, err - } - - return w.root1, w.root2, nil -} - -// Given a FileInfo, its path info, and a reference to the root of the tree -// being constructed, register this file with the tree. -func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error { - if fi == nil { - return nil - } - parent := root.LookUp(filepath.Dir(path)) - if parent == nil { - return fmt.Errorf("walkchunk: Unexpectedly no parent for %s", path) - } - info := &FileInfo{ - name: filepath.Base(path), - children: make(map[string]*FileInfo), - parent: parent, - } - cpath := filepath.Join(dir, path) - stat, err := system.FromStatT(fi.Sys().(*syscall.Stat_t)) - if err != nil { - return err - } - info.stat = stat - info.capability, _ = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access - parent.children[info.name] = info - return nil -} - -// Walk a subtree rooted at the same path in both trees being iterated. For -// example, /docker/overlay/1234/a/b/c/d and /docker/overlay/8888/a/b/c/d -func (w *walker) walk(path string, i1, i2 os.FileInfo) (err error) { - // Register these nodes with the return trees, unless we're still at the - // (already-created) roots: - if path != "/" { - if err := walkchunk(path, i1, w.dir1, w.root1); err != nil { - return err - } - if err := walkchunk(path, i2, w.dir2, w.root2); err != nil { - return err - } - } - - is1Dir := i1 != nil && i1.IsDir() - is2Dir := i2 != nil && i2.IsDir() - - sameDevice := false - if i1 != nil && i2 != nil { - si1 := i1.Sys().(*syscall.Stat_t) - si2 := i2.Sys().(*syscall.Stat_t) - if si1.Dev == si2.Dev { - sameDevice = true - } - } - - // If these files are both non-existent, or leaves (non-dirs), we are done. - if !is1Dir && !is2Dir { - return nil - } - - // Fetch the names of all the files contained in both directories being walked: - var names1, names2 []nameIno - if is1Dir { - names1, err = readdirnames(filepath.Join(w.dir1, path)) // getdents(2): fs access - if err != nil { - return err - } - } - if is2Dir { - names2, err = readdirnames(filepath.Join(w.dir2, path)) // getdents(2): fs access - if err != nil { - return err - } - } - - // We have lists of the files contained in both parallel directories, sorted - // in the same order. Walk them in parallel, generating a unique merged list - // of all items present in either or both directories. - var names []string - ix1 := 0 - ix2 := 0 - - for { - if ix1 >= len(names1) { - break - } - if ix2 >= len(names2) { - break - } - - ni1 := names1[ix1] - ni2 := names2[ix2] - - switch bytes.Compare([]byte(ni1.name), []byte(ni2.name)) { - case -1: // ni1 < ni2 -- advance ni1 - // we will not encounter ni1 in names2 - names = append(names, ni1.name) - ix1++ - case 0: // ni1 == ni2 - if ni1.ino != ni2.ino || !sameDevice { - names = append(names, ni1.name) - } - ix1++ - ix2++ - case 1: // ni1 > ni2 -- advance ni2 - // we will not encounter ni2 in names1 - names = append(names, ni2.name) - ix2++ - } - } - for ix1 < len(names1) { - names = append(names, names1[ix1].name) - ix1++ - } - for ix2 < len(names2) { - names = append(names, names2[ix2].name) - ix2++ - } - - // For each of the names present in either or both of the directories being - // iterated, stat the name under each root, and recurse the pair of them: - for _, name := range names { - fname := filepath.Join(path, name) - var cInfo1, cInfo2 os.FileInfo - if is1Dir { - cInfo1, err = os.Lstat(filepath.Join(w.dir1, fname)) // lstat(2): fs access - if err != nil && !os.IsNotExist(err) { - return err - } - } - if is2Dir { - cInfo2, err = os.Lstat(filepath.Join(w.dir2, fname)) // lstat(2): fs access - if err != nil && !os.IsNotExist(err) { - return err - } - } - if err = w.walk(fname, cInfo1, cInfo2); err != nil { - return err - } - } - return nil -} - -// {name,inode} pairs used to support the early-pruning logic of the walker type -type nameIno struct { - name string - ino uint64 -} - -type nameInoSlice []nameIno - -func (s nameInoSlice) Len() int { return len(s) } -func (s nameInoSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s nameInoSlice) Less(i, j int) bool { return s[i].name < s[j].name } - -// readdirnames is a hacked-apart version of the Go stdlib code, exposing inode -// numbers further up the stack when reading directory contents. Unlike -// os.Readdirnames, which returns a list of filenames, this function returns a -// list of {filename,inode} pairs. -func readdirnames(dirname string) (names []nameIno, err error) { - var ( - size = 100 - buf = make([]byte, 4096) - nbuf int - bufp int - nb int - ) - - f, err := os.Open(dirname) - if err != nil { - return nil, err - } - defer f.Close() - - names = make([]nameIno, 0, size) // Empty with room to grow. - for { - // Refill the buffer if necessary - if bufp >= nbuf { - bufp = 0 - nbuf, err = unix.ReadDirent(int(f.Fd()), buf) // getdents on linux - if nbuf < 0 { - nbuf = 0 - } - if err != nil { - return nil, os.NewSyscallError("readdirent", err) - } - if nbuf <= 0 { - break // EOF - } - } - - // Drain the buffer - nb, names = parseDirent(buf[bufp:nbuf], names) - bufp += nb - } - - sl := nameInoSlice(names) - sort.Sort(sl) - return sl, nil -} - -// parseDirent is a minor modification of unix.ParseDirent (linux version) -// which returns {name,inode} pairs instead of just names. -func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) { - origlen := len(buf) - for len(buf) > 0 { - dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) - buf = buf[dirent.Reclen:] - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) - var name = string(bytes[0:clen(bytes[:])]) - if name == "." || name == ".." { // Useless names - continue - } - names = append(names, nameIno{name, dirent.Ino}) - } - return origlen - len(buf), names -} - -func clen(n []byte) int { - for i := 0; i < len(n); i++ { - if n[i] == 0 { - return i - } - } - return len(n) -} - -// OverlayChanges walks the path rw and determines changes for the files in the path, -// with respect to the parent layers -func OverlayChanges(layers []string, rw string) ([]Change, error) { - return changes(layers, rw, overlayDeletedFile, nil) -} - -func overlayDeletedFile(root, path string, fi os.FileInfo) (string, error) { - if fi.Mode()&os.ModeCharDevice != 0 { - s := fi.Sys().(*syscall.Stat_t) - if major(s.Rdev) == 0 && minor(s.Rdev) == 0 { - return path, nil - } - } - if fi.Mode()&os.ModeDir != 0 { - opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque") - if err != nil { - return "", err - } - if len(opaque) == 1 && opaque[0] == 'y' { - return path, nil - } - } - - return "", nil - -} diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_other.go b/vendor/github.com/containers/storage/pkg/archive/changes_other.go deleted file mode 100644 index e1d1e7a91e..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/changes_other.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build !linux - -package archive - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/containers/storage/pkg/system" -) - -func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { - var ( - oldRoot, newRoot *FileInfo - err1, err2 error - errs = make(chan error, 2) - ) - go func() { - oldRoot, err1 = collectFileInfo(oldDir) - errs <- err1 - }() - go func() { - newRoot, err2 = collectFileInfo(newDir) - errs <- err2 - }() - - // block until both routines have returned - for i := 0; i < 2; i++ { - if err := <-errs; err != nil { - return nil, nil, err - } - } - - return oldRoot, newRoot, nil -} - -func collectFileInfo(sourceDir string) (*FileInfo, error) { - root := newRootFileInfo() - - err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - - // Rebase path - relPath, err := filepath.Rel(sourceDir, path) - if err != nil { - return err - } - - // As this runs on the daemon side, file paths are OS specific. - relPath = filepath.Join(string(os.PathSeparator), relPath) - - // See https://github.com/golang/go/issues/9168 - bug in filepath.Join. - // Temporary workaround. If the returned path starts with two backslashes, - // trim it down to a single backslash. Only relevant on Windows. - if runtime.GOOS == "windows" { - if strings.HasPrefix(relPath, `\\`) { - relPath = relPath[1:] - } - } - - if relPath == string(os.PathSeparator) { - return nil - } - - parent := root.LookUp(filepath.Dir(relPath)) - if parent == nil { - return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) - } - - info := &FileInfo{ - name: filepath.Base(relPath), - children: make(map[string]*FileInfo), - parent: parent, - } - - s, err := system.Lstat(path) - if err != nil { - return err - } - info.stat = s - - info.capability, _ = system.Lgetxattr(path, "security.capability") - - parent.children[info.name] = info - - return nil - }) - if err != nil { - return nil, err - } - return root, nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go b/vendor/github.com/containers/storage/pkg/archive/changes_unix.go deleted file mode 100644 index d669c01b46..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build !windows - -package archive - -import ( - "os" - "syscall" - - "github.com/containers/storage/pkg/system" - "golang.org/x/sys/unix" -) - -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { - // Don't look at size for dirs, its not a good measure of change - if oldStat.Mode() != newStat.Mode() || - oldStat.UID() != newStat.UID() || - oldStat.GID() != newStat.GID() || - oldStat.Rdev() != newStat.Rdev() || - // Don't look at size for dirs, its not a good measure of change - (oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR && - (!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) { - return true - } - return false -} - -func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode()&unix.S_IFDIR != 0 -} - -func getIno(fi os.FileInfo) uint64 { - return fi.Sys().(*syscall.Stat_t).Ino -} - -func hasHardlinks(fi os.FileInfo) bool { - return fi.Sys().(*syscall.Stat_t).Nlink > 1 -} diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_windows.go b/vendor/github.com/containers/storage/pkg/archive/changes_windows.go deleted file mode 100644 index 5ad3d7e38d..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/changes_windows.go +++ /dev/null @@ -1,30 +0,0 @@ -package archive - -import ( - "os" - - "github.com/containers/storage/pkg/system" -) - -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { - - // Don't look at size for dirs, its not a good measure of change - if oldStat.Mtim() != newStat.Mtim() || - oldStat.Mode() != newStat.Mode() || - oldStat.Size() != newStat.Size() && !oldStat.Mode().IsDir() { - return true - } - return false -} - -func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode().IsDir() -} - -func getIno(fi os.FileInfo) (inode uint64) { - return -} - -func hasHardlinks(fi os.FileInfo) bool { - return false -} diff --git a/vendor/github.com/containers/storage/pkg/archive/copy.go b/vendor/github.com/containers/storage/pkg/archive/copy.go deleted file mode 100644 index ea012b2d99..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/copy.go +++ /dev/null @@ -1,461 +0,0 @@ -package archive - -import ( - "archive/tar" - "errors" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/containers/storage/pkg/system" - "github.com/sirupsen/logrus" -) - -// Errors used or returned by this file. -var ( - ErrNotDirectory = errors.New("not a directory") - ErrDirNotExists = errors.New("no such directory") - ErrCannotCopyDir = errors.New("cannot copy directory") - ErrInvalidCopySource = errors.New("invalid copy source content") -) - -// PreserveTrailingDotOrSeparator returns the given cleaned path (after -// processing using any utility functions from the path or filepath stdlib -// packages) and appends a trailing `/.` or `/` if its corresponding original -// path (from before being processed by utility functions from the path or -// filepath stdlib packages) ends with a trailing `/.` or `/`. If the cleaned -// path already ends in a `.` path segment, then another is not added. If the -// clean path already ends in a path separator, then another is not added. -func PreserveTrailingDotOrSeparator(cleanedPath, originalPath string) string { - // Ensure paths are in platform semantics - cleanedPath = normalizePath(cleanedPath) - originalPath = normalizePath(originalPath) - - if !specifiesCurrentDir(cleanedPath) && specifiesCurrentDir(originalPath) { - if !hasTrailingPathSeparator(cleanedPath) { - // Add a separator if it doesn't already end with one (a cleaned - // path would only end in a separator if it is the root). - cleanedPath += string(filepath.Separator) - } - cleanedPath += "." - } - - if !hasTrailingPathSeparator(cleanedPath) && hasTrailingPathSeparator(originalPath) { - cleanedPath += string(filepath.Separator) - } - - return cleanedPath -} - -// assertsDirectory returns whether the given path is -// asserted to be a directory, i.e., the path ends with -// a trailing '/' or `/.`, assuming a path separator of `/`. -func assertsDirectory(path string) bool { - return hasTrailingPathSeparator(path) || specifiesCurrentDir(path) -} - -// hasTrailingPathSeparator returns whether the given -// path ends with the system's path separator character. -func hasTrailingPathSeparator(path string) bool { - return len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) -} - -// specifiesCurrentDir returns whether the given path specifies -// a "current directory", i.e., the last path segment is `.`. -func specifiesCurrentDir(path string) bool { - return filepath.Base(path) == "." -} - -// SplitPathDirEntry splits the given path between its directory name and its -// basename by first cleaning the path but preserves a trailing "." if the -// original path specified the current directory. -func SplitPathDirEntry(path string) (dir, base string) { - cleanedPath := filepath.Clean(normalizePath(path)) - - if specifiesCurrentDir(path) { - cleanedPath += string(filepath.Separator) + "." - } - - return filepath.Dir(cleanedPath), filepath.Base(cleanedPath) -} - -// TarResource archives the resource described by the given CopyInfo to a Tar -// archive. A non-nil error is returned if sourcePath does not exist or is -// asserted to be a directory but exists as another type of file. -// -// This function acts as a convenient wrapper around TarWithOptions, which -// requires a directory as the source path. TarResource accepts either a -// directory or a file path and correctly sets the Tar options. -func TarResource(sourceInfo CopyInfo) (content io.ReadCloser, err error) { - return TarResourceRebase(sourceInfo.Path, sourceInfo.RebaseName) -} - -// TarResourceRebase is like TarResource but renames the first path element of -// items in the resulting tar archive to match the given rebaseName if not "". -func TarResourceRebase(sourcePath, rebaseName string) (content io.ReadCloser, err error) { - sourcePath = normalizePath(sourcePath) - if _, err = os.Lstat(sourcePath); err != nil { - // Catches the case where the source does not exist or is not a - // directory if asserted to be a directory, as this also causes an - // error. - return - } - - // Separate the source path between its directory and - // the entry in that directory which we are archiving. - sourceDir, sourceBase := SplitPathDirEntry(sourcePath) - - filter := []string{sourceBase} - - logrus.Debugf("copying %q from %q", sourceBase, sourceDir) - - return TarWithOptions(sourceDir, &TarOptions{ - Compression: Uncompressed, - IncludeFiles: filter, - IncludeSourceDir: true, - RebaseNames: map[string]string{ - sourceBase: rebaseName, - }, - }) -} - -// CopyInfo holds basic info about the source -// or destination path of a copy operation. -type CopyInfo struct { - Path string - Exists bool - IsDir bool - RebaseName string -} - -// CopyInfoSourcePath stats the given path to create a CopyInfo -// struct representing that resource for the source of an archive copy -// operation. The given path should be an absolute local path. A source path -// has all symlinks evaluated that appear before the last path separator ("/" -// on Unix). As it is to be a copy source, the path must exist. -func CopyInfoSourcePath(path string, followLink bool) (CopyInfo, error) { - // normalize the file path and then evaluate the symbol link - // we will use the target file instead of the symbol link if - // followLink is set - path = normalizePath(path) - - resolvedPath, rebaseName, err := ResolveHostSourcePath(path, followLink) - if err != nil { - return CopyInfo{}, err - } - - stat, err := os.Lstat(resolvedPath) - if err != nil { - return CopyInfo{}, err - } - - return CopyInfo{ - Path: resolvedPath, - Exists: true, - IsDir: stat.IsDir(), - RebaseName: rebaseName, - }, nil -} - -// CopyInfoDestinationPath stats the given path to create a CopyInfo -// struct representing that resource for the destination of an archive copy -// operation. The given path should be an absolute local path. -func CopyInfoDestinationPath(path string) (info CopyInfo, err error) { - maxSymlinkIter := 10 // filepath.EvalSymlinks uses 255, but 10 already seems like a lot. - path = normalizePath(path) - originalPath := path - - stat, err := os.Lstat(path) - - if err == nil && stat.Mode()&os.ModeSymlink == 0 { - // The path exists and is not a symlink. - return CopyInfo{ - Path: path, - Exists: true, - IsDir: stat.IsDir(), - }, nil - } - - // While the path is a symlink. - for n := 0; err == nil && stat.Mode()&os.ModeSymlink != 0; n++ { - if n > maxSymlinkIter { - // Don't follow symlinks more than this arbitrary number of times. - return CopyInfo{}, errors.New("too many symlinks in " + originalPath) - } - - // The path is a symbolic link. We need to evaluate it so that the - // destination of the copy operation is the link target and not the - // link itself. This is notably different than CopyInfoSourcePath which - // only evaluates symlinks before the last appearing path separator. - // Also note that it is okay if the last path element is a broken - // symlink as the copy operation should create the target. - var linkTarget string - - linkTarget, err = os.Readlink(path) - if err != nil { - return CopyInfo{}, err - } - - if !system.IsAbs(linkTarget) { - // Join with the parent directory. - dstParent, _ := SplitPathDirEntry(path) - linkTarget = filepath.Join(dstParent, linkTarget) - } - - path = linkTarget - stat, err = os.Lstat(path) - } - - if err != nil { - // It's okay if the destination path doesn't exist. We can still - // continue the copy operation if the parent directory exists. - if !os.IsNotExist(err) { - return CopyInfo{}, err - } - - // Ensure destination parent dir exists. - dstParent, _ := SplitPathDirEntry(path) - - parentDirStat, err := os.Lstat(dstParent) - if err != nil { - return CopyInfo{}, err - } - if !parentDirStat.IsDir() { - return CopyInfo{}, ErrNotDirectory - } - - return CopyInfo{Path: path}, nil - } - - // The path exists after resolving symlinks. - return CopyInfo{ - Path: path, - Exists: true, - IsDir: stat.IsDir(), - }, nil -} - -// PrepareArchiveCopy prepares the given srcContent archive, which should -// contain the archived resource described by srcInfo, to the destination -// described by dstInfo. Returns the possibly modified content archive along -// with the path to the destination directory which it should be extracted to. -func PrepareArchiveCopy(srcContent io.Reader, srcInfo, dstInfo CopyInfo) (dstDir string, content io.ReadCloser, err error) { - // Ensure in platform semantics - srcInfo.Path = normalizePath(srcInfo.Path) - dstInfo.Path = normalizePath(dstInfo.Path) - - // Separate the destination path between its directory and base - // components in case the source archive contents need to be rebased. - dstDir, dstBase := SplitPathDirEntry(dstInfo.Path) - _, srcBase := SplitPathDirEntry(srcInfo.Path) - - switch { - case dstInfo.Exists && dstInfo.IsDir: - // The destination exists as a directory. No alteration - // to srcContent is needed as its contents can be - // simply extracted to the destination directory. - return dstInfo.Path, ioutil.NopCloser(srcContent), nil - case dstInfo.Exists && srcInfo.IsDir: - // The destination exists as some type of file and the source - // content is a directory. This is an error condition since - // you cannot copy a directory to an existing file location. - return "", nil, ErrCannotCopyDir - case dstInfo.Exists: - // The destination exists as some type of file and the source content - // is also a file. The source content entry will have to be renamed to - // have a basename which matches the destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - case srcInfo.IsDir: - // The destination does not exist and the source content is an archive - // of a directory. The archive should be extracted to the parent of - // the destination path instead, and when it is, the directory that is - // created as a result should take the name of the destination path. - // The source content entries will have to be renamed to have a - // basename which matches the destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - case assertsDirectory(dstInfo.Path): - // The destination does not exist and is asserted to be created as a - // directory, but the source content is not a directory. This is an - // error condition since you cannot create a directory from a file - // source. - return "", nil, ErrDirNotExists - default: - // The last remaining case is when the destination does not exist, is - // not asserted to be a directory, and the source content is not an - // archive of a directory. It this case, the destination file will need - // to be created when the archive is extracted and the source content - // entry will have to be renamed to have a basename which matches the - // destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - } - -} - -// RebaseArchiveEntries rewrites the given srcContent archive replacing -// an occurrence of oldBase with newBase at the beginning of entry names. -func RebaseArchiveEntries(srcContent io.Reader, oldBase, newBase string) io.ReadCloser { - if oldBase == string(os.PathSeparator) { - // If oldBase specifies the root directory, use an empty string as - // oldBase instead so that newBase doesn't replace the path separator - // that all paths will start with. - oldBase = "" - } - - rebased, w := io.Pipe() - - go func() { - srcTar := tar.NewReader(srcContent) - rebasedTar := tar.NewWriter(w) - - for { - hdr, err := srcTar.Next() - if err == io.EOF { - // Signals end of archive. - rebasedTar.Close() - w.Close() - return - } - if err != nil { - w.CloseWithError(err) - return - } - - hdr.Name = strings.Replace(hdr.Name, oldBase, newBase, 1) - if hdr.Typeflag == tar.TypeLink { - hdr.Linkname = strings.Replace(hdr.Linkname, oldBase, newBase, 1) - } - - if err = rebasedTar.WriteHeader(hdr); err != nil { - w.CloseWithError(err) - return - } - - if _, err = io.Copy(rebasedTar, srcTar); err != nil { - w.CloseWithError(err) - return - } - } - }() - - return rebased -} - -// CopyResource performs an archive copy from the given source path to the -// given destination path. The source path MUST exist and the destination -// path's parent directory must exist. -func CopyResource(srcPath, dstPath string, followLink bool) error { - var ( - srcInfo CopyInfo - err error - ) - - // Ensure in platform semantics - srcPath = normalizePath(srcPath) - dstPath = normalizePath(dstPath) - - // Clean the source and destination paths. - srcPath = PreserveTrailingDotOrSeparator(filepath.Clean(srcPath), srcPath) - dstPath = PreserveTrailingDotOrSeparator(filepath.Clean(dstPath), dstPath) - - if srcInfo, err = CopyInfoSourcePath(srcPath, followLink); err != nil { - return err - } - - content, err := TarResource(srcInfo) - if err != nil { - return err - } - defer content.Close() - - return CopyTo(content, srcInfo, dstPath) -} - -// CopyTo handles extracting the given content whose -// entries should be sourced from srcInfo to dstPath. -func CopyTo(content io.Reader, srcInfo CopyInfo, dstPath string) error { - // The destination path need not exist, but CopyInfoDestinationPath will - // ensure that at least the parent directory exists. - dstInfo, err := CopyInfoDestinationPath(normalizePath(dstPath)) - if err != nil { - return err - } - - dstDir, copyArchive, err := PrepareArchiveCopy(content, srcInfo, dstInfo) - if err != nil { - return err - } - defer copyArchive.Close() - - options := &TarOptions{ - NoLchown: true, - NoOverwriteDirNonDir: true, - } - - return Untar(copyArchive, dstDir, options) -} - -// ResolveHostSourcePath decides real path need to be copied with parameters such as -// whether to follow symbol link or not, if followLink is true, resolvedPath will return -// link target of any symbol link file, else it will only resolve symlink of directory -// but return symbol link file itself without resolving. -func ResolveHostSourcePath(path string, followLink bool) (resolvedPath, rebaseName string, err error) { - if followLink { - resolvedPath, err = filepath.EvalSymlinks(path) - if err != nil { - return - } - - resolvedPath, rebaseName = GetRebaseName(path, resolvedPath) - } else { - dirPath, basePath := filepath.Split(path) - - // if not follow symbol link, then resolve symbol link of parent dir - var resolvedDirPath string - resolvedDirPath, err = filepath.EvalSymlinks(dirPath) - if err != nil { - return - } - // resolvedDirPath will have been cleaned (no trailing path separators) so - // we can manually join it with the base path element. - resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath - if hasTrailingPathSeparator(path) && filepath.Base(path) != filepath.Base(resolvedPath) { - rebaseName = filepath.Base(path) - } - } - return resolvedPath, rebaseName, nil -} - -// GetRebaseName normalizes and compares path and resolvedPath, -// return completed resolved path and rebased file name -func GetRebaseName(path, resolvedPath string) (string, string) { - // linkTarget will have been cleaned (no trailing path separators and dot) so - // we can manually join it with them - var rebaseName string - if specifiesCurrentDir(path) && !specifiesCurrentDir(resolvedPath) { - resolvedPath += string(filepath.Separator) + "." - } - - if hasTrailingPathSeparator(path) && !hasTrailingPathSeparator(resolvedPath) { - resolvedPath += string(filepath.Separator) - } - - if filepath.Base(path) != filepath.Base(resolvedPath) { - // In the case where the path had a trailing separator and a symlink - // evaluation has changed the last path component, we will need to - // rebase the name in the archive that is being copied to match the - // originally requested name. - rebaseName = filepath.Base(path) - } - return resolvedPath, rebaseName -} diff --git a/vendor/github.com/containers/storage/pkg/archive/copy_unix.go b/vendor/github.com/containers/storage/pkg/archive/copy_unix.go deleted file mode 100644 index e305b5e4af..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/copy_unix.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !windows - -package archive - -import ( - "path/filepath" -) - -func normalizePath(path string) string { - return filepath.ToSlash(path) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/copy_windows.go b/vendor/github.com/containers/storage/pkg/archive/copy_windows.go deleted file mode 100644 index 2b775b45c4..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/copy_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -package archive - -import ( - "path/filepath" -) - -func normalizePath(path string) string { - return filepath.FromSlash(path) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/diff.go b/vendor/github.com/containers/storage/pkg/archive/diff.go deleted file mode 100644 index f93f4cb175..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/diff.go +++ /dev/null @@ -1,256 +0,0 @@ -package archive - -import ( - "archive/tar" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/pools" - "github.com/containers/storage/pkg/system" - "github.com/sirupsen/logrus" -) - -// UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be -// compressed or uncompressed. -// Returns the size in bytes of the contents of the layer. -func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, err error) { - tr := tar.NewReader(layer) - trBuf := pools.BufioReader32KPool.Get(tr) - defer pools.BufioReader32KPool.Put(trBuf) - - var dirs []*tar.Header - unpackedPaths := make(map[string]struct{}) - - if options == nil { - options = &TarOptions{} - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) - - aufsTempdir := "" - aufsHardlinks := make(map[string]*tar.Header) - - // Iterate through the files in the archive. - for { - hdr, err := tr.Next() - if err == io.EOF { - // end of tar archive - break - } - if err != nil { - return 0, err - } - - size += hdr.Size - - // Normalize name, for safety and for a simple is-root check - hdr.Name = filepath.Clean(hdr.Name) - - // Windows does not support filenames with colons in them. Ignore - // these files. This is not a problem though (although it might - // appear that it is). Let's suppose a client is running docker pull. - // The daemon it points to is Windows. Would it make sense for the - // client to be doing a docker pull Ubuntu for example (which has files - // with colons in the name under /usr/share/man/man3)? No, absolutely - // not as it would really only make sense that they were pulling a - // Windows image. However, for development, it is necessary to be able - // to pull Linux images which are in the repository. - // - // TODO Windows. Once the registry is aware of what images are Windows- - // specific or Linux-specific, this warning should be changed to an error - // to cater for the situation where someone does manage to upload a Linux - // image but have it tagged as Windows inadvertently. - if runtime.GOOS == "windows" { - if strings.Contains(hdr.Name, ":") { - logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name) - continue - } - } - - // Note as these operations are platform specific, so must the slash be. - if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) { - // Not the root directory, ensure that the parent directory exists. - // This happened in some tests where an image had a tarfile without any - // parent directories. - parent := filepath.Dir(hdr.Name) - parentPath := filepath.Join(dest, parent) - - if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { - err = system.MkdirAll(parentPath, 0600, "") - if err != nil { - return 0, err - } - } - } - - // Skip AUFS metadata dirs - if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) { - // Regular files inside /.wh..wh.plnk can be used as hardlink targets - // We don't want this directory, but we need the files in them so that - // such hardlinks can be resolved. - if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg { - basename := filepath.Base(hdr.Name) - aufsHardlinks[basename] = hdr - if aufsTempdir == "" { - if aufsTempdir, err = ioutil.TempDir("", "storageplnk"); err != nil { - return 0, err - } - defer os.RemoveAll(aufsTempdir) - } - if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS); err != nil { - return 0, err - } - } - - if hdr.Name != WhiteoutOpaqueDir { - continue - } - } - path := filepath.Join(dest, hdr.Name) - rel, err := filepath.Rel(dest, path) - if err != nil { - return 0, err - } - - // Note as these operations are platform specific, so must the slash be. - if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { - return 0, breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) - } - base := filepath.Base(path) - - if strings.HasPrefix(base, WhiteoutPrefix) { - dir := filepath.Dir(path) - if base == WhiteoutOpaqueDir { - _, err := os.Lstat(dir) - if err != nil { - return 0, err - } - err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - if os.IsNotExist(err) { - err = nil // parent was deleted - } - return err - } - if path == dir { - return nil - } - if _, exists := unpackedPaths[path]; !exists { - err := os.RemoveAll(path) - return err - } - return nil - }) - if err != nil { - return 0, err - } - } else { - originalBase := base[len(WhiteoutPrefix):] - originalPath := filepath.Join(dir, originalBase) - if err := os.RemoveAll(originalPath); err != nil { - return 0, err - } - } - } else { - // If path exits we almost always just want to remove and replace it. - // The only exception is when it is a directory *and* the file from - // the layer is also a directory. Then we want to merge them (i.e. - // just apply the metadata from the layer). - if fi, err := os.Lstat(path); err == nil { - if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) { - if err := os.RemoveAll(path); err != nil { - return 0, err - } - } - } - - trBuf.Reset(tr) - srcData := io.Reader(trBuf) - srcHdr := hdr - - // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so - // we manually retarget these into the temporary files we extracted them into - if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) { - linkBasename := filepath.Base(hdr.Linkname) - srcHdr = aufsHardlinks[linkBasename] - if srcHdr == nil { - return 0, fmt.Errorf("Invalid aufs hardlink") - } - tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename)) - if err != nil { - return 0, err - } - defer tmpFile.Close() - srcData = tmpFile - } - - if err := remapIDs(idMappings, srcHdr); err != nil { - return 0, err - } - - if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS); err != nil { - return 0, err - } - - // Directory mtimes must be handled at the end to avoid further - // file creation in them to modify the directory mtime - if hdr.Typeflag == tar.TypeDir { - dirs = append(dirs, hdr) - } - unpackedPaths[path] = struct{}{} - } - } - - for _, hdr := range dirs { - path := filepath.Join(dest, hdr.Name) - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { - return 0, err - } - } - - return size, nil -} - -// ApplyLayer parses a diff in the standard layer format from `layer`, -// and applies it to the directory `dest`. The stream `layer` can be -// compressed or uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyLayer(dest string, layer io.Reader) (int64, error) { - return applyLayerHandler(dest, layer, &TarOptions{}, true) -} - -// ApplyUncompressedLayer parses a diff in the standard layer format from -// `layer`, and applies it to the directory `dest`. The stream `layer` -// can only be uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyUncompressedLayer(dest string, layer io.Reader, options *TarOptions) (int64, error) { - return applyLayerHandler(dest, layer, options, false) -} - -// do the bulk load of ApplyLayer, but allow for not calling DecompressStream -func applyLayerHandler(dest string, layer io.Reader, options *TarOptions, decompress bool) (int64, error) { - dest = filepath.Clean(dest) - - // We need to be able to set any perms - oldmask, err := system.Umask(0) - if err != nil { - return 0, err - } - defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform - - if decompress { - layer, err = DecompressStream(layer) - if err != nil { - return 0, err - } - } - return UnpackLayer(dest, layer, options) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/example_changes.go b/vendor/github.com/containers/storage/pkg/archive/example_changes.go deleted file mode 100644 index 70f9c5564a..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/example_changes.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build ignore - -// Simple tool to create an archive stream from an old and new directory -// -// By default it will stream the comparison of two temporary directories with junk files -package main - -import ( - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path" - - "github.com/containers/storage/pkg/archive" - "github.com/sirupsen/logrus" -) - -var ( - flDebug = flag.Bool("D", false, "debugging output") - flNewDir = flag.String("newdir", "", "") - flOldDir = flag.String("olddir", "", "") - log = logrus.New() -) - -func main() { - flag.Usage = func() { - fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") - fmt.Printf("%s [OPTIONS]\n", os.Args[0]) - flag.PrintDefaults() - } - flag.Parse() - log.Out = os.Stderr - if (len(os.Getenv("DEBUG")) > 0) || *flDebug { - logrus.SetLevel(logrus.DebugLevel) - } - var newDir, oldDir string - - if len(*flNewDir) == 0 { - var err error - newDir, err = ioutil.TempDir("", "storage-test-newDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(newDir) - if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { - log.Fatal(err) - } - } else { - newDir = *flNewDir - } - - if len(*flOldDir) == 0 { - oldDir, err := ioutil.TempDir("", "storage-test-oldDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(oldDir) - } else { - oldDir = *flOldDir - } - - changes, err := archive.ChangesDirs(newDir, oldDir) - if err != nil { - log.Fatal(err) - } - - a, err := archive.ExportChanges(newDir, changes) - if err != nil { - log.Fatal(err) - } - defer a.Close() - - i, err := io.Copy(os.Stdout, a) - if err != nil && err != io.EOF { - log.Fatal(err) - } - fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) -} - -func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { - fileData := []byte("fooo") - for n := 0; n < numberOfFiles; n++ { - fileName := fmt.Sprintf("file-%d", n) - if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { - return 0, err - } - if makeLinks { - if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { - return 0, err - } - } - } - totalSize := numberOfFiles * len(fileData) - return totalSize, nil -} diff --git a/vendor/github.com/containers/storage/pkg/archive/time_linux.go b/vendor/github.com/containers/storage/pkg/archive/time_linux.go deleted file mode 100644 index 3448569b1e..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/time_linux.go +++ /dev/null @@ -1,16 +0,0 @@ -package archive - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - if time.IsZero() { - // Return UTIME_OMIT special value - ts.Sec = 0 - ts.Nsec = ((1 << 30) - 2) - return - } - return syscall.NsecToTimespec(time.UnixNano()) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/time_unsupported.go b/vendor/github.com/containers/storage/pkg/archive/time_unsupported.go deleted file mode 100644 index e85aac0540..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/time_unsupported.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !linux - -package archive - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - nsec := int64(0) - if !time.IsZero() { - nsec = time.UnixNano() - } - return syscall.NsecToTimespec(nsec) -} diff --git a/vendor/github.com/containers/storage/pkg/archive/whiteouts.go b/vendor/github.com/containers/storage/pkg/archive/whiteouts.go deleted file mode 100644 index d20478a10d..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/whiteouts.go +++ /dev/null @@ -1,23 +0,0 @@ -package archive - -// Whiteouts are files with a special meaning for the layered filesystem. -// Docker uses AUFS whiteout files inside exported archives. In other -// filesystems these files are generated/handled on tar creation/extraction. - -// WhiteoutPrefix prefix means file is a whiteout. If this is followed by a -// filename this means that file has been removed from the base layer. -const WhiteoutPrefix = ".wh." - -// WhiteoutMetaPrefix prefix means whiteout has a special meaning and is not -// for removing an actual file. Normally these files are excluded from exported -// archives. -const WhiteoutMetaPrefix = WhiteoutPrefix + WhiteoutPrefix - -// WhiteoutLinkDir is a directory AUFS uses for storing hardlink links to other -// layers. Normally these should not go into exported archives and all changed -// hardlinks should be copied to the top layer. -const WhiteoutLinkDir = WhiteoutMetaPrefix + "plnk" - -// WhiteoutOpaqueDir file means directory has been made opaque - meaning -// readdir calls to this directory do not follow to lower layers. -const WhiteoutOpaqueDir = WhiteoutMetaPrefix + ".opq" diff --git a/vendor/github.com/containers/storage/pkg/archive/wrap.go b/vendor/github.com/containers/storage/pkg/archive/wrap.go deleted file mode 100644 index b39d12c878..0000000000 --- a/vendor/github.com/containers/storage/pkg/archive/wrap.go +++ /dev/null @@ -1,59 +0,0 @@ -package archive - -import ( - "archive/tar" - "bytes" - "io" -) - -// Generate generates a new archive from the content provided -// as input. -// -// `files` is a sequence of path/content pairs. A new file is -// added to the archive for each pair. -// If the last pair is incomplete, the file is created with an -// empty content. For example: -// -// Generate("foo.txt", "hello world", "emptyfile") -// -// The above call will return an archive with 2 files: -// * ./foo.txt with content "hello world" -// * ./empty with empty content -// -// FIXME: stream content instead of buffering -// FIXME: specify permissions and other archive metadata -func Generate(input ...string) (io.Reader, error) { - files := parseStringPairs(input...) - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - for _, file := range files { - name, content := file[0], file[1] - hdr := &tar.Header{ - Name: name, - Size: int64(len(content)), - } - if err := tw.WriteHeader(hdr); err != nil { - return nil, err - } - if _, err := tw.Write([]byte(content)); err != nil { - return nil, err - } - } - if err := tw.Close(); err != nil { - return nil, err - } - return buf, nil -} - -func parseStringPairs(input ...string) (output [][2]string) { - output = make([][2]string, 0, len(input)/2+1) - for i := 0; i < len(input); i += 2 { - var pair [2]string - pair[0] = input[i] - if i+1 < len(input) { - pair[1] = input[i+1] - } - output = append(output, pair) - } - return -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/archive.go b/vendor/github.com/containers/storage/pkg/chrootarchive/archive.go deleted file mode 100644 index 2735f14001..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/archive.go +++ /dev/null @@ -1,70 +0,0 @@ -package chrootarchive - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/idtools" -) - -// NewArchiver returns a new Archiver which uses chrootarchive.Untar -func NewArchiver(idMappings *idtools.IDMappings) *archive.Archiver { - if idMappings == nil { - idMappings = &idtools.IDMappings{} - } - return &archive.Archiver{Untar: Untar, IDMappings: idMappings} -} - -// Untar reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive may be compressed with one of the following algorithms: -// identity (uncompressed), gzip, bzip2, xz. -func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error { - return untarHandler(tarArchive, dest, options, true) -} - -// UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive must be an uncompressed stream. -func UntarUncompressed(tarArchive io.Reader, dest string, options *archive.TarOptions) error { - return untarHandler(tarArchive, dest, options, false) -} - -// Handler for teasing out the automatic decompression -func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool) error { - if tarArchive == nil { - return fmt.Errorf("Empty archive") - } - if options == nil { - options = &archive.TarOptions{} - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - - idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) - rootIDs := idMappings.RootPair() - - dest = filepath.Clean(dest) - if _, err := os.Stat(dest); os.IsNotExist(err) { - if err := idtools.MkdirAllAndChownNew(dest, 0755, rootIDs); err != nil { - return err - } - } - - r := ioutil.NopCloser(tarArchive) - if decompress { - decompressedArchive, err := archive.DecompressStream(tarArchive) - if err != nil { - return err - } - defer decompressedArchive.Close() - r = decompressedArchive - } - - return invokeUnpack(r, dest, options) -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/archive_unix.go b/vendor/github.com/containers/storage/pkg/chrootarchive/archive_unix.go deleted file mode 100644 index e04ed787c0..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/archive_unix.go +++ /dev/null @@ -1,86 +0,0 @@ -// +build !windows - -package chrootarchive - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "runtime" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/reexec" -) - -// untar is the entry-point for storage-untar on re-exec. This is not used on -// Windows as it does not support chroot, hence no point sandboxing through -// chroot and rexec. -func untar() { - runtime.LockOSThread() - flag.Parse() - - var options *archive.TarOptions - - //read the options from the pipe "ExtraFiles" - if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil { - fatal(err) - } - - if err := chroot(flag.Arg(0)); err != nil { - fatal(err) - } - - if err := archive.Unpack(os.Stdin, "/", options); err != nil { - fatal(err) - } - // fully consume stdin in case it is zero padded - if _, err := flush(os.Stdin); err != nil { - fatal(err) - } - - os.Exit(0) -} - -func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions) error { - - // We can't pass a potentially large exclude list directly via cmd line - // because we easily overrun the kernel's max argument/environment size - // when the full image list is passed (e.g. when this is used by - // `docker load`). We will marshall the options via a pipe to the - // child - r, w, err := os.Pipe() - if err != nil { - return fmt.Errorf("Untar pipe failure: %v", err) - } - - cmd := reexec.Command("storage-untar", dest) - cmd.Stdin = decompressedArchive - - cmd.ExtraFiles = append(cmd.ExtraFiles, r) - output := bytes.NewBuffer(nil) - cmd.Stdout = output - cmd.Stderr = output - - if err := cmd.Start(); err != nil { - return fmt.Errorf("Untar error on re-exec cmd: %v", err) - } - //write the options to the pipe for the untar exec to read - if err := json.NewEncoder(w).Encode(options); err != nil { - return fmt.Errorf("Untar json encode to pipe failed: %v", err) - } - w.Close() - - if err := cmd.Wait(); err != nil { - // when `xz -d -c -q | storage-untar ...` failed on storage-untar side, - // we need to exhaust `xz`'s output, otherwise the `xz` side will be - // pending on write pipe forever - io.Copy(ioutil.Discard, decompressedArchive) - - return fmt.Errorf("Error processing tar file(%v): %s", err, output) - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/archive_windows.go b/vendor/github.com/containers/storage/pkg/chrootarchive/archive_windows.go deleted file mode 100644 index 93fde42206..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/archive_windows.go +++ /dev/null @@ -1,22 +0,0 @@ -package chrootarchive - -import ( - "io" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/longpath" -) - -// chroot is not supported by Windows -func chroot(path string) error { - return nil -} - -func invokeUnpack(decompressedArchive io.ReadCloser, - dest string, - options *archive.TarOptions) error { - // Windows is different to Linux here because Windows does not support - // chroot. Hence there is no point sandboxing a chrooted process to - // do the unpack. We call inline instead within the daemon process. - return archive.Unpack(decompressedArchive, longpath.AddPrefix(dest), options) -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go b/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go deleted file mode 100644 index e8bd22e36b..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go +++ /dev/null @@ -1,108 +0,0 @@ -package chrootarchive - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containers/storage/pkg/mount" - rsystem "github.com/opencontainers/runc/libcontainer/system" - "golang.org/x/sys/unix" -) - -// chroot on linux uses pivot_root instead of chroot -// pivot_root takes a new root and an old root. -// Old root must be a sub-dir of new root, it is where the current rootfs will reside after the call to pivot_root. -// New root is where the new rootfs is set to. -// Old root is removed after the call to pivot_root so it is no longer available under the new root. -// This is similar to how libcontainer sets up a container's rootfs -func chroot(path string) (err error) { - // if the engine is running in a user namespace we need to use actual chroot - if rsystem.RunningInUserNS() { - return realChroot(path) - } - if err := unix.Unshare(unix.CLONE_NEWNS); err != nil { - return fmt.Errorf("Error creating mount namespace before pivot: %v", err) - } - - // make everything in new ns private - if err := mount.MakeRPrivate("/"); err != nil { - return err - } - - if mounted, _ := mount.Mounted(path); !mounted { - if err := mount.Mount(path, path, "bind", "rbind,rw"); err != nil { - return realChroot(path) - } - } - - // setup oldRoot for pivot_root - pivotDir, err := ioutil.TempDir(path, ".pivot_root") - if err != nil { - return fmt.Errorf("Error setting up pivot dir: %v", err) - } - - var mounted bool - defer func() { - if mounted { - // make sure pivotDir is not mounted before we try to remove it - if errCleanup := unix.Unmount(pivotDir, unix.MNT_DETACH); errCleanup != nil { - if err == nil { - err = errCleanup - } - return - } - } - - errCleanup := os.Remove(pivotDir) - // pivotDir doesn't exist if pivot_root failed and chroot+chdir was successful - // because we already cleaned it up on failed pivot_root - if errCleanup != nil && !os.IsNotExist(errCleanup) { - errCleanup = fmt.Errorf("Error cleaning up after pivot: %v", errCleanup) - if err == nil { - err = errCleanup - } - } - }() - - if err := unix.PivotRoot(path, pivotDir); err != nil { - // If pivot fails, fall back to the normal chroot after cleaning up temp dir - if err := os.Remove(pivotDir); err != nil { - return fmt.Errorf("Error cleaning up after failed pivot: %v", err) - } - return realChroot(path) - } - mounted = true - - // This is the new path for where the old root (prior to the pivot) has been moved to - // This dir contains the rootfs of the caller, which we need to remove so it is not visible during extraction - pivotDir = filepath.Join("/", filepath.Base(pivotDir)) - - if err := unix.Chdir("/"); err != nil { - return fmt.Errorf("Error changing to new root: %v", err) - } - - // Make the pivotDir (where the old root lives) private so it can be unmounted without propagating to the host - if err := unix.Mount("", pivotDir, "", unix.MS_PRIVATE|unix.MS_REC, ""); err != nil { - return fmt.Errorf("Error making old root private after pivot: %v", err) - } - - // Now unmount the old root so it's no longer visible from the new root - if err := unix.Unmount(pivotDir, unix.MNT_DETACH); err != nil { - return fmt.Errorf("Error while unmounting old root after pivot: %v", err) - } - mounted = false - - return nil -} - -func realChroot(path string) error { - if err := unix.Chroot(path); err != nil { - return fmt.Errorf("Error after fallback to chroot: %v", err) - } - if err := unix.Chdir("/"); err != nil { - return fmt.Errorf("Error changing to new root after chroot: %v", err) - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_unix.go b/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_unix.go deleted file mode 100644 index f9b5dece8c..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/chroot_unix.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !windows,!linux - -package chrootarchive - -import "golang.org/x/sys/unix" - -func chroot(path string) error { - if err := unix.Chroot(path); err != nil { - return err - } - return unix.Chdir("/") -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/diff.go b/vendor/github.com/containers/storage/pkg/chrootarchive/diff.go deleted file mode 100644 index 68b8f74f77..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/diff.go +++ /dev/null @@ -1,23 +0,0 @@ -package chrootarchive - -import ( - "io" - - "github.com/containers/storage/pkg/archive" -) - -// ApplyLayer parses a diff in the standard layer format from `layer`, -// and applies it to the directory `dest`. The stream `layer` can only be -// uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyLayer(dest string, layer io.Reader) (size int64, err error) { - return applyLayerHandler(dest, layer, &archive.TarOptions{}, true) -} - -// ApplyUncompressedLayer parses a diff in the standard layer format from -// `layer`, and applies it to the directory `dest`. The stream `layer` -// can only be uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyUncompressedLayer(dest string, layer io.Reader, options *archive.TarOptions) (int64, error) { - return applyLayerHandler(dest, layer, options, false) -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/diff_unix.go b/vendor/github.com/containers/storage/pkg/chrootarchive/diff_unix.go deleted file mode 100644 index 4369f30c99..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/diff_unix.go +++ /dev/null @@ -1,130 +0,0 @@ -//+build !windows - -package chrootarchive - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/reexec" - "github.com/containers/storage/pkg/system" - rsystem "github.com/opencontainers/runc/libcontainer/system" -) - -type applyLayerResponse struct { - LayerSize int64 `json:"layerSize"` -} - -// applyLayer is the entry-point for storage-applylayer on re-exec. This is not -// used on Windows as it does not support chroot, hence no point sandboxing -// through chroot and rexec. -func applyLayer() { - - var ( - tmpDir string - err error - options *archive.TarOptions - ) - runtime.LockOSThread() - flag.Parse() - - inUserns := rsystem.RunningInUserNS() - if err := chroot(flag.Arg(0)); err != nil { - fatal(err) - } - - // We need to be able to set any perms - oldmask, err := system.Umask(0) - defer system.Umask(oldmask) - if err != nil { - fatal(err) - } - - if err := json.Unmarshal([]byte(os.Getenv("OPT")), &options); err != nil { - fatal(err) - } - - if inUserns { - options.InUserNS = true - } - - if tmpDir, err = ioutil.TempDir("/", "temp-storage-extract"); err != nil { - fatal(err) - } - - os.Setenv("TMPDIR", tmpDir) - size, err := archive.UnpackLayer("/", os.Stdin, options) - os.RemoveAll(tmpDir) - if err != nil { - fatal(err) - } - - encoder := json.NewEncoder(os.Stdout) - if err := encoder.Encode(applyLayerResponse{size}); err != nil { - fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err)) - } - - if _, err := flush(os.Stdin); err != nil { - fatal(err) - } - - os.Exit(0) -} - -// applyLayerHandler parses a diff in the standard layer format from `layer`, and -// applies it to the directory `dest`. Returns the size in bytes of the -// contents of the layer. -func applyLayerHandler(dest string, layer io.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) { - dest = filepath.Clean(dest) - if decompress { - decompressed, err := archive.DecompressStream(layer) - if err != nil { - return 0, err - } - defer decompressed.Close() - - layer = decompressed - } - if options == nil { - options = &archive.TarOptions{} - if rsystem.RunningInUserNS() { - options.InUserNS = true - } - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - - data, err := json.Marshal(options) - if err != nil { - return 0, fmt.Errorf("ApplyLayer json encode: %v", err) - } - - cmd := reexec.Command("storage-applyLayer", dest) - cmd.Stdin = layer - cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) - - outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer) - cmd.Stdout, cmd.Stderr = outBuf, errBuf - - if err = cmd.Run(); err != nil { - return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf) - } - - // Stdout should be a valid JSON struct representing an applyLayerResponse. - response := applyLayerResponse{} - decoder := json.NewDecoder(outBuf) - if err = decoder.Decode(&response); err != nil { - return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err) - } - - return response.LayerSize, nil -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/diff_windows.go b/vendor/github.com/containers/storage/pkg/chrootarchive/diff_windows.go deleted file mode 100644 index 8f8e88bfbe..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/diff_windows.go +++ /dev/null @@ -1,45 +0,0 @@ -package chrootarchive - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/longpath" -) - -// applyLayerHandler parses a diff in the standard layer format from `layer`, and -// applies it to the directory `dest`. Returns the size in bytes of the -// contents of the layer. -func applyLayerHandler(dest string, layer io.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) { - dest = filepath.Clean(dest) - - // Ensure it is a Windows-style volume path - dest = longpath.AddPrefix(dest) - - if decompress { - decompressed, err := archive.DecompressStream(layer) - if err != nil { - return 0, err - } - defer decompressed.Close() - - layer = decompressed - } - - tmpDir, err := ioutil.TempDir(os.Getenv("temp"), "temp-storage-extract") - if err != nil { - return 0, fmt.Errorf("ApplyLayer failed to create temp-storage-extract under %s. %s", dest, err) - } - - s, err := archive.UnpackLayer(dest, layer, nil) - os.RemoveAll(tmpDir) - if err != nil { - return 0, fmt.Errorf("ApplyLayer %s failed UnpackLayer to %s: %s", layer, dest, err) - } - - return s, nil -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/init_unix.go b/vendor/github.com/containers/storage/pkg/chrootarchive/init_unix.go deleted file mode 100644 index 21cd879928..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/init_unix.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !windows - -package chrootarchive - -import ( - "fmt" - "io" - "io/ioutil" - "os" - - "github.com/containers/storage/pkg/reexec" -) - -func init() { - reexec.Register("storage-applyLayer", applyLayer) - reexec.Register("storage-untar", untar) -} - -func fatal(err error) { - fmt.Fprint(os.Stderr, err) - os.Exit(1) -} - -// flush consumes all the bytes from the reader discarding -// any errors -func flush(r io.Reader) (bytes int64, err error) { - return io.Copy(ioutil.Discard, r) -} diff --git a/vendor/github.com/containers/storage/pkg/chrootarchive/init_windows.go b/vendor/github.com/containers/storage/pkg/chrootarchive/init_windows.go deleted file mode 100644 index fa17c9bf83..0000000000 --- a/vendor/github.com/containers/storage/pkg/chrootarchive/init_windows.go +++ /dev/null @@ -1,4 +0,0 @@ -package chrootarchive - -func init() { -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper.go deleted file mode 100644 index 6a0ac24647..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper.go +++ /dev/null @@ -1,821 +0,0 @@ -// +build linux,cgo - -package devicemapper - -import ( - "errors" - "fmt" - "os" - "runtime" - "unsafe" - - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// Same as DM_DEVICE_* enum values from libdevmapper.h -// nolint: deadcode -const ( - deviceCreate TaskType = iota - deviceReload - deviceRemove - deviceRemoveAll - deviceSuspend - deviceResume - deviceInfo - deviceDeps - deviceRename - deviceVersion - deviceStatus - deviceTable - deviceWaitevent - deviceList - deviceClear - deviceMknodes - deviceListVersions - deviceTargetMsg - deviceSetGeometry -) - -const ( - addNodeOnResume AddNodeType = iota - addNodeOnCreate -) - -// List of errors returned when using devicemapper. -var ( - ErrTaskRun = errors.New("dm_task_run failed") - ErrTaskSetName = errors.New("dm_task_set_name failed") - ErrTaskSetMessage = errors.New("dm_task_set_message failed") - ErrTaskSetAddNode = errors.New("dm_task_set_add_node failed") - ErrTaskSetRo = errors.New("dm_task_set_ro failed") - ErrTaskAddTarget = errors.New("dm_task_add_target failed") - ErrTaskSetSector = errors.New("dm_task_set_sector failed") - ErrTaskGetDeps = errors.New("dm_task_get_deps failed") - ErrTaskGetInfo = errors.New("dm_task_get_info failed") - ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed") - ErrTaskDeferredRemove = errors.New("dm_task_deferred_remove failed") - ErrTaskSetCookie = errors.New("dm_task_set_cookie failed") - ErrNilCookie = errors.New("cookie ptr can't be nil") - ErrGetBlockSize = errors.New("Can't get block size") - ErrUdevWait = errors.New("wait on udev cookie failed") - ErrSetDevDir = errors.New("dm_set_dev_dir failed") - ErrGetLibraryVersion = errors.New("dm_get_library_version failed") - ErrCreateRemoveTask = errors.New("Can't create task of type deviceRemove") - ErrRunRemoveDevice = errors.New("running RemoveDevice failed") - ErrInvalidAddNode = errors.New("Invalid AddNode type") - ErrBusy = errors.New("Device is Busy") - ErrDeviceIDExists = errors.New("Device Id Exists") - ErrEnxio = errors.New("No such device or address") -) - -var ( - dmSawBusy bool - dmSawExist bool - dmSawEnxio bool // No Such Device or Address -) - -type ( - // Task represents a devicemapper task (like lvcreate, etc.) ; a task is needed for each ioctl - // command to execute. - Task struct { - unmanaged *cdmTask - } - // Deps represents dependents (layer) of a device. - Deps struct { - Count uint32 - Filler uint32 - Device []uint64 - } - // Info represents information about a device. - Info struct { - Exists int - Suspended int - LiveTable int - InactiveTable int - OpenCount int32 - EventNr uint32 - Major uint32 - Minor uint32 - ReadOnly int - TargetCount int32 - DeferredRemove int - } - // TaskType represents a type of task - TaskType int - // AddNodeType represents a type of node to be added - AddNodeType int -) - -// DeviceIDExists returns whether error conveys the information about device Id already -// exist or not. This will be true if device creation or snap creation -// operation fails if device or snap device already exists in pool. -// Current implementation is little crude as it scans the error string -// for exact pattern match. Replacing it with more robust implementation -// is desirable. -func DeviceIDExists(err error) bool { - return fmt.Sprint(err) == fmt.Sprint(ErrDeviceIDExists) -} - -func (t *Task) destroy() { - if t != nil { - DmTaskDestroy(t.unmanaged) - runtime.SetFinalizer(t, nil) - } -} - -// TaskCreateNamed is a convenience function for TaskCreate when a name -// will be set on the task as well -func TaskCreateNamed(t TaskType, name string) (*Task, error) { - task := TaskCreate(t) - if task == nil { - return nil, fmt.Errorf("devicemapper: Can't create task of type %d", int(t)) - } - if err := task.setName(name); err != nil { - return nil, fmt.Errorf("devicemapper: Can't set task name %s", name) - } - return task, nil -} - -// TaskCreate initializes a devicemapper task of tasktype -func TaskCreate(tasktype TaskType) *Task { - Ctask := DmTaskCreate(int(tasktype)) - if Ctask == nil { - return nil - } - task := &Task{unmanaged: Ctask} - runtime.SetFinalizer(task, (*Task).destroy) - return task -} - -func (t *Task) run() error { - if res := DmTaskRun(t.unmanaged); res != 1 { - return ErrTaskRun - } - runtime.KeepAlive(t) - return nil -} - -func (t *Task) setName(name string) error { - if res := DmTaskSetName(t.unmanaged, name); res != 1 { - return ErrTaskSetName - } - return nil -} - -func (t *Task) setMessage(message string) error { - if res := DmTaskSetMessage(t.unmanaged, message); res != 1 { - return ErrTaskSetMessage - } - return nil -} - -func (t *Task) setSector(sector uint64) error { - if res := DmTaskSetSector(t.unmanaged, sector); res != 1 { - return ErrTaskSetSector - } - return nil -} - -func (t *Task) setCookie(cookie *uint, flags uint16) error { - if cookie == nil { - return ErrNilCookie - } - if res := DmTaskSetCookie(t.unmanaged, cookie, flags); res != 1 { - return ErrTaskSetCookie - } - return nil -} - -func (t *Task) setAddNode(addNode AddNodeType) error { - if addNode != addNodeOnResume && addNode != addNodeOnCreate { - return ErrInvalidAddNode - } - if res := DmTaskSetAddNode(t.unmanaged, addNode); res != 1 { - return ErrTaskSetAddNode - } - return nil -} - -func (t *Task) setRo() error { - if res := DmTaskSetRo(t.unmanaged); res != 1 { - return ErrTaskSetRo - } - return nil -} - -func (t *Task) addTarget(start, size uint64, ttype, params string) error { - if res := DmTaskAddTarget(t.unmanaged, start, size, - ttype, params); res != 1 { - return ErrTaskAddTarget - } - return nil -} - -func (t *Task) getDeps() (*Deps, error) { - var deps *Deps - if deps = DmTaskGetDeps(t.unmanaged); deps == nil { - return nil, ErrTaskGetDeps - } - return deps, nil -} - -func (t *Task) getInfo() (*Info, error) { - info := &Info{} - if res := DmTaskGetInfo(t.unmanaged, info); res != 1 { - return nil, ErrTaskGetInfo - } - return info, nil -} - -func (t *Task) getInfoWithDeferred() (*Info, error) { - info := &Info{} - if res := DmTaskGetInfoWithDeferred(t.unmanaged, info); res != 1 { - return nil, ErrTaskGetInfo - } - return info, nil -} - -func (t *Task) getDriverVersion() (string, error) { - res := DmTaskGetDriverVersion(t.unmanaged) - if res == "" { - return "", ErrTaskGetDriverVersion - } - return res, nil -} - -func (t *Task) getNextTarget(next unsafe.Pointer) (nextPtr unsafe.Pointer, start uint64, - length uint64, targetType string, params string) { - - return DmGetNextTarget(t.unmanaged, next, &start, &length, - &targetType, ¶ms), - start, length, targetType, params -} - -// UdevWait waits for any processes that are waiting for udev to complete the specified cookie. -func UdevWait(cookie *uint) error { - if res := DmUdevWait(*cookie); res != 1 { - logrus.Debugf("devicemapper: Failed to wait on udev cookie %d, %d", *cookie, res) - return ErrUdevWait - } - return nil -} - -// SetDevDir sets the dev folder for the device mapper library (usually /dev). -func SetDevDir(dir string) error { - if res := DmSetDevDir(dir); res != 1 { - logrus.Debug("devicemapper: Error dm_set_dev_dir") - return ErrSetDevDir - } - return nil -} - -// GetLibraryVersion returns the device mapper library version. -func GetLibraryVersion() (string, error) { - var version string - if res := DmGetLibraryVersion(&version); res != 1 { - return "", ErrGetLibraryVersion - } - return version, nil -} - -// UdevSyncSupported returns whether device-mapper is able to sync with udev -// -// This is essential otherwise race conditions can arise where both udev and -// device-mapper attempt to create and destroy devices. -func UdevSyncSupported() bool { - return DmUdevGetSyncSupport() != 0 -} - -// UdevSetSyncSupport allows setting whether the udev sync should be enabled. -// The return bool indicates the state of whether the sync is enabled. -func UdevSetSyncSupport(enable bool) bool { - if enable { - DmUdevSetSyncSupport(1) - } else { - DmUdevSetSyncSupport(0) - } - - return UdevSyncSupported() -} - -// CookieSupported returns whether the version of device-mapper supports the -// use of cookie's in the tasks. -// This is largely a lower level call that other functions use. -func CookieSupported() bool { - return DmCookieSupported() != 0 -} - -// RemoveDevice is a useful helper for cleaning up a device. -func RemoveDevice(name string) error { - task, err := TaskCreateNamed(deviceRemove, name) - if task == nil { - return err - } - - cookie := new(uint) - if err := task.setCookie(cookie, 0); err != nil { - return fmt.Errorf("devicemapper: Can not set cookie: %s", err) - } - defer UdevWait(cookie) - - dmSawBusy = false // reset before the task is run - dmSawEnxio = false - if err = task.run(); err != nil { - if dmSawBusy { - return ErrBusy - } - if dmSawEnxio { - return ErrEnxio - } - return fmt.Errorf("devicemapper: Error running RemoveDevice %s", err) - } - - return nil -} - -// RemoveDeviceDeferred is a useful helper for cleaning up a device, but deferred. -func RemoveDeviceDeferred(name string) error { - logrus.Debugf("devicemapper: RemoveDeviceDeferred START(%s)", name) - defer logrus.Debugf("devicemapper: RemoveDeviceDeferred END(%s)", name) - task, err := TaskCreateNamed(deviceRemove, name) - if task == nil { - return err - } - - if err := DmTaskDeferredRemove(task.unmanaged); err != 1 { - return ErrTaskDeferredRemove - } - - // set a task cookie and disable library fallback, or else libdevmapper will - // disable udev dm rules and delete the symlink under /dev/mapper by itself, - // even if the removal is deferred by the kernel. - cookie := new(uint) - var flags uint16 - flags = DmUdevDisableLibraryFallback - if err := task.setCookie(cookie, flags); err != nil { - return fmt.Errorf("devicemapper: Can not set cookie: %s", err) - } - - // libdevmapper and udev relies on System V semaphore for synchronization, - // semaphores created in `task.setCookie` will be cleaned up in `UdevWait`. - // So these two function call must come in pairs, otherwise semaphores will - // be leaked, and the limit of number of semaphores defined in `/proc/sys/kernel/sem` - // will be reached, which will eventually make all following calls to 'task.SetCookie' - // fail. - // this call will not wait for the deferred removal's final executing, since no - // udev event will be generated, and the semaphore's value will not be incremented - // by udev, what UdevWait is just cleaning up the semaphore. - defer UdevWait(cookie) - - dmSawEnxio = false - if err = task.run(); err != nil { - if dmSawEnxio { - return ErrEnxio - } - return fmt.Errorf("devicemapper: Error running RemoveDeviceDeferred %s", err) - } - - return nil -} - -// CancelDeferredRemove cancels a deferred remove for a device. -func CancelDeferredRemove(deviceName string) error { - task, err := TaskCreateNamed(deviceTargetMsg, deviceName) - if task == nil { - return err - } - - if err := task.setSector(0); err != nil { - return fmt.Errorf("devicemapper: Can't set sector %s", err) - } - - if err := task.setMessage(fmt.Sprintf("@cancel_deferred_remove")); err != nil { - return fmt.Errorf("devicemapper: Can't set message %s", err) - } - - dmSawBusy = false - dmSawEnxio = false - if err := task.run(); err != nil { - // A device might be being deleted already - if dmSawBusy { - return ErrBusy - } else if dmSawEnxio { - return ErrEnxio - } - return fmt.Errorf("devicemapper: Error running CancelDeferredRemove %s", err) - - } - return nil -} - -// GetBlockDeviceSize returns the size of a block device identified by the specified file. -func GetBlockDeviceSize(file *os.File) (uint64, error) { - size, err := ioctlBlkGetSize64(file.Fd()) - if err != nil { - logrus.Errorf("devicemapper: Error getblockdevicesize: %s", err) - return 0, ErrGetBlockSize - } - return uint64(size), nil -} - -// BlockDeviceDiscard runs discard for the given path. -// This is used as a workaround for the kernel not discarding block so -// on the thin pool when we remove a thinp device, so we do it -// manually -func BlockDeviceDiscard(path string) error { - file, err := os.OpenFile(path, os.O_RDWR, 0) - if err != nil { - return err - } - defer file.Close() - - size, err := GetBlockDeviceSize(file) - if err != nil { - return err - } - - if err := ioctlBlkDiscard(file.Fd(), 0, size); err != nil { - return err - } - - // Without this sometimes the remove of the device that happens after - // discard fails with EBUSY. - unix.Sync() - - return nil -} - -// CreatePool is the programmatic example of "dmsetup create". -// It creates a device with the specified poolName, data and metadata file and block size. -func CreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error { - task, err := TaskCreateNamed(deviceCreate, poolName) - if task == nil { - return err - } - - size, err := GetBlockDeviceSize(dataFile) - if err != nil { - return fmt.Errorf("devicemapper: Can't get data size %s", err) - } - - params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize) - if err := task.addTarget(0, size/512, "thin-pool", params); err != nil { - return fmt.Errorf("devicemapper: Can't add target %s", err) - } - - cookie := new(uint) - var flags uint16 - flags = DmUdevDisableSubsystemRulesFlag | DmUdevDisableDiskRulesFlag | DmUdevDisableOtherRulesFlag - if err := task.setCookie(cookie, flags); err != nil { - return fmt.Errorf("devicemapper: Can't set cookie %s", err) - } - defer UdevWait(cookie) - - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running deviceCreate (CreatePool) %s", err) - } - - return nil -} - -// ReloadPool is the programmatic example of "dmsetup reload". -// It reloads the table with the specified poolName, data and metadata file and block size. -func ReloadPool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error { - task, err := TaskCreateNamed(deviceReload, poolName) - if task == nil { - return err - } - - size, err := GetBlockDeviceSize(dataFile) - if err != nil { - return fmt.Errorf("devicemapper: Can't get data size %s", err) - } - - params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize) - if err := task.addTarget(0, size/512, "thin-pool", params); err != nil { - return fmt.Errorf("devicemapper: Can't add target %s", err) - } - - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running ReloadPool %s", err) - } - - return nil -} - -// GetDeps is the programmatic example of "dmsetup deps". -// It outputs a list of devices referenced by the live table for the specified device. -func GetDeps(name string) (*Deps, error) { - task, err := TaskCreateNamed(deviceDeps, name) - if task == nil { - return nil, err - } - if err := task.run(); err != nil { - return nil, err - } - return task.getDeps() -} - -// GetInfo is the programmatic example of "dmsetup info". -// It outputs some brief information about the device. -func GetInfo(name string) (*Info, error) { - task, err := TaskCreateNamed(deviceInfo, name) - if task == nil { - return nil, err - } - if err := task.run(); err != nil { - return nil, err - } - return task.getInfo() -} - -// GetInfoWithDeferred is the programmatic example of "dmsetup info", but deferred. -// It outputs some brief information about the device. -func GetInfoWithDeferred(name string) (*Info, error) { - task, err := TaskCreateNamed(deviceInfo, name) - if task == nil { - return nil, err - } - if err := task.run(); err != nil { - return nil, err - } - return task.getInfoWithDeferred() -} - -// GetDriverVersion is the programmatic example of "dmsetup version". -// It outputs version information of the driver. -func GetDriverVersion() (string, error) { - task := TaskCreate(deviceVersion) - if task == nil { - return "", fmt.Errorf("devicemapper: Can't create deviceVersion task") - } - if err := task.run(); err != nil { - return "", err - } - return task.getDriverVersion() -} - -// GetStatus is the programmatic example of "dmsetup status". -// It outputs status information for the specified device name. -func GetStatus(name string) (uint64, uint64, string, string, error) { - task, err := TaskCreateNamed(deviceStatus, name) - if task == nil { - logrus.Debugf("devicemapper: GetStatus() Error TaskCreateNamed: %s", err) - return 0, 0, "", "", err - } - if err := task.run(); err != nil { - logrus.Debugf("devicemapper: GetStatus() Error Run: %s", err) - return 0, 0, "", "", err - } - - devinfo, err := task.getInfo() - if err != nil { - logrus.Debugf("devicemapper: GetStatus() Error GetInfo: %s", err) - return 0, 0, "", "", err - } - if devinfo.Exists == 0 { - logrus.Debugf("devicemapper: GetStatus() Non existing device %s", name) - return 0, 0, "", "", fmt.Errorf("devicemapper: Non existing device %s", name) - } - - _, start, length, targetType, params := task.getNextTarget(unsafe.Pointer(nil)) - return start, length, targetType, params, nil -} - -// GetTable is the programmatic example for "dmsetup table". -// It outputs the current table for the specified device name. -func GetTable(name string) (uint64, uint64, string, string, error) { - task, err := TaskCreateNamed(deviceTable, name) - if task == nil { - logrus.Debugf("devicemapper: GetTable() Error TaskCreateNamed: %s", err) - return 0, 0, "", "", err - } - if err := task.run(); err != nil { - logrus.Debugf("devicemapper: GetTable() Error Run: %s", err) - return 0, 0, "", "", err - } - - devinfo, err := task.getInfo() - if err != nil { - logrus.Debugf("devicemapper: GetTable() Error GetInfo: %s", err) - return 0, 0, "", "", err - } - if devinfo.Exists == 0 { - logrus.Debugf("devicemapper: GetTable() Non existing device %s", name) - return 0, 0, "", "", fmt.Errorf("devicemapper: Non existing device %s", name) - } - - _, start, length, targetType, params := task.getNextTarget(unsafe.Pointer(nil)) - return start, length, targetType, params, nil -} - -// SetTransactionID sets a transaction id for the specified device name. -func SetTransactionID(poolName string, oldID uint64, newID uint64) error { - task, err := TaskCreateNamed(deviceTargetMsg, poolName) - if task == nil { - return err - } - - if err := task.setSector(0); err != nil { - return fmt.Errorf("devicemapper: Can't set sector %s", err) - } - - if err := task.setMessage(fmt.Sprintf("set_transaction_id %d %d", oldID, newID)); err != nil { - return fmt.Errorf("devicemapper: Can't set message %s", err) - } - - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running SetTransactionID %s", err) - } - return nil -} - -// SuspendDevice is the programmatic example of "dmsetup suspend". -// It suspends the specified device. -func SuspendDevice(name string) error { - task, err := TaskCreateNamed(deviceSuspend, name) - if task == nil { - return err - } - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running deviceSuspend %s", err) - } - return nil -} - -// ResumeDevice is the programmatic example of "dmsetup resume". -// It un-suspends the specified device. -func ResumeDevice(name string) error { - task, err := TaskCreateNamed(deviceResume, name) - if task == nil { - return err - } - - cookie := new(uint) - if err := task.setCookie(cookie, 0); err != nil { - return fmt.Errorf("devicemapper: Can't set cookie %s", err) - } - defer UdevWait(cookie) - - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running deviceResume %s", err) - } - - return nil -} - -// CreateDevice creates a device with the specified poolName with the specified device id. -func CreateDevice(poolName string, deviceID int) error { - logrus.Debugf("devicemapper: CreateDevice(poolName=%v, deviceID=%v)", poolName, deviceID) - task, err := TaskCreateNamed(deviceTargetMsg, poolName) - if task == nil { - return err - } - - if err := task.setSector(0); err != nil { - return fmt.Errorf("devicemapper: Can't set sector %s", err) - } - - if err := task.setMessage(fmt.Sprintf("create_thin %d", deviceID)); err != nil { - return fmt.Errorf("devicemapper: Can't set message %s", err) - } - - dmSawExist = false // reset before the task is run - if err := task.run(); err != nil { - // Caller wants to know about ErrDeviceIDExists so that it can try with a different device id. - if dmSawExist { - return ErrDeviceIDExists - } - - return fmt.Errorf("devicemapper: Error running CreateDevice %s", err) - - } - return nil -} - -// DeleteDevice deletes a device with the specified poolName with the specified device id. -func DeleteDevice(poolName string, deviceID int) error { - task, err := TaskCreateNamed(deviceTargetMsg, poolName) - if task == nil { - return err - } - - if err := task.setSector(0); err != nil { - return fmt.Errorf("devicemapper: Can't set sector %s", err) - } - - if err := task.setMessage(fmt.Sprintf("delete %d", deviceID)); err != nil { - return fmt.Errorf("devicemapper: Can't set message %s", err) - } - - dmSawBusy = false - if err := task.run(); err != nil { - if dmSawBusy { - return ErrBusy - } - return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err) - } - return nil -} - -// ActivateDevice activates the device identified by the specified -// poolName, name and deviceID with the specified size. -func ActivateDevice(poolName string, name string, deviceID int, size uint64) error { - return activateDevice(poolName, name, deviceID, size, "") -} - -// ActivateDeviceWithExternal activates the device identified by the specified -// poolName, name and deviceID with the specified size. -func ActivateDeviceWithExternal(poolName string, name string, deviceID int, size uint64, external string) error { - return activateDevice(poolName, name, deviceID, size, external) -} - -func activateDevice(poolName string, name string, deviceID int, size uint64, external string) error { - task, err := TaskCreateNamed(deviceCreate, name) - if task == nil { - return err - } - - var params string - if len(external) > 0 { - params = fmt.Sprintf("%s %d %s", poolName, deviceID, external) - } else { - params = fmt.Sprintf("%s %d", poolName, deviceID) - } - if err := task.addTarget(0, size/512, "thin", params); err != nil { - return fmt.Errorf("devicemapper: Can't add target %s", err) - } - if err := task.setAddNode(addNodeOnCreate); err != nil { - return fmt.Errorf("devicemapper: Can't add node %s", err) - } - - cookie := new(uint) - if err := task.setCookie(cookie, 0); err != nil { - return fmt.Errorf("devicemapper: Can't set cookie %s", err) - } - - defer UdevWait(cookie) - - if err := task.run(); err != nil { - return fmt.Errorf("devicemapper: Error running deviceCreate (ActivateDevice) %s", err) - } - - return nil -} - -// CreateSnapDeviceRaw creates a snapshot device. Caller needs to suspend and resume the origin device if it is active. -func CreateSnapDeviceRaw(poolName string, deviceID int, baseDeviceID int) error { - task, err := TaskCreateNamed(deviceTargetMsg, poolName) - if task == nil { - return err - } - - if err := task.setSector(0); err != nil { - return fmt.Errorf("devicemapper: Can't set sector %s", err) - } - - if err := task.setMessage(fmt.Sprintf("create_snap %d %d", deviceID, baseDeviceID)); err != nil { - return fmt.Errorf("devicemapper: Can't set message %s", err) - } - - dmSawExist = false // reset before the task is run - if err := task.run(); err != nil { - // Caller wants to know about ErrDeviceIDExists so that it can try with a different device id. - if dmSawExist { - return ErrDeviceIDExists - } - return fmt.Errorf("devicemapper: Error running deviceCreate (CreateSnapDeviceRaw) %s", err) - } - - return nil -} - -// CreateSnapDevice creates a snapshot based on the device identified by the baseName and baseDeviceId, -func CreateSnapDevice(poolName string, deviceID int, baseName string, baseDeviceID int) error { - devinfo, _ := GetInfo(baseName) - doSuspend := devinfo != nil && devinfo.Exists != 0 - - if doSuspend { - if err := SuspendDevice(baseName); err != nil { - return err - } - } - - if err := CreateSnapDeviceRaw(poolName, deviceID, baseDeviceID); err != nil { - if doSuspend { - if err2 := ResumeDevice(baseName); err2 != nil { - return fmt.Errorf("CreateSnapDeviceRaw Error: (%v): ResumeDevice Error: (%v)", err, err2) - } - } - return err - } - - if doSuspend { - if err := ResumeDevice(baseName); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go deleted file mode 100644 index b540281fab..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go +++ /dev/null @@ -1,121 +0,0 @@ -// +build linux,cgo - -package devicemapper - -import "C" - -import ( - "fmt" - "strings" - - "github.com/sirupsen/logrus" -) - -// DevmapperLogger defines methods required to register as a callback for -// logging events recieved from devicemapper. Note that devicemapper will send -// *all* logs regardless to callbacks (including debug logs) so it's -// recommended to not spam the console with the outputs. -type DevmapperLogger interface { - // DMLog is the logging callback containing all of the information from - // devicemapper. The interface is identical to the C libdm counterpart. - DMLog(level int, file string, line int, dmError int, message string) -} - -// dmLogger is the current logger in use that is being forwarded our messages. -var dmLogger DevmapperLogger - -// LogInit changes the logging callback called after processing libdm logs for -// error message information. The default logger simply forwards all logs to -// logrus. Calling LogInit(nil) disables the calling of callbacks. -func LogInit(logger DevmapperLogger) { - dmLogger = logger -} - -// Due to the way cgo works this has to be in a separate file, as devmapper.go has -// definitions in the cgo block, which is incompatible with using "//export" - -// StorageDevmapperLogCallback exports the devmapper log callback for cgo. Note that -// because we are using callbacks, this function will be called for *every* log -// in libdm (even debug ones because there's no way of setting the verbosity -// level for an external logging callback). -//export StorageDevmapperLogCallback -func StorageDevmapperLogCallback(level C.int, file *C.char, line, dmErrnoOrClass C.int, message *C.char) { - msg := C.GoString(message) - - // Track what errno libdm saw, because the library only gives us 0 or 1. - if level < LogLevelDebug { - if strings.Contains(msg, "busy") { - dmSawBusy = true - } - - if strings.Contains(msg, "File exists") { - dmSawExist = true - } - - if strings.Contains(msg, "No such device or address") { - dmSawEnxio = true - } - } - - if dmLogger != nil { - dmLogger.DMLog(int(level), C.GoString(file), int(line), int(dmErrnoOrClass), msg) - } -} - -// DefaultLogger is the default logger used by pkg/devicemapper. It forwards -// all logs that are of higher or equal priority to the given level to the -// corresponding logrus level. -type DefaultLogger struct { - // Level corresponds to the highest libdm level that will be forwarded to - // logrus. In order to change this, register a new DefaultLogger. - Level int -} - -// DMLog is the logging callback containing all of the information from -// devicemapper. The interface is identical to the C libdm counterpart. -func (l DefaultLogger) DMLog(level int, file string, line, dmError int, message string) { - if level <= l.Level { - // Forward the log to the correct logrus level, if allowed by dmLogLevel. - logMsg := fmt.Sprintf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message) - switch level { - case LogLevelFatal, LogLevelErr: - logrus.Error(logMsg) - case LogLevelWarn: - logrus.Warn(logMsg) - case LogLevelNotice, LogLevelInfo: - logrus.Info(logMsg) - case LogLevelDebug: - logrus.Debug(logMsg) - default: - // Don't drop any "unknown" levels. - logrus.Info(logMsg) - } - } -} - -// registerLogCallback registers our own logging callback function for libdm -// (which is StorageDevmapperLogCallback). -// -// Because libdm only gives us {0,1} error codes we need to parse the logs -// produced by libdm (to set dmSawBusy and so on). Note that by registering a -// callback using StorageDevmapperLogCallback, libdm will no longer output logs to -// stderr so we have to log everything ourselves. None of this handling is -// optional because we depend on log callbacks to parse the logs, and if we -// don't forward the log information we'll be in a lot of trouble when -// debugging things. -func registerLogCallback() { - LogWithErrnoInit() -} - -func init() { - // Use the default logger by default. We only allow LogLevelFatal by - // default, because internally we mask a lot of libdm errors by retrying - // and similar tricks. Also, libdm is very chatty and we don't want to - // worry users for no reason. - dmLogger = DefaultLogger{ - Level: LogLevelFatal, - } - - // Register as early as possible so we don't miss anything. - registerLogCallback() -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper.go deleted file mode 100644 index 190d83d499..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper.go +++ /dev/null @@ -1,252 +0,0 @@ -// +build linux,cgo - -package devicemapper - -/* -#define _GNU_SOURCE -#include -#include // FIXME: present only for BLKGETSIZE64, maybe we can remove it? - -// FIXME: Can't we find a way to do the logging in pure Go? -extern void StorageDevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str); - -static void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...) -{ - char *buffer = NULL; - va_list ap; - int ret; - - va_start(ap, f); - ret = vasprintf(&buffer, f, ap); - va_end(ap); - if (ret < 0) { - // memory allocation failed -- should never happen? - return; - } - - StorageDevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer); - free(buffer); -} - -static void log_with_errno_init() -{ - dm_log_with_errno_init(log_cb); -} -*/ -import "C" - -import ( - "reflect" - "unsafe" -) - -type ( - cdmTask C.struct_dm_task -) - -// IOCTL consts -const ( - BlkGetSize64 = C.BLKGETSIZE64 - BlkDiscard = C.BLKDISCARD -) - -// Devicemapper cookie flags. -const ( - DmUdevDisableSubsystemRulesFlag = C.DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG - DmUdevDisableDiskRulesFlag = C.DM_UDEV_DISABLE_DISK_RULES_FLAG - DmUdevDisableOtherRulesFlag = C.DM_UDEV_DISABLE_OTHER_RULES_FLAG - DmUdevDisableLibraryFallback = C.DM_UDEV_DISABLE_LIBRARY_FALLBACK -) - -// DeviceMapper mapped functions. -var ( - DmGetLibraryVersion = dmGetLibraryVersionFct - DmGetNextTarget = dmGetNextTargetFct - DmSetDevDir = dmSetDevDirFct - DmTaskAddTarget = dmTaskAddTargetFct - DmTaskCreate = dmTaskCreateFct - DmTaskDestroy = dmTaskDestroyFct - DmTaskGetDeps = dmTaskGetDepsFct - DmTaskGetInfo = dmTaskGetInfoFct - DmTaskGetDriverVersion = dmTaskGetDriverVersionFct - DmTaskRun = dmTaskRunFct - DmTaskSetAddNode = dmTaskSetAddNodeFct - DmTaskSetCookie = dmTaskSetCookieFct - DmTaskSetMessage = dmTaskSetMessageFct - DmTaskSetName = dmTaskSetNameFct - DmTaskSetRo = dmTaskSetRoFct - DmTaskSetSector = dmTaskSetSectorFct - DmUdevWait = dmUdevWaitFct - DmUdevSetSyncSupport = dmUdevSetSyncSupportFct - DmUdevGetSyncSupport = dmUdevGetSyncSupportFct - DmCookieSupported = dmCookieSupportedFct - LogWithErrnoInit = logWithErrnoInitFct - DmTaskDeferredRemove = dmTaskDeferredRemoveFct - DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct -) - -func free(p *C.char) { - C.free(unsafe.Pointer(p)) -} - -func dmTaskDestroyFct(task *cdmTask) { - C.dm_task_destroy((*C.struct_dm_task)(task)) -} - -func dmTaskCreateFct(taskType int) *cdmTask { - return (*cdmTask)(C.dm_task_create(C.int(taskType))) -} - -func dmTaskRunFct(task *cdmTask) int { - ret, _ := C.dm_task_run((*C.struct_dm_task)(task)) - return int(ret) -} - -func dmTaskSetNameFct(task *cdmTask, name string) int { - Cname := C.CString(name) - defer free(Cname) - - return int(C.dm_task_set_name((*C.struct_dm_task)(task), Cname)) -} - -func dmTaskSetMessageFct(task *cdmTask, message string) int { - Cmessage := C.CString(message) - defer free(Cmessage) - - return int(C.dm_task_set_message((*C.struct_dm_task)(task), Cmessage)) -} - -func dmTaskSetSectorFct(task *cdmTask, sector uint64) int { - return int(C.dm_task_set_sector((*C.struct_dm_task)(task), C.uint64_t(sector))) -} - -func dmTaskSetCookieFct(task *cdmTask, cookie *uint, flags uint16) int { - cCookie := C.uint32_t(*cookie) - defer func() { - *cookie = uint(cCookie) - }() - return int(C.dm_task_set_cookie((*C.struct_dm_task)(task), &cCookie, C.uint16_t(flags))) -} - -func dmTaskSetAddNodeFct(task *cdmTask, addNode AddNodeType) int { - return int(C.dm_task_set_add_node((*C.struct_dm_task)(task), C.dm_add_node_t(addNode))) -} - -func dmTaskSetRoFct(task *cdmTask) int { - return int(C.dm_task_set_ro((*C.struct_dm_task)(task))) -} - -func dmTaskAddTargetFct(task *cdmTask, - start, size uint64, ttype, params string) int { - - Cttype := C.CString(ttype) - defer free(Cttype) - - Cparams := C.CString(params) - defer free(Cparams) - - return int(C.dm_task_add_target((*C.struct_dm_task)(task), C.uint64_t(start), C.uint64_t(size), Cttype, Cparams)) -} - -func dmTaskGetDepsFct(task *cdmTask) *Deps { - Cdeps := C.dm_task_get_deps((*C.struct_dm_task)(task)) - if Cdeps == nil { - return nil - } - - // golang issue: https://github.com/golang/go/issues/11925 - hdr := reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))), - Len: int(Cdeps.count), - Cap: int(Cdeps.count), - } - devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr)) - - deps := &Deps{ - Count: uint32(Cdeps.count), - Filler: uint32(Cdeps.filler), - } - for _, device := range devices { - deps.Device = append(deps.Device, uint64(device)) - } - return deps -} - -func dmTaskGetInfoFct(task *cdmTask, info *Info) int { - Cinfo := C.struct_dm_info{} - defer func() { - info.Exists = int(Cinfo.exists) - info.Suspended = int(Cinfo.suspended) - info.LiveTable = int(Cinfo.live_table) - info.InactiveTable = int(Cinfo.inactive_table) - info.OpenCount = int32(Cinfo.open_count) - info.EventNr = uint32(Cinfo.event_nr) - info.Major = uint32(Cinfo.major) - info.Minor = uint32(Cinfo.minor) - info.ReadOnly = int(Cinfo.read_only) - info.TargetCount = int32(Cinfo.target_count) - }() - return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) -} - -func dmTaskGetDriverVersionFct(task *cdmTask) string { - buffer := C.malloc(128) - defer C.free(buffer) - res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128) - if res == 0 { - return "" - } - return C.GoString((*C.char)(buffer)) -} - -func dmGetNextTargetFct(task *cdmTask, next unsafe.Pointer, start, length *uint64, target, params *string) unsafe.Pointer { - var ( - Cstart, Clength C.uint64_t - CtargetType, Cparams *C.char - ) - defer func() { - *start = uint64(Cstart) - *length = uint64(Clength) - *target = C.GoString(CtargetType) - *params = C.GoString(Cparams) - }() - - nextp := C.dm_get_next_target((*C.struct_dm_task)(task), next, &Cstart, &Clength, &CtargetType, &Cparams) - return nextp -} - -func dmUdevSetSyncSupportFct(syncWithUdev int) { - (C.dm_udev_set_sync_support(C.int(syncWithUdev))) -} - -func dmUdevGetSyncSupportFct() int { - return int(C.dm_udev_get_sync_support()) -} - -func dmUdevWaitFct(cookie uint) int { - return int(C.dm_udev_wait(C.uint32_t(cookie))) -} - -func dmCookieSupportedFct() int { - return int(C.dm_cookie_supported()) -} - -func logWithErrnoInitFct() { - C.log_with_errno_init() -} - -func dmSetDevDirFct(dir string) int { - Cdir := C.CString(dir) - defer free(Cdir) - - return int(C.dm_set_dev_dir(Cdir)) -} - -func dmGetLibraryVersionFct(version *string) int { - buffer := C.CString(string(make([]byte, 128))) - defer free(buffer) - defer func() { - *version = C.GoString(buffer) - }() - return int(C.dm_get_library_version(buffer, 128)) -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_deferred_remove.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_deferred_remove.go deleted file mode 100644 index 7f793c2708..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_deferred_remove.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build linux,cgo,!libdm_no_deferred_remove - -package devicemapper - -// #include -import "C" - -// LibraryDeferredRemovalSupport tells if the feature is enabled in the build -const LibraryDeferredRemovalSupport = true - -func dmTaskDeferredRemoveFct(task *cdmTask) int { - return int(C.dm_task_deferred_remove((*C.struct_dm_task)(task))) -} - -func dmTaskGetInfoWithDeferredFct(task *cdmTask, info *Info) int { - Cinfo := C.struct_dm_info{} - defer func() { - info.Exists = int(Cinfo.exists) - info.Suspended = int(Cinfo.suspended) - info.LiveTable = int(Cinfo.live_table) - info.InactiveTable = int(Cinfo.inactive_table) - info.OpenCount = int32(Cinfo.open_count) - info.EventNr = uint32(Cinfo.event_nr) - info.Major = uint32(Cinfo.major) - info.Minor = uint32(Cinfo.minor) - info.ReadOnly = int(Cinfo.read_only) - info.TargetCount = int32(Cinfo.target_count) - info.DeferredRemove = int(Cinfo.deferred_remove) - }() - return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_dynamic.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_dynamic.go deleted file mode 100644 index 7d84508982..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_dynamic.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build linux,cgo,!static_build - -package devicemapper - -// #cgo pkg-config: devmapper -import "C" diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_no_deferred_remove.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_no_deferred_remove.go deleted file mode 100644 index a880fec8c4..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_no_deferred_remove.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build linux,cgo,libdm_no_deferred_remove - -package devicemapper - -// LibraryDeferredRemovalSupport tells if the feature is enabled in the build -const LibraryDeferredRemovalSupport = false - -func dmTaskDeferredRemoveFct(task *cdmTask) int { - // Error. Nobody should be calling it. - return -1 -} - -func dmTaskGetInfoWithDeferredFct(task *cdmTask, info *Info) int { - return -1 -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_static.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_static.go deleted file mode 100644 index cf7f26a4c6..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_wrapper_static.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build linux,cgo,static_build - -package devicemapper - -// #cgo pkg-config: --static devmapper -import "C" diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/ioctl.go b/vendor/github.com/containers/storage/pkg/devicemapper/ioctl.go deleted file mode 100644 index 50ea7c4823..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/ioctl.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build linux,cgo - -package devicemapper - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -func ioctlBlkGetSize64(fd uintptr) (int64, error) { - var size int64 - if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, BlkGetSize64, uintptr(unsafe.Pointer(&size))); err != 0 { - return 0, err - } - return size, nil -} - -func ioctlBlkDiscard(fd uintptr, offset, length uint64) error { - var r [2]uint64 - r[0] = offset - r[1] = length - - if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, BlkDiscard, uintptr(unsafe.Pointer(&r[0]))); err != 0 { - return err - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/log.go b/vendor/github.com/containers/storage/pkg/devicemapper/log.go deleted file mode 100644 index cee5e54549..0000000000 --- a/vendor/github.com/containers/storage/pkg/devicemapper/log.go +++ /dev/null @@ -1,11 +0,0 @@ -package devicemapper - -// definitions from lvm2 lib/log/log.h -const ( - LogLevelFatal = 2 + iota // _LOG_FATAL - LogLevelErr // _LOG_ERR - LogLevelWarn // _LOG_WARN - LogLevelNotice // _LOG_NOTICE - LogLevelInfo // _LOG_INFO - LogLevelDebug // _LOG_DEBUG -) diff --git a/vendor/github.com/containers/storage/pkg/directory/directory.go b/vendor/github.com/containers/storage/pkg/directory/directory.go deleted file mode 100644 index 1715ef45d9..0000000000 --- a/vendor/github.com/containers/storage/pkg/directory/directory.go +++ /dev/null @@ -1,26 +0,0 @@ -package directory - -import ( - "io/ioutil" - "os" - "path/filepath" -) - -// MoveToSubdir moves all contents of a directory to a subdirectory underneath the original path -func MoveToSubdir(oldpath, subdir string) error { - - infos, err := ioutil.ReadDir(oldpath) - if err != nil { - return err - } - for _, info := range infos { - if info.Name() != subdir { - oldName := filepath.Join(oldpath, info.Name()) - newName := filepath.Join(oldpath, subdir, info.Name()) - if err := os.Rename(oldName, newName); err != nil { - return err - } - } - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/directory/directory_unix.go b/vendor/github.com/containers/storage/pkg/directory/directory_unix.go deleted file mode 100644 index 397251bdb8..0000000000 --- a/vendor/github.com/containers/storage/pkg/directory/directory_unix.go +++ /dev/null @@ -1,48 +0,0 @@ -// +build linux freebsd solaris - -package directory - -import ( - "os" - "path/filepath" - "syscall" -) - -// Size walks a directory tree and returns its total size in bytes. -func Size(dir string) (size int64, err error) { - data := make(map[uint64]struct{}) - err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, err error) error { - if err != nil { - // if dir does not exist, Size() returns the error. - // if dir/x disappeared while walking, Size() ignores dir/x. - if os.IsNotExist(err) && d != dir { - return nil - } - return err - } - - // Ignore directory sizes - if fileInfo == nil { - return nil - } - - s := fileInfo.Size() - if fileInfo.IsDir() || s == 0 { - return nil - } - - // Check inode to handle hard links correctly - inode := fileInfo.Sys().(*syscall.Stat_t).Ino - // inode is not a uint64 on all platforms. Cast it to avoid issues. - if _, exists := data[uint64(inode)]; exists { - return nil - } - // inode is not a uint64 on all platforms. Cast it to avoid issues. - data[uint64(inode)] = struct{}{} - - size += s - - return nil - }) - return -} diff --git a/vendor/github.com/containers/storage/pkg/directory/directory_windows.go b/vendor/github.com/containers/storage/pkg/directory/directory_windows.go deleted file mode 100644 index 6fb0917c4c..0000000000 --- a/vendor/github.com/containers/storage/pkg/directory/directory_windows.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build windows - -package directory - -import ( - "os" - "path/filepath" -) - -// Size walks a directory tree and returns its total size in bytes. -func Size(dir string) (size int64, err error) { - err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, err error) error { - if err != nil { - // if dir does not exist, Size() returns the error. - // if dir/x disappeared while walking, Size() ignores dir/x. - if os.IsNotExist(err) && d != dir { - return nil - } - return err - } - - // Ignore directory sizes - if fileInfo == nil { - return nil - } - - s := fileInfo.Size() - if fileInfo.IsDir() || s == 0 { - return nil - } - - size += s - - return nil - }) - return -} diff --git a/vendor/github.com/containers/storage/pkg/dmesg/dmesg_linux.go b/vendor/github.com/containers/storage/pkg/dmesg/dmesg_linux.go deleted file mode 100644 index 7df7f3d436..0000000000 --- a/vendor/github.com/containers/storage/pkg/dmesg/dmesg_linux.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build linux - -package dmesg - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -// Dmesg returns last messages from the kernel log, up to size bytes -func Dmesg(size int) []byte { - t := uintptr(3) // SYSLOG_ACTION_READ_ALL - b := make([]byte, size) - amt, _, err := unix.Syscall(unix.SYS_SYSLOG, t, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))) - if err != 0 { - return []byte{} - } - return b[:amt] -} diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go deleted file mode 100644 index a129e654ea..0000000000 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go +++ /dev/null @@ -1,298 +0,0 @@ -package fileutils - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "regexp" - "strings" - "text/scanner" - - "github.com/sirupsen/logrus" -) - -// PatternMatcher allows checking paths agaist a list of patterns -type PatternMatcher struct { - patterns []*Pattern - exclusions bool -} - -// NewPatternMatcher creates a new matcher object for specific patterns that can -// be used later to match against patterns against paths -func NewPatternMatcher(patterns []string) (*PatternMatcher, error) { - pm := &PatternMatcher{ - patterns: make([]*Pattern, 0, len(patterns)), - } - for _, p := range patterns { - // Eliminate leading and trailing whitespace. - p = strings.TrimSpace(p) - if p == "" { - continue - } - p = filepath.Clean(p) - newp := &Pattern{} - if p[0] == '!' { - if len(p) == 1 { - return nil, errors.New("illegal exclusion pattern: \"!\"") - } - newp.exclusion = true - p = p[1:] - pm.exclusions = true - } - // Do some syntax checking on the pattern. - // filepath's Match() has some really weird rules that are inconsistent - // so instead of trying to dup their logic, just call Match() for its - // error state and if there is an error in the pattern return it. - // If this becomes an issue we can remove this since its really only - // needed in the error (syntax) case - which isn't really critical. - if _, err := filepath.Match(p, "."); err != nil { - return nil, err - } - newp.cleanedPattern = p - newp.dirs = strings.Split(p, string(os.PathSeparator)) - pm.patterns = append(pm.patterns, newp) - } - return pm, nil -} - -// Matches matches path against all the patterns. Matches is not safe to be -// called concurrently -func (pm *PatternMatcher) Matches(file string) (bool, error) { - matched := false - file = filepath.FromSlash(file) - parentPath := filepath.Dir(file) - parentPathDirs := strings.Split(parentPath, string(os.PathSeparator)) - - for _, pattern := range pm.patterns { - negative := false - - if pattern.exclusion { - negative = true - } - - match, err := pattern.match(file) - if err != nil { - return false, err - } - - if !match && parentPath != "." { - // Check to see if the pattern matches one of our parent dirs. - if len(pattern.dirs) <= len(parentPathDirs) { - match, _ = pattern.match(strings.Join(parentPathDirs[:len(pattern.dirs)], string(os.PathSeparator))) - } - } - - if match { - matched = !negative - } - } - - if matched { - logrus.Debugf("Skipping excluded path: %s", file) - } - - return matched, nil -} - -// Exclusions returns true if any of the patterns define exclusions -func (pm *PatternMatcher) Exclusions() bool { - return pm.exclusions -} - -// Patterns returns array of active patterns -func (pm *PatternMatcher) Patterns() []*Pattern { - return pm.patterns -} - -// Pattern defines a single regexp used used to filter file paths. -type Pattern struct { - cleanedPattern string - dirs []string - regexp *regexp.Regexp - exclusion bool -} - -func (p *Pattern) String() string { - return p.cleanedPattern -} - -// Exclusion returns true if this pattern defines exclusion -func (p *Pattern) Exclusion() bool { - return p.exclusion -} - -func (p *Pattern) match(path string) (bool, error) { - - if p.regexp == nil { - if err := p.compile(); err != nil { - return false, filepath.ErrBadPattern - } - } - - b := p.regexp.MatchString(path) - - return b, nil -} - -func (p *Pattern) compile() error { - regStr := "^" - pattern := p.cleanedPattern - // Go through the pattern and convert it to a regexp. - // We use a scanner so we can support utf-8 chars. - var scan scanner.Scanner - scan.Init(strings.NewReader(pattern)) - - sl := string(os.PathSeparator) - escSL := sl - if sl == `\` { - escSL += `\` - } - - for scan.Peek() != scanner.EOF { - ch := scan.Next() - - if ch == '*' { - if scan.Peek() == '*' { - // is some flavor of "**" - scan.Next() - - // Treat **/ as ** so eat the "/" - if string(scan.Peek()) == sl { - scan.Next() - } - - if scan.Peek() == scanner.EOF { - // is "**EOF" - to align with .gitignore just accept all - regStr += ".*" - } else { - // is "**" - // Note that this allows for any # of /'s (even 0) because - // the .* will eat everything, even /'s - regStr += "(.*" + escSL + ")?" - } - } else { - // is "*" so map it to anything but "/" - regStr += "[^" + escSL + "]*" - } - } else if ch == '?' { - // "?" is any char except "/" - regStr += "[^" + escSL + "]" - } else if ch == '.' || ch == '$' { - // Escape some regexp special chars that have no meaning - // in golang's filepath.Match - regStr += `\` + string(ch) - } else if ch == '\\' { - // escape next char. Note that a trailing \ in the pattern - // will be left alone (but need to escape it) - if sl == `\` { - // On windows map "\" to "\\", meaning an escaped backslash, - // and then just continue because filepath.Match on - // Windows doesn't allow escaping at all - regStr += escSL - continue - } - if scan.Peek() != scanner.EOF { - regStr += `\` + string(scan.Next()) - } else { - regStr += `\` - } - } else { - regStr += string(ch) - } - } - - regStr += "$" - - re, err := regexp.Compile(regStr) - if err != nil { - return err - } - - p.regexp = re - return nil -} - -// Matches returns true if file matches any of the patterns -// and isn't excluded by any of the subsequent patterns. -func Matches(file string, patterns []string) (bool, error) { - pm, err := NewPatternMatcher(patterns) - if err != nil { - return false, err - } - file = filepath.Clean(file) - - if file == "." { - // Don't let them exclude everything, kind of silly. - return false, nil - } - - return pm.Matches(file) -} - -// CopyFile copies from src to dst until either EOF is reached -// on src or an error occurs. It verifies src exists and removes -// the dst if it exists. -func CopyFile(src, dst string) (int64, error) { - cleanSrc := filepath.Clean(src) - cleanDst := filepath.Clean(dst) - if cleanSrc == cleanDst { - return 0, nil - } - sf, err := os.Open(cleanSrc) - if err != nil { - return 0, err - } - defer sf.Close() - if err := os.Remove(cleanDst); err != nil && !os.IsNotExist(err) { - return 0, err - } - df, err := os.Create(cleanDst) - if err != nil { - return 0, err - } - defer df.Close() - return io.Copy(df, sf) -} - -// ReadSymlinkedDirectory returns the target directory of a symlink. -// The target of the symbolic link may not be a file. -func ReadSymlinkedDirectory(path string) (string, error) { - var realPath string - var err error - if realPath, err = filepath.Abs(path); err != nil { - return "", fmt.Errorf("unable to get absolute path for %s: %s", path, err) - } - if realPath, err = filepath.EvalSymlinks(realPath); err != nil { - return "", fmt.Errorf("failed to canonicalise path for %s: %s", path, err) - } - realPathInfo, err := os.Stat(realPath) - if err != nil { - return "", fmt.Errorf("failed to stat target '%s' of '%s': %s", realPath, path, err) - } - if !realPathInfo.Mode().IsDir() { - return "", fmt.Errorf("canonical path points to a file '%s'", realPath) - } - return realPath, nil -} - -// CreateIfNotExists creates a file or a directory only if it does not already exist. -func CreateIfNotExists(path string, isDir bool) error { - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - if isDir { - return os.MkdirAll(path, 0755) - } - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { - return err - } - f, err := os.OpenFile(path, os.O_CREATE, 0755) - if err != nil { - return err - } - f.Close() - } - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_darwin.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_darwin.go deleted file mode 100644 index ccd648fac3..0000000000 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_darwin.go +++ /dev/null @@ -1,27 +0,0 @@ -package fileutils - -import ( - "os" - "os/exec" - "strconv" - "strings" -) - -// GetTotalUsedFds returns the number of used File Descriptors by -// executing `lsof -p PID` -func GetTotalUsedFds() int { - pid := os.Getpid() - - cmd := exec.Command("lsof", "-p", strconv.Itoa(pid)) - - output, err := cmd.CombinedOutput() - if err != nil { - return -1 - } - - outputStr := strings.TrimSpace(string(output)) - - fds := strings.Split(outputStr, "\n") - - return len(fds) - 1 -} diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_solaris.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_solaris.go deleted file mode 100644 index 0f2cb7ab93..0000000000 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_solaris.go +++ /dev/null @@ -1,7 +0,0 @@ -package fileutils - -// GetTotalUsedFds Returns the number of used File Descriptors. -// On Solaris these limits are per process and not systemwide -func GetTotalUsedFds() int { - return -1 -} diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go deleted file mode 100644 index 9e0e97bd64..0000000000 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build linux freebsd - -package fileutils - -import ( - "fmt" - "io/ioutil" - "os" - - "github.com/sirupsen/logrus" -) - -// GetTotalUsedFds Returns the number of used File Descriptors by -// reading it via /proc filesystem. -func GetTotalUsedFds() int { - if fds, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/fd", os.Getpid())); err != nil { - logrus.Errorf("Error opening /proc/%d/fd: %s", os.Getpid(), err) - } else { - return len(fds) - } - return -1 -} diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_windows.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_windows.go deleted file mode 100644 index 5ec21cace5..0000000000 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -package fileutils - -// GetTotalUsedFds Returns the number of used File Descriptors. Not supported -// on Windows. -func GetTotalUsedFds() int { - return -1 -} diff --git a/vendor/github.com/containers/storage/pkg/fsutils/fsutils_linux.go b/vendor/github.com/containers/storage/pkg/fsutils/fsutils_linux.go deleted file mode 100644 index e6094b55b7..0000000000 --- a/vendor/github.com/containers/storage/pkg/fsutils/fsutils_linux.go +++ /dev/null @@ -1,88 +0,0 @@ -// +build linux - -package fsutils - -import ( - "fmt" - "io/ioutil" - "os" - "unsafe" - - "golang.org/x/sys/unix" -) - -func locateDummyIfEmpty(path string) (string, error) { - children, err := ioutil.ReadDir(path) - if err != nil { - return "", err - } - if len(children) != 0 { - return "", nil - } - dummyFile, err := ioutil.TempFile(path, "fsutils-dummy") - if err != nil { - return "", err - } - name := dummyFile.Name() - err = dummyFile.Close() - return name, err -} - -// SupportsDType returns whether the filesystem mounted on path supports d_type -func SupportsDType(path string) (bool, error) { - // locate dummy so that we have at least one dirent - dummy, err := locateDummyIfEmpty(path) - if err != nil { - return false, err - } - if dummy != "" { - defer os.Remove(dummy) - } - - visited := 0 - supportsDType := true - fn := func(ent *unix.Dirent) bool { - visited++ - if ent.Type == unix.DT_UNKNOWN { - supportsDType = false - // stop iteration - return true - } - // continue iteration - return false - } - if err = iterateReadDir(path, fn); err != nil { - return false, err - } - if visited == 0 { - return false, fmt.Errorf("did not hit any dirent during iteration %s", path) - } - return supportsDType, nil -} - -func iterateReadDir(path string, fn func(*unix.Dirent) bool) error { - d, err := os.Open(path) - if err != nil { - return err - } - defer d.Close() - fd := int(d.Fd()) - buf := make([]byte, 4096) - for { - nbytes, err := unix.ReadDirent(fd, buf) - if err != nil { - return err - } - if nbytes == 0 { - break - } - for off := 0; off < nbytes; { - ent := (*unix.Dirent)(unsafe.Pointer(&buf[off])) - if stop := fn(ent); stop { - return nil - } - off += int(ent.Reclen) - } - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go deleted file mode 100644 index c001fbecbf..0000000000 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build linux - -package homedir - -import ( - "os" - - "github.com/containers/storage/pkg/idtools" -) - -// GetStatic returns the home directory for the current user without calling -// os/user.Current(). This is useful for static-linked binary on glibc-based -// system, because a call to os/user.Current() in a static binary leads to -// segfault due to a glibc issue that won't be fixed in a short term. -// (#29344, golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) -func GetStatic() (string, error) { - uid := os.Getuid() - usr, err := idtools.LookupUID(uid) - if err != nil { - return "", err - } - return usr.Home, nil -} diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go deleted file mode 100644 index 6b96b856f6..0000000000 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package homedir - -import ( - "errors" -) - -// GetStatic is not needed for non-linux systems. -// (Precisely, it is needed only for glibc-based linux systems.) -func GetStatic() (string, error) { - return "", errors.New("homedir.GetStatic() is not supported on this system") -} diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go deleted file mode 100644 index f2a20ea8f8..0000000000 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build !windows - -package homedir - -import ( - "os" - - "github.com/opencontainers/runc/libcontainer/user" -) - -// Key returns the env var name for the user's home dir based on -// the platform being run on -func Key() string { - return "HOME" -} - -// Get returns the home directory of the current user with the help of -// environment variables depending on the target operating system. -// Returned path should be used with "path/filepath" to form new paths. -func Get() string { - home := os.Getenv(Key()) - if home == "" { - if u, err := user.CurrentUser(); err == nil { - return u.Home - } - } - return home -} - -// GetShortcutString returns the string that is shortcut to user's home directory -// in the native shell of the platform running on. -func GetShortcutString() string { - return "~" -} diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go deleted file mode 100644 index fafdb2bbf9..0000000000 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go +++ /dev/null @@ -1,24 +0,0 @@ -package homedir - -import ( - "os" -) - -// Key returns the env var name for the user's home dir based on -// the platform being run on -func Key() string { - return "USERPROFILE" -} - -// Get returns the home directory of the current user with the help of -// environment variables depending on the target operating system. -// Returned path should be used with "path/filepath" to form new paths. -func Get() string { - return os.Getenv(Key()) -} - -// GetShortcutString returns the string that is shortcut to user's home directory -// in the native shell of the platform running on. -func GetShortcutString() string { - return "%USERPROFILE%" // be careful while using in format functions -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools.go b/vendor/github.com/containers/storage/pkg/idtools/idtools.go deleted file mode 100644 index 68a072db22..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/idtools.go +++ /dev/null @@ -1,279 +0,0 @@ -package idtools - -import ( - "bufio" - "fmt" - "os" - "sort" - "strconv" - "strings" -) - -// IDMap contains a single entry for user namespace range remapping. An array -// of IDMap entries represents the structure that will be provided to the Linux -// kernel for creating a user namespace. -type IDMap struct { - ContainerID int `json:"container_id"` - HostID int `json:"host_id"` - Size int `json:"size"` -} - -type subIDRange struct { - Start int - Length int -} - -type ranges []subIDRange - -func (e ranges) Len() int { return len(e) } -func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] } -func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start } - -const ( - subuidFileName string = "/etc/subuid" - subgidFileName string = "/etc/subgid" -) - -// MkdirAllAs creates a directory (include any along the path) and then modifies -// ownership to the requested uid/gid. If the directory already exists, this -// function will still change ownership to the requested uid/gid pair. -// Deprecated: Use MkdirAllAndChown -func MkdirAllAs(path string, mode os.FileMode, ownerUID, ownerGID int) error { - return mkdirAs(path, mode, ownerUID, ownerGID, true, true) -} - -// MkdirAs creates a directory and then modifies ownership to the requested uid/gid. -// If the directory already exists, this function still changes ownership -// Deprecated: Use MkdirAndChown with a IDPair -func MkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int) error { - return mkdirAs(path, mode, ownerUID, ownerGID, false, true) -} - -// MkdirAllAndChown creates a directory (include any along the path) and then modifies -// ownership to the requested uid/gid. If the directory already exists, this -// function will still change ownership to the requested uid/gid pair. -func MkdirAllAndChown(path string, mode os.FileMode, ids IDPair) error { - return mkdirAs(path, mode, ids.UID, ids.GID, true, true) -} - -// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid. -// If the directory already exists, this function still changes ownership -func MkdirAndChown(path string, mode os.FileMode, ids IDPair) error { - return mkdirAs(path, mode, ids.UID, ids.GID, false, true) -} - -// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies -// ownership ONLY of newly created directories to the requested uid/gid. If the -// directories along the path exist, no change of ownership will be performed -func MkdirAllAndChownNew(path string, mode os.FileMode, ids IDPair) error { - return mkdirAs(path, mode, ids.UID, ids.GID, true, false) -} - -// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps. -// If the maps are empty, then the root uid/gid will default to "real" 0/0 -func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) { - uid, err := toHost(0, uidMap) - if err != nil { - return -1, -1, err - } - gid, err := toHost(0, gidMap) - if err != nil { - return -1, -1, err - } - return uid, gid, nil -} - -// toContainer takes an id mapping, and uses it to translate a -// host ID to the remapped ID. If no map is provided, then the translation -// assumes a 1-to-1 mapping and returns the passed in id -func toContainer(hostID int, idMap []IDMap) (int, error) { - if idMap == nil { - return hostID, nil - } - for _, m := range idMap { - if (hostID >= m.HostID) && (hostID <= (m.HostID + m.Size - 1)) { - contID := m.ContainerID + (hostID - m.HostID) - return contID, nil - } - } - return -1, fmt.Errorf("Host ID %d cannot be mapped to a container ID", hostID) -} - -// toHost takes an id mapping and a remapped ID, and translates the -// ID to the mapped host ID. If no map is provided, then the translation -// assumes a 1-to-1 mapping and returns the passed in id # -func toHost(contID int, idMap []IDMap) (int, error) { - if idMap == nil { - return contID, nil - } - for _, m := range idMap { - if (contID >= m.ContainerID) && (contID <= (m.ContainerID + m.Size - 1)) { - hostID := m.HostID + (contID - m.ContainerID) - return hostID, nil - } - } - return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID) -} - -// IDPair is a UID and GID pair -type IDPair struct { - UID int - GID int -} - -// IDMappings contains a mappings of UIDs and GIDs -type IDMappings struct { - uids []IDMap - gids []IDMap -} - -// NewIDMappings takes a requested user and group name and -// using the data from /etc/sub{uid,gid} ranges, creates the -// proper uid and gid remapping ranges for that user/group pair -func NewIDMappings(username, groupname string) (*IDMappings, error) { - subuidRanges, err := parseSubuid(username) - if err != nil { - return nil, err - } - subgidRanges, err := parseSubgid(groupname) - if err != nil { - return nil, err - } - if len(subuidRanges) == 0 { - return nil, fmt.Errorf("No subuid ranges found for user %q", username) - } - if len(subgidRanges) == 0 { - return nil, fmt.Errorf("No subgid ranges found for group %q", groupname) - } - - return &IDMappings{ - uids: createIDMap(subuidRanges), - gids: createIDMap(subgidRanges), - }, nil -} - -// NewIDMappingsFromMaps creates a new mapping from two slices -// Deprecated: this is a temporary shim while transitioning to IDMapping -func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IDMappings { - return &IDMappings{uids: uids, gids: gids} -} - -// RootPair returns a uid and gid pair for the root user. The error is ignored -// because a root user always exists, and the defaults are correct when the uid -// and gid maps are empty. -func (i *IDMappings) RootPair() IDPair { - uid, gid, _ := GetRootUIDGID(i.uids, i.gids) - return IDPair{UID: uid, GID: gid} -} - -// ToHost returns the host UID and GID for the container uid, gid. -// Remapping is only performed if the ids aren't already the remapped root ids -func (i *IDMappings) ToHost(pair IDPair) (IDPair, error) { - var err error - target := i.RootPair() - - if pair.UID != target.UID { - target.UID, err = toHost(pair.UID, i.uids) - if err != nil { - return target, err - } - } - - if pair.GID != target.GID { - target.GID, err = toHost(pair.GID, i.gids) - } - return target, err -} - -// ToContainer returns the container UID and GID for the host uid and gid -func (i *IDMappings) ToContainer(pair IDPair) (int, int, error) { - uid, err := toContainer(pair.UID, i.uids) - if err != nil { - return -1, -1, err - } - gid, err := toContainer(pair.GID, i.gids) - return uid, gid, err -} - -// Empty returns true if there are no id mappings -func (i *IDMappings) Empty() bool { - return len(i.uids) == 0 && len(i.gids) == 0 -} - -// UIDs return the UID mapping -// TODO: remove this once everything has been refactored to use pairs -func (i *IDMappings) UIDs() []IDMap { - return i.uids -} - -// GIDs return the UID mapping -// TODO: remove this once everything has been refactored to use pairs -func (i *IDMappings) GIDs() []IDMap { - return i.gids -} - -func createIDMap(subidRanges ranges) []IDMap { - idMap := []IDMap{} - - // sort the ranges by lowest ID first - sort.Sort(subidRanges) - containerID := 0 - for _, idrange := range subidRanges { - idMap = append(idMap, IDMap{ - ContainerID: containerID, - HostID: idrange.Start, - Size: idrange.Length, - }) - containerID = containerID + idrange.Length - } - return idMap -} - -func parseSubuid(username string) (ranges, error) { - return parseSubidFile(subuidFileName, username) -} - -func parseSubgid(username string) (ranges, error) { - return parseSubidFile(subgidFileName, username) -} - -// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid) -// and return all found ranges for a specified username. If the special value -// "ALL" is supplied for username, then all ranges in the file will be returned -func parseSubidFile(path, username string) (ranges, error) { - var rangeList ranges - - subidFile, err := os.Open(path) - if err != nil { - return rangeList, err - } - defer subidFile.Close() - - s := bufio.NewScanner(subidFile) - for s.Scan() { - if err := s.Err(); err != nil { - return rangeList, err - } - - text := strings.TrimSpace(s.Text()) - if text == "" || strings.HasPrefix(text, "#") { - continue - } - parts := strings.Split(text, ":") - if len(parts) != 3 { - return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path) - } - if parts[0] == username || username == "ALL" { - startid, err := strconv.Atoi(parts[1]) - if err != nil { - return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) - } - length, err := strconv.Atoi(parts[2]) - if err != nil { - return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) - } - rangeList = append(rangeList, subIDRange{startid, length}) - } - } - return rangeList, nil -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools_unix.go b/vendor/github.com/containers/storage/pkg/idtools/idtools_unix.go deleted file mode 100644 index b5870506a0..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/idtools_unix.go +++ /dev/null @@ -1,204 +0,0 @@ -// +build !windows - -package idtools - -import ( - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "sync" - - "github.com/containers/storage/pkg/system" - "github.com/opencontainers/runc/libcontainer/user" -) - -var ( - entOnce sync.Once - getentCmd string -) - -func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error { - // make an array containing the original path asked for, plus (for mkAll == true) - // all path components leading up to the complete path that don't exist before we MkdirAll - // so that we can chown all of them properly at the end. If chownExisting is false, we won't - // chown the full directory path if it exists - var paths []string - if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { - paths = []string{path} - } else if err == nil && chownExisting { - // short-circuit--we were called with an existing directory and chown was requested - return os.Chown(path, ownerUID, ownerGID) - } else if err == nil { - // nothing to do; directory path fully exists already and chown was NOT requested - return nil - } - - if mkAll { - // walk back to "/" looking for directories which do not exist - // and add them to the paths array for chown after creation - dirPath := path - for { - dirPath = filepath.Dir(dirPath) - if dirPath == "/" { - break - } - if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) { - paths = append(paths, dirPath) - } - } - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { - return err - } - } else { - if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) { - return err - } - } - // even if it existed, we will chown the requested path + any subpaths that - // didn't exist when we called MkdirAll - for _, pathComponent := range paths { - if err := os.Chown(pathComponent, ownerUID, ownerGID); err != nil { - return err - } - } - return nil -} - -// CanAccess takes a valid (existing) directory and a uid, gid pair and determines -// if that uid, gid pair has access (execute bit) to the directory -func CanAccess(path string, pair IDPair) bool { - statInfo, err := system.Stat(path) - if err != nil { - return false - } - fileMode := os.FileMode(statInfo.Mode()) - permBits := fileMode.Perm() - return accessible(statInfo.UID() == uint32(pair.UID), - statInfo.GID() == uint32(pair.GID), permBits) -} - -func accessible(isOwner, isGroup bool, perms os.FileMode) bool { - if isOwner && (perms&0100 == 0100) { - return true - } - if isGroup && (perms&0010 == 0010) { - return true - } - if perms&0001 == 0001 { - return true - } - return false -} - -// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs -func LookupUser(username string) (user.User, error) { - // first try a local system files lookup using existing capabilities - usr, err := user.LookupUser(username) - if err == nil { - return usr, nil - } - // local files lookup failed; attempt to call `getent` to query configured passwd dbs - usr, err = getentUser(fmt.Sprintf("%s %s", "passwd", username)) - if err != nil { - return user.User{}, err - } - return usr, nil -} - -// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs -func LookupUID(uid int) (user.User, error) { - // first try a local system files lookup using existing capabilities - usr, err := user.LookupUid(uid) - if err == nil { - return usr, nil - } - // local files lookup failed; attempt to call `getent` to query configured passwd dbs - return getentUser(fmt.Sprintf("%s %d", "passwd", uid)) -} - -func getentUser(args string) (user.User, error) { - reader, err := callGetent(args) - if err != nil { - return user.User{}, err - } - users, err := user.ParsePasswd(reader) - if err != nil { - return user.User{}, err - } - if len(users) == 0 { - return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", strings.Split(args, " ")[1]) - } - return users[0], nil -} - -// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs -func LookupGroup(groupname string) (user.Group, error) { - // first try a local system files lookup using existing capabilities - group, err := user.LookupGroup(groupname) - if err == nil { - return group, nil - } - // local files lookup failed; attempt to call `getent` to query configured group dbs - return getentGroup(fmt.Sprintf("%s %s", "group", groupname)) -} - -// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs -func LookupGID(gid int) (user.Group, error) { - // first try a local system files lookup using existing capabilities - group, err := user.LookupGid(gid) - if err == nil { - return group, nil - } - // local files lookup failed; attempt to call `getent` to query configured group dbs - return getentGroup(fmt.Sprintf("%s %d", "group", gid)) -} - -func getentGroup(args string) (user.Group, error) { - reader, err := callGetent(args) - if err != nil { - return user.Group{}, err - } - groups, err := user.ParseGroup(reader) - if err != nil { - return user.Group{}, err - } - if len(groups) == 0 { - return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", strings.Split(args, " ")[1]) - } - return groups[0], nil -} - -func callGetent(args string) (io.Reader, error) { - entOnce.Do(func() { getentCmd, _ = resolveBinary("getent") }) - // if no `getent` command on host, can't do anything else - if getentCmd == "" { - return nil, fmt.Errorf("") - } - out, err := execCmd(getentCmd, args) - if err != nil { - exitCode, errC := system.GetExitCode(err) - if errC != nil { - return nil, err - } - switch exitCode { - case 1: - return nil, fmt.Errorf("getent reported invalid parameters/database unknown") - case 2: - terms := strings.Split(args, " ") - return nil, fmt.Errorf("getent unable to find entry %q in %s database", terms[1], terms[0]) - case 3: - return nil, fmt.Errorf("getent database doesn't support enumeration") - default: - return nil, err - } - - } - return bytes.NewReader(out), nil -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools_windows.go b/vendor/github.com/containers/storage/pkg/idtools/idtools_windows.go deleted file mode 100644 index dbf6bc4c94..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/idtools_windows.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build windows - -package idtools - -import ( - "os" - - "github.com/containers/storage/pkg/system" -) - -// Platforms such as Windows do not support the UID/GID concept. So make this -// just a wrapper around system.MkdirAll. -func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error { - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { - return err - } - return nil -} - -// CanAccess takes a valid (existing) directory and a uid, gid pair and determines -// if that uid, gid pair has access (execute bit) to the directory -// Windows does not require/support this function, so always return true -func CanAccess(path string, pair IDPair) bool { - return true -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_linux.go deleted file mode 100644 index 9da7975e2c..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_linux.go +++ /dev/null @@ -1,164 +0,0 @@ -package idtools - -import ( - "fmt" - "regexp" - "sort" - "strconv" - "strings" - "sync" -) - -// add a user and/or group to Linux /etc/passwd, /etc/group using standard -// Linux distribution commands: -// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group -// useradd -r -s /bin/false - -var ( - once sync.Once - userCommand string - - cmdTemplates = map[string]string{ - "adduser": "--system --shell /bin/false --no-create-home --disabled-login --disabled-password --group %s", - "useradd": "-r -s /bin/false %s", - "usermod": "-%s %d-%d %s", - } - - idOutRegexp = regexp.MustCompile(`uid=([0-9]+).*gid=([0-9]+)`) - // default length for a UID/GID subordinate range - defaultRangeLen = 65536 - defaultRangeStart = 100000 - userMod = "usermod" -) - -// AddNamespaceRangesUser takes a username and uses the standard system -// utility to create a system user/group pair used to hold the -// /etc/sub{uid,gid} ranges which will be used for user namespace -// mapping ranges in containers. -func AddNamespaceRangesUser(name string) (int, int, error) { - if err := addUser(name); err != nil { - return -1, -1, fmt.Errorf("Error adding user %q: %v", name, err) - } - - // Query the system for the created uid and gid pair - out, err := execCmd("id", name) - if err != nil { - return -1, -1, fmt.Errorf("Error trying to find uid/gid for new user %q: %v", name, err) - } - matches := idOutRegexp.FindStringSubmatch(strings.TrimSpace(string(out))) - if len(matches) != 3 { - return -1, -1, fmt.Errorf("Can't find uid, gid from `id` output: %q", string(out)) - } - uid, err := strconv.Atoi(matches[1]) - if err != nil { - return -1, -1, fmt.Errorf("Can't convert found uid (%s) to int: %v", matches[1], err) - } - gid, err := strconv.Atoi(matches[2]) - if err != nil { - return -1, -1, fmt.Errorf("Can't convert found gid (%s) to int: %v", matches[2], err) - } - - // Now we need to create the subuid/subgid ranges for our new user/group (system users - // do not get auto-created ranges in subuid/subgid) - - if err := createSubordinateRanges(name); err != nil { - return -1, -1, fmt.Errorf("Couldn't create subordinate ID ranges: %v", err) - } - return uid, gid, nil -} - -func addUser(userName string) error { - once.Do(func() { - // set up which commands are used for adding users/groups dependent on distro - if _, err := resolveBinary("adduser"); err == nil { - userCommand = "adduser" - } else if _, err := resolveBinary("useradd"); err == nil { - userCommand = "useradd" - } - }) - if userCommand == "" { - return fmt.Errorf("Cannot add user; no useradd/adduser binary found") - } - args := fmt.Sprintf(cmdTemplates[userCommand], userName) - out, err := execCmd(userCommand, args) - if err != nil { - return fmt.Errorf("Failed to add user with error: %v; output: %q", err, string(out)) - } - return nil -} - -func createSubordinateRanges(name string) error { - - // first, we should verify that ranges weren't automatically created - // by the distro tooling - ranges, err := parseSubuid(name) - if err != nil { - return fmt.Errorf("Error while looking for subuid ranges for user %q: %v", name, err) - } - if len(ranges) == 0 { - // no UID ranges; let's create one - startID, err := findNextUIDRange() - if err != nil { - return fmt.Errorf("Can't find available subuid range: %v", err) - } - out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "v", startID, startID+defaultRangeLen-1, name)) - if err != nil { - return fmt.Errorf("Unable to add subuid range to user: %q; output: %s, err: %v", name, out, err) - } - } - - ranges, err = parseSubgid(name) - if err != nil { - return fmt.Errorf("Error while looking for subgid ranges for user %q: %v", name, err) - } - if len(ranges) == 0 { - // no GID ranges; let's create one - startID, err := findNextGIDRange() - if err != nil { - return fmt.Errorf("Can't find available subgid range: %v", err) - } - out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "w", startID, startID+defaultRangeLen-1, name)) - if err != nil { - return fmt.Errorf("Unable to add subgid range to user: %q; output: %s, err: %v", name, out, err) - } - } - return nil -} - -func findNextUIDRange() (int, error) { - ranges, err := parseSubuid("ALL") - if err != nil { - return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subuid file: %v", err) - } - sort.Sort(ranges) - return findNextRangeStart(ranges) -} - -func findNextGIDRange() (int, error) { - ranges, err := parseSubgid("ALL") - if err != nil { - return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subgid file: %v", err) - } - sort.Sort(ranges) - return findNextRangeStart(ranges) -} - -func findNextRangeStart(rangeList ranges) (int, error) { - startID := defaultRangeStart - for _, arange := range rangeList { - if wouldOverlap(arange, startID) { - startID = arange.Start + arange.Length - } - } - return startID, nil -} - -func wouldOverlap(arange subIDRange, ID int) bool { - low := ID - high := ID + defaultRangeLen - if (low >= arange.Start && low <= arange.Start+arange.Length) || - (high <= arange.Start+arange.Length && high >= arange.Start) { - return true - } - return false -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_unsupported.go b/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_unsupported.go deleted file mode 100644 index d98b354cbd..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/usergroupadd_unsupported.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !linux - -package idtools - -import "fmt" - -// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair -// and calls the appropriate helper function to add the group and then -// the user to the group in /etc/group and /etc/passwd respectively. -func AddNamespaceRangesUser(name string) (int, int, error) { - return -1, -1, fmt.Errorf("No support for adding users or groups on this OS") -} diff --git a/vendor/github.com/containers/storage/pkg/idtools/utils_unix.go b/vendor/github.com/containers/storage/pkg/idtools/utils_unix.go deleted file mode 100644 index 9703ecbd9d..0000000000 --- a/vendor/github.com/containers/storage/pkg/idtools/utils_unix.go +++ /dev/null @@ -1,32 +0,0 @@ -// +build !windows - -package idtools - -import ( - "fmt" - "os/exec" - "path/filepath" - "strings" -) - -func resolveBinary(binname string) (string, error) { - binaryPath, err := exec.LookPath(binname) - if err != nil { - return "", err - } - resolvedPath, err := filepath.EvalSymlinks(binaryPath) - if err != nil { - return "", err - } - //only return no error if the final resolved binary basename - //matches what was searched for - if filepath.Base(resolvedPath) == binname { - return resolvedPath, nil - } - return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath) -} - -func execCmd(cmd, args string) ([]byte, error) { - execCmd := exec.Command(cmd, strings.Split(args, " ")...) - return execCmd.CombinedOutput() -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/buffer.go b/vendor/github.com/containers/storage/pkg/ioutils/buffer.go deleted file mode 100644 index 3d737b3e19..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/buffer.go +++ /dev/null @@ -1,51 +0,0 @@ -package ioutils - -import ( - "errors" - "io" -) - -var errBufferFull = errors.New("buffer is full") - -type fixedBuffer struct { - buf []byte - pos int - lastRead int -} - -func (b *fixedBuffer) Write(p []byte) (int, error) { - n := copy(b.buf[b.pos:cap(b.buf)], p) - b.pos += n - - if n < len(p) { - if b.pos == cap(b.buf) { - return n, errBufferFull - } - return n, io.ErrShortWrite - } - return n, nil -} - -func (b *fixedBuffer) Read(p []byte) (int, error) { - n := copy(p, b.buf[b.lastRead:b.pos]) - b.lastRead += n - return n, nil -} - -func (b *fixedBuffer) Len() int { - return b.pos - b.lastRead -} - -func (b *fixedBuffer) Cap() int { - return cap(b.buf) -} - -func (b *fixedBuffer) Reset() { - b.pos = 0 - b.lastRead = 0 - b.buf = b.buf[:0] -} - -func (b *fixedBuffer) String() string { - return string(b.buf[b.lastRead:b.pos]) -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/bytespipe.go b/vendor/github.com/containers/storage/pkg/ioutils/bytespipe.go deleted file mode 100644 index 72a04f3491..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/bytespipe.go +++ /dev/null @@ -1,186 +0,0 @@ -package ioutils - -import ( - "errors" - "io" - "sync" -) - -// maxCap is the highest capacity to use in byte slices that buffer data. -const maxCap = 1e6 - -// minCap is the lowest capacity to use in byte slices that buffer data -const minCap = 64 - -// blockThreshold is the minimum number of bytes in the buffer which will cause -// a write to BytesPipe to block when allocating a new slice. -const blockThreshold = 1e6 - -var ( - // ErrClosed is returned when Write is called on a closed BytesPipe. - ErrClosed = errors.New("write to closed BytesPipe") - - bufPools = make(map[int]*sync.Pool) - bufPoolsLock sync.Mutex -) - -// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue). -// All written data may be read at most once. Also, BytesPipe allocates -// and releases new byte slices to adjust to current needs, so the buffer -// won't be overgrown after peak loads. -type BytesPipe struct { - mu sync.Mutex - wait *sync.Cond - buf []*fixedBuffer - bufLen int - closeErr error // error to return from next Read. set to nil if not closed. -} - -// NewBytesPipe creates new BytesPipe, initialized by specified slice. -// If buf is nil, then it will be initialized with slice which cap is 64. -// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf). -func NewBytesPipe() *BytesPipe { - bp := &BytesPipe{} - bp.buf = append(bp.buf, getBuffer(minCap)) - bp.wait = sync.NewCond(&bp.mu) - return bp -} - -// Write writes p to BytesPipe. -// It can allocate new []byte slices in a process of writing. -func (bp *BytesPipe) Write(p []byte) (int, error) { - bp.mu.Lock() - - written := 0 -loop0: - for { - if bp.closeErr != nil { - bp.mu.Unlock() - return written, ErrClosed - } - - if len(bp.buf) == 0 { - bp.buf = append(bp.buf, getBuffer(64)) - } - // get the last buffer - b := bp.buf[len(bp.buf)-1] - - n, err := b.Write(p) - written += n - bp.bufLen += n - - // errBufferFull is an error we expect to get if the buffer is full - if err != nil && err != errBufferFull { - bp.wait.Broadcast() - bp.mu.Unlock() - return written, err - } - - // if there was enough room to write all then break - if len(p) == n { - break - } - - // more data: write to the next slice - p = p[n:] - - // make sure the buffer doesn't grow too big from this write - for bp.bufLen >= blockThreshold { - bp.wait.Wait() - if bp.closeErr != nil { - continue loop0 - } - } - - // add new byte slice to the buffers slice and continue writing - nextCap := b.Cap() * 2 - if nextCap > maxCap { - nextCap = maxCap - } - bp.buf = append(bp.buf, getBuffer(nextCap)) - } - bp.wait.Broadcast() - bp.mu.Unlock() - return written, nil -} - -// CloseWithError causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) CloseWithError(err error) error { - bp.mu.Lock() - if err != nil { - bp.closeErr = err - } else { - bp.closeErr = io.EOF - } - bp.wait.Broadcast() - bp.mu.Unlock() - return nil -} - -// Close causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) Close() error { - return bp.CloseWithError(nil) -} - -// Read reads bytes from BytesPipe. -// Data could be read only once. -func (bp *BytesPipe) Read(p []byte) (n int, err error) { - bp.mu.Lock() - if bp.bufLen == 0 { - if bp.closeErr != nil { - bp.mu.Unlock() - return 0, bp.closeErr - } - bp.wait.Wait() - if bp.bufLen == 0 && bp.closeErr != nil { - err := bp.closeErr - bp.mu.Unlock() - return 0, err - } - } - - for bp.bufLen > 0 { - b := bp.buf[0] - read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error - n += read - bp.bufLen -= read - - if b.Len() == 0 { - // it's empty so return it to the pool and move to the next one - returnBuffer(b) - bp.buf[0] = nil - bp.buf = bp.buf[1:] - } - - if len(p) == read { - break - } - - p = p[read:] - } - - bp.wait.Broadcast() - bp.mu.Unlock() - return -} - -func returnBuffer(b *fixedBuffer) { - b.Reset() - bufPoolsLock.Lock() - pool := bufPools[b.Cap()] - bufPoolsLock.Unlock() - if pool != nil { - pool.Put(b) - } -} - -func getBuffer(size int) *fixedBuffer { - bufPoolsLock.Lock() - pool, ok := bufPools[size] - if !ok { - pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }} - bufPools[size] = pool - } - bufPoolsLock.Unlock() - return pool.Get().(*fixedBuffer) -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/fswriters.go b/vendor/github.com/containers/storage/pkg/ioutils/fswriters.go deleted file mode 100644 index a56c462651..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/fswriters.go +++ /dev/null @@ -1,162 +0,0 @@ -package ioutils - -import ( - "io" - "io/ioutil" - "os" - "path/filepath" -) - -// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a -// temporary file and closing it atomically changes the temporary file to -// destination path. Writing and closing concurrently is not allowed. -func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { - f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) - if err != nil { - return nil, err - } - - abspath, err := filepath.Abs(filename) - if err != nil { - return nil, err - } - return &atomicFileWriter{ - f: f, - fn: abspath, - perm: perm, - }, nil -} - -// AtomicWriteFile atomically writes data to a file named by filename. -func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := NewAtomicFileWriter(filename, perm) - if err != nil { - return err - } - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - f.(*atomicFileWriter).writeErr = err - } - if err1 := f.Close(); err == nil { - err = err1 - } - return err -} - -type atomicFileWriter struct { - f *os.File - fn string - writeErr error - perm os.FileMode -} - -func (w *atomicFileWriter) Write(dt []byte) (int, error) { - n, err := w.f.Write(dt) - if err != nil { - w.writeErr = err - } - return n, err -} - -func (w *atomicFileWriter) Close() (retErr error) { - defer func() { - if retErr != nil || w.writeErr != nil { - os.Remove(w.f.Name()) - } - }() - if err := w.f.Sync(); err != nil { - w.f.Close() - return err - } - if err := w.f.Close(); err != nil { - return err - } - if err := os.Chmod(w.f.Name(), w.perm); err != nil { - return err - } - if w.writeErr == nil { - return os.Rename(w.f.Name(), w.fn) - } - return nil -} - -// AtomicWriteSet is used to atomically write a set -// of files and ensure they are visible at the same time. -// Must be committed to a new directory. -type AtomicWriteSet struct { - root string -} - -// NewAtomicWriteSet creates a new atomic write set to -// atomically create a set of files. The given directory -// is used as the base directory for storing files before -// commit. If no temporary directory is given the system -// default is used. -func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) { - td, err := ioutil.TempDir(tmpDir, "write-set-") - if err != nil { - return nil, err - } - - return &AtomicWriteSet{ - root: td, - }, nil -} - -// WriteFile writes a file to the set, guaranteeing the file -// has been synced. -func (ws *AtomicWriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := ws.FileWriter(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) - if err != nil { - return err - } - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - } - if err1 := f.Close(); err == nil { - err = err1 - } - return err -} - -type syncFileCloser struct { - *os.File -} - -func (w syncFileCloser) Close() error { - err := w.File.Sync() - if err1 := w.File.Close(); err == nil { - err = err1 - } - return err -} - -// FileWriter opens a file writer inside the set. The file -// should be synced and closed before calling commit. -func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { - f, err := os.OpenFile(filepath.Join(ws.root, name), flag, perm) - if err != nil { - return nil, err - } - return syncFileCloser{f}, nil -} - -// Cancel cancels the set and removes all temporary data -// created in the set. -func (ws *AtomicWriteSet) Cancel() error { - return os.RemoveAll(ws.root) -} - -// Commit moves all created files to the target directory. The -// target directory must not exist and the parent of the target -// directory must exist. -func (ws *AtomicWriteSet) Commit(target string) error { - return os.Rename(ws.root, target) -} - -// String returns the location the set is writing to. -func (ws *AtomicWriteSet) String() string { - return ws.root -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/readers.go b/vendor/github.com/containers/storage/pkg/ioutils/readers.go deleted file mode 100644 index 63f3c07f46..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/readers.go +++ /dev/null @@ -1,154 +0,0 @@ -package ioutils - -import ( - "crypto/sha256" - "encoding/hex" - "io" - - "golang.org/x/net/context" -) - -type readCloserWrapper struct { - io.Reader - closer func() error -} - -func (r *readCloserWrapper) Close() error { - return r.closer() -} - -// NewReadCloserWrapper returns a new io.ReadCloser. -func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &readCloserWrapper{ - Reader: r, - closer: closer, - } -} - -type readerErrWrapper struct { - reader io.Reader - closer func() -} - -func (r *readerErrWrapper) Read(p []byte) (int, error) { - n, err := r.reader.Read(p) - if err != nil { - r.closer() - } - return n, err -} - -// NewReaderErrWrapper returns a new io.Reader. -func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader { - return &readerErrWrapper{ - reader: r, - closer: closer, - } -} - -// HashData returns the sha256 sum of src. -func HashData(src io.Reader) (string, error) { - h := sha256.New() - if _, err := io.Copy(h, src); err != nil { - return "", err - } - return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil -} - -// OnEOFReader wraps an io.ReadCloser and a function -// the function will run at the end of file or close the file. -type OnEOFReader struct { - Rc io.ReadCloser - Fn func() -} - -func (r *OnEOFReader) Read(p []byte) (n int, err error) { - n, err = r.Rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -// Close closes the file and run the function. -func (r *OnEOFReader) Close() error { - err := r.Rc.Close() - r.runFunc() - return err -} - -func (r *OnEOFReader) runFunc() { - if fn := r.Fn; fn != nil { - fn() - r.Fn = nil - } -} - -// cancelReadCloser wraps an io.ReadCloser with a context for cancelling read -// operations. -type cancelReadCloser struct { - cancel func() - pR *io.PipeReader // Stream to read from - pW *io.PipeWriter -} - -// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the -// context is cancelled. The returned io.ReadCloser must be closed when it is -// no longer needed. -func NewCancelReadCloser(ctx context.Context, in io.ReadCloser) io.ReadCloser { - pR, pW := io.Pipe() - - // Create a context used to signal when the pipe is closed - doneCtx, cancel := context.WithCancel(context.Background()) - - p := &cancelReadCloser{ - cancel: cancel, - pR: pR, - pW: pW, - } - - go func() { - _, err := io.Copy(pW, in) - select { - case <-ctx.Done(): - // If the context was closed, p.closeWithError - // was already called. Calling it again would - // change the error that Read returns. - default: - p.closeWithError(err) - } - in.Close() - }() - go func() { - for { - select { - case <-ctx.Done(): - p.closeWithError(ctx.Err()) - case <-doneCtx.Done(): - return - } - } - }() - - return p -} - -// Read wraps the Read method of the pipe that provides data from the wrapped -// ReadCloser. -func (p *cancelReadCloser) Read(buf []byte) (n int, err error) { - return p.pR.Read(buf) -} - -// closeWithError closes the wrapper and its underlying reader. It will -// cause future calls to Read to return err. -func (p *cancelReadCloser) closeWithError(err error) { - p.pW.CloseWithError(err) - p.cancel() -} - -// Close closes the wrapper its underlying reader. It will cause -// future calls to Read to return io.EOF. -func (p *cancelReadCloser) Close() error { - p.closeWithError(io.EOF) - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/temp_unix.go b/vendor/github.com/containers/storage/pkg/ioutils/temp_unix.go deleted file mode 100644 index 1539ad21b5..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/temp_unix.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !windows - -package ioutils - -import "io/ioutil" - -// TempDir on Unix systems is equivalent to ioutil.TempDir. -func TempDir(dir, prefix string) (string, error) { - return ioutil.TempDir(dir, prefix) -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/temp_windows.go b/vendor/github.com/containers/storage/pkg/ioutils/temp_windows.go deleted file mode 100644 index c719c120b5..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/temp_windows.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build windows - -package ioutils - -import ( - "io/ioutil" - - "github.com/containers/storage/pkg/longpath" -) - -// TempDir is the equivalent of ioutil.TempDir, except that the result is in Windows longpath format. -func TempDir(dir, prefix string) (string, error) { - tempDir, err := ioutil.TempDir(dir, prefix) - if err != nil { - return "", err - } - return longpath.AddPrefix(tempDir), nil -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/writeflusher.go b/vendor/github.com/containers/storage/pkg/ioutils/writeflusher.go deleted file mode 100644 index 52a4901ade..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/writeflusher.go +++ /dev/null @@ -1,92 +0,0 @@ -package ioutils - -import ( - "io" - "sync" -) - -// WriteFlusher wraps the Write and Flush operation ensuring that every write -// is a flush. In addition, the Close method can be called to intercept -// Read/Write calls if the targets lifecycle has already ended. -type WriteFlusher struct { - w io.Writer - flusher flusher - flushed chan struct{} - flushedOnce sync.Once - closed chan struct{} - closeLock sync.Mutex -} - -type flusher interface { - Flush() -} - -var errWriteFlusherClosed = io.EOF - -func (wf *WriteFlusher) Write(b []byte) (n int, err error) { - select { - case <-wf.closed: - return 0, errWriteFlusherClosed - default: - } - - n, err = wf.w.Write(b) - wf.Flush() // every write is a flush. - return n, err -} - -// Flush the stream immediately. -func (wf *WriteFlusher) Flush() { - select { - case <-wf.closed: - return - default: - } - - wf.flushedOnce.Do(func() { - close(wf.flushed) - }) - wf.flusher.Flush() -} - -// Flushed returns the state of flushed. -// If it's flushed, return true, or else it return false. -func (wf *WriteFlusher) Flushed() bool { - // BUG(stevvooe): Remove this method. Its use is inherently racy. Seems to - // be used to detect whether or a response code has been issued or not. - // Another hook should be used instead. - var flushed bool - select { - case <-wf.flushed: - flushed = true - default: - } - return flushed -} - -// Close closes the write flusher, disallowing any further writes to the -// target. After the flusher is closed, all calls to write or flush will -// result in an error. -func (wf *WriteFlusher) Close() error { - wf.closeLock.Lock() - defer wf.closeLock.Unlock() - - select { - case <-wf.closed: - return errWriteFlusherClosed - default: - close(wf.closed) - } - return nil -} - -// NewWriteFlusher returns a new WriteFlusher. -func NewWriteFlusher(w io.Writer) *WriteFlusher { - var fl flusher - if f, ok := w.(flusher); ok { - fl = f - } else { - fl = &NopFlusher{} - } - return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})} -} diff --git a/vendor/github.com/containers/storage/pkg/ioutils/writers.go b/vendor/github.com/containers/storage/pkg/ioutils/writers.go deleted file mode 100644 index ccc7f9c23e..0000000000 --- a/vendor/github.com/containers/storage/pkg/ioutils/writers.go +++ /dev/null @@ -1,66 +0,0 @@ -package ioutils - -import "io" - -// NopWriter represents a type which write operation is nop. -type NopWriter struct{} - -func (*NopWriter) Write(buf []byte) (int, error) { - return len(buf), nil -} - -type nopWriteCloser struct { - io.Writer -} - -func (w *nopWriteCloser) Close() error { return nil } - -// NopWriteCloser returns a nopWriteCloser. -func NopWriteCloser(w io.Writer) io.WriteCloser { - return &nopWriteCloser{w} -} - -// NopFlusher represents a type which flush operation is nop. -type NopFlusher struct{} - -// Flush is a nop operation. -func (f *NopFlusher) Flush() {} - -type writeCloserWrapper struct { - io.Writer - closer func() error -} - -func (r *writeCloserWrapper) Close() error { - return r.closer() -} - -// NewWriteCloserWrapper returns a new io.WriteCloser. -func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { - return &writeCloserWrapper{ - Writer: r, - closer: closer, - } -} - -// WriteCounter wraps a concrete io.Writer and hold a count of the number -// of bytes written to the writer during a "session". -// This can be convenient when write return is masked -// (e.g., json.Encoder.Encode()) -type WriteCounter struct { - Count int64 - Writer io.Writer -} - -// NewWriteCounter returns a new WriteCounter. -func NewWriteCounter(w io.Writer) *WriteCounter { - return &WriteCounter{ - Writer: w, - } -} - -func (wc *WriteCounter) Write(p []byte) (count int, err error) { - count, err = wc.Writer.Write(p) - wc.Count += int64(count) - return -} diff --git a/vendor/github.com/containers/storage/pkg/locker/locker.go b/vendor/github.com/containers/storage/pkg/locker/locker.go deleted file mode 100644 index 0b22ddfab8..0000000000 --- a/vendor/github.com/containers/storage/pkg/locker/locker.go +++ /dev/null @@ -1,112 +0,0 @@ -/* -Package locker provides a mechanism for creating finer-grained locking to help -free up more global locks to handle other tasks. - -The implementation looks close to a sync.Mutex, however the user must provide a -reference to use to refer to the underlying lock when locking and unlocking, -and unlock may generate an error. - -If a lock with a given name does not exist when `Lock` is called, one is -created. -Lock references are automatically cleaned up on `Unlock` if nothing else is -waiting for the lock. -*/ -package locker - -import ( - "errors" - "sync" - "sync/atomic" -) - -// ErrNoSuchLock is returned when the requested lock does not exist -var ErrNoSuchLock = errors.New("no such lock") - -// Locker provides a locking mechanism based on the passed in reference name -type Locker struct { - mu sync.Mutex - locks map[string]*lockCtr -} - -// lockCtr is used by Locker to represent a lock with a given name. -type lockCtr struct { - mu sync.Mutex - // waiters is the number of waiters waiting to acquire the lock - // this is int32 instead of uint32 so we can add `-1` in `dec()` - waiters int32 -} - -// inc increments the number of waiters waiting for the lock -func (l *lockCtr) inc() { - atomic.AddInt32(&l.waiters, 1) -} - -// dec decrements the number of waiters waiting on the lock -func (l *lockCtr) dec() { - atomic.AddInt32(&l.waiters, -1) -} - -// count gets the current number of waiters -func (l *lockCtr) count() int32 { - return atomic.LoadInt32(&l.waiters) -} - -// Lock locks the mutex -func (l *lockCtr) Lock() { - l.mu.Lock() -} - -// Unlock unlocks the mutex -func (l *lockCtr) Unlock() { - l.mu.Unlock() -} - -// New creates a new Locker -func New() *Locker { - return &Locker{ - locks: make(map[string]*lockCtr), - } -} - -// Lock locks a mutex with the given name. If it doesn't exist, one is created -func (l *Locker) Lock(name string) { - l.mu.Lock() - if l.locks == nil { - l.locks = make(map[string]*lockCtr) - } - - nameLock, exists := l.locks[name] - if !exists { - nameLock = &lockCtr{} - l.locks[name] = nameLock - } - - // increment the nameLock waiters while inside the main mutex - // this makes sure that the lock isn't deleted if `Lock` and `Unlock` are called concurrently - nameLock.inc() - l.mu.Unlock() - - // Lock the nameLock outside the main mutex so we don't block other operations - // once locked then we can decrement the number of waiters for this lock - nameLock.Lock() - nameLock.dec() -} - -// Unlock unlocks the mutex with the given name -// If the given lock is not being waited on by any other callers, it is deleted -func (l *Locker) Unlock(name string) error { - l.mu.Lock() - nameLock, exists := l.locks[name] - if !exists { - l.mu.Unlock() - return ErrNoSuchLock - } - - if nameLock.count() == 0 { - delete(l.locks, name) - } - nameLock.Unlock() - - l.mu.Unlock() - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/longpath/longpath.go b/vendor/github.com/containers/storage/pkg/longpath/longpath.go deleted file mode 100644 index 9b15bfff4c..0000000000 --- a/vendor/github.com/containers/storage/pkg/longpath/longpath.go +++ /dev/null @@ -1,26 +0,0 @@ -// longpath introduces some constants and helper functions for handling long paths -// in Windows, which are expected to be prepended with `\\?\` and followed by either -// a drive letter, a UNC server\share, or a volume identifier. - -package longpath - -import ( - "strings" -) - -// Prefix is the longpath prefix for Windows file paths. -const Prefix = `\\?\` - -// AddPrefix will add the Windows long path prefix to the path provided if -// it does not already have it. -func AddPrefix(path string) string { - if !strings.HasPrefix(path, Prefix) { - if strings.HasPrefix(path, `\\`) { - // This is a UNC path, so we need to add 'UNC' to the path as well. - path = Prefix + `UNC` + path[1:] - } else { - path = Prefix + path - } - } - return path -} diff --git a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go b/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go deleted file mode 100644 index 34c80548d2..0000000000 --- a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go +++ /dev/null @@ -1,157 +0,0 @@ -// +build linux - -package loopback - -import ( - "errors" - "fmt" - "os" - "syscall" - - "github.com/sirupsen/logrus" -) - -// Loopback related errors -var ( - ErrAttachLoopbackDevice = errors.New("loopback attach failed") - ErrGetLoopbackBackingFile = errors.New("Unable to get loopback backing file") - ErrSetCapacity = errors.New("Unable set loopback capacity") -) - -func stringToLoopName(src string) [LoNameSize]uint8 { - var dst [LoNameSize]uint8 - copy(dst[:], src[:]) - return dst -} - -func getNextFreeLoopbackIndex() (int, error) { - f, err := os.OpenFile("/dev/loop-control", os.O_RDONLY, 0644) - if err != nil { - return 0, err - } - defer f.Close() - - index, err := ioctlLoopCtlGetFree(f.Fd()) - if index < 0 { - index = 0 - } - return index, err -} - -func openNextAvailableLoopback(index int, sparseName string, sparseFile *os.File) (loopFile *os.File, err error) { - // Read information about the loopback file. - var st syscall.Stat_t - err = syscall.Fstat(int(sparseFile.Fd()), &st) - if err != nil { - logrus.Errorf("Error reading information about loopback file %s: %v", sparseName, err) - return nil, ErrAttachLoopbackDevice - } - - // Start looking for a free /dev/loop - for { - target := fmt.Sprintf("/dev/loop%d", index) - index++ - - fi, err := os.Stat(target) - if err != nil { - if os.IsNotExist(err) { - logrus.Error("There are no more loopback devices available.") - } - return nil, ErrAttachLoopbackDevice - } - - if fi.Mode()&os.ModeDevice != os.ModeDevice { - logrus.Errorf("Loopback device %s is not a block device.", target) - continue - } - - // OpenFile adds O_CLOEXEC - loopFile, err = os.OpenFile(target, os.O_RDWR, 0644) - if err != nil { - logrus.Errorf("Error opening loopback device: %s", err) - return nil, ErrAttachLoopbackDevice - } - - // Try to attach to the loop file - if err := ioctlLoopSetFd(loopFile.Fd(), sparseFile.Fd()); err != nil { - loopFile.Close() - - // If the error is EBUSY, then try the next loopback - if err != syscall.EBUSY { - logrus.Errorf("Cannot set up loopback device %s: %s", target, err) - return nil, ErrAttachLoopbackDevice - } - - // Otherwise, we keep going with the loop - continue - } - - // Check if the loopback driver and underlying filesystem agree on the loopback file's - // device and inode numbers. - dev, ino, err := getLoopbackBackingFile(loopFile) - if err != nil { - logrus.Errorf("Error getting loopback backing file: %s", err) - return nil, ErrGetLoopbackBackingFile - } - if dev != st.Dev || ino != st.Ino { - logrus.Errorf("Loopback device and filesystem disagree on device/inode for %q: %#x(%d):%#x(%d) vs %#x(%d):%#x(%d)", sparseName, dev, dev, ino, ino, st.Dev, st.Dev, st.Ino, st.Ino) - } - - // In case of success, we finished. Break the loop. - break - } - - // This can't happen, but let's be sure - if loopFile == nil { - logrus.Errorf("Unreachable code reached! Error attaching %s to a loopback device.", sparseFile.Name()) - return nil, ErrAttachLoopbackDevice - } - - return loopFile, nil -} - -// AttachLoopDevice attaches the given sparse file to the next -// available loopback device. It returns an opened *os.File. -func AttachLoopDevice(sparseName string) (loop *os.File, err error) { - - // Try to retrieve the next available loopback device via syscall. - // If it fails, we discard error and start looping for a - // loopback from index 0. - startIndex, err := getNextFreeLoopbackIndex() - if err != nil { - logrus.Debugf("Error retrieving the next available loopback: %s", err) - } - - // OpenFile adds O_CLOEXEC - sparseFile, err := os.OpenFile(sparseName, os.O_RDWR, 0644) - if err != nil { - logrus.Errorf("Error opening sparse file %s: %s", sparseName, err) - return nil, ErrAttachLoopbackDevice - } - defer sparseFile.Close() - - loopFile, err := openNextAvailableLoopback(startIndex, sparseName, sparseFile) - if err != nil { - return nil, err - } - - // Set the status of the loopback device - loopInfo := &loopInfo64{ - loFileName: stringToLoopName(loopFile.Name()), - loOffset: 0, - loFlags: LoFlagsAutoClear, - } - - if err := ioctlLoopSetStatus64(loopFile.Fd(), loopInfo); err != nil { - logrus.Errorf("Cannot set up loopback device info: %s", err) - - // If the call failed, then free the loopback device - if err := ioctlLoopClrFd(loopFile.Fd()); err != nil { - logrus.Error("Error while cleaning up the loopback device") - } - loopFile.Close() - return nil, ErrAttachLoopbackDevice - } - - return loopFile, nil -} diff --git a/vendor/github.com/containers/storage/pkg/loopback/ioctl.go b/vendor/github.com/containers/storage/pkg/loopback/ioctl.go deleted file mode 100644 index 0714eb5f87..0000000000 --- a/vendor/github.com/containers/storage/pkg/loopback/ioctl.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build linux - -package loopback - -import ( - "syscall" - "unsafe" -) - -func ioctlLoopCtlGetFree(fd uintptr) (int, error) { - index, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, LoopCtlGetFree, 0) - if err != 0 { - return 0, err - } - return int(index), nil -} - -func ioctlLoopSetFd(loopFd, sparseFd uintptr) error { - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, loopFd, LoopSetFd, sparseFd); err != 0 { - return err - } - return nil -} - -func ioctlLoopSetStatus64(loopFd uintptr, loopInfo *loopInfo64) error { - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, loopFd, LoopSetStatus64, uintptr(unsafe.Pointer(loopInfo))); err != 0 { - return err - } - return nil -} - -func ioctlLoopClrFd(loopFd uintptr) error { - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, loopFd, LoopClrFd, 0); err != 0 { - return err - } - return nil -} - -func ioctlLoopGetStatus64(loopFd uintptr) (*loopInfo64, error) { - loopInfo := &loopInfo64{} - - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, loopFd, LoopGetStatus64, uintptr(unsafe.Pointer(loopInfo))); err != 0 { - return nil, err - } - return loopInfo, nil -} - -func ioctlLoopSetCapacity(loopFd uintptr, value int) error { - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, loopFd, LoopSetCapacity, uintptr(value)); err != 0 { - return err - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go b/vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go deleted file mode 100644 index e1100ce156..0000000000 --- a/vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go +++ /dev/null @@ -1,52 +0,0 @@ -// +build linux - -package loopback - -/* -#include // FIXME: present only for defines, maybe we can remove it? - -#ifndef LOOP_CTL_GET_FREE - #define LOOP_CTL_GET_FREE 0x4C82 -#endif - -#ifndef LO_FLAGS_PARTSCAN - #define LO_FLAGS_PARTSCAN 8 -#endif - -*/ -import "C" - -type loopInfo64 struct { - loDevice uint64 /* ioctl r/o */ - loInode uint64 /* ioctl r/o */ - loRdevice uint64 /* ioctl r/o */ - loOffset uint64 - loSizelimit uint64 /* bytes, 0 == max available */ - loNumber uint32 /* ioctl r/o */ - loEncryptType uint32 - loEncryptKeySize uint32 /* ioctl w/o */ - loFlags uint32 /* ioctl r/o */ - loFileName [LoNameSize]uint8 - loCryptName [LoNameSize]uint8 - loEncryptKey [LoKeySize]uint8 /* ioctl w/o */ - loInit [2]uint64 -} - -// IOCTL consts -const ( - LoopSetFd = C.LOOP_SET_FD - LoopCtlGetFree = C.LOOP_CTL_GET_FREE - LoopGetStatus64 = C.LOOP_GET_STATUS64 - LoopSetStatus64 = C.LOOP_SET_STATUS64 - LoopClrFd = C.LOOP_CLR_FD - LoopSetCapacity = C.LOOP_SET_CAPACITY -) - -// LOOP consts. -const ( - LoFlagsAutoClear = C.LO_FLAGS_AUTOCLEAR - LoFlagsReadOnly = C.LO_FLAGS_READ_ONLY - LoFlagsPartScan = C.LO_FLAGS_PARTSCAN - LoKeySize = C.LO_KEY_SIZE - LoNameSize = C.LO_NAME_SIZE -) diff --git a/vendor/github.com/containers/storage/pkg/loopback/loopback.go b/vendor/github.com/containers/storage/pkg/loopback/loopback.go deleted file mode 100644 index a8ec3c6163..0000000000 --- a/vendor/github.com/containers/storage/pkg/loopback/loopback.go +++ /dev/null @@ -1,63 +0,0 @@ -// +build linux - -package loopback - -import ( - "fmt" - "os" - "syscall" - - "github.com/sirupsen/logrus" -) - -func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) { - loopInfo, err := ioctlLoopGetStatus64(file.Fd()) - if err != nil { - logrus.Errorf("Error get loopback backing file: %s", err) - return 0, 0, ErrGetLoopbackBackingFile - } - return loopInfo.loDevice, loopInfo.loInode, nil -} - -// SetCapacity reloads the size for the loopback device. -func SetCapacity(file *os.File) error { - if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil { - logrus.Errorf("Error loopbackSetCapacity: %s", err) - return ErrSetCapacity - } - return nil -} - -// FindLoopDeviceFor returns a loopback device file for the specified file which -// is backing file of a loop back device. -func FindLoopDeviceFor(file *os.File) *os.File { - stat, err := file.Stat() - if err != nil { - return nil - } - targetInode := stat.Sys().(*syscall.Stat_t).Ino - targetDevice := stat.Sys().(*syscall.Stat_t).Dev - - for i := 0; true; i++ { - path := fmt.Sprintf("/dev/loop%d", i) - - file, err := os.OpenFile(path, os.O_RDWR, 0) - if err != nil { - if os.IsNotExist(err) { - return nil - } - - // Ignore all errors until the first not-exist - // we want to continue looking for the file - continue - } - - dev, inode, err := getLoopbackBackingFile(file) - if err == nil && dev == targetDevice && inode == targetInode { - return file - } - file.Close() - } - - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/mflag/LICENSE b/vendor/github.com/containers/storage/pkg/mflag/LICENSE deleted file mode 100644 index 9b4f4a294e..0000000000 --- a/vendor/github.com/containers/storage/pkg/mflag/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/containers/storage/pkg/mount/flags.go b/vendor/github.com/containers/storage/pkg/mount/flags.go deleted file mode 100644 index 607dbed43a..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/flags.go +++ /dev/null @@ -1,149 +0,0 @@ -package mount - -import ( - "fmt" - "strings" -) - -var flags = map[string]struct { - clear bool - flag int -}{ - "defaults": {false, 0}, - "ro": {false, RDONLY}, - "rw": {true, RDONLY}, - "suid": {true, NOSUID}, - "nosuid": {false, NOSUID}, - "dev": {true, NODEV}, - "nodev": {false, NODEV}, - "exec": {true, NOEXEC}, - "noexec": {false, NOEXEC}, - "sync": {false, SYNCHRONOUS}, - "async": {true, SYNCHRONOUS}, - "dirsync": {false, DIRSYNC}, - "remount": {false, REMOUNT}, - "mand": {false, MANDLOCK}, - "nomand": {true, MANDLOCK}, - "atime": {true, NOATIME}, - "noatime": {false, NOATIME}, - "diratime": {true, NODIRATIME}, - "nodiratime": {false, NODIRATIME}, - "bind": {false, BIND}, - "rbind": {false, RBIND}, - "unbindable": {false, UNBINDABLE}, - "runbindable": {false, RUNBINDABLE}, - "private": {false, PRIVATE}, - "rprivate": {false, RPRIVATE}, - "shared": {false, SHARED}, - "rshared": {false, RSHARED}, - "slave": {false, SLAVE}, - "rslave": {false, RSLAVE}, - "relatime": {false, RELATIME}, - "norelatime": {true, RELATIME}, - "strictatime": {false, STRICTATIME}, - "nostrictatime": {true, STRICTATIME}, -} - -var validFlags = map[string]bool{ - "": true, - "size": true, - "mode": true, - "uid": true, - "gid": true, - "nr_inodes": true, - "nr_blocks": true, - "mpol": true, -} - -var propagationFlags = map[string]bool{ - "bind": true, - "rbind": true, - "unbindable": true, - "runbindable": true, - "private": true, - "rprivate": true, - "shared": true, - "rshared": true, - "slave": true, - "rslave": true, -} - -// MergeTmpfsOptions merge mount options to make sure there is no duplicate. -func MergeTmpfsOptions(options []string) ([]string, error) { - // We use collisions maps to remove duplicates. - // For flag, the key is the flag value (the key for propagation flag is -1) - // For data=value, the key is the data - flagCollisions := map[int]bool{} - dataCollisions := map[string]bool{} - - var newOptions []string - // We process in reverse order - for i := len(options) - 1; i >= 0; i-- { - option := options[i] - if option == "defaults" { - continue - } - if f, ok := flags[option]; ok && f.flag != 0 { - // There is only one propagation mode - key := f.flag - if propagationFlags[option] { - key = -1 - } - // Check to see if there is collision for flag - if !flagCollisions[key] { - // We prepend the option and add to collision map - newOptions = append([]string{option}, newOptions...) - flagCollisions[key] = true - } - continue - } - opt := strings.SplitN(option, "=", 2) - if len(opt) != 2 || !validFlags[opt[0]] { - return nil, fmt.Errorf("Invalid tmpfs option %q", opt) - } - if !dataCollisions[opt[0]] { - // We prepend the option and add to collision map - newOptions = append([]string{option}, newOptions...) - dataCollisions[opt[0]] = true - } - } - - return newOptions, nil -} - -// Parse fstab type mount options into mount() flags -// and device specific data -func parseOptions(options string) (int, string) { - var ( - flag int - data []string - ) - - for _, o := range strings.Split(options, ",") { - // If the option does not exist in the flags table or the flag - // is not supported on the platform, - // then it is a data value for a specific fs type - if f, exists := flags[o]; exists && f.flag != 0 { - if f.clear { - flag &= ^f.flag - } else { - flag |= f.flag - } - } else { - data = append(data, o) - } - } - return flag, strings.Join(data, ",") -} - -// ParseTmpfsOptions parse fstab type mount options into flags and data -func ParseTmpfsOptions(options string) (int, string, error) { - flags, data := parseOptions(options) - for _, o := range strings.Split(data, ",") { - opt := strings.SplitN(o, "=", 2) - if !validFlags[opt[0]] { - return 0, "", fmt.Errorf("Invalid tmpfs option %q", opt) - } - } - return flags, data, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go b/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go deleted file mode 100644 index 5f76f331b6..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go +++ /dev/null @@ -1,49 +0,0 @@ -// +build freebsd,cgo - -package mount - -/* -#include -*/ -import "C" - -const ( - // RDONLY will mount the filesystem as read-only. - RDONLY = C.MNT_RDONLY - - // NOSUID will not allow set-user-identifier or set-group-identifier bits to - // take effect. - NOSUID = C.MNT_NOSUID - - // NOEXEC will not allow execution of any binaries on the mounted file system. - NOEXEC = C.MNT_NOEXEC - - // SYNCHRONOUS will allow any I/O to the file system to be done synchronously. - SYNCHRONOUS = C.MNT_SYNCHRONOUS - - // NOATIME will not update the file access time when reading from a file. - NOATIME = C.MNT_NOATIME -) - -// These flags are unsupported. -const ( - BIND = 0 - DIRSYNC = 0 - MANDLOCK = 0 - NODEV = 0 - NODIRATIME = 0 - UNBINDABLE = 0 - RUNBINDABLE = 0 - PRIVATE = 0 - RPRIVATE = 0 - SHARED = 0 - RSHARED = 0 - SLAVE = 0 - RSLAVE = 0 - RBIND = 0 - RELATIVE = 0 - RELATIME = 0 - REMOUNT = 0 - STRICTATIME = 0 - mntDetach = 0 -) diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go b/vendor/github.com/containers/storage/pkg/mount/flags_linux.go deleted file mode 100644 index 0425d0dd63..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go +++ /dev/null @@ -1,87 +0,0 @@ -package mount - -import ( - "golang.org/x/sys/unix" -) - -const ( - // RDONLY will mount the file system read-only. - RDONLY = unix.MS_RDONLY - - // NOSUID will not allow set-user-identifier or set-group-identifier bits to - // take effect. - NOSUID = unix.MS_NOSUID - - // NODEV will not interpret character or block special devices on the file - // system. - NODEV = unix.MS_NODEV - - // NOEXEC will not allow execution of any binaries on the mounted file system. - NOEXEC = unix.MS_NOEXEC - - // SYNCHRONOUS will allow I/O to the file system to be done synchronously. - SYNCHRONOUS = unix.MS_SYNCHRONOUS - - // DIRSYNC will force all directory updates within the file system to be done - // synchronously. This affects the following system calls: create, link, - // unlink, symlink, mkdir, rmdir, mknod and rename. - DIRSYNC = unix.MS_DIRSYNC - - // REMOUNT will attempt to remount an already-mounted file system. This is - // commonly used to change the mount flags for a file system, especially to - // make a readonly file system writeable. It does not change device or mount - // point. - REMOUNT = unix.MS_REMOUNT - - // MANDLOCK will force mandatory locks on a filesystem. - MANDLOCK = unix.MS_MANDLOCK - - // NOATIME will not update the file access time when reading from a file. - NOATIME = unix.MS_NOATIME - - // NODIRATIME will not update the directory access time. - NODIRATIME = unix.MS_NODIRATIME - - // BIND remounts a subtree somewhere else. - BIND = unix.MS_BIND - - // RBIND remounts a subtree and all possible submounts somewhere else. - RBIND = unix.MS_BIND | unix.MS_REC - - // UNBINDABLE creates a mount which cannot be cloned through a bind operation. - UNBINDABLE = unix.MS_UNBINDABLE - - // RUNBINDABLE marks the entire mount tree as UNBINDABLE. - RUNBINDABLE = unix.MS_UNBINDABLE | unix.MS_REC - - // PRIVATE creates a mount which carries no propagation abilities. - PRIVATE = unix.MS_PRIVATE - - // RPRIVATE marks the entire mount tree as PRIVATE. - RPRIVATE = unix.MS_PRIVATE | unix.MS_REC - - // SLAVE creates a mount which receives propagation from its master, but not - // vice versa. - SLAVE = unix.MS_SLAVE - - // RSLAVE marks the entire mount tree as SLAVE. - RSLAVE = unix.MS_SLAVE | unix.MS_REC - - // SHARED creates a mount which provides the ability to create mirrors of - // that mount such that mounts and unmounts within any of the mirrors - // propagate to the other mirrors. - SHARED = unix.MS_SHARED - - // RSHARED marks the entire mount tree as SHARED. - RSHARED = unix.MS_SHARED | unix.MS_REC - - // RELATIME updates inode access times relative to modify or change time. - RELATIME = unix.MS_RELATIME - - // STRICTATIME allows to explicitly request full atime updates. This makes - // it possible for the kernel to default to relatime or noatime but still - // allow userspace to override it. - STRICTATIME = unix.MS_STRICTATIME - - mntDetach = unix.MNT_DETACH -) diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go deleted file mode 100644 index 9ed741e3ff..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build !linux,!freebsd freebsd,!cgo solaris,!cgo - -package mount - -// These flags are unsupported. -const ( - BIND = 0 - DIRSYNC = 0 - MANDLOCK = 0 - NOATIME = 0 - NODEV = 0 - NODIRATIME = 0 - NOEXEC = 0 - NOSUID = 0 - UNBINDABLE = 0 - RUNBINDABLE = 0 - PRIVATE = 0 - RPRIVATE = 0 - SHARED = 0 - RSHARED = 0 - SLAVE = 0 - RSLAVE = 0 - RBIND = 0 - RELATIME = 0 - RELATIVE = 0 - REMOUNT = 0 - STRICTATIME = 0 - SYNCHRONOUS = 0 - RDONLY = 0 - mntDetach = 0 -) diff --git a/vendor/github.com/containers/storage/pkg/mount/mount.go b/vendor/github.com/containers/storage/pkg/mount/mount.go deleted file mode 100644 index d3caa16bda..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mount.go +++ /dev/null @@ -1,106 +0,0 @@ -package mount - -import ( - "sort" - "strings" - "time" - - "github.com/containers/storage/pkg/fileutils" -) - -// GetMounts retrieves a list of mounts for the current running process. -func GetMounts() ([]*Info, error) { - return parseMountTable() -} - -// Mounted determines if a specified mountpoint has been mounted. -// On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab. -func Mounted(mountpoint string) (bool, error) { - entries, err := parseMountTable() - if err != nil { - return false, err - } - - mountpoint, err = fileutils.ReadSymlinkedDirectory(mountpoint) - if err != nil { - return false, err - } - // Search the table for the mountpoint - for _, e := range entries { - if e.Mountpoint == mountpoint { - return true, nil - } - } - return false, nil -} - -// Mount will mount filesystem according to the specified configuration, on the -// condition that the target path is *not* already mounted. Options must be -// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See -// flags.go for supported option flags. -func Mount(device, target, mType, options string) error { - flag, _ := parseOptions(options) - if flag&REMOUNT != REMOUNT { - if mounted, err := Mounted(target); err != nil || mounted { - return err - } - } - return ForceMount(device, target, mType, options) -} - -// ForceMount will mount a filesystem according to the specified configuration, -// *regardless* if the target path is not already mounted. Options must be -// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See -// flags.go for supported option flags. -func ForceMount(device, target, mType, options string) error { - flag, data := parseOptions(options) - return mount(device, target, mType, uintptr(flag), data) -} - -// Unmount lazily unmounts a filesystem on supported platforms, otherwise -// does a normal unmount. -func Unmount(target string) error { - if mounted, err := Mounted(target); err != nil || !mounted { - return err - } - return ForceUnmount(target) -} - -// RecursiveUnmount unmounts the target and all mounts underneath, starting with -// the deepsest mount first. -func RecursiveUnmount(target string) error { - mounts, err := GetMounts() - if err != nil { - return err - } - - // Make the deepest mount be first - sort.Sort(sort.Reverse(byMountpoint(mounts))) - - for i, m := range mounts { - if !strings.HasPrefix(m.Mountpoint, target) { - continue - } - if err := Unmount(m.Mountpoint); err != nil && i == len(mounts)-1 { - if mounted, err := Mounted(m.Mountpoint); err != nil || mounted { - return err - } - // Ignore errors for submounts and continue trying to unmount others - // The final unmount should fail if there ane any submounts remaining - } - } - return nil -} - -// ForceUnmount will force an unmount of the target filesystem, regardless if -// it is mounted or not. -func ForceUnmount(target string) (err error) { - // Simple retry logic for unmount - for i := 0; i < 10; i++ { - if err = unmount(target, 0); err == nil { - return nil - } - time.Sleep(100 * time.Millisecond) - } - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go b/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go deleted file mode 100644 index 814896cc9e..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go +++ /dev/null @@ -1,60 +0,0 @@ -package mount - -/* -#include -#include -#include -#include -#include -#include -*/ -import "C" - -import ( - "fmt" - "strings" - "unsafe" - - "golang.org/x/sys/unix" -) - -func allocateIOVecs(options []string) []C.struct_iovec { - out := make([]C.struct_iovec, len(options)) - for i, option := range options { - out[i].iov_base = unsafe.Pointer(C.CString(option)) - out[i].iov_len = C.size_t(len(option) + 1) - } - return out -} - -func mount(device, target, mType string, flag uintptr, data string) error { - isNullFS := false - - xs := strings.Split(data, ",") - for _, x := range xs { - if x == "bind" { - isNullFS = true - } - } - - options := []string{"fspath", target} - if isNullFS { - options = append(options, "fstype", "nullfs", "target", device) - } else { - options = append(options, "fstype", mType, "from", device) - } - rawOptions := allocateIOVecs(options) - for _, rawOption := range rawOptions { - defer C.free(rawOption.iov_base) - } - - if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 { - reason := C.GoString(C.strerror(*C.__error())) - return fmt.Errorf("Failed to call nmount: %s", reason) - } - return nil -} - -func unmount(target string, flag int) error { - return unix.Unmount(target, flag) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go b/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go deleted file mode 100644 index 39c36d472a..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go +++ /dev/null @@ -1,57 +0,0 @@ -package mount - -import ( - "golang.org/x/sys/unix" -) - -const ( - // ptypes is the set propagation types. - ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE - - // pflags is the full set valid flags for a change propagation call. - pflags = ptypes | unix.MS_REC | unix.MS_SILENT - - // broflags is the combination of bind and read only - broflags = unix.MS_BIND | unix.MS_RDONLY -) - -// isremount returns true if either device name or flags identify a remount request, false otherwise. -func isremount(device string, flags uintptr) bool { - switch { - // We treat device "" and "none" as a remount request to provide compatibility with - // requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts. - case flags&unix.MS_REMOUNT != 0, device == "", device == "none": - return true - default: - return false - } -} - -func mount(device, target, mType string, flags uintptr, data string) error { - oflags := flags &^ ptypes - if !isremount(device, flags) || data != "" { - // Initial call applying all non-propagation flags for mount - // or remount with changed data - if err := unix.Mount(device, target, mType, oflags, data); err != nil { - return err - } - } - - if flags&ptypes != 0 { - // Change the propagation type. - if err := unix.Mount("", target, "", flags&pflags, ""); err != nil { - return err - } - } - - if oflags&broflags == broflags { - // Remount the bind to apply read only. - return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "") - } - - return nil -} - -func unmount(target string, flag int) error { - return unix.Unmount(target, flag) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go b/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go deleted file mode 100644 index 48b86771e7..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build solaris,cgo - -package mount - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -// #include -// #include -// #include -// int Mount(const char *spec, const char *dir, int mflag, -// char *fstype, char *dataptr, int datalen, char *optptr, int optlen) { -// return mount(spec, dir, mflag, fstype, dataptr, datalen, optptr, optlen); -// } -import "C" - -func mount(device, target, mType string, flag uintptr, data string) error { - spec := C.CString(device) - dir := C.CString(target) - fstype := C.CString(mType) - _, err := C.Mount(spec, dir, C.int(flag), fstype, nil, 0, nil, 0) - C.free(unsafe.Pointer(spec)) - C.free(unsafe.Pointer(dir)) - C.free(unsafe.Pointer(fstype)) - return err -} - -func unmount(target string, flag int) error { - err := unix.Unmount(target, flag) - return err -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go deleted file mode 100644 index a2a3bb457f..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo - -package mount - -func mount(device, target, mType string, flag uintptr, data string) error { - panic("Not implemented") -} - -func unmount(target string, flag int) error { - panic("Not implemented") -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo.go deleted file mode 100644 index ff4cc1d86b..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go +++ /dev/null @@ -1,54 +0,0 @@ -package mount - -// Info reveals information about a particular mounted filesystem. This -// struct is populated from the content in the /proc//mountinfo file. -type Info struct { - // ID is a unique identifier of the mount (may be reused after umount). - ID int - - // Parent indicates the ID of the mount parent (or of self for the top of the - // mount tree). - Parent int - - // Major indicates one half of the device ID which identifies the device class. - Major int - - // Minor indicates one half of the device ID which identifies a specific - // instance of device. - Minor int - - // Root of the mount within the filesystem. - Root string - - // Mountpoint indicates the mount point relative to the process's root. - Mountpoint string - - // Opts represents mount-specific options. - Opts string - - // Optional represents optional fields. - Optional string - - // Fstype indicates the type of filesystem, such as EXT3. - Fstype string - - // Source indicates filesystem specific information or "none". - Source string - - // VfsOpts represents per super block options. - VfsOpts string -} - -type byMountpoint []*Info - -func (by byMountpoint) Len() int { - return len(by) -} - -func (by byMountpoint) Less(i, j int) bool { - return by[i].Mountpoint < by[j].Mountpoint -} - -func (by byMountpoint) Swap(i, j int) { - by[i], by[j] = by[j], by[i] -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_freebsd.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_freebsd.go deleted file mode 100644 index 4f32edcd90..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_freebsd.go +++ /dev/null @@ -1,41 +0,0 @@ -package mount - -/* -#include -#include -#include -*/ -import "C" - -import ( - "fmt" - "reflect" - "unsafe" -) - -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from -// bind mounts. -func parseMountTable() ([]*Info, error) { - var rawEntries *C.struct_statfs - - count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT)) - if count == 0 { - return nil, fmt.Errorf("Failed to call getmntinfo") - } - - var entries []C.struct_statfs - header := (*reflect.SliceHeader)(unsafe.Pointer(&entries)) - header.Cap = count - header.Len = count - header.Data = uintptr(unsafe.Pointer(rawEntries)) - - var out []*Info - for _, entry := range entries { - var mountinfo Info - mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0]) - mountinfo.Source = C.GoString(&entry.f_mntfromname[0]) - mountinfo.Fstype = C.GoString(&entry.f_fstypename[0]) - out = append(out, &mountinfo) - } - return out, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go deleted file mode 100644 index be69fee1d7..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go +++ /dev/null @@ -1,95 +0,0 @@ -// +build linux - -package mount - -import ( - "bufio" - "fmt" - "io" - "os" - "strings" -) - -const ( - /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue - (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) - - (1) mount ID: unique identifier of the mount (may be reused after umount) - (2) parent ID: ID of parent (or of self for the top of the mount tree) - (3) major:minor: value of st_dev for files on filesystem - (4) root: root of the mount within the filesystem - (5) mount point: mount point relative to the process's root - (6) mount options: per mount options - (7) optional fields: zero or more fields of the form "tag[:value]" - (8) separator: marks the end of the optional fields - (9) filesystem type: name of filesystem of the form "type[.subtype]" - (10) mount source: filesystem specific information or "none" - (11) super options: per super block options*/ - mountinfoFormat = "%d %d %d:%d %s %s %s %s" -) - -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from -// bind mounts -func parseMountTable() ([]*Info, error) { - f, err := os.Open("/proc/self/mountinfo") - if err != nil { - return nil, err - } - defer f.Close() - - return parseInfoFile(f) -} - -func parseInfoFile(r io.Reader) ([]*Info, error) { - var ( - s = bufio.NewScanner(r) - out = []*Info{} - ) - - for s.Scan() { - if err := s.Err(); err != nil { - return nil, err - } - - var ( - p = &Info{} - text = s.Text() - optionalFields string - ) - - if _, err := fmt.Sscanf(text, mountinfoFormat, - &p.ID, &p.Parent, &p.Major, &p.Minor, - &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { - return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) - } - // Safe as mountinfo encodes mountpoints with spaces as \040. - index := strings.Index(text, " - ") - postSeparatorFields := strings.Fields(text[index+3:]) - if len(postSeparatorFields) < 3 { - return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text) - } - - if optionalFields != "-" { - p.Optional = optionalFields - } - - p.Fstype = postSeparatorFields[0] - p.Source = postSeparatorFields[1] - p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") - out = append(out, p) - } - return out, nil -} - -// PidMountInfo collects the mounts for a specific process ID. If the process -// ID is unknown, it is better to use `GetMounts` which will inspect -// "/proc/self/mountinfo" instead. -func PidMountInfo(pid int) ([]*Info, error) { - f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) - if err != nil { - return nil, err - } - defer f.Close() - - return parseInfoFile(f) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go deleted file mode 100644 index ad9ab57f8b..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build solaris,cgo - -package mount - -/* -#include -#include -*/ -import "C" - -import ( - "fmt" -) - -func parseMountTable() ([]*Info, error) { - mnttab := C.fopen(C.CString(C.MNTTAB), C.CString("r")) - if mnttab == nil { - return nil, fmt.Errorf("Failed to open %s", C.MNTTAB) - } - - var out []*Info - var mp C.struct_mnttab - - ret := C.getmntent(mnttab, &mp) - for ret == 0 { - var mountinfo Info - mountinfo.Mountpoint = C.GoString(mp.mnt_mountp) - mountinfo.Source = C.GoString(mp.mnt_special) - mountinfo.Fstype = C.GoString(mp.mnt_fstype) - mountinfo.Opts = C.GoString(mp.mnt_mntopts) - out = append(out, &mountinfo) - ret = C.getmntent(mnttab, &mp) - } - - C.fclose(mnttab) - return out, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go deleted file mode 100644 index 7fbcf19214..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo - -package mount - -import ( - "fmt" - "runtime" -) - -func parseMountTable() ([]*Info, error) { - return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go deleted file mode 100644 index dab8a37ed0..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package mount - -func parseMountTable() ([]*Info, error) { - // Do NOT return an error! - return nil, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go b/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go deleted file mode 100644 index 8ceec84bc6..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go +++ /dev/null @@ -1,69 +0,0 @@ -// +build linux - -package mount - -// MakeShared ensures a mounted filesystem has the SHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "shared") -} - -// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "rshared") -} - -// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. -// See the supported options in flags.go for further reference. -func MakePrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "private") -} - -// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeRPrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "rprivate") -} - -// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "slave") -} - -// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "rslave") -} - -// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "unbindable") -} - -// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount -// option enabled. See the supported options in flags.go for further reference. -func MakeRUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "runbindable") -} - -func ensureMountedAs(mountPoint, options string) error { - mounted, err := Mounted(mountPoint) - if err != nil { - return err - } - - if !mounted { - if err := Mount(mountPoint, mountPoint, "none", "bind,rw"); err != nil { - return err - } - } - if _, err = Mounted(mountPoint); err != nil { - return err - } - - return ForceMount("", mountPoint, "none", options) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go b/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go deleted file mode 100644 index 09f6b03cbc..0000000000 --- a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build solaris - -package mount - -// MakeShared ensures a mounted filesystem has the SHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "shared") -} - -// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "rshared") -} - -// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. -// See the supported options in flags.go for further reference. -func MakePrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "private") -} - -// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeRPrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "rprivate") -} - -// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "slave") -} - -// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "rslave") -} - -// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "unbindable") -} - -// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount -// option enabled. See the supported options in flags.go for further reference. -func MakeRUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "runbindable") -} - -func ensureMountedAs(mountPoint, options string) error { - // TODO: Solaris does not support bind mounts. - // Evaluate lofs and also look at the relevant - // mount flags to be supported. - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel.go deleted file mode 100644 index 7738fc7411..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel.go +++ /dev/null @@ -1,74 +0,0 @@ -// +build !windows - -// Package kernel provides helper function to get, parse and compare kernel -// versions for different platforms. -package kernel - -import ( - "errors" - "fmt" -) - -// VersionInfo holds information about the kernel. -type VersionInfo struct { - Kernel int // Version of the kernel (e.g. 4.1.2-generic -> 4) - Major int // Major part of the kernel version (e.g. 4.1.2-generic -> 1) - Minor int // Minor part of the kernel version (e.g. 4.1.2-generic -> 2) - Flavor string // Flavor of the kernel version (e.g. 4.1.2-generic -> generic) -} - -func (k *VersionInfo) String() string { - return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor) -} - -// CompareKernelVersion compares two kernel.VersionInfo structs. -// Returns -1 if a < b, 0 if a == b, 1 it a > b -func CompareKernelVersion(a, b VersionInfo) int { - if a.Kernel < b.Kernel { - return -1 - } else if a.Kernel > b.Kernel { - return 1 - } - - if a.Major < b.Major { - return -1 - } else if a.Major > b.Major { - return 1 - } - - if a.Minor < b.Minor { - return -1 - } else if a.Minor > b.Minor { - return 1 - } - - return 0 -} - -// ParseRelease parses a string and creates a VersionInfo based on it. -func ParseRelease(release string) (*VersionInfo, error) { - var ( - kernel, major, minor, parsed int - flavor, partial string - ) - - // Ignore error from Sscanf to allow an empty flavor. Instead, just - // make sure we got all the version numbers. - parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial) - if parsed < 2 { - return nil, errors.New("Can't parse kernel version " + release) - } - - // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64 - parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor) - if parsed < 1 { - flavor = partial - } - - return &VersionInfo{ - Kernel: kernel, - Major: major, - Minor: minor, - Flavor: flavor, - }, nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_darwin.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_darwin.go deleted file mode 100644 index 71f205b285..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_darwin.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build darwin - -// Package kernel provides helper function to get, parse and compare kernel -// versions for different platforms. -package kernel - -import ( - "fmt" - "os/exec" - "strings" - - "github.com/mattn/go-shellwords" -) - -// GetKernelVersion gets the current kernel version. -func GetKernelVersion() (*VersionInfo, error) { - release, err := getRelease() - if err != nil { - return nil, err - } - - return ParseRelease(release) -} - -// getRelease uses `system_profiler SPSoftwareDataType` to get OSX kernel version -func getRelease() (string, error) { - cmd := exec.Command("system_profiler", "SPSoftwareDataType") - osName, err := cmd.Output() - if err != nil { - return "", err - } - - var release string - data := strings.Split(string(osName), "\n") - for _, line := range data { - if strings.Contains(line, "Kernel Version") { - // It has the format like ' Kernel Version: Darwin 14.5.0' - content := strings.SplitN(line, ":", 2) - if len(content) != 2 { - return "", fmt.Errorf("Kernel Version is invalid") - } - - prettyNames, err := shellwords.Parse(content[1]) - if err != nil { - return "", fmt.Errorf("Kernel Version is invalid: %s", err.Error()) - } - - if len(prettyNames) != 2 { - return "", fmt.Errorf("Kernel Version needs to be 'Darwin x.x.x' ") - } - release = prettyNames[1] - } - } - - return release, nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go deleted file mode 100644 index 76e1e499f3..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build linux freebsd solaris openbsd - -// Package kernel provides helper function to get, parse and compare kernel -// versions for different platforms. -package kernel - -import ( - "bytes" - - "github.com/sirupsen/logrus" -) - -// GetKernelVersion gets the current kernel version. -func GetKernelVersion() (*VersionInfo, error) { - uts, err := uname() - if err != nil { - return nil, err - } - - release := make([]byte, len(uts.Release)) - - i := 0 - for _, c := range uts.Release { - release[i] = byte(c) - i++ - } - - // Remove the \x00 from the release for Atoi to parse correctly - release = release[:bytes.IndexByte(release, 0)] - - return ParseRelease(string(release)) -} - -// CheckKernelVersion checks if current kernel is newer than (or equal to) -// the given version. -func CheckKernelVersion(k, major, minor int) bool { - if v, err := GetKernelVersion(); err != nil { - logrus.Warnf("error getting kernel version: %s", err) - } else { - if CompareKernelVersion(*v, VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 { - return false - } - } - return true -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_windows.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_windows.go deleted file mode 100644 index e598672776..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_windows.go +++ /dev/null @@ -1,70 +0,0 @@ -// +build windows - -package kernel - -import ( - "fmt" - "unsafe" - - "golang.org/x/sys/windows" -) - -// VersionInfo holds information about the kernel. -type VersionInfo struct { - kvi string // Version of the kernel (e.g. 6.1.7601.17592 -> 6) - major int // Major part of the kernel version (e.g. 6.1.7601.17592 -> 1) - minor int // Minor part of the kernel version (e.g. 6.1.7601.17592 -> 7601) - build int // Build number of the kernel version (e.g. 6.1.7601.17592 -> 17592) -} - -func (k *VersionInfo) String() string { - return fmt.Sprintf("%d.%d %d (%s)", k.major, k.minor, k.build, k.kvi) -} - -// GetKernelVersion gets the current kernel version. -func GetKernelVersion() (*VersionInfo, error) { - - var ( - h windows.Handle - dwVersion uint32 - err error - ) - - KVI := &VersionInfo{"Unknown", 0, 0, 0} - - if err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, - windows.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), - 0, - windows.KEY_READ, - &h); err != nil { - return KVI, err - } - defer windows.RegCloseKey(h) - - var buf [1 << 10]uint16 - var typ uint32 - n := uint32(len(buf) * 2) // api expects array of bytes, not uint16 - - if err = windows.RegQueryValueEx(h, - windows.StringToUTF16Ptr("BuildLabEx"), - nil, - &typ, - (*byte)(unsafe.Pointer(&buf[0])), - &n); err != nil { - return KVI, err - } - - KVI.kvi = windows.UTF16ToString(buf[:]) - - // Important - docker.exe MUST be manifested for this API to return - // the correct information. - if dwVersion, err = windows.GetVersion(); err != nil { - return KVI, err - } - - KVI.major = int(dwVersion & 0xFF) - KVI.minor = int((dwVersion & 0XFF00) >> 8) - KVI.build = int((dwVersion & 0xFFFF0000) >> 16) - - return KVI, nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_linux.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_linux.go deleted file mode 100644 index e913fad001..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_linux.go +++ /dev/null @@ -1,17 +0,0 @@ -package kernel - -import "golang.org/x/sys/unix" - -// Utsname represents the system name structure. -// It is passthrough for unix.Utsname in order to make it portable with -// other platforms where it is not available. -type Utsname unix.Utsname - -func uname() (*unix.Utsname, error) { - uts := &unix.Utsname{} - - if err := unix.Uname(uts); err != nil { - return nil, err - } - return uts, nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_solaris.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_solaris.go deleted file mode 100644 index 49370bd3dd..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_solaris.go +++ /dev/null @@ -1,14 +0,0 @@ -package kernel - -import ( - "golang.org/x/sys/unix" -) - -func uname() (*unix.Utsname, error) { - uts := &unix.Utsname{} - - if err := unix.Uname(uts); err != nil { - return nil, err - } - return uts, nil -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_unsupported.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_unsupported.go deleted file mode 100644 index 1da3f239fa..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/kernel/uname_unsupported.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !linux,!solaris - -package kernel - -import ( - "errors" -) - -// Utsname represents the system name structure. -// It is defined here to make it portable as it is available on linux but not -// on windows. -type Utsname struct { - Release [65]byte -} - -func uname() (*Utsname, error) { - return nil, errors.New("Kernel version detection is available only on linux") -} diff --git a/vendor/github.com/containers/storage/pkg/parsers/parsers.go b/vendor/github.com/containers/storage/pkg/parsers/parsers.go deleted file mode 100644 index acc897168f..0000000000 --- a/vendor/github.com/containers/storage/pkg/parsers/parsers.go +++ /dev/null @@ -1,69 +0,0 @@ -// Package parsers provides helper functions to parse and validate different type -// of string. It can be hosts, unix addresses, tcp addresses, filters, kernel -// operating system versions. -package parsers - -import ( - "fmt" - "strconv" - "strings" -) - -// ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value) -func ParseKeyValueOpt(opt string) (string, string, error) { - parts := strings.SplitN(opt, "=", 2) - if len(parts) != 2 { - return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt) - } - return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil -} - -// ParseUintList parses and validates the specified string as the value -// found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be -// one of the formats below. Note that duplicates are actually allowed in the -// input string. It returns a `map[int]bool` with available elements from `val` -// set to `true`. -// Supported formats: -// 7 -// 1-6 -// 0,3-4,7,8-10 -// 0-0,0,1-7 -// 03,1-3 <- this is gonna get parsed as [1,2,3] -// 3,2,1 -// 0-2,3,1 -func ParseUintList(val string) (map[int]bool, error) { - if val == "" { - return map[int]bool{}, nil - } - - availableInts := make(map[int]bool) - split := strings.Split(val, ",") - errInvalidFormat := fmt.Errorf("invalid format: %s", val) - - for _, r := range split { - if !strings.Contains(r, "-") { - v, err := strconv.Atoi(r) - if err != nil { - return nil, errInvalidFormat - } - availableInts[v] = true - } else { - split := strings.SplitN(r, "-", 2) - min, err := strconv.Atoi(split[0]) - if err != nil { - return nil, errInvalidFormat - } - max, err := strconv.Atoi(split[1]) - if err != nil { - return nil, errInvalidFormat - } - if max < min { - return nil, errInvalidFormat - } - for i := min; i <= max; i++ { - availableInts[i] = true - } - } - } - return availableInts, nil -} diff --git a/vendor/github.com/containers/storage/pkg/pools/pools.go b/vendor/github.com/containers/storage/pkg/pools/pools.go deleted file mode 100644 index a15e3688b9..0000000000 --- a/vendor/github.com/containers/storage/pkg/pools/pools.go +++ /dev/null @@ -1,119 +0,0 @@ -// Package pools provides a collection of pools which provide various -// data types with buffers. These can be used to lower the number of -// memory allocations and reuse buffers. -// -// New pools should be added to this package to allow them to be -// shared across packages. -// -// Utility functions which operate on pools should be added to this -// package to allow them to be reused. -package pools - -import ( - "bufio" - "io" - "sync" - - "github.com/containers/storage/pkg/ioutils" -) - -var ( - // BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer. - BufioReader32KPool *BufioReaderPool - // BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer. - BufioWriter32KPool *BufioWriterPool -) - -const buffer32K = 32 * 1024 - -// BufioReaderPool is a bufio reader that uses sync.Pool. -type BufioReaderPool struct { - pool *sync.Pool -} - -func init() { - BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K) - BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K) -} - -// newBufioReaderPoolWithSize is unexported because new pools should be -// added here to be shared where required. -func newBufioReaderPoolWithSize(size int) *BufioReaderPool { - pool := &sync.Pool{ - New: func() interface{} { return bufio.NewReaderSize(nil, size) }, - } - return &BufioReaderPool{pool: pool} -} - -// Get returns a bufio.Reader which reads from r. The buffer size is that of the pool. -func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader { - buf := bufPool.pool.Get().(*bufio.Reader) - buf.Reset(r) - return buf -} - -// Put puts the bufio.Reader back into the pool. -func (bufPool *BufioReaderPool) Put(b *bufio.Reader) { - b.Reset(nil) - bufPool.pool.Put(b) -} - -// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy. -func Copy(dst io.Writer, src io.Reader) (written int64, err error) { - buf := BufioReader32KPool.Get(src) - written, err = io.Copy(dst, buf) - BufioReader32KPool.Put(buf) - return -} - -// NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back -// into the pool and closes the reader if it's an io.ReadCloser. -func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { - return ioutils.NewReadCloserWrapper(r, func() error { - if readCloser, ok := r.(io.ReadCloser); ok { - readCloser.Close() - } - bufPool.Put(buf) - return nil - }) -} - -// BufioWriterPool is a bufio writer that uses sync.Pool. -type BufioWriterPool struct { - pool *sync.Pool -} - -// newBufioWriterPoolWithSize is unexported because new pools should be -// added here to be shared where required. -func newBufioWriterPoolWithSize(size int) *BufioWriterPool { - pool := &sync.Pool{ - New: func() interface{} { return bufio.NewWriterSize(nil, size) }, - } - return &BufioWriterPool{pool: pool} -} - -// Get returns a bufio.Writer which writes to w. The buffer size is that of the pool. -func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer { - buf := bufPool.pool.Get().(*bufio.Writer) - buf.Reset(w) - return buf -} - -// Put puts the bufio.Writer back into the pool. -func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { - b.Reset(nil) - bufPool.pool.Put(b) -} - -// NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back -// into the pool and closes the writer if it's an io.Writecloser. -func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser { - return ioutils.NewWriteCloserWrapper(w, func() error { - buf.Flush() - if writeCloser, ok := w.(io.WriteCloser); ok { - writeCloser.Close() - } - bufPool.Put(buf) - return nil - }) -} diff --git a/vendor/github.com/containers/storage/pkg/promise/promise.go b/vendor/github.com/containers/storage/pkg/promise/promise.go deleted file mode 100644 index dd52b9082f..0000000000 --- a/vendor/github.com/containers/storage/pkg/promise/promise.go +++ /dev/null @@ -1,11 +0,0 @@ -package promise - -// Go is a basic promise implementation: it wraps calls a function in a goroutine, -// and returns a channel which will later return the function's return value. -func Go(f func() error) chan error { - ch := make(chan error, 1) - go func() { - ch <- f() - }() - return ch -} diff --git a/vendor/github.com/containers/storage/pkg/reexec/command_linux.go b/vendor/github.com/containers/storage/pkg/reexec/command_linux.go deleted file mode 100644 index 05319eacc9..0000000000 --- a/vendor/github.com/containers/storage/pkg/reexec/command_linux.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build linux - -package reexec - -import ( - "os/exec" - "syscall" - - "golang.org/x/sys/unix" -) - -// Self returns the path to the current process's binary. -// Returns "/proc/self/exe". -func Self() string { - return "/proc/self/exe" -} - -// Command returns *exec.Cmd which has Path as current binary. Also it setting -// SysProcAttr.Pdeathsig to SIGTERM. -// This will use the in-memory version (/proc/self/exe) of the current binary, -// it is thus safe to delete or replace the on-disk binary (os.Args[0]). -func Command(args ...string) *exec.Cmd { - return &exec.Cmd{ - Path: Self(), - Args: args, - SysProcAttr: &syscall.SysProcAttr{ - Pdeathsig: unix.SIGTERM, - }, - } -} diff --git a/vendor/github.com/containers/storage/pkg/reexec/command_unix.go b/vendor/github.com/containers/storage/pkg/reexec/command_unix.go deleted file mode 100644 index 778a720e3b..0000000000 --- a/vendor/github.com/containers/storage/pkg/reexec/command_unix.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build freebsd solaris darwin - -package reexec - -import ( - "os/exec" -) - -// Self returns the path to the current process's binary. -// Uses os.Args[0]. -func Self() string { - return naiveSelf() -} - -// Command returns *exec.Cmd which has Path as current binary. -// For example if current binary is "docker" at "/usr/bin/", then cmd.Path will -// be set to "/usr/bin/docker". -func Command(args ...string) *exec.Cmd { - return &exec.Cmd{ - Path: Self(), - Args: args, - } -} diff --git a/vendor/github.com/containers/storage/pkg/reexec/command_unsupported.go b/vendor/github.com/containers/storage/pkg/reexec/command_unsupported.go deleted file mode 100644 index 76edd82427..0000000000 --- a/vendor/github.com/containers/storage/pkg/reexec/command_unsupported.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !linux,!windows,!freebsd,!solaris,!darwin - -package reexec - -import ( - "os/exec" -) - -// Command is unsupported on operating systems apart from Linux, Windows, Solaris and Darwin. -func Command(args ...string) *exec.Cmd { - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/reexec/command_windows.go b/vendor/github.com/containers/storage/pkg/reexec/command_windows.go deleted file mode 100644 index ca871c4227..0000000000 --- a/vendor/github.com/containers/storage/pkg/reexec/command_windows.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build windows - -package reexec - -import ( - "os/exec" -) - -// Self returns the path to the current process's binary. -// Uses os.Args[0]. -func Self() string { - return naiveSelf() -} - -// Command returns *exec.Cmd which has Path as current binary. -// For example if current binary is "docker.exe" at "C:\", then cmd.Path will -// be set to "C:\docker.exe". -func Command(args ...string) *exec.Cmd { - return &exec.Cmd{ - Path: Self(), - Args: args, - } -} diff --git a/vendor/github.com/containers/storage/pkg/reexec/reexec.go b/vendor/github.com/containers/storage/pkg/reexec/reexec.go deleted file mode 100644 index c56671d919..0000000000 --- a/vendor/github.com/containers/storage/pkg/reexec/reexec.go +++ /dev/null @@ -1,47 +0,0 @@ -package reexec - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -var registeredInitializers = make(map[string]func()) - -// Register adds an initialization func under the specified name -func Register(name string, initializer func()) { - if _, exists := registeredInitializers[name]; exists { - panic(fmt.Sprintf("reexec func already registered under name %q", name)) - } - - registeredInitializers[name] = initializer -} - -// Init is called as the first part of the exec process and returns true if an -// initialization function was called. -func Init() bool { - initializer, exists := registeredInitializers[os.Args[0]] - if exists { - initializer() - - return true - } - return false -} - -func naiveSelf() string { - name := os.Args[0] - if filepath.Base(name) == name { - if lp, err := exec.LookPath(name); err == nil { - return lp - } - } - // handle conversion of relative paths to absolute - if absName, err := filepath.Abs(name); err == nil { - return absName - } - // if we couldn't get absolute name, return original - // (NOTE: Go only errors on Abs() if os.Getwd fails) - return name -} diff --git a/vendor/github.com/containers/storage/pkg/stringid/stringid.go b/vendor/github.com/containers/storage/pkg/stringid/stringid.go deleted file mode 100644 index a0c7c42a05..0000000000 --- a/vendor/github.com/containers/storage/pkg/stringid/stringid.go +++ /dev/null @@ -1,99 +0,0 @@ -// Package stringid provides helper functions for dealing with string identifiers -package stringid - -import ( - cryptorand "crypto/rand" - "encoding/hex" - "fmt" - "io" - "math" - "math/big" - "math/rand" - "regexp" - "strconv" - "strings" - "time" -) - -const shortLen = 12 - -var ( - validShortID = regexp.MustCompile("^[a-f0-9]{12}$") - validHex = regexp.MustCompile(`^[a-f0-9]{64}$`) -) - -// IsShortID determines if an arbitrary string *looks like* a short ID. -func IsShortID(id string) bool { - return validShortID.MatchString(id) -} - -// TruncateID returns a shorthand version of a string identifier for convenience. -// A collision with other shorthands is very unlikely, but possible. -// In case of a collision a lookup with TruncIndex.Get() will fail, and the caller -// will need to use a longer prefix, or the full-length Id. -func TruncateID(id string) string { - if i := strings.IndexRune(id, ':'); i >= 0 { - id = id[i+1:] - } - if len(id) > shortLen { - id = id[:shortLen] - } - return id -} - -func generateID(r io.Reader) string { - b := make([]byte, 32) - for { - if _, err := io.ReadFull(r, b); err != nil { - panic(err) // This shouldn't happen - } - id := hex.EncodeToString(b) - // if we try to parse the truncated for as an int and we don't have - // an error then the value is all numeric and causes issues when - // used as a hostname. ref #3869 - if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil { - continue - } - return id - } -} - -// GenerateRandomID returns a unique id. -func GenerateRandomID() string { - return generateID(cryptorand.Reader) -} - -// GenerateNonCryptoID generates unique id without using cryptographically -// secure sources of random. -// It helps you to save entropy. -func GenerateNonCryptoID() string { - return generateID(readerFunc(rand.Read)) -} - -// ValidateID checks whether an ID string is a valid image ID. -func ValidateID(id string) error { - if ok := validHex.MatchString(id); !ok { - return fmt.Errorf("image ID %q is invalid", id) - } - return nil -} - -func init() { - // safely set the seed globally so we generate random ids. Tries to use a - // crypto seed before falling back to time. - var seed int64 - if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil { - // This should not happen, but worst-case fallback to time-based seed. - seed = time.Now().UnixNano() - } else { - seed = cryptoseed.Int64() - } - - rand.Seed(seed) -} - -type readerFunc func(p []byte) (int, error) - -func (fn readerFunc) Read(p []byte) (int, error) { - return fn(p) -} diff --git a/vendor/github.com/containers/storage/pkg/system/chtimes.go b/vendor/github.com/containers/storage/pkg/system/chtimes.go deleted file mode 100644 index 056d19954d..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/chtimes.go +++ /dev/null @@ -1,35 +0,0 @@ -package system - -import ( - "os" - "time" -) - -// Chtimes changes the access time and modified time of a file at the given path -func Chtimes(name string, atime time.Time, mtime time.Time) error { - unixMinTime := time.Unix(0, 0) - unixMaxTime := maxTime - - // If the modified time is prior to the Unix Epoch, or after the - // end of Unix Time, os.Chtimes has undefined behavior - // default to Unix Epoch in this case, just in case - - if atime.Before(unixMinTime) || atime.After(unixMaxTime) { - atime = unixMinTime - } - - if mtime.Before(unixMinTime) || mtime.After(unixMaxTime) { - mtime = unixMinTime - } - - if err := os.Chtimes(name, atime, mtime); err != nil { - return err - } - - // Take platform specific action for setting create time. - if err := setCTime(name, mtime); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/chtimes_unix.go b/vendor/github.com/containers/storage/pkg/system/chtimes_unix.go deleted file mode 100644 index 09d58bcbfd..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/chtimes_unix.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build !windows - -package system - -import ( - "time" -) - -//setCTime will set the create time on a file. On Unix, the create -//time is updated as a side effect of setting the modified time, so -//no action is required. -func setCTime(path string, ctime time.Time) error { - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/chtimes_windows.go b/vendor/github.com/containers/storage/pkg/system/chtimes_windows.go deleted file mode 100644 index 45428c141c..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/chtimes_windows.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build windows - -package system - -import ( - "time" - - "golang.org/x/sys/windows" -) - -//setCTime will set the create time on a file. On Windows, this requires -//calling SetFileTime and explicitly including the create time. -func setCTime(path string, ctime time.Time) error { - ctimespec := windows.NsecToTimespec(ctime.UnixNano()) - pathp, e := windows.UTF16PtrFromString(path) - if e != nil { - return e - } - h, e := windows.CreateFile(pathp, - windows.FILE_WRITE_ATTRIBUTES, windows.FILE_SHARE_WRITE, nil, - windows.OPEN_EXISTING, windows.FILE_FLAG_BACKUP_SEMANTICS, 0) - if e != nil { - return e - } - defer windows.Close(h) - c := windows.NsecToFiletime(windows.TimespecToNsec(ctimespec)) - return windows.SetFileTime(h, &c, nil, nil) -} diff --git a/vendor/github.com/containers/storage/pkg/system/errors.go b/vendor/github.com/containers/storage/pkg/system/errors.go deleted file mode 100644 index 288318985e..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package system - -import ( - "errors" -) - -var ( - // ErrNotSupportedPlatform means the platform is not supported. - ErrNotSupportedPlatform = errors.New("platform and architecture is not supported") -) diff --git a/vendor/github.com/containers/storage/pkg/system/exitcode.go b/vendor/github.com/containers/storage/pkg/system/exitcode.go deleted file mode 100644 index 60f0514b1d..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/exitcode.go +++ /dev/null @@ -1,33 +0,0 @@ -package system - -import ( - "fmt" - "os/exec" - "syscall" -) - -// GetExitCode returns the ExitStatus of the specified error if its type is -// exec.ExitError, returns 0 and an error otherwise. -func GetExitCode(err error) (int, error) { - exitCode := 0 - if exiterr, ok := err.(*exec.ExitError); ok { - if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok { - return procExit.ExitStatus(), nil - } - } - return exitCode, fmt.Errorf("failed to get exit code") -} - -// ProcessExitCode process the specified error and returns the exit status code -// if the error was of type exec.ExitError, returns nothing otherwise. -func ProcessExitCode(err error) (exitCode int) { - if err != nil { - var exiterr error - if exitCode, exiterr = GetExitCode(err); exiterr != nil { - // TODO: Fix this so we check the error's text. - // we've failed to retrieve exit code, so we set it to 127 - exitCode = 127 - } - } - return -} diff --git a/vendor/github.com/containers/storage/pkg/system/filesys.go b/vendor/github.com/containers/storage/pkg/system/filesys.go deleted file mode 100644 index 102565f760..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/filesys.go +++ /dev/null @@ -1,67 +0,0 @@ -// +build !windows - -package system - -import ( - "io/ioutil" - "os" - "path/filepath" -) - -// MkdirAllWithACL is a wrapper for MkdirAll on unix systems. -func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error { - return MkdirAll(path, perm, sddl) -} - -// MkdirAll creates a directory named path along with any necessary parents, -// with permission specified by attribute perm for all dir created. -func MkdirAll(path string, perm os.FileMode, sddl string) error { - return os.MkdirAll(path, perm) -} - -// IsAbs is a platform-specific wrapper for filepath.IsAbs. -func IsAbs(path string) bool { - return filepath.IsAbs(path) -} - -// The functions below here are wrappers for the equivalents in the os and ioutils packages. -// They are passthrough on Unix platforms, and only relevant on Windows. - -// CreateSequential creates the named file with mode 0666 (before umask), truncating -// it if it already exists. If successful, methods on the returned -// File can be used for I/O; the associated file descriptor has mode -// O_RDWR. -// If there is an error, it will be of type *PathError. -func CreateSequential(name string) (*os.File, error) { - return os.Create(name) -} - -// OpenSequential opens the named file for reading. If successful, methods on -// the returned file can be used for reading; the associated file -// descriptor has mode O_RDONLY. -// If there is an error, it will be of type *PathError. -func OpenSequential(name string) (*os.File, error) { - return os.Open(name) -} - -// OpenFileSequential is the generalized open call; most users will use Open -// or Create instead. It opens the named file with specified flag -// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, -// methods on the returned File can be used for I/O. -// If there is an error, it will be of type *PathError. -func OpenFileSequential(name string, flag int, perm os.FileMode) (*os.File, error) { - return os.OpenFile(name, flag, perm) -} - -// TempFileSequential creates a new temporary file in the directory dir -// with a name beginning with prefix, opens the file for reading -// and writing, and returns the resulting *os.File. -// If dir is the empty string, TempFile uses the default directory -// for temporary files (see os.TempDir). -// Multiple programs calling TempFile simultaneously -// will not choose the same file. The caller can use f.Name() -// to find the pathname of the file. It is the caller's responsibility -// to remove the file when no longer needed. -func TempFileSequential(dir, prefix string) (f *os.File, err error) { - return ioutil.TempFile(dir, prefix) -} diff --git a/vendor/github.com/containers/storage/pkg/system/filesys_windows.go b/vendor/github.com/containers/storage/pkg/system/filesys_windows.go deleted file mode 100644 index a61b53d0ba..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/filesys_windows.go +++ /dev/null @@ -1,298 +0,0 @@ -// +build windows - -package system - -import ( - "os" - "path/filepath" - "regexp" - "strconv" - "strings" - "sync" - "syscall" - "time" - "unsafe" - - winio "github.com/Microsoft/go-winio" - "golang.org/x/sys/windows" -) - -const ( - // SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System - SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)" - // SddlNtvmAdministratorsLocalSystem is NT VIRTUAL MACHINE\Virtual Machines plus local administrators plus NT AUTHORITY\System - SddlNtvmAdministratorsLocalSystem = "D:P(A;OICI;GA;;;S-1-5-83-0)(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)" -) - -// MkdirAllWithACL is a wrapper for MkdirAll that creates a directory -// with an appropriate SDDL defined ACL. -func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error { - return mkdirall(path, true, sddl) -} - -// MkdirAll implementation that is volume path aware for Windows. -func MkdirAll(path string, _ os.FileMode, sddl string) error { - return mkdirall(path, false, sddl) -} - -// mkdirall is a custom version of os.MkdirAll modified for use on Windows -// so that it is both volume path aware, and can create a directory with -// a DACL. -func mkdirall(path string, applyACL bool, sddl string) error { - if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) { - return nil - } - - // The rest of this method is largely copied from os.MkdirAll and should be kept - // as-is to ensure compatibility. - - // Fast path: if we can tell whether path is a directory or file, stop with success or error. - dir, err := os.Stat(path) - if err == nil { - if dir.IsDir() { - return nil - } - return &os.PathError{ - Op: "mkdir", - Path: path, - Err: syscall.ENOTDIR, - } - } - - // Slow path: make sure parent exists and then call Mkdir for path. - i := len(path) - for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. - i-- - } - - j := i - for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. - j-- - } - - if j > 1 { - // Create parent - err = mkdirall(path[0:j-1], false, sddl) - if err != nil { - return err - } - } - - // Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result. - if applyACL { - err = mkdirWithACL(path, sddl) - } else { - err = os.Mkdir(path, 0) - } - - if err != nil { - // Handle arguments like "foo/." by - // double-checking that directory doesn't exist. - dir, err1 := os.Lstat(path) - if err1 == nil && dir.IsDir() { - return nil - } - return err - } - return nil -} - -// mkdirWithACL creates a new directory. If there is an error, it will be of -// type *PathError. . -// -// This is a modified and combined version of os.Mkdir and windows.Mkdir -// in golang to cater for creating a directory am ACL permitting full -// access, with inheritance, to any subfolder/file for Built-in Administrators -// and Local System. -func mkdirWithACL(name string, sddl string) error { - sa := windows.SecurityAttributes{Length: 0} - sd, err := winio.SddlToSecurityDescriptor(sddl) - if err != nil { - return &os.PathError{Op: "mkdir", Path: name, Err: err} - } - sa.Length = uint32(unsafe.Sizeof(sa)) - sa.InheritHandle = 1 - sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) - - namep, err := windows.UTF16PtrFromString(name) - if err != nil { - return &os.PathError{Op: "mkdir", Path: name, Err: err} - } - - e := windows.CreateDirectory(namep, &sa) - if e != nil { - return &os.PathError{Op: "mkdir", Path: name, Err: e} - } - return nil -} - -// IsAbs is a platform-specific wrapper for filepath.IsAbs. On Windows, -// golang filepath.IsAbs does not consider a path \windows\system32 as absolute -// as it doesn't start with a drive-letter/colon combination. However, in -// docker we need to verify things such as WORKDIR /windows/system32 in -// a Dockerfile (which gets translated to \windows\system32 when being processed -// by the daemon. This SHOULD be treated as absolute from a docker processing -// perspective. -func IsAbs(path string) bool { - if !filepath.IsAbs(path) { - if !strings.HasPrefix(path, string(os.PathSeparator)) { - return false - } - } - return true -} - -// The origin of the functions below here are the golang OS and windows packages, -// slightly modified to only cope with files, not directories due to the -// specific use case. -// -// The alteration is to allow a file on Windows to be opened with -// FILE_FLAG_SEQUENTIAL_SCAN (particular for docker load), to avoid eating -// the standby list, particularly when accessing large files such as layer.tar. - -// CreateSequential creates the named file with mode 0666 (before umask), truncating -// it if it already exists. If successful, methods on the returned -// File can be used for I/O; the associated file descriptor has mode -// O_RDWR. -// If there is an error, it will be of type *PathError. -func CreateSequential(name string) (*os.File, error) { - return OpenFileSequential(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0) -} - -// OpenSequential opens the named file for reading. If successful, methods on -// the returned file can be used for reading; the associated file -// descriptor has mode O_RDONLY. -// If there is an error, it will be of type *PathError. -func OpenSequential(name string) (*os.File, error) { - return OpenFileSequential(name, os.O_RDONLY, 0) -} - -// OpenFileSequential is the generalized open call; most users will use Open -// or Create instead. -// If there is an error, it will be of type *PathError. -func OpenFileSequential(name string, flag int, _ os.FileMode) (*os.File, error) { - if name == "" { - return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT} - } - r, errf := windowsOpenFileSequential(name, flag, 0) - if errf == nil { - return r, nil - } - return nil, &os.PathError{Op: "open", Path: name, Err: errf} -} - -func windowsOpenFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) { - r, e := windowsOpenSequential(name, flag|windows.O_CLOEXEC, 0) - if e != nil { - return nil, e - } - return os.NewFile(uintptr(r), name), nil -} - -func makeInheritSa() *windows.SecurityAttributes { - var sa windows.SecurityAttributes - sa.Length = uint32(unsafe.Sizeof(sa)) - sa.InheritHandle = 1 - return &sa -} - -func windowsOpenSequential(path string, mode int, _ uint32) (fd windows.Handle, err error) { - if len(path) == 0 { - return windows.InvalidHandle, windows.ERROR_FILE_NOT_FOUND - } - pathp, err := windows.UTF16PtrFromString(path) - if err != nil { - return windows.InvalidHandle, err - } - var access uint32 - switch mode & (windows.O_RDONLY | windows.O_WRONLY | windows.O_RDWR) { - case windows.O_RDONLY: - access = windows.GENERIC_READ - case windows.O_WRONLY: - access = windows.GENERIC_WRITE - case windows.O_RDWR: - access = windows.GENERIC_READ | windows.GENERIC_WRITE - } - if mode&windows.O_CREAT != 0 { - access |= windows.GENERIC_WRITE - } - if mode&windows.O_APPEND != 0 { - access &^= windows.GENERIC_WRITE - access |= windows.FILE_APPEND_DATA - } - sharemode := uint32(windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE) - var sa *windows.SecurityAttributes - if mode&windows.O_CLOEXEC == 0 { - sa = makeInheritSa() - } - var createmode uint32 - switch { - case mode&(windows.O_CREAT|windows.O_EXCL) == (windows.O_CREAT | windows.O_EXCL): - createmode = windows.CREATE_NEW - case mode&(windows.O_CREAT|windows.O_TRUNC) == (windows.O_CREAT | windows.O_TRUNC): - createmode = windows.CREATE_ALWAYS - case mode&windows.O_CREAT == windows.O_CREAT: - createmode = windows.OPEN_ALWAYS - case mode&windows.O_TRUNC == windows.O_TRUNC: - createmode = windows.TRUNCATE_EXISTING - default: - createmode = windows.OPEN_EXISTING - } - // Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang. - //https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx - const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN - h, e := windows.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0) - return h, e -} - -// Helpers for TempFileSequential -var rand uint32 -var randmu sync.Mutex - -func reseed() uint32 { - return uint32(time.Now().UnixNano() + int64(os.Getpid())) -} -func nextSuffix() string { - randmu.Lock() - r := rand - if r == 0 { - r = reseed() - } - r = r*1664525 + 1013904223 // constants from Numerical Recipes - rand = r - randmu.Unlock() - return strconv.Itoa(int(1e9 + r%1e9))[1:] -} - -// TempFileSequential is a copy of ioutil.TempFile, modified to use sequential -// file access. Below is the original comment from golang: -// TempFile creates a new temporary file in the directory dir -// with a name beginning with prefix, opens the file for reading -// and writing, and returns the resulting *os.File. -// If dir is the empty string, TempFile uses the default directory -// for temporary files (see os.TempDir). -// Multiple programs calling TempFile simultaneously -// will not choose the same file. The caller can use f.Name() -// to find the pathname of the file. It is the caller's responsibility -// to remove the file when no longer needed. -func TempFileSequential(dir, prefix string) (f *os.File, err error) { - if dir == "" { - dir = os.TempDir() - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+nextSuffix()) - f, err = OpenFileSequential(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if os.IsExist(err) { - if nconflict++; nconflict > 10 { - randmu.Lock() - rand = reseed() - randmu.Unlock() - } - continue - } - break - } - return -} diff --git a/vendor/github.com/containers/storage/pkg/system/init.go b/vendor/github.com/containers/storage/pkg/system/init.go deleted file mode 100644 index 17935088de..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/init.go +++ /dev/null @@ -1,22 +0,0 @@ -package system - -import ( - "syscall" - "time" - "unsafe" -) - -// Used by chtimes -var maxTime time.Time - -func init() { - // chtimes initialization - if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 { - // This is a 64 bit timespec - // os.Chtimes limits time to the following - maxTime = time.Unix(0, 1<<63-1) - } else { - // This is a 32 bit timespec - maxTime = time.Unix(1<<31-1, 0) - } -} diff --git a/vendor/github.com/containers/storage/pkg/system/init_windows.go b/vendor/github.com/containers/storage/pkg/system/init_windows.go deleted file mode 100644 index 019c66441c..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/init_windows.go +++ /dev/null @@ -1,17 +0,0 @@ -package system - -import "os" - -// LCOWSupported determines if Linux Containers on Windows are supported. -// Note: This feature is in development (06/17) and enabled through an -// environment variable. At a future time, it will be enabled based -// on build number. @jhowardmsft -var lcowSupported = false - -func init() { - // LCOW initialization - if os.Getenv("LCOW_SUPPORTED") != "" { - lcowSupported = true - } - -} diff --git a/vendor/github.com/containers/storage/pkg/system/lcow_unix.go b/vendor/github.com/containers/storage/pkg/system/lcow_unix.go deleted file mode 100644 index cff33bb408..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/lcow_unix.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !windows - -package system - -// LCOWSupported returns true if Linux containers on Windows are supported. -func LCOWSupported() bool { - return false -} diff --git a/vendor/github.com/containers/storage/pkg/system/lcow_windows.go b/vendor/github.com/containers/storage/pkg/system/lcow_windows.go deleted file mode 100644 index e54d01e696..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/lcow_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package system - -// LCOWSupported returns true if Linux containers on Windows are supported. -func LCOWSupported() bool { - return lcowSupported -} diff --git a/vendor/github.com/containers/storage/pkg/system/lstat_unix.go b/vendor/github.com/containers/storage/pkg/system/lstat_unix.go deleted file mode 100644 index bd23c4d50b..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/lstat_unix.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package system - -import ( - "syscall" -) - -// Lstat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Lstat(path string) (*StatT, error) { - s := &syscall.Stat_t{} - if err := syscall.Lstat(path, s); err != nil { - return nil, err - } - return fromStatT(s) -} diff --git a/vendor/github.com/containers/storage/pkg/system/lstat_windows.go b/vendor/github.com/containers/storage/pkg/system/lstat_windows.go deleted file mode 100644 index e51df0dafe..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/lstat_windows.go +++ /dev/null @@ -1,14 +0,0 @@ -package system - -import "os" - -// Lstat calls os.Lstat to get a fileinfo interface back. -// This is then copied into our own locally defined structure. -func Lstat(path string) (*StatT, error) { - fi, err := os.Lstat(path) - if err != nil { - return nil, err - } - - return fromStatT(&fi) -} diff --git a/vendor/github.com/containers/storage/pkg/system/meminfo.go b/vendor/github.com/containers/storage/pkg/system/meminfo.go deleted file mode 100644 index 3b6e947e67..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/meminfo.go +++ /dev/null @@ -1,17 +0,0 @@ -package system - -// MemInfo contains memory statistics of the host system. -type MemInfo struct { - // Total usable RAM (i.e. physical RAM minus a few reserved bits and the - // kernel binary code). - MemTotal int64 - - // Amount of free memory. - MemFree int64 - - // Total amount of swap space available. - SwapTotal int64 - - // Amount of swap space that is currently unused. - SwapFree int64 -} diff --git a/vendor/github.com/containers/storage/pkg/system/meminfo_linux.go b/vendor/github.com/containers/storage/pkg/system/meminfo_linux.go deleted file mode 100644 index 385f1d5e73..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/meminfo_linux.go +++ /dev/null @@ -1,65 +0,0 @@ -package system - -import ( - "bufio" - "io" - "os" - "strconv" - "strings" - - "github.com/docker/go-units" -) - -// ReadMemInfo retrieves memory statistics of the host system and returns a -// MemInfo type. -func ReadMemInfo() (*MemInfo, error) { - file, err := os.Open("/proc/meminfo") - if err != nil { - return nil, err - } - defer file.Close() - return parseMemInfo(file) -} - -// parseMemInfo parses the /proc/meminfo file into -// a MemInfo object given an io.Reader to the file. -// Throws error if there are problems reading from the file -func parseMemInfo(reader io.Reader) (*MemInfo, error) { - meminfo := &MemInfo{} - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - // Expected format: ["MemTotal:", "1234", "kB"] - parts := strings.Fields(scanner.Text()) - - // Sanity checks: Skip malformed entries. - if len(parts) < 3 || parts[2] != "kB" { - continue - } - - // Convert to bytes. - size, err := strconv.Atoi(parts[1]) - if err != nil { - continue - } - bytes := int64(size) * units.KiB - - switch parts[0] { - case "MemTotal:": - meminfo.MemTotal = bytes - case "MemFree:": - meminfo.MemFree = bytes - case "SwapTotal:": - meminfo.SwapTotal = bytes - case "SwapFree:": - meminfo.SwapFree = bytes - } - - } - - // Handle errors that may have occurred during the reading of the file. - if err := scanner.Err(); err != nil { - return nil, err - } - - return meminfo, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/meminfo_solaris.go b/vendor/github.com/containers/storage/pkg/system/meminfo_solaris.go deleted file mode 100644 index 925776e789..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/meminfo_solaris.go +++ /dev/null @@ -1,129 +0,0 @@ -// +build solaris,cgo - -package system - -import ( - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -std=c99 -// #cgo LDFLAGS: -lkstat -// #include -// #include -// #include -// #include -// #include -// #include -// struct swaptable *allocSwaptable(int num) { -// struct swaptable *st; -// struct swapent *swapent; -// st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int)); -// swapent = st->swt_ent; -// for (int i = 0; i < num; i++,swapent++) { -// swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char)); -// } -// st->swt_n = num; -// return st; -//} -// void freeSwaptable (struct swaptable *st) { -// struct swapent *swapent = st->swt_ent; -// for (int i = 0; i < st->swt_n; i++,swapent++) { -// free(swapent->ste_path); -// } -// free(st); -// } -// swapent_t getSwapEnt(swapent_t *ent, int i) { -// return ent[i]; -// } -// int64_t getPpKernel() { -// int64_t pp_kernel = 0; -// kstat_ctl_t *ksc; -// kstat_t *ks; -// kstat_named_t *knp; -// kid_t kid; -// -// if ((ksc = kstat_open()) == NULL) { -// return -1; -// } -// if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) { -// return -1; -// } -// if (((kid = kstat_read(ksc, ks, NULL)) == -1) || -// ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) { -// return -1; -// } -// switch (knp->data_type) { -// case KSTAT_DATA_UINT64: -// pp_kernel = knp->value.ui64; -// break; -// case KSTAT_DATA_UINT32: -// pp_kernel = knp->value.ui32; -// break; -// } -// pp_kernel *= sysconf(_SC_PAGESIZE); -// return (pp_kernel > 0 ? pp_kernel : -1); -// } -import "C" - -// Get the system memory info using sysconf same as prtconf -func getTotalMem() int64 { - pagesize := C.sysconf(C._SC_PAGESIZE) - npages := C.sysconf(C._SC_PHYS_PAGES) - return int64(pagesize * npages) -} - -func getFreeMem() int64 { - pagesize := C.sysconf(C._SC_PAGESIZE) - npages := C.sysconf(C._SC_AVPHYS_PAGES) - return int64(pagesize * npages) -} - -// ReadMemInfo retrieves memory statistics of the host system and returns a -// MemInfo type. -func ReadMemInfo() (*MemInfo, error) { - - ppKernel := C.getPpKernel() - MemTotal := getTotalMem() - MemFree := getFreeMem() - SwapTotal, SwapFree, err := getSysSwap() - - if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 || - SwapFree < 0 { - return nil, fmt.Errorf("error getting system memory info %v\n", err) - } - - meminfo := &MemInfo{} - // Total memory is total physical memory less than memory locked by kernel - meminfo.MemTotal = MemTotal - int64(ppKernel) - meminfo.MemFree = MemFree - meminfo.SwapTotal = SwapTotal - meminfo.SwapFree = SwapFree - - return meminfo, nil -} - -func getSysSwap() (int64, int64, error) { - var tSwap int64 - var fSwap int64 - var diskblksPerPage int64 - num, err := C.swapctl(C.SC_GETNSWP, nil) - if err != nil { - return -1, -1, err - } - st := C.allocSwaptable(num) - _, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st)) - if err != nil { - C.freeSwaptable(st) - return -1, -1, err - } - - diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT) - for i := 0; i < int(num); i++ { - swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i)) - tSwap += int64(swapent.ste_pages) * diskblksPerPage - fSwap += int64(swapent.ste_free) * diskblksPerPage - } - C.freeSwaptable(st) - return tSwap, fSwap, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/meminfo_unsupported.go b/vendor/github.com/containers/storage/pkg/system/meminfo_unsupported.go deleted file mode 100644 index 3ce019dffd..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/meminfo_unsupported.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !linux,!windows,!solaris - -package system - -// ReadMemInfo is not supported on platforms other than linux and windows. -func ReadMemInfo() (*MemInfo, error) { - return nil, ErrNotSupportedPlatform -} diff --git a/vendor/github.com/containers/storage/pkg/system/meminfo_windows.go b/vendor/github.com/containers/storage/pkg/system/meminfo_windows.go deleted file mode 100644 index 883944a4c5..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/meminfo_windows.go +++ /dev/null @@ -1,45 +0,0 @@ -package system - -import ( - "unsafe" - - "golang.org/x/sys/windows" -) - -var ( - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - - procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx") -) - -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx -type memorystatusex struct { - dwLength uint32 - dwMemoryLoad uint32 - ullTotalPhys uint64 - ullAvailPhys uint64 - ullTotalPageFile uint64 - ullAvailPageFile uint64 - ullTotalVirtual uint64 - ullAvailVirtual uint64 - ullAvailExtendedVirtual uint64 -} - -// ReadMemInfo retrieves memory statistics of the host system and returns a -// MemInfo type. -func ReadMemInfo() (*MemInfo, error) { - msi := &memorystatusex{ - dwLength: 64, - } - r1, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msi))) - if r1 == 0 { - return &MemInfo{}, nil - } - return &MemInfo{ - MemTotal: int64(msi.ullTotalPhys), - MemFree: int64(msi.ullAvailPhys), - SwapTotal: int64(msi.ullTotalPageFile), - SwapFree: int64(msi.ullAvailPageFile), - }, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/mknod.go b/vendor/github.com/containers/storage/pkg/system/mknod.go deleted file mode 100644 index af79a65383..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/mknod.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build !windows - -package system - -import ( - "golang.org/x/sys/unix" -) - -// Mknod creates a filesystem node (file, device special file or named pipe) named path -// with attributes specified by mode and dev. -func Mknod(path string, mode uint32, dev int) error { - return unix.Mknod(path, mode, dev) -} - -// Mkdev is used to build the value of linux devices (in /dev/) which specifies major -// and minor number of the newly created device special file. -// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes. -// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major, -// then the top 12 bits of the minor. -func Mkdev(major int64, minor int64) uint32 { - return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff)) -} diff --git a/vendor/github.com/containers/storage/pkg/system/mknod_windows.go b/vendor/github.com/containers/storage/pkg/system/mknod_windows.go deleted file mode 100644 index 2e863c0215..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/mknod_windows.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build windows - -package system - -// Mknod is not implemented on Windows. -func Mknod(path string, mode uint32, dev int) error { - return ErrNotSupportedPlatform -} - -// Mkdev is not implemented on Windows. -func Mkdev(major int64, minor int64) uint32 { - panic("Mkdev not implemented on Windows.") -} diff --git a/vendor/github.com/containers/storage/pkg/system/path.go b/vendor/github.com/containers/storage/pkg/system/path.go deleted file mode 100644 index f634a6be67..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/path.go +++ /dev/null @@ -1,21 +0,0 @@ -package system - -import "runtime" - -const defaultUnixPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -// DefaultPathEnv is unix style list of directories to search for -// executables. Each directory is separated from the next by a colon -// ':' character . -func DefaultPathEnv(platform string) string { - if runtime.GOOS == "windows" { - if platform != runtime.GOOS && LCOWSupported() { - return defaultUnixPathEnv - } - // Deliberately empty on Windows containers on Windows as the default path will be set by - // the container. Docker has no context of what the default path should be. - return "" - } - return defaultUnixPathEnv - -} diff --git a/vendor/github.com/containers/storage/pkg/system/path_unix.go b/vendor/github.com/containers/storage/pkg/system/path_unix.go deleted file mode 100644 index f3762e69d3..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/path_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build !windows - -package system - -// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter, -// is the system drive. This is a no-op on Linux. -func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) { - return path, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/path_windows.go b/vendor/github.com/containers/storage/pkg/system/path_windows.go deleted file mode 100644 index aab891522d..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/path_windows.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build windows - -package system - -import ( - "fmt" - "path/filepath" - "strings" -) - -// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path. -// This is used, for example, when validating a user provided path in docker cp. -// If a drive letter is supplied, it must be the system drive. The drive letter -// is always removed. Also, it translates it to OS semantics (IOW / to \). We -// need the path in this syntax so that it can ultimately be concatenated with -// a Windows long-path which doesn't support drive-letters. Examples: -// C: --> Fail -// C:\ --> \ -// a --> a -// /a --> \a -// d:\ --> Fail -func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) { - if len(path) == 2 && string(path[1]) == ":" { - return "", fmt.Errorf("No relative path specified in %q", path) - } - if !filepath.IsAbs(path) || len(path) < 2 { - return filepath.FromSlash(path), nil - } - if string(path[1]) == ":" && !strings.EqualFold(string(path[0]), "c") { - return "", fmt.Errorf("The specified path is not on the system drive (C:)") - } - return filepath.FromSlash(path[2:]), nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/process_unix.go b/vendor/github.com/containers/storage/pkg/system/process_unix.go deleted file mode 100644 index 26c8b42c17..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/process_unix.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build linux freebsd solaris darwin - -package system - -import ( - "syscall" - - "golang.org/x/sys/unix" -) - -// IsProcessAlive returns true if process with a given pid is running. -func IsProcessAlive(pid int) bool { - err := unix.Kill(pid, syscall.Signal(0)) - if err == nil || err == unix.EPERM { - return true - } - - return false -} - -// KillProcess force-stops a process. -func KillProcess(pid int) { - unix.Kill(pid, unix.SIGKILL) -} diff --git a/vendor/github.com/containers/storage/pkg/system/rm.go b/vendor/github.com/containers/storage/pkg/system/rm.go deleted file mode 100644 index fc03c3e6b6..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/rm.go +++ /dev/null @@ -1,80 +0,0 @@ -package system - -import ( - "os" - "syscall" - "time" - - "github.com/containers/storage/pkg/mount" - "github.com/pkg/errors" -) - -// EnsureRemoveAll wraps `os.RemoveAll` to check for specific errors that can -// often be remedied. -// Only use `EnsureRemoveAll` if you really want to make every effort to remove -// a directory. -// -// Because of the way `os.Remove` (and by extension `os.RemoveAll`) works, there -// can be a race between reading directory entries and then actually attempting -// to remove everything in the directory. -// These types of errors do not need to be returned since it's ok for the dir to -// be gone we can just retry the remove operation. -// -// This should not return a `os.ErrNotExist` kind of error under any circumstances -func EnsureRemoveAll(dir string) error { - notExistErr := make(map[string]bool) - - // track retries - exitOnErr := make(map[string]int) - maxRetry := 5 - - // Attempt to unmount anything beneath this dir first - mount.RecursiveUnmount(dir) - - for { - err := os.RemoveAll(dir) - if err == nil { - return err - } - - pe, ok := err.(*os.PathError) - if !ok { - return err - } - - if os.IsNotExist(err) { - if notExistErr[pe.Path] { - return err - } - notExistErr[pe.Path] = true - - // There is a race where some subdir can be removed but after the parent - // dir entries have been read. - // So the path could be from `os.Remove(subdir)` - // If the reported non-existent path is not the passed in `dir` we - // should just retry, but otherwise return with no error. - if pe.Path == dir { - return nil - } - continue - } - - if pe.Err != syscall.EBUSY { - return err - } - - if mounted, _ := mount.Mounted(pe.Path); mounted { - if e := mount.Unmount(pe.Path); e != nil { - if mounted, _ := mount.Mounted(pe.Path); mounted { - return errors.Wrapf(e, "error while removing %s", dir) - } - } - } - - if exitOnErr[pe.Path] == maxRetry { - return err - } - exitOnErr[pe.Path]++ - time.Sleep(100 * time.Millisecond) - } -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_darwin.go b/vendor/github.com/containers/storage/pkg/system/stat_darwin.go deleted file mode 100644 index 715f05b938..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -package system - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtimespec}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_freebsd.go b/vendor/github.com/containers/storage/pkg/system/stat_freebsd.go deleted file mode 100644 index 715f05b938..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_freebsd.go +++ /dev/null @@ -1,13 +0,0 @@ -package system - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtimespec}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_linux.go b/vendor/github.com/containers/storage/pkg/system/stat_linux.go deleted file mode 100644 index 1939f95181..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_linux.go +++ /dev/null @@ -1,19 +0,0 @@ -package system - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{size: s.Size, - mode: s.Mode, - uid: s.Uid, - gid: s.Gid, - rdev: s.Rdev, - mtim: s.Mtim}, nil -} - -// FromStatT converts a syscall.Stat_t type to a system.Stat_t type -// This is exposed on Linux as pkg/archive/changes uses it. -func FromStatT(s *syscall.Stat_t) (*StatT, error) { - return fromStatT(s) -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_openbsd.go b/vendor/github.com/containers/storage/pkg/system/stat_openbsd.go deleted file mode 100644 index b607dea946..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_openbsd.go +++ /dev/null @@ -1,13 +0,0 @@ -package system - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtim}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_solaris.go b/vendor/github.com/containers/storage/pkg/system/stat_solaris.go deleted file mode 100644 index b607dea946..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_solaris.go +++ /dev/null @@ -1,13 +0,0 @@ -package system - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtim}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_unix.go b/vendor/github.com/containers/storage/pkg/system/stat_unix.go deleted file mode 100644 index 91c7d121cc..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_unix.go +++ /dev/null @@ -1,60 +0,0 @@ -// +build !windows - -package system - -import ( - "syscall" -) - -// StatT type contains status of a file. It contains metadata -// like permission, owner, group, size, etc about a file. -type StatT struct { - mode uint32 - uid uint32 - gid uint32 - rdev uint64 - size int64 - mtim syscall.Timespec -} - -// Mode returns file's permission mode. -func (s StatT) Mode() uint32 { - return s.mode -} - -// UID returns file's user id of owner. -func (s StatT) UID() uint32 { - return s.uid -} - -// GID returns file's group id of owner. -func (s StatT) GID() uint32 { - return s.gid -} - -// Rdev returns file's device ID (if it's special file). -func (s StatT) Rdev() uint64 { - return s.rdev -} - -// Size returns file's size. -func (s StatT) Size() int64 { - return s.size -} - -// Mtim returns file's last modification time. -func (s StatT) Mtim() syscall.Timespec { - return s.mtim -} - -// Stat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Stat(path string) (*StatT, error) { - s := &syscall.Stat_t{} - if err := syscall.Stat(path, s); err != nil { - return nil, err - } - return fromStatT(s) -} diff --git a/vendor/github.com/containers/storage/pkg/system/stat_windows.go b/vendor/github.com/containers/storage/pkg/system/stat_windows.go deleted file mode 100644 index 6c63972682..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/stat_windows.go +++ /dev/null @@ -1,49 +0,0 @@ -package system - -import ( - "os" - "time" -) - -// StatT type contains status of a file. It contains metadata -// like permission, size, etc about a file. -type StatT struct { - mode os.FileMode - size int64 - mtim time.Time -} - -// Size returns file's size. -func (s StatT) Size() int64 { - return s.size -} - -// Mode returns file's permission mode. -func (s StatT) Mode() os.FileMode { - return os.FileMode(s.mode) -} - -// Mtim returns file's last modification time. -func (s StatT) Mtim() time.Time { - return time.Time(s.mtim) -} - -// Stat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Stat(path string) (*StatT, error) { - fi, err := os.Stat(path) - if err != nil { - return nil, err - } - return fromStatT(&fi) -} - -// fromStatT converts a os.FileInfo type to a system.StatT type -func fromStatT(fi *os.FileInfo) (*StatT, error) { - return &StatT{ - size: (*fi).Size(), - mode: (*fi).Mode(), - mtim: (*fi).ModTime()}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/syscall_unix.go b/vendor/github.com/containers/storage/pkg/system/syscall_unix.go deleted file mode 100644 index 49dbdd3781..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/syscall_unix.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build linux freebsd - -package system - -import "golang.org/x/sys/unix" - -// Unmount is a platform-specific helper function to call -// the unmount syscall. -func Unmount(dest string) error { - return unix.Unmount(dest, 0) -} - -// CommandLineToArgv should not be used on Unix. -// It simply returns commandLine in the only element in the returned array. -func CommandLineToArgv(commandLine string) ([]string, error) { - return []string{commandLine}, nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/syscall_windows.go b/vendor/github.com/containers/storage/pkg/system/syscall_windows.go deleted file mode 100644 index 23e9b207c7..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/syscall_windows.go +++ /dev/null @@ -1,122 +0,0 @@ -package system - -import ( - "unsafe" - - "github.com/sirupsen/logrus" - "golang.org/x/sys/windows" -) - -var ( - ntuserApiset = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0") - procGetVersionExW = modkernel32.NewProc("GetVersionExW") - procGetProductInfo = modkernel32.NewProc("GetProductInfo") -) - -// OSVersion is a wrapper for Windows version information -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx -type OSVersion struct { - Version uint32 - MajorVersion uint8 - MinorVersion uint8 - Build uint16 -} - -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx -type osVersionInfoEx struct { - OSVersionInfoSize uint32 - MajorVersion uint32 - MinorVersion uint32 - BuildNumber uint32 - PlatformID uint32 - CSDVersion [128]uint16 - ServicePackMajor uint16 - ServicePackMinor uint16 - SuiteMask uint16 - ProductType byte - Reserve byte -} - -// GetOSVersion gets the operating system version on Windows. Note that -// docker.exe must be manifested to get the correct version information. -func GetOSVersion() OSVersion { - var err error - osv := OSVersion{} - osv.Version, err = windows.GetVersion() - if err != nil { - // GetVersion never fails. - panic(err) - } - osv.MajorVersion = uint8(osv.Version & 0xFF) - osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF) - osv.Build = uint16(osv.Version >> 16) - return osv -} - -// IsWindowsClient returns true if the SKU is client -// @engine maintainers - this function should not be removed or modified as it -// is used to enforce licensing restrictions on Windows. -func IsWindowsClient() bool { - osviex := &osVersionInfoEx{OSVersionInfoSize: 284} - r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex))) - if r1 == 0 { - logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err) - return false - } - const verNTWorkstation = 0x00000001 - return osviex.ProductType == verNTWorkstation -} - -// IsIoTCore returns true if the currently running image is based off of -// Windows 10 IoT Core. -// @engine maintainers - this function should not be removed or modified as it -// is used to enforce licensing restrictions on Windows. -func IsIoTCore() bool { - var returnedProductType uint32 - r1, _, err := procGetProductInfo.Call(6, 1, 0, 0, uintptr(unsafe.Pointer(&returnedProductType))) - if r1 == 0 { - logrus.Warnf("GetProductInfo failed - assuming this is not IoT: %v", err) - return false - } - const productIoTUAP = 0x0000007B - const productIoTUAPCommercial = 0x00000083 - return returnedProductType == productIoTUAP || returnedProductType == productIoTUAPCommercial -} - -// Unmount is a platform-specific helper function to call -// the unmount syscall. Not supported on Windows -func Unmount(dest string) error { - return nil -} - -// CommandLineToArgv wraps the Windows syscall to turn a commandline into an argument array. -func CommandLineToArgv(commandLine string) ([]string, error) { - var argc int32 - - argsPtr, err := windows.UTF16PtrFromString(commandLine) - if err != nil { - return nil, err - } - - argv, err := windows.CommandLineToArgv(argsPtr, &argc) - if err != nil { - return nil, err - } - defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argv)))) - - newArgs := make([]string, argc) - for i, v := range (*argv)[:argc] { - newArgs[i] = string(windows.UTF16ToString((*v)[:])) - } - - return newArgs, nil -} - -// HasWin32KSupport determines whether containers that depend on win32k can -// run on this machine. Win32k is the driver used to implement windowing. -func HasWin32KSupport() bool { - // For now, check for ntuser API support on the host. In the future, a host - // may support win32k in containers even if the host does not support ntuser - // APIs. - return ntuserApiset.Load() == nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/umask.go b/vendor/github.com/containers/storage/pkg/system/umask.go deleted file mode 100644 index 5a10eda5af..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/umask.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !windows - -package system - -import ( - "golang.org/x/sys/unix" -) - -// Umask sets current process's file mode creation mask to newmask -// and returns oldmask. -func Umask(newmask int) (oldmask int, err error) { - return unix.Umask(newmask), nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/umask_windows.go b/vendor/github.com/containers/storage/pkg/system/umask_windows.go deleted file mode 100644 index 13f1de1769..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/umask_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build windows - -package system - -// Umask is not supported on the windows platform. -func Umask(newmask int) (oldmask int, err error) { - // should not be called on cli code path - return 0, ErrNotSupportedPlatform -} diff --git a/vendor/github.com/containers/storage/pkg/system/utimes_freebsd.go b/vendor/github.com/containers/storage/pkg/system/utimes_freebsd.go deleted file mode 100644 index 6a77524376..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/utimes_freebsd.go +++ /dev/null @@ -1,24 +0,0 @@ -package system - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/unix" -) - -// LUtimesNano is used to change access and modification time of the specified path. -// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm. -func LUtimesNano(path string, ts []syscall.Timespec) error { - var _path *byte - _path, err := unix.BytePtrFromString(path) - if err != nil { - return err - } - - if _, _, err := unix.Syscall(unix.SYS_LUTIMES, uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), 0); err != 0 && err != unix.ENOSYS { - return err - } - - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/utimes_linux.go b/vendor/github.com/containers/storage/pkg/system/utimes_linux.go deleted file mode 100644 index edc588a63f..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/utimes_linux.go +++ /dev/null @@ -1,25 +0,0 @@ -package system - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/unix" -) - -// LUtimesNano is used to change access and modification time of the specified path. -// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm. -func LUtimesNano(path string, ts []syscall.Timespec) error { - atFdCwd := unix.AT_FDCWD - - var _path *byte - _path, err := unix.BytePtrFromString(path) - if err != nil { - return err - } - if _, _, err := unix.Syscall6(unix.SYS_UTIMENSAT, uintptr(atFdCwd), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), unix.AT_SYMLINK_NOFOLLOW, 0, 0); err != 0 && err != unix.ENOSYS { - return err - } - - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/system/utimes_unsupported.go b/vendor/github.com/containers/storage/pkg/system/utimes_unsupported.go deleted file mode 100644 index 139714544d..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/utimes_unsupported.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !linux,!freebsd - -package system - -import "syscall" - -// LUtimesNano is only supported on linux and freebsd. -func LUtimesNano(path string, ts []syscall.Timespec) error { - return ErrNotSupportedPlatform -} diff --git a/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go b/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go deleted file mode 100644 index 98b111be42..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go +++ /dev/null @@ -1,29 +0,0 @@ -package system - -import "golang.org/x/sys/unix" - -// Lgetxattr retrieves the value of the extended attribute identified by attr -// and associated with the given path in the file system. -// It will returns a nil slice and nil error if the xattr is not set. -func Lgetxattr(path string, attr string) ([]byte, error) { - dest := make([]byte, 128) - sz, errno := unix.Lgetxattr(path, attr, dest) - if errno == unix.ENODATA { - return nil, nil - } - if errno == unix.ERANGE { - dest = make([]byte, sz) - sz, errno = unix.Lgetxattr(path, attr, dest) - } - if errno != nil { - return nil, errno - } - - return dest[:sz], nil -} - -// Lsetxattr sets the value of the extended attribute identified by attr -// and associated with the given path in the file system. -func Lsetxattr(path string, attr string, data []byte, flags int) error { - return unix.Lsetxattr(path, attr, data, flags) -} diff --git a/vendor/github.com/containers/storage/pkg/system/xattrs_unsupported.go b/vendor/github.com/containers/storage/pkg/system/xattrs_unsupported.go deleted file mode 100644 index 0114f2227c..0000000000 --- a/vendor/github.com/containers/storage/pkg/system/xattrs_unsupported.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package system - -// Lgetxattr is not supported on platforms other than linux. -func Lgetxattr(path string, attr string) ([]byte, error) { - return nil, ErrNotSupportedPlatform -} - -// Lsetxattr is not supported on platforms other than linux. -func Lsetxattr(path string, attr string, data []byte, flags int) error { - return ErrNotSupportedPlatform -} diff --git a/vendor/github.com/containers/storage/pkg/truncindex/truncindex.go b/vendor/github.com/containers/storage/pkg/truncindex/truncindex.go deleted file mode 100644 index 74776e65e6..0000000000 --- a/vendor/github.com/containers/storage/pkg/truncindex/truncindex.go +++ /dev/null @@ -1,139 +0,0 @@ -// Package truncindex provides a general 'index tree', used by Docker -// in order to be able to reference containers by only a few unambiguous -// characters of their id. -package truncindex - -import ( - "errors" - "fmt" - "strings" - "sync" - - "github.com/tchap/go-patricia/patricia" -) - -var ( - // ErrEmptyPrefix is an error returned if the prefix was empty. - ErrEmptyPrefix = errors.New("Prefix can't be empty") - - // ErrIllegalChar is returned when a space is in the ID - ErrIllegalChar = errors.New("illegal character: ' '") - - // ErrNotExist is returned when ID or its prefix not found in index. - ErrNotExist = errors.New("ID does not exist") -) - -// ErrAmbiguousPrefix is returned if the prefix was ambiguous -// (multiple ids for the prefix). -type ErrAmbiguousPrefix struct { - prefix string -} - -func (e ErrAmbiguousPrefix) Error() string { - return fmt.Sprintf("Multiple IDs found with provided prefix: %s", e.prefix) -} - -// TruncIndex allows the retrieval of string identifiers by any of their unique prefixes. -// This is used to retrieve image and container IDs by more convenient shorthand prefixes. -type TruncIndex struct { - sync.RWMutex - trie *patricia.Trie - ids map[string]struct{} -} - -// NewTruncIndex creates a new TruncIndex and initializes with a list of IDs. -func NewTruncIndex(ids []string) (idx *TruncIndex) { - idx = &TruncIndex{ - ids: make(map[string]struct{}), - - // Change patricia max prefix per node length, - // because our len(ID) always 64 - trie: patricia.NewTrie(patricia.MaxPrefixPerNode(64)), - } - for _, id := range ids { - idx.addID(id) - } - return -} - -func (idx *TruncIndex) addID(id string) error { - if strings.Contains(id, " ") { - return ErrIllegalChar - } - if id == "" { - return ErrEmptyPrefix - } - if _, exists := idx.ids[id]; exists { - return fmt.Errorf("id already exists: '%s'", id) - } - idx.ids[id] = struct{}{} - if inserted := idx.trie.Insert(patricia.Prefix(id), struct{}{}); !inserted { - return fmt.Errorf("failed to insert id: %s", id) - } - return nil -} - -// Add adds a new ID to the TruncIndex. -func (idx *TruncIndex) Add(id string) error { - idx.Lock() - defer idx.Unlock() - return idx.addID(id) -} - -// Delete removes an ID from the TruncIndex. If there are multiple IDs -// with the given prefix, an error is thrown. -func (idx *TruncIndex) Delete(id string) error { - idx.Lock() - defer idx.Unlock() - if _, exists := idx.ids[id]; !exists || id == "" { - return fmt.Errorf("no such id: '%s'", id) - } - delete(idx.ids, id) - if deleted := idx.trie.Delete(patricia.Prefix(id)); !deleted { - return fmt.Errorf("no such id: '%s'", id) - } - return nil -} - -// Get retrieves an ID from the TruncIndex. If there are multiple IDs -// with the given prefix, an error is thrown. -func (idx *TruncIndex) Get(s string) (string, error) { - if s == "" { - return "", ErrEmptyPrefix - } - var ( - id string - ) - subTreeVisitFunc := func(prefix patricia.Prefix, item patricia.Item) error { - if id != "" { - // we haven't found the ID if there are two or more IDs - id = "" - return ErrAmbiguousPrefix{prefix: string(prefix)} - } - id = string(prefix) - return nil - } - - idx.RLock() - defer idx.RUnlock() - if err := idx.trie.VisitSubtree(patricia.Prefix(s), subTreeVisitFunc); err != nil { - return "", err - } - if id != "" { - return id, nil - } - return "", ErrNotExist -} - -// Iterate iterates over all stored IDs and passes each of them to the given -// handler. Take care that the handler method does not call any public -// method on truncindex as the internal locking is not reentrant/recursive -// and will result in deadlock. -func (idx *TruncIndex) Iterate(handler func(id string)) { - idx.Lock() - defer idx.Unlock() - idx.trie.Visit(func(prefix patricia.Prefix, item patricia.Item) error { - handler(string(prefix)) - return nil - }) -} diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go deleted file mode 100644 index a31a08b2a4..0000000000 --- a/vendor/github.com/containers/storage/store.go +++ /dev/null @@ -1,2425 +0,0 @@ -package storage - -import ( - "encoding/base64" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "sync" - "time" - - // register all of the built-in drivers - _ "github.com/containers/storage/drivers/register" - - "github.com/BurntSushi/toml" - drivers "github.com/containers/storage/drivers" - "github.com/containers/storage/pkg/archive" - "github.com/containers/storage/pkg/idtools" - "github.com/containers/storage/pkg/ioutils" - "github.com/containers/storage/pkg/stringid" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -var ( - // DefaultStoreOptions is a reasonable default set of options. - DefaultStoreOptions StoreOptions - stores []*store - storesLock sync.Mutex -) - -// ROFileBasedStore wraps up the methods of the various types of file-based -// data stores that we implement which are needed for both read-only and -// read-write files. -type ROFileBasedStore interface { - Locker - - // Load reloads the contents of the store from disk. It should be called - // with the lock held. - Load() error -} - -// RWFileBasedStore wraps up the methods of various types of file-based data -// stores that we implement using read-write files. -type RWFileBasedStore interface { - // Save saves the contents of the store to disk. It should be called with - // the lock held, and Touch() should be called afterward before releasing the - // lock. - Save() error -} - -// FileBasedStore wraps up the common methods of various types of file-based -// data stores that we implement. -type FileBasedStore interface { - ROFileBasedStore - RWFileBasedStore -} - -// ROMetadataStore wraps a method for reading metadata associated with an ID. -type ROMetadataStore interface { - // Metadata reads metadata associated with an item with the specified ID. - Metadata(id string) (string, error) -} - -// RWMetadataStore wraps a method for setting metadata associated with an ID. -type RWMetadataStore interface { - // SetMetadata updates the metadata associated with the item with the specified ID. - SetMetadata(id, metadata string) error -} - -// MetadataStore wraps up methods for getting and setting metadata associated with IDs. -type MetadataStore interface { - ROMetadataStore - RWMetadataStore -} - -// An ROBigDataStore wraps up the read-only big-data related methods of the -// various types of file-based lookaside stores that we implement. -type ROBigDataStore interface { - // BigData retrieves a (potentially large) piece of data associated with - // this ID, if it has previously been set. - BigData(id, key string) ([]byte, error) - - // BigDataSize retrieves the size of a (potentially large) piece of - // data associated with this ID, if it has previously been set. - BigDataSize(id, key string) (int64, error) - - // BigDataDigest retrieves the digest of a (potentially large) piece of - // data associated with this ID, if it has previously been set. - BigDataDigest(id, key string) (digest.Digest, error) - - // BigDataNames() returns a list of the names of previously-stored pieces of - // data. - BigDataNames(id string) ([]string, error) -} - -// A RWBigDataStore wraps up the read-write big-data related methods of the -// various types of file-based lookaside stores that we implement. -type RWBigDataStore interface { - // SetBigData stores a (potentially large) piece of data associated with this - // ID. - SetBigData(id, key string, data []byte) error -} - -// A BigDataStore wraps up the most common big-data related methods of the -// various types of file-based lookaside stores that we implement. -type BigDataStore interface { - ROBigDataStore - RWBigDataStore -} - -// A FlaggableStore can have flags set and cleared on items which it manages. -type FlaggableStore interface { - // ClearFlag removes a named flag from an item in the store. - ClearFlag(id string, flag string) error - - // SetFlag sets a named flag and its value on an item in the store. - SetFlag(id string, flag string, value interface{}) error -} - -// StoreOptions is used for passing initialization options to GetStore(), for -// initializing a Store object and the underlying storage that it controls. -type StoreOptions struct { - // RunRoot is the filesystem path under which we can store run-time - // information, such as the locations of active mount points, that we - // want to lose if the host is rebooted. - RunRoot string `json:"runroot,omitempty"` - // GraphRoot is the filesystem path under which we will store the - // contents of layers, images, and containers. - GraphRoot string `json:"root,omitempty"` - // GraphDriverName is the underlying storage driver that we'll be - // using. It only needs to be specified the first time a Store is - // initialized for a given RunRoot and GraphRoot. - GraphDriverName string `json:"driver,omitempty"` - // GraphDriverOptions are driver-specific options. - GraphDriverOptions []string `json:"driver-options,omitempty"` - // UIDMap and GIDMap are used mainly for deciding on the ownership of - // files in layers as they're stored on disk, which is often necessary - // when user namespaces are being used. - UIDMap []idtools.IDMap `json:"uidmap,omitempty"` - GIDMap []idtools.IDMap `json:"gidmap,omitempty"` -} - -// Store wraps up the various types of file-based stores that we use into a -// singleton object that initializes and manages them all together. -type Store interface { - // RunRoot, GraphRoot, GraphDriverName, and GraphOptions retrieve - // settings that were passed to GetStore() when the object was created. - RunRoot() string - GraphRoot() string - GraphDriverName() string - GraphOptions() []string - - // GraphDriver obtains and returns a handle to the graph Driver object used - // by the Store. - GraphDriver() (drivers.Driver, error) - - // CreateLayer creates a new layer in the underlying storage driver, - // optionally having the specified ID (one will be assigned if none is - // specified), with the specified layer (or no layer) as its parent, - // and with optional names. (The writeable flag is ignored.) - CreateLayer(id, parent string, names []string, mountLabel string, writeable bool) (*Layer, error) - - // PutLayer combines the functions of CreateLayer and ApplyDiff, - // marking the layer for automatic removal if applying the diff fails - // for any reason. - // - // Note that we do some of this work in a child process. The calling - // process's main() function needs to import our pkg/reexec package and - // should begin with something like this in order to allow us to - // properly start that child process: - // if reexec.Init { - // return - // } - PutLayer(id, parent string, names []string, mountLabel string, writeable bool, diff io.Reader) (*Layer, int64, error) - - // CreateImage creates a new image, optionally with the specified ID - // (one will be assigned if none is specified), with optional names, - // referring to a specified image, and with optional metadata. An - // image is a record which associates the ID of a layer with a - // additional bookkeeping information which the library stores for the - // convenience of its caller. - CreateImage(id string, names []string, layer, metadata string, options *ImageOptions) (*Image, error) - - // CreateContainer creates a new container, optionally with the - // specified ID (one will be assigned if none is specified), with - // optional names, using the specified image's top layer as the basis - // for the container's layer, and assigning the specified ID to that - // layer (one will be created if none is specified). A container is a - // layer which is associated with additional bookkeeping information - // which the library stores for the convenience of its caller. - CreateContainer(id string, names []string, image, layer, metadata string, options *ContainerOptions) (*Container, error) - - // Metadata retrieves the metadata which is associated with a layer, - // image, or container (whichever the passed-in ID refers to). - Metadata(id string) (string, error) - - // SetMetadata updates the metadata which is associated with a layer, - // image, or container (whichever the passed-in ID refers to) to match - // the specified value. The metadata value can be retrieved at any - // time using Metadata, or using Layer, Image, or Container and reading - // the object directly. - SetMetadata(id, metadata string) error - - // Exists checks if there is a layer, image, or container which has the - // passed-in ID or name. - Exists(id string) bool - - // Status asks for a status report, in the form of key-value pairs, - // from the underlying storage driver. The contents vary from driver - // to driver. - Status() ([][2]string, error) - - // Delete removes the layer, image, or container which has the - // passed-in ID or name. Note that no safety checks are performed, so - // this can leave images with references to layers which do not exist, - // and layers with references to parents which no longer exist. - Delete(id string) error - - // DeleteLayer attempts to remove the specified layer. If the layer is the - // parent of any other layer, or is referred to by any images, it will return - // an error. - DeleteLayer(id string) error - - // DeleteImage removes the specified image if it is not referred to by - // any containers. If its top layer is then no longer referred to by - // any other images and is not the parent of any other layers, its top - // layer will be removed. If that layer's parent is no longer referred - // to by any other images and is not the parent of any other layers, - // then it, too, will be removed. This procedure will be repeated - // until a layer which should not be removed, or the base layer, is - // reached, at which point the list of removed layers is returned. If - // the commit argument is false, the image and layers are not removed, - // but the list of layers which would be removed is still returned. - DeleteImage(id string, commit bool) (layers []string, err error) - - // DeleteContainer removes the specified container and its layer. If - // there is no matching container, or if the container exists but its - // layer does not, an error will be returned. - DeleteContainer(id string) error - - // Wipe removes all known layers, images, and containers. - Wipe() error - - // Mount attempts to mount a layer, image, or container for access, and - // returns the pathname if it succeeds. - // - // Note that we do some of this work in a child process. The calling - // process's main() function needs to import our pkg/reexec package and - // should begin with something like this in order to allow us to - // properly start that child process: - // if reexec.Init { - // return - // } - Mount(id, mountLabel string) (string, error) - - // Unmount attempts to unmount a layer, image, or container, given an ID, a - // name, or a mount path. - Unmount(id string) error - - // Changes returns a summary of the changes which would need to be made - // to one layer to make its contents the same as a second layer. If - // the first layer is not specified, the second layer's parent is - // assumed. Each Change structure contains a Path relative to the - // layer's root directory, and a Kind which is either ChangeAdd, - // ChangeModify, or ChangeDelete. - Changes(from, to string) ([]archive.Change, error) - - // DiffSize returns a count of the size of the tarstream which would - // specify the changes returned by Changes. - DiffSize(from, to string) (int64, error) - - // Diff returns the tarstream which would specify the changes returned - // by Changes. If options are passed in, they can override default - // behaviors. - Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) - - // ApplyDiff applies a tarstream to a layer. Information about the - // tarstream is cached with the layer. Typically, a layer which is - // populated using a tarstream will be expected to not be modified in - // any other way, either before or after the diff is applied. - // - // Note that we do some of this work in a child process. The calling - // process's main() function needs to import our pkg/reexec package and - // should begin with something like this in order to allow us to - // properly start that child process: - // if reexec.Init { - // return - // } - ApplyDiff(to string, diff io.Reader) (int64, error) - - // LayersByCompressedDigest returns a slice of the layers with the - // specified compressed digest value recorded for them. - LayersByCompressedDigest(d digest.Digest) ([]Layer, error) - - // LayersByUncompressedDigest returns a slice of the layers with the - // specified uncompressed digest value recorded for them. - LayersByUncompressedDigest(d digest.Digest) ([]Layer, error) - - // LayerSize returns a cached approximation of the layer's size, or -1 - // if we don't have a value on hand. - LayerSize(id string) (int64, error) - - // Layers returns a list of the currently known layers. - Layers() ([]Layer, error) - - // Images returns a list of the currently known images. - Images() ([]Image, error) - - // Containers returns a list of the currently known containers. - Containers() ([]Container, error) - - // Names returns the list of names for a layer, image, or container. - Names(id string) ([]string, error) - - // SetNames changes the list of names for a layer, image, or container. - // Duplicate names are removed from the list automatically. - SetNames(id string, names []string) error - - // ListImageBigData retrieves a list of the (possibly large) chunks of - // named data associated with an image. - ListImageBigData(id string) ([]string, error) - - // ImageBigData retrieves a (possibly large) chunk of named data - // associated with an image. - ImageBigData(id, key string) ([]byte, error) - - // ImageBigDataSize retrieves the size of a (possibly large) chunk - // of named data associated with an image. - ImageBigDataSize(id, key string) (int64, error) - - // ImageBigDataDigest retrieves the digest of a (possibly large) chunk - // of named data associated with an image. - ImageBigDataDigest(id, key string) (digest.Digest, error) - - // SetImageBigData stores a (possibly large) chunk of named data associated - // with an image. - SetImageBigData(id, key string, data []byte) error - - // ListContainerBigData retrieves a list of the (possibly large) chunks of - // named data associated with a container. - ListContainerBigData(id string) ([]string, error) - - // ContainerBigData retrieves a (possibly large) chunk of named data - // associated with a container. - ContainerBigData(id, key string) ([]byte, error) - - // ContainerBigDataSize retrieves the size of a (possibly large) - // chunk of named data associated with a container. - ContainerBigDataSize(id, key string) (int64, error) - - // ContainerBigDataDigest retrieves the digest of a (possibly large) - // chunk of named data associated with a container. - ContainerBigDataDigest(id, key string) (digest.Digest, error) - - // SetContainerBigData stores a (possibly large) chunk of named data - // associated with a container. - SetContainerBigData(id, key string, data []byte) error - - // Layer returns a specific layer. - Layer(id string) (*Layer, error) - - // Image returns a specific image. - Image(id string) (*Image, error) - - // ImagesByTopLayer returns a list of images which reference the specified - // layer as their top layer. They will have different IDs and names - // and may have different metadata, big data items, and flags. - ImagesByTopLayer(id string) ([]*Image, error) - - // ImagesByDigest returns a list of images which contain a big data item - // named ImageDigestBigDataKey whose contents have the specified digest. - ImagesByDigest(d digest.Digest) ([]*Image, error) - - // Container returns a specific container. - Container(id string) (*Container, error) - - // ContainerByLayer returns a specific container based on its layer ID or - // name. - ContainerByLayer(id string) (*Container, error) - - // ContainerDirectory returns a path of a directory which the caller - // can use to store data, specific to the container, which the library - // does not directly manage. The directory will be deleted when the - // container is deleted. - ContainerDirectory(id string) (string, error) - - // SetContainerDirectoryFile is a convenience function which stores - // a piece of data in the specified file relative to the container's - // directory. - SetContainerDirectoryFile(id, file string, data []byte) error - - // FromContainerDirectory is a convenience function which reads - // the contents of the specified file relative to the container's - // directory. - FromContainerDirectory(id, file string) ([]byte, error) - - // ContainerRunDirectory returns a path of a directory which the - // caller can use to store data, specific to the container, which the - // library does not directly manage. The directory will be deleted - // when the host system is restarted. - ContainerRunDirectory(id string) (string, error) - - // SetContainerRunDirectoryFile is a convenience function which stores - // a piece of data in the specified file relative to the container's - // run directory. - SetContainerRunDirectoryFile(id, file string, data []byte) error - - // FromContainerRunDirectory is a convenience function which reads - // the contents of the specified file relative to the container's run - // directory. - FromContainerRunDirectory(id, file string) ([]byte, error) - - // Lookup returns the ID of a layer, image, or container with the specified - // name or ID. - Lookup(name string) (string, error) - - // Shutdown attempts to free any kernel resources which are being used - // by the underlying driver. If "force" is true, any mounted (i.e., in - // use) layers are unmounted beforehand. If "force" is not true, then - // layers being in use is considered to be an error condition. A list - // of still-mounted layers is returned along with possible errors. - Shutdown(force bool) (layers []string, err error) - - // Version returns version information, in the form of key-value pairs, from - // the storage package. - Version() ([][2]string, error) -} - -// ImageOptions is used for passing options to a Store's CreateImage() method. -type ImageOptions struct { - // CreationDate, if not zero, will override the default behavior of marking the image as having been - // created when CreateImage() was called, recording CreationDate instead. - CreationDate time.Time - // Digest is a hard-coded digest value that we can use to look up the image. It is optional. - Digest digest.Digest -} - -// ContainerOptions is used for passing options to a Store's CreateContainer() method. -type ContainerOptions struct { -} - -type store struct { - lastLoaded time.Time - runRoot string - graphLock Locker - graphRoot string - graphDriverName string - graphOptions []string - uidMap []idtools.IDMap - gidMap []idtools.IDMap - graphDriver drivers.Driver - layerStore LayerStore - roLayerStores []ROLayerStore - imageStore ImageStore - roImageStores []ROImageStore - containerStore ContainerStore -} - -// GetStore attempts to find an already-created Store object matching the -// specified location and graph driver, and if it can't, it creates and -// initializes a new Store object, and the underlying storage that it controls. -// -// If StoreOptions `options` haven't been fully populated, then DefaultStoreOptions are used. -// -// These defaults observe environment variables: -// * `STORAGE_DRIVER` for the name of the storage driver to attempt to use -// * `STORAGE_OPTS` for the string of options to pass to the driver -func GetStore(options StoreOptions) (Store, error) { - if options.RunRoot == "" && options.GraphRoot == "" && options.GraphDriverName == "" && len(options.GraphDriverOptions) == 0 { - options = DefaultStoreOptions - } - - if options.GraphRoot != "" { - options.GraphRoot = filepath.Clean(options.GraphRoot) - } - if options.RunRoot != "" { - options.RunRoot = filepath.Clean(options.RunRoot) - } - - storesLock.Lock() - defer storesLock.Unlock() - - for _, s := range stores { - if s.graphRoot == options.GraphRoot && (options.GraphDriverName == "" || s.graphDriverName == options.GraphDriverName) { - return s, nil - } - } - - if options.GraphRoot == "" { - return nil, ErrIncompleteOptions - } - if options.RunRoot == "" { - return nil, ErrIncompleteOptions - } - - if err := os.MkdirAll(options.RunRoot, 0700); err != nil && !os.IsExist(err) { - return nil, err - } - if err := os.MkdirAll(options.GraphRoot, 0700); err != nil && !os.IsExist(err) { - return nil, err - } - for _, subdir := range []string{"mounts", "tmp", options.GraphDriverName} { - if err := os.MkdirAll(filepath.Join(options.GraphRoot, subdir), 0700); err != nil && !os.IsExist(err) { - return nil, err - } - } - - graphLock, err := GetLockfile(filepath.Join(options.GraphRoot, "storage.lock")) - if err != nil { - return nil, err - } - s := &store{ - runRoot: options.RunRoot, - graphLock: graphLock, - graphRoot: options.GraphRoot, - graphDriverName: options.GraphDriverName, - graphOptions: options.GraphDriverOptions, - uidMap: copyIDMap(options.UIDMap), - gidMap: copyIDMap(options.GIDMap), - } - if err := s.load(); err != nil { - return nil, err - } - - stores = append(stores, s) - - return s, nil -} - -func copyIDMap(idmap []idtools.IDMap) []idtools.IDMap { - m := []idtools.IDMap{} - if idmap != nil { - m = make([]idtools.IDMap, len(idmap)) - copy(m, idmap) - } - if len(m) > 0 { - return m[:] - } - return nil -} - -func (s *store) RunRoot() string { - return s.runRoot -} - -func (s *store) GraphDriverName() string { - return s.graphDriverName -} - -func (s *store) GraphRoot() string { - return s.graphRoot -} - -func (s *store) GraphOptions() []string { - return s.graphOptions -} - -func (s *store) load() error { - driver, err := s.GraphDriver() - if err != nil { - return err - } - s.graphDriver = driver - s.graphDriverName = driver.String() - driverPrefix := s.graphDriverName + "-" - - rls, err := s.LayerStore() - if err != nil { - return err - } - s.layerStore = rls - if _, err := s.ROLayerStores(); err != nil { - return err - } - - gipath := filepath.Join(s.graphRoot, driverPrefix+"images") - if err := os.MkdirAll(gipath, 0700); err != nil { - return err - } - ris, err := newImageStore(gipath) - if err != nil { - return err - } - s.imageStore = ris - if _, err := s.ROImageStores(); err != nil { - return err - } - - gcpath := filepath.Join(s.graphRoot, driverPrefix+"containers") - if err := os.MkdirAll(gcpath, 0700); err != nil { - return err - } - rcs, err := newContainerStore(gcpath) - if err != nil { - return err - } - rcpath := filepath.Join(s.runRoot, driverPrefix+"containers") - if err := os.MkdirAll(rcpath, 0700); err != nil { - return err - } - s.containerStore = rcs - return nil -} - -func (s *store) getGraphDriver() (drivers.Driver, error) { - if s.graphDriver != nil { - return s.graphDriver, nil - } - config := drivers.Options{ - Root: s.graphRoot, - DriverOptions: s.graphOptions, - UIDMaps: s.uidMap, - GIDMaps: s.gidMap, - } - driver, err := drivers.New(s.graphDriverName, config) - if err != nil { - return nil, err - } - s.graphDriver = driver - s.graphDriverName = driver.String() - return driver, nil -} - -func (s *store) GraphDriver() (drivers.Driver, error) { - s.graphLock.Lock() - defer s.graphLock.Unlock() - if s.graphLock.TouchedSince(s.lastLoaded) { - s.graphDriver = nil - s.layerStore = nil - s.lastLoaded = time.Now() - } - return s.getGraphDriver() -} - -// LayerStore obtains and returns a handle to the writeable layer store object -// used by the Store. Accessing this store directly will bypass locking and -// synchronization, so it is not a part of the exported Store interface. -func (s *store) LayerStore() (LayerStore, error) { - s.graphLock.Lock() - defer s.graphLock.Unlock() - if s.graphLock.TouchedSince(s.lastLoaded) { - s.graphDriver = nil - s.layerStore = nil - s.lastLoaded = time.Now() - } - if s.layerStore != nil { - return s.layerStore, nil - } - driver, err := s.getGraphDriver() - if err != nil { - return nil, err - } - driverPrefix := s.graphDriverName + "-" - rlpath := filepath.Join(s.runRoot, driverPrefix+"layers") - if err := os.MkdirAll(rlpath, 0700); err != nil { - return nil, err - } - glpath := filepath.Join(s.graphRoot, driverPrefix+"layers") - if err := os.MkdirAll(glpath, 0700); err != nil { - return nil, err - } - rls, err := newLayerStore(rlpath, glpath, driver) - if err != nil { - return nil, err - } - s.layerStore = rls - return s.layerStore, nil -} - -// ROLayerStores obtains additional read/only layer store objects used by the -// Store. Accessing these stores directly will bypass locking and -// synchronization, so it is not part of the exported Store interface. -func (s *store) ROLayerStores() ([]ROLayerStore, error) { - s.graphLock.Lock() - defer s.graphLock.Unlock() - if s.roLayerStores != nil { - return s.roLayerStores, nil - } - driver, err := s.getGraphDriver() - if err != nil { - return nil, err - } - driverPrefix := s.graphDriverName + "-" - rlpath := filepath.Join(s.runRoot, driverPrefix+"layers") - if err := os.MkdirAll(rlpath, 0700); err != nil { - return nil, err - } - for _, store := range driver.AdditionalImageStores() { - glpath := filepath.Join(store, driverPrefix+"layers") - rls, err := newROLayerStore(rlpath, glpath, driver) - if err != nil { - return nil, err - } - s.roLayerStores = append(s.roLayerStores, rls) - } - return s.roLayerStores, nil -} - -// ImageStore obtains and returns a handle to the writable image store object -// used by the Store. Accessing this store directly will bypass locking and -// synchronization, so it is not a part of the exported Store interface. -func (s *store) ImageStore() (ImageStore, error) { - if s.imageStore != nil { - return s.imageStore, nil - } - return nil, ErrLoadError -} - -// ROImageStores obtains additional read/only image store objects used by the -// Store. Accessing these stores directly will bypass locking and -// synchronization, so it is not a part of the exported Store interface. -func (s *store) ROImageStores() ([]ROImageStore, error) { - if len(s.roImageStores) != 0 { - return s.roImageStores, nil - } - driver, err := s.getGraphDriver() - if err != nil { - return nil, err - } - driverPrefix := s.graphDriverName + "-" - for _, store := range driver.AdditionalImageStores() { - gipath := filepath.Join(store, driverPrefix+"images") - ris, err := newROImageStore(gipath) - if err != nil { - return nil, err - } - s.roImageStores = append(s.roImageStores, ris) - } - return s.roImageStores, nil -} - -// ContainerStore obtains and returns a handle to the container store object -// used by the Store. Accessing this store directly will bypass locking and -// synchronization, so it is not a part of the exported Store interface. -func (s *store) ContainerStore() (ContainerStore, error) { - if s.containerStore != nil { - return s.containerStore, nil - } - return nil, ErrLoadError -} - -func (s *store) PutLayer(id, parent string, names []string, mountLabel string, writeable bool, diff io.Reader) (*Layer, int64, error) { - rlstore, err := s.LayerStore() - if err != nil { - return nil, -1, err - } - rlstores, err := s.ROLayerStores() - if err != nil { - return nil, -1, err - } - rcstore, err := s.ContainerStore() - if err != nil { - return nil, -1, err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - if id == "" { - id = stringid.GenerateRandomID() - } - if parent != "" { - var ilayer *Layer - for _, lstore := range append([]ROLayerStore{rlstore}, rlstores...) { - if l, err := lstore.Get(parent); err == nil && l != nil { - ilayer = l - parent = ilayer.ID - break - } - } - if ilayer == nil { - return nil, -1, ErrLayerUnknown - } - containers, err := rcstore.Containers() - if err != nil { - return nil, -1, err - } - for _, container := range containers { - if container.LayerID == parent { - return nil, -1, ErrParentIsContainer - } - } - } - return rlstore.Put(id, parent, names, mountLabel, nil, writeable, nil, diff) -} - -func (s *store) CreateLayer(id, parent string, names []string, mountLabel string, writeable bool) (*Layer, error) { - layer, _, err := s.PutLayer(id, parent, names, mountLabel, writeable, nil) - return layer, err -} - -func (s *store) CreateImage(id string, names []string, layer, metadata string, options *ImageOptions) (*Image, error) { - if id == "" { - id = stringid.GenerateRandomID() - } - - if layer != "" { - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - var ilayer *Layer - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - ilayer, err = store.Get(layer) - if err == nil { - break - } - } - if ilayer == nil { - return nil, ErrLayerUnknown - } - layer = ilayer.ID - } - - ristore, err := s.ImageStore() - if err != nil { - return nil, err - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - - creationDate := time.Now().UTC() - if options != nil && !options.CreationDate.IsZero() { - creationDate = options.CreationDate - } - - return ristore.Create(id, names, layer, metadata, creationDate, options.Digest) -} - -func (s *store) CreateContainer(id string, names []string, image, layer, metadata string, options *ContainerOptions) (*Container, error) { - rlstore, err := s.LayerStore() - if err != nil { - return nil, err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - if id == "" { - id = stringid.GenerateRandomID() - } - - imageTopLayer := "" - imageID := "" - if image != "" { - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - var cimage *Image - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - cimage, err = store.Get(image) - if err == nil { - break - } - } - if cimage == nil { - return nil, ErrImageUnknown - } - imageTopLayer = cimage.TopLayer - imageID = cimage.ID - } - clayer, err := rlstore.Create(layer, imageTopLayer, nil, "", nil, true) - if err != nil { - return nil, err - } - layer = clayer.ID - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - container, err := rcstore.Create(id, names, imageID, layer, metadata) - if err != nil || container == nil { - rlstore.Delete(layer) - } - return container, err -} - -func (s *store) SetMetadata(id, metadata string) error { - rlstore, err := s.LayerStore() - if err != nil { - return err - } - ristore, err := s.ImageStore() - if err != nil { - return err - } - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - if rlstore.Exists(id) { - return rlstore.SetMetadata(id, metadata) - } - if ristore.Exists(id) { - return ristore.SetMetadata(id, metadata) - } - if rcstore.Exists(id) { - return rcstore.SetMetadata(id, metadata) - } - return ErrNotAnID -} - -func (s *store) Metadata(id string) (string, error) { - lstore, err := s.LayerStore() - if err != nil { - return "", err - } - lstores, err := s.ROLayerStores() - if err != nil { - return "", err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(id) { - return store.Metadata(id) - } - } - - istore, err := s.ImageStore() - if err != nil { - return "", err - } - istores, err := s.ROImageStores() - if err != nil { - return "", err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(id) { - return store.Metadata(id) - } - } - - cstore, err := s.ContainerStore() - if err != nil { - return "", err - } - cstore.Lock() - defer cstore.Unlock() - if modified, err := cstore.Modified(); modified || err != nil { - cstore.Load() - } - if cstore.Exists(id) { - return cstore.Metadata(id) - } - return "", ErrNotAnID -} - -func (s *store) ListImageBigData(id string) ([]string, error) { - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - bigDataNames, err := store.BigDataNames(id) - if err == nil { - return bigDataNames, err - } - } - return nil, ErrImageUnknown -} - -func (s *store) ImageBigDataSize(id, key string) (int64, error) { - istore, err := s.ImageStore() - if err != nil { - return -1, err - } - istores, err := s.ROImageStores() - if err != nil { - return -1, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - size, err := store.BigDataSize(id, key) - if err == nil { - return size, nil - } - } - return -1, ErrSizeUnknown -} - -func (s *store) ImageBigDataDigest(id, key string) (digest.Digest, error) { - ristore, err := s.ImageStore() - if err != nil { - return "", err - } - stores, err := s.ROImageStores() - if err != nil { - return "", err - } - stores = append([]ROImageStore{ristore}, stores...) - for _, ristore := range stores { - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - d, err := ristore.BigDataDigest(id, key) - if err == nil && d.Validate() == nil { - return d, nil - } - } - return "", ErrDigestUnknown -} - -func (s *store) ImageBigData(id, key string) ([]byte, error) { - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - data, err := store.BigData(id, key) - if err == nil { - return data, nil - } - } - return nil, ErrImageUnknown -} - -func (s *store) SetImageBigData(id, key string, data []byte) error { - ristore, err := s.ImageStore() - if err != nil { - return err - } - - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - - return ristore.SetBigData(id, key, data) -} - -func (s *store) ListContainerBigData(id string) ([]string, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - return rcstore.BigDataNames(id) -} - -func (s *store) ContainerBigDataSize(id, key string) (int64, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return -1, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - return rcstore.BigDataSize(id, key) -} - -func (s *store) ContainerBigDataDigest(id, key string) (digest.Digest, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return "", err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - return rcstore.BigDataDigest(id, key) -} - -func (s *store) ContainerBigData(id, key string) ([]byte, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - return rcstore.BigData(id, key) -} - -func (s *store) SetContainerBigData(id, key string, data []byte) error { - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - return rcstore.SetBigData(id, key, data) -} - -func (s *store) Exists(id string) bool { - lstore, err := s.LayerStore() - if err != nil { - return false - } - lstores, err := s.ROLayerStores() - if err != nil { - return false - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(id) { - return true - } - } - - istore, err := s.ImageStore() - if err != nil { - return false - } - istores, err := s.ROImageStores() - if err != nil { - return false - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(id) { - return true - } - } - - rcstore, err := s.ContainerStore() - if err != nil { - return false - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - if rcstore.Exists(id) { - return true - } - - return false -} - -func dedupeNames(names []string) []string { - seen := make(map[string]bool) - deduped := make([]string, 0, len(names)) - for _, name := range names { - if _, wasSeen := seen[name]; !wasSeen { - seen[name] = true - deduped = append(deduped, name) - } - } - return deduped -} - -func (s *store) SetNames(id string, names []string) error { - deduped := dedupeNames(names) - - rlstore, err := s.LayerStore() - if err != nil { - return err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - if rlstore.Exists(id) { - return rlstore.SetNames(id, deduped) - } - - ristore, err := s.ImageStore() - if err != nil { - return err - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - if ristore.Exists(id) { - return ristore.SetNames(id, deduped) - } - - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - if rcstore.Exists(id) { - return rcstore.SetNames(id, deduped) - } - return ErrLayerUnknown -} - -func (s *store) Names(id string) ([]string, error) { - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if l, err := store.Get(id); l != nil && err == nil { - return l.Names, nil - } - } - - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if i, err := store.Get(id); i != nil && err == nil { - return i.Names, nil - } - } - - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - if c, err := rcstore.Get(id); c != nil && err == nil { - return c.Names, nil - } - return nil, ErrLayerUnknown -} - -func (s *store) Lookup(name string) (string, error) { - lstore, err := s.LayerStore() - if err != nil { - return "", err - } - lstores, err := s.ROLayerStores() - if err != nil { - return "", err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if l, err := store.Get(name); l != nil && err == nil { - return l.ID, nil - } - } - - istore, err := s.ImageStore() - if err != nil { - return "", err - } - istores, err := s.ROImageStores() - if err != nil { - return "", err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if i, err := store.Get(name); i != nil && err == nil { - return i.ID, nil - } - } - - cstore, err := s.ContainerStore() - if err != nil { - return "", err - } - cstore.Lock() - defer cstore.Unlock() - if modified, err := cstore.Modified(); modified || err != nil { - cstore.Load() - } - if c, err := cstore.Get(name); c != nil && err == nil { - return c.ID, nil - } - - return "", ErrLayerUnknown -} - -func (s *store) DeleteLayer(id string) error { - rlstore, err := s.LayerStore() - if err != nil { - return err - } - ristore, err := s.ImageStore() - if err != nil { - return err - } - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - if rlstore.Exists(id) { - if l, err := rlstore.Get(id); err != nil { - id = l.ID - } - layers, err := rlstore.Layers() - if err != nil { - return err - } - for _, layer := range layers { - if layer.Parent == id { - return ErrLayerHasChildren - } - } - images, err := ristore.Images() - if err != nil { - return err - } - for _, image := range images { - if image.TopLayer == id { - return errors.Wrapf(ErrLayerUsedByImage, "Layer %v used by image %v", id, image.ID) - } - } - containers, err := rcstore.Containers() - if err != nil { - return err - } - for _, container := range containers { - if container.LayerID == id { - return errors.Wrapf(ErrLayerUsedByContainer, "Layer %v used by container %v", id, container.ID) - } - } - return rlstore.Delete(id) - } - return ErrNotALayer -} - -func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) { - rlstore, err := s.LayerStore() - if err != nil { - return nil, err - } - ristore, err := s.ImageStore() - if err != nil { - return nil, err - } - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - layersToRemove := []string{} - if ristore.Exists(id) { - image, err := ristore.Get(id) - if err != nil { - return nil, err - } - id = image.ID - containers, err := rcstore.Containers() - if err != nil { - return nil, err - } - aContainerByImage := make(map[string]string) - for _, container := range containers { - aContainerByImage[container.ImageID] = container.ID - } - if container, ok := aContainerByImage[id]; ok { - return nil, errors.Wrapf(ErrImageUsedByContainer, "Image used by %v", container) - } - images, err := ristore.Images() - if err != nil { - return nil, err - } - layers, err := rlstore.Layers() - if err != nil { - return nil, err - } - childrenByParent := make(map[string]*[]string) - for _, layer := range layers { - parent := layer.Parent - if list, ok := childrenByParent[parent]; ok { - newList := append(*list, layer.ID) - childrenByParent[parent] = &newList - } else { - childrenByParent[parent] = &([]string{layer.ID}) - } - } - anyImageByTopLayer := make(map[string]string) - for _, img := range images { - if img.ID != id { - anyImageByTopLayer[img.TopLayer] = img.ID - } - } - if commit { - if err = ristore.Delete(id); err != nil { - return nil, err - } - } - layer := image.TopLayer - lastRemoved := "" - for layer != "" { - if rcstore.Exists(layer) { - break - } - if _, ok := anyImageByTopLayer[layer]; ok { - break - } - parent := "" - if l, err := rlstore.Get(layer); err == nil { - parent = l.Parent - } - otherRefs := 0 - if childList, ok := childrenByParent[layer]; ok && childList != nil { - children := *childList - for _, child := range children { - if child != lastRemoved { - otherRefs++ - } - } - } - if otherRefs != 0 { - break - } - lastRemoved = layer - layersToRemove = append(layersToRemove, lastRemoved) - layer = parent - } - } else { - return nil, ErrNotAnImage - } - if commit { - for _, layer := range layersToRemove { - if err = rlstore.Delete(layer); err != nil { - return nil, err - } - } - } - return layersToRemove, nil -} - -func (s *store) DeleteContainer(id string) error { - rlstore, err := s.LayerStore() - if err != nil { - return err - } - ristore, err := s.ImageStore() - if err != nil { - return err - } - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - if rcstore.Exists(id) { - if container, err := rcstore.Get(id); err == nil { - if rlstore.Exists(container.LayerID) { - if err = rlstore.Delete(container.LayerID); err != nil { - return err - } - if err = rcstore.Delete(id); err != nil { - return err - } - middleDir := s.graphDriverName + "-containers" - gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID) - if err = os.RemoveAll(gcpath); err != nil { - return err - } - rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID) - if err = os.RemoveAll(rcpath); err != nil { - return err - } - return nil - } - return ErrNotALayer - } - } - return ErrNotAContainer -} - -func (s *store) Delete(id string) error { - rlstore, err := s.LayerStore() - if err != nil { - return err - } - ristore, err := s.ImageStore() - if err != nil { - return err - } - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - if rcstore.Exists(id) { - if container, err := rcstore.Get(id); err == nil { - if rlstore.Exists(container.LayerID) { - if err = rlstore.Delete(container.LayerID); err != nil { - return err - } - if err = rcstore.Delete(id); err != nil { - return err - } - middleDir := s.graphDriverName + "-containers" - gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID, "userdata") - if err = os.RemoveAll(gcpath); err != nil { - return err - } - rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID, "userdata") - if err = os.RemoveAll(rcpath); err != nil { - return err - } - return nil - } - return ErrNotALayer - } - } - if ristore.Exists(id) { - return ristore.Delete(id) - } - if rlstore.Exists(id) { - return rlstore.Delete(id) - } - return ErrLayerUnknown -} - -func (s *store) Wipe() error { - rcstore, err := s.ContainerStore() - if err != nil { - return err - } - ristore, err := s.ImageStore() - if err != nil { - return err - } - rlstore, err := s.LayerStore() - if err != nil { - return err - } - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - ristore.Lock() - defer ristore.Unlock() - if modified, err := ristore.Modified(); modified || err != nil { - ristore.Load() - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - if err = rcstore.Wipe(); err != nil { - return err - } - if err = ristore.Wipe(); err != nil { - return err - } - return rlstore.Wipe() -} - -func (s *store) Status() ([][2]string, error) { - rlstore, err := s.LayerStore() - if err != nil { - return nil, err - } - return rlstore.Status() -} - -func (s *store) Version() ([][2]string, error) { - return [][2]string{}, nil -} - -func (s *store) Mount(id, mountLabel string) (string, error) { - if layerID, err := s.ContainerLayerID(id); err == nil { - id = layerID - } - rlstore, err := s.LayerStore() - if err != nil { - return "", err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - if rlstore.Exists(id) { - return rlstore.Mount(id, mountLabel) - } - return "", ErrLayerUnknown -} - -func (s *store) Unmount(id string) error { - if layerID, err := s.ContainerLayerID(id); err == nil { - id = layerID - } - rlstore, err := s.LayerStore() - if err != nil { - return err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - if rlstore.Exists(id) { - return rlstore.Unmount(id) - } - return ErrLayerUnknown -} - -func (s *store) Changes(from, to string) ([]archive.Change, error) { - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(to) { - return store.Changes(from, to) - } - } - return nil, ErrLayerUnknown -} - -func (s *store) DiffSize(from, to string) (int64, error) { - lstore, err := s.LayerStore() - if err != nil { - return -1, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return -1, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(to) { - return store.DiffSize(from, to) - } - } - return -1, ErrLayerUnknown -} - -func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) { - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(to) { - return store.Diff(from, to, options) - } - } - return nil, ErrLayerUnknown -} - -func (s *store) ApplyDiff(to string, diff io.Reader) (int64, error) { - rlstore, err := s.LayerStore() - if err != nil { - return -1, err - } - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - if rlstore.Exists(to) { - return rlstore.ApplyDiff(to, diff) - } - return -1, ErrLayerUnknown -} - -func (s *store) layersByMappedDigest(m func(ROLayerStore, digest.Digest) ([]Layer, error), d digest.Digest) ([]Layer, error) { - var layers []Layer - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - storeLayers, err := m(store, d) - if err != nil { - if errors.Cause(err) != ErrLayerUnknown { - return nil, err - } - continue - } - layers = append(layers, storeLayers...) - } - if len(layers) == 0 { - return nil, ErrLayerUnknown - } - return layers, nil -} - -func (s *store) LayersByCompressedDigest(d digest.Digest) ([]Layer, error) { - if err := d.Validate(); err != nil { - return nil, errors.Wrapf(err, "error looking for compressed layers matching digest %q", d) - } - return s.layersByMappedDigest(func(r ROLayerStore, d digest.Digest) ([]Layer, error) { return r.LayersByCompressedDigest(d) }, d) -} - -func (s *store) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error) { - if err := d.Validate(); err != nil { - return nil, errors.Wrapf(err, "error looking for layers matching digest %q", d) - } - return s.layersByMappedDigest(func(r ROLayerStore, d digest.Digest) ([]Layer, error) { return r.LayersByUncompressedDigest(d) }, d) -} - -func (s *store) LayerSize(id string) (int64, error) { - lstore, err := s.LayerStore() - if err != nil { - return -1, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return -1, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - if store.Exists(id) { - return store.Size(id) - } - } - return -1, ErrLayerUnknown -} - -func (s *store) Layers() ([]Layer, error) { - var layers []Layer - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - storeLayers, err := store.Layers() - if err != nil { - return nil, err - } - layers = append(layers, storeLayers...) - } - return layers, nil -} - -func (s *store) Images() ([]Image, error) { - var images []Image - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - storeImages, err := store.Images() - if err != nil { - return nil, err - } - images = append(images, storeImages...) - } - return images, nil -} - -func (s *store) Containers() ([]Container, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - return rcstore.Containers() -} - -func (s *store) Layer(id string) (*Layer, error) { - lstore, err := s.LayerStore() - if err != nil { - return nil, err - } - lstores, err := s.ROLayerStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - layer, err := store.Get(id) - if err == nil { - return layer, nil - } - } - return nil, ErrLayerUnknown -} - -func (s *store) Image(id string) (*Image, error) { - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - image, err := store.Get(id) - if err == nil { - return image, nil - } - } - return nil, ErrImageUnknown -} - -func (s *store) ImagesByTopLayer(id string) ([]*Image, error) { - images := []*Image{} - layer, err := s.Layer(id) - if err != nil { - return nil, err - } - - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - imageList, err := store.Images() - if err != nil { - return nil, err - } - for _, image := range imageList { - if image.TopLayer == layer.ID { - images = append(images, &image) - } - } - } - return images, nil -} - -func (s *store) ImagesByDigest(d digest.Digest) ([]*Image, error) { - images := []*Image{} - - istore, err := s.ImageStore() - if err != nil { - return nil, err - } - - istores, err := s.ROImageStores() - if err != nil { - return nil, err - } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() - defer store.Unlock() - if modified, err := store.Modified(); modified || err != nil { - store.Load() - } - imageList, err := store.ByDigest(d) - if err != nil && err != ErrImageUnknown { - return nil, err - } - images = append(images, imageList...) - } - return images, nil -} - -func (s *store) Container(id string) (*Container, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - return rcstore.Get(id) -} - -func (s *store) ContainerLayerID(id string) (string, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return "", err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - container, err := rcstore.Get(id) - if err != nil { - return "", err - } - return container.LayerID, nil -} - -func (s *store) ContainerByLayer(id string) (*Container, error) { - layer, err := s.Layer(id) - if err != nil { - return nil, err - } - rcstore, err := s.ContainerStore() - if err != nil { - return nil, err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - containerList, err := rcstore.Containers() - if err != nil { - return nil, err - } - for _, container := range containerList { - if container.LayerID == layer.ID { - return &container, nil - } - } - - return nil, ErrContainerUnknown -} - -func (s *store) ContainerDirectory(id string) (string, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return "", err - } - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - id, err = rcstore.Lookup(id) - if err != nil { - return "", err - } - - middleDir := s.graphDriverName + "-containers" - gcpath := filepath.Join(s.GraphRoot(), middleDir, id, "userdata") - if err := os.MkdirAll(gcpath, 0700); err != nil { - return "", err - } - return gcpath, nil -} - -func (s *store) ContainerRunDirectory(id string) (string, error) { - rcstore, err := s.ContainerStore() - if err != nil { - return "", err - } - - rcstore.Lock() - defer rcstore.Unlock() - if modified, err := rcstore.Modified(); modified || err != nil { - rcstore.Load() - } - - id, err = rcstore.Lookup(id) - if err != nil { - return "", err - } - - middleDir := s.graphDriverName + "-containers" - rcpath := filepath.Join(s.RunRoot(), middleDir, id, "userdata") - if err := os.MkdirAll(rcpath, 0700); err != nil { - return "", err - } - return rcpath, nil -} - -func (s *store) SetContainerDirectoryFile(id, file string, data []byte) error { - dir, err := s.ContainerDirectory(id) - if err != nil { - return err - } - err = os.MkdirAll(filepath.Dir(filepath.Join(dir, file)), 0700) - if err != nil { - return err - } - return ioutils.AtomicWriteFile(filepath.Join(dir, file), data, 0600) -} - -func (s *store) FromContainerDirectory(id, file string) ([]byte, error) { - dir, err := s.ContainerDirectory(id) - if err != nil { - return nil, err - } - return ioutil.ReadFile(filepath.Join(dir, file)) -} - -func (s *store) SetContainerRunDirectoryFile(id, file string, data []byte) error { - dir, err := s.ContainerRunDirectory(id) - if err != nil { - return err - } - err = os.MkdirAll(filepath.Dir(filepath.Join(dir, file)), 0700) - if err != nil { - return err - } - return ioutils.AtomicWriteFile(filepath.Join(dir, file), data, 0600) -} - -func (s *store) FromContainerRunDirectory(id, file string) ([]byte, error) { - dir, err := s.ContainerRunDirectory(id) - if err != nil { - return nil, err - } - return ioutil.ReadFile(filepath.Join(dir, file)) -} - -func (s *store) Shutdown(force bool) ([]string, error) { - mounted := []string{} - modified := false - - rlstore, err := s.LayerStore() - if err != nil { - return mounted, err - } - - s.graphLock.Lock() - defer s.graphLock.Unlock() - - rlstore.Lock() - defer rlstore.Unlock() - if modified, err := rlstore.Modified(); modified || err != nil { - rlstore.Load() - } - - layers, err := rlstore.Layers() - if err != nil { - return mounted, err - } - for _, layer := range layers { - if layer.MountCount == 0 { - continue - } - mounted = append(mounted, layer.ID) - if force { - for layer.MountCount > 0 { - err2 := rlstore.Unmount(layer.ID) - if err2 != nil { - if err == nil { - err = err2 - } - break - } - modified = true - } - } - } - if len(mounted) > 0 && err == nil { - err = errors.Wrap(ErrLayerUsedByContainer, "A layer is mounted") - } - if err == nil { - err = s.graphDriver.Cleanup() - s.graphLock.Touch() - modified = true - } - if modified { - rlstore.Touch() - } - return mounted, err -} - -// Convert a BigData key name into an acceptable file name. -func makeBigDataBaseName(key string) string { - reader := strings.NewReader(key) - for reader.Len() > 0 { - ch, size, err := reader.ReadRune() - if err != nil || size != 1 { - break - } - if ch != '.' && !(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z') { - break - } - } - if reader.Len() > 0 { - return "=" + base64.StdEncoding.EncodeToString([]byte(key)) - } - return key -} - -func stringSliceWithoutValue(slice []string, value string) []string { - modified := make([]string, 0, len(slice)) - for _, v := range slice { - if v == value { - continue - } - modified = append(modified, v) - } - return modified -} - -const configFile = "/etc/containers/storage.conf" - -// OptionsConfig represents the "storage.options" TOML config table. -type OptionsConfig struct { - // AdditionalImagesStores is the location of additional read/only - // Image stores. Usually used to access Networked File System - // for shared image content - AdditionalImageStores []string `toml:"additionalimagestores"` - - // Size - Size string `toml:"size"` - - // OverrideKernelCheck - OverrideKernelCheck string `toml:"override_kernel_check"` -} - -// TOML-friendly explicit tables used for conversions. -type tomlConfig struct { - Storage struct { - Driver string `toml:"driver"` - RunRoot string `toml:"runroot"` - GraphRoot string `toml:"graphroot"` - Options struct{ OptionsConfig } `toml:"options"` - } `toml:"storage"` -} - -func init() { - DefaultStoreOptions.RunRoot = "/var/run/containers/storage" - DefaultStoreOptions.GraphRoot = "/var/lib/containers/storage" - DefaultStoreOptions.GraphDriverName = "" - - data, err := ioutil.ReadFile(configFile) - if err != nil { - if !os.IsNotExist(err) { - fmt.Printf("Failed to read %s %v\n", configFile, err.Error()) - return - } - } - - config := new(tomlConfig) - - if _, err := toml.Decode(string(data), config); err != nil { - fmt.Printf("Failed to parse %s %v\n", configFile, err.Error()) - return - } - if config.Storage.Driver != "" { - DefaultStoreOptions.GraphDriverName = config.Storage.Driver - } - if config.Storage.RunRoot != "" { - DefaultStoreOptions.RunRoot = config.Storage.RunRoot - } - if config.Storage.GraphRoot != "" { - DefaultStoreOptions.GraphRoot = config.Storage.GraphRoot - } - for _, s := range config.Storage.Options.AdditionalImageStores { - DefaultStoreOptions.GraphDriverOptions = append(DefaultStoreOptions.GraphDriverOptions, fmt.Sprintf("%s.imagestore=%s", config.Storage.Driver, s)) - } - if config.Storage.Options.Size != "" { - DefaultStoreOptions.GraphDriverOptions = append(DefaultStoreOptions.GraphDriverOptions, fmt.Sprintf("%s.size=%s", config.Storage.Driver, config.Storage.Options.Size)) - } - if config.Storage.Options.OverrideKernelCheck != "" { - DefaultStoreOptions.GraphDriverOptions = append(DefaultStoreOptions.GraphDriverOptions, fmt.Sprintf("%s.override_kernel_check=%s", config.Storage.Driver, config.Storage.Options.OverrideKernelCheck)) - } - if os.Getenv("STORAGE_DRIVER") != "" { - DefaultStoreOptions.GraphDriverName = os.Getenv("STORAGE_DRIVER") - } - if os.Getenv("STORAGE_OPTS") != "" { - DefaultStoreOptions.GraphDriverOptions = append(DefaultStoreOptions.GraphDriverOptions, strings.Split(os.Getenv("STORAGE_OPTS"), ",")...) - } - if len(DefaultStoreOptions.GraphDriverOptions) == 1 && DefaultStoreOptions.GraphDriverOptions[0] == "" { - DefaultStoreOptions.GraphDriverOptions = nil - } -} diff --git a/vendor/github.com/docker/distribution/AUTHORS b/vendor/github.com/docker/distribution/AUTHORS deleted file mode 100644 index 252ff8aa2a..0000000000 --- a/vendor/github.com/docker/distribution/AUTHORS +++ /dev/null @@ -1,182 +0,0 @@ -a-palchikov -Aaron Lehmann -Aaron Schlesinger -Aaron Vinson -Adam Duke -Adam Enger -Adrian Mouat -Ahmet Alp Balkan -Alex Chan -Alex Elman -Alexey Gladkov -allencloud -amitshukla -Amy Lindburg -Andrew Hsu -Andrew Meredith -Andrew T Nguyen -Andrey Kostov -Andy Goldstein -Anis Elleuch -Anton Tiurin -Antonio Mercado -Antonio Murdaca -Anusha Ragunathan -Arien Holthuizen -Arnaud Porterie -Arthur Baars -Asuka Suzuki -Avi Miller -Ayose Cazorla -BadZen -Ben Bodenmiller -Ben Firshman -bin liu -Brian Bland -burnettk -Carson A -Cezar Sa Espinola -Charles Smith -Chris Dillon -cuiwei13 -cyli -Daisuke Fujita -Daniel Huhn -Darren Shepherd -Dave Trombley -Dave Tucker -David Lawrence -David Verhasselt -David Xia -davidli -Dejan Golja -Derek McGowan -Diogo Mónica -DJ Enriquez -Donald Huang -Doug Davis -Edgar Lee -Eric Yang -Fabio Berchtold -Fabio Huser -farmerworking -Felix Yan -Florentin Raud -Frank Chen -Frederick F. Kautz IV -gabriell nascimento -Gleb Schukin -harche -Henri Gomez -Hu Keping -Hua Wang -HuKeping -Ian Babrou -igayoso -Jack Griffin -James Findley -Jason Freidman -Jason Heiss -Jeff Nickoloff -Jess Frazelle -Jessie Frazelle -jhaohai -Jianqing Wang -Jihoon Chung -Joao Fernandes -John Mulhausen -John Starks -Jon Johnson -Jon Poler -Jonathan Boulle -Jordan Liggitt -Josh Chorlton -Josh Hawn -Julien Fernandez -Ke Xu -Keerthan Mala -Kelsey Hightower -Kenneth Lim -Kenny Leung -Li Yi -Liu Hua -liuchang0812 -Lloyd Ramey -Louis Kottmann -Luke Carpenter -Marcus Martins -Mary Anthony -Matt Bentley -Matt Duch -Matt Moore -Matt Robenolt -Matthew Green -Michael Prokop -Michal Minar -Michal Minář -Mike Brown -Miquel Sabaté -Misty Stanley-Jones -Misty Stanley-Jones -Morgan Bauer -moxiegirl -Nathan Sullivan -nevermosby -Nghia Tran -Nikita Tarasov -Noah Treuhaft -Nuutti Kotivuori -Oilbeater -Olivier Gambier -Olivier Jacques -Omer Cohen -Patrick Devine -Phil Estes -Philip Misiowiec -Pierre-Yves Ritschard -Qiao Anran -Randy Barlow -Richard Scothern -Rodolfo Carvalho -Rusty Conover -Sean Boran -Sebastiaan van Stijn -Sebastien Coavoux -Serge Dubrouski -Sharif Nassar -Shawn Falkner-Horine -Shreyas Karnik -Simon Thulbourn -spacexnice -Spencer Rinehart -Stan Hu -Stefan Majewsky -Stefan Weil -Stephen J Day -Sungho Moon -Sven Dowideit -Sylvain Baubeau -Ted Reed -tgic -Thomas Sjögren -Tianon Gravi -Tibor Vass -Tonis Tiigi -Tony Holdstock-Brown -Trevor Pounds -Troels Thomsen -Victor Vieux -Victoria Bialas -Vincent Batts -Vincent Demeester -Vincent Giersch -W. Trevor King -weiyuan.yl -xg.song -xiekeyang -Yann ROBERT -yaoyao.xyy -yuexiao-wang -yuzou -zhouhaibing089 -姜继忠 diff --git a/vendor/github.com/docker/distribution/LICENSE b/vendor/github.com/docker/distribution/LICENSE deleted file mode 100644 index e06d208186..0000000000 --- a/vendor/github.com/docker/distribution/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/vendor/github.com/docker/distribution/blobs.go b/vendor/github.com/docker/distribution/blobs.go deleted file mode 100644 index 145b078532..0000000000 --- a/vendor/github.com/docker/distribution/blobs.go +++ /dev/null @@ -1,257 +0,0 @@ -package distribution - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "time" - - "github.com/docker/distribution/reference" - "github.com/opencontainers/go-digest" -) - -var ( - // ErrBlobExists returned when blob already exists - ErrBlobExists = errors.New("blob exists") - - // ErrBlobDigestUnsupported when blob digest is an unsupported version. - ErrBlobDigestUnsupported = errors.New("unsupported blob digest") - - // ErrBlobUnknown when blob is not found. - ErrBlobUnknown = errors.New("unknown blob") - - // ErrBlobUploadUnknown returned when upload is not found. - ErrBlobUploadUnknown = errors.New("blob upload unknown") - - // ErrBlobInvalidLength returned when the blob has an expected length on - // commit, meaning mismatched with the descriptor or an invalid value. - ErrBlobInvalidLength = errors.New("blob invalid length") -) - -// ErrBlobInvalidDigest returned when digest check fails. -type ErrBlobInvalidDigest struct { - Digest digest.Digest - Reason error -} - -func (err ErrBlobInvalidDigest) Error() string { - return fmt.Sprintf("invalid digest for referenced layer: %v, %v", - err.Digest, err.Reason) -} - -// ErrBlobMounted returned when a blob is mounted from another repository -// instead of initiating an upload session. -type ErrBlobMounted struct { - From reference.Canonical - Descriptor Descriptor -} - -func (err ErrBlobMounted) Error() string { - return fmt.Sprintf("blob mounted from: %v to: %v", - err.From, err.Descriptor) -} - -// Descriptor describes targeted content. Used in conjunction with a blob -// store, a descriptor can be used to fetch, store and target any kind of -// blob. The struct also describes the wire protocol format. Fields should -// only be added but never changed. -type Descriptor struct { - // MediaType describe the type of the content. All text based formats are - // encoded as utf-8. - MediaType string `json:"mediaType,omitempty"` - - // Size in bytes of content. - Size int64 `json:"size,omitempty"` - - // Digest uniquely identifies the content. A byte stream can be verified - // against against this digest. - Digest digest.Digest `json:"digest,omitempty"` - - // URLs contains the source URLs of this content. - URLs []string `json:"urls,omitempty"` - - // NOTE: Before adding a field here, please ensure that all - // other options have been exhausted. Much of the type relationships - // depend on the simplicity of this type. -} - -// Descriptor returns the descriptor, to make it satisfy the Describable -// interface. Note that implementations of Describable are generally objects -// which can be described, not simply descriptors; this exception is in place -// to make it more convenient to pass actual descriptors to functions that -// expect Describable objects. -func (d Descriptor) Descriptor() Descriptor { - return d -} - -// BlobStatter makes blob descriptors available by digest. The service may -// provide a descriptor of a different digest if the provided digest is not -// canonical. -type BlobStatter interface { - // Stat provides metadata about a blob identified by the digest. If the - // blob is unknown to the describer, ErrBlobUnknown will be returned. - Stat(ctx context.Context, dgst digest.Digest) (Descriptor, error) -} - -// BlobDeleter enables deleting blobs from storage. -type BlobDeleter interface { - Delete(ctx context.Context, dgst digest.Digest) error -} - -// BlobEnumerator enables iterating over blobs from storage -type BlobEnumerator interface { - Enumerate(ctx context.Context, ingester func(dgst digest.Digest) error) error -} - -// BlobDescriptorService manages metadata about a blob by digest. Most -// implementations will not expose such an interface explicitly. Such mappings -// should be maintained by interacting with the BlobIngester. Hence, this is -// left off of BlobService and BlobStore. -type BlobDescriptorService interface { - BlobStatter - - // SetDescriptor assigns the descriptor to the digest. The provided digest and - // the digest in the descriptor must map to identical content but they may - // differ on their algorithm. The descriptor must have the canonical - // digest of the content and the digest algorithm must match the - // annotators canonical algorithm. - // - // Such a facility can be used to map blobs between digest domains, with - // the restriction that the algorithm of the descriptor must match the - // canonical algorithm (ie sha256) of the annotator. - SetDescriptor(ctx context.Context, dgst digest.Digest, desc Descriptor) error - - // Clear enables descriptors to be unlinked - Clear(ctx context.Context, dgst digest.Digest) error -} - -// BlobDescriptorServiceFactory creates middleware for BlobDescriptorService. -type BlobDescriptorServiceFactory interface { - BlobAccessController(svc BlobDescriptorService) BlobDescriptorService -} - -// ReadSeekCloser is the primary reader type for blob data, combining -// io.ReadSeeker with io.Closer. -type ReadSeekCloser interface { - io.ReadSeeker - io.Closer -} - -// BlobProvider describes operations for getting blob data. -type BlobProvider interface { - // Get returns the entire blob identified by digest along with the descriptor. - Get(ctx context.Context, dgst digest.Digest) ([]byte, error) - - // Open provides a ReadSeekCloser to the blob identified by the provided - // descriptor. If the blob is not known to the service, an error will be - // returned. - Open(ctx context.Context, dgst digest.Digest) (ReadSeekCloser, error) -} - -// BlobServer can serve blobs via http. -type BlobServer interface { - // ServeBlob attempts to serve the blob, identified by dgst, via http. The - // service may decide to redirect the client elsewhere or serve the data - // directly. - // - // This handler only issues successful responses, such as 2xx or 3xx, - // meaning it serves data or issues a redirect. If the blob is not - // available, an error will be returned and the caller may still issue a - // response. - // - // The implementation may serve the same blob from a different digest - // domain. The appropriate headers will be set for the blob, unless they - // have already been set by the caller. - ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error -} - -// BlobIngester ingests blob data. -type BlobIngester interface { - // Put inserts the content p into the blob service, returning a descriptor - // or an error. - Put(ctx context.Context, mediaType string, p []byte) (Descriptor, error) - - // Create allocates a new blob writer to add a blob to this service. The - // returned handle can be written to and later resumed using an opaque - // identifier. With this approach, one can Close and Resume a BlobWriter - // multiple times until the BlobWriter is committed or cancelled. - Create(ctx context.Context, options ...BlobCreateOption) (BlobWriter, error) - - // Resume attempts to resume a write to a blob, identified by an id. - Resume(ctx context.Context, id string) (BlobWriter, error) -} - -// BlobCreateOption is a general extensible function argument for blob creation -// methods. A BlobIngester may choose to honor any or none of the given -// BlobCreateOptions, which can be specific to the implementation of the -// BlobIngester receiving them. -// TODO (brianbland): unify this with ManifestServiceOption in the future -type BlobCreateOption interface { - Apply(interface{}) error -} - -// CreateOptions is a collection of blob creation modifiers relevant to general -// blob storage intended to be configured by the BlobCreateOption.Apply method. -type CreateOptions struct { - Mount struct { - ShouldMount bool - From reference.Canonical - // Stat allows to pass precalculated descriptor to link and return. - // Blob access check will be skipped if set. - Stat *Descriptor - } -} - -// BlobWriter provides a handle for inserting data into a blob store. -// Instances should be obtained from BlobWriteService.Writer and -// BlobWriteService.Resume. If supported by the store, a writer can be -// recovered with the id. -type BlobWriter interface { - io.WriteCloser - io.ReaderFrom - - // Size returns the number of bytes written to this blob. - Size() int64 - - // ID returns the identifier for this writer. The ID can be used with the - // Blob service to later resume the write. - ID() string - - // StartedAt returns the time this blob write was started. - StartedAt() time.Time - - // Commit completes the blob writer process. The content is verified - // against the provided provisional descriptor, which may result in an - // error. Depending on the implementation, written data may be validated - // against the provisional descriptor fields. If MediaType is not present, - // the implementation may reject the commit or assign "application/octet- - // stream" to the blob. The returned descriptor may have a different - // digest depending on the blob store, referred to as the canonical - // descriptor. - Commit(ctx context.Context, provisional Descriptor) (canonical Descriptor, err error) - - // Cancel ends the blob write without storing any data and frees any - // associated resources. Any data written thus far will be lost. Cancel - // implementations should allow multiple calls even after a commit that - // result in a no-op. This allows use of Cancel in a defer statement, - // increasing the assurance that it is correctly called. - Cancel(ctx context.Context) error -} - -// BlobService combines the operations to access, read and write blobs. This -// can be used to describe remote blob services. -type BlobService interface { - BlobStatter - BlobProvider - BlobIngester -} - -// BlobStore represent the entire suite of blob related operations. Such an -// implementation can access, read, write, delete and serve blobs. -type BlobStore interface { - BlobService - BlobServer - BlobDeleter -} diff --git a/vendor/github.com/docker/distribution/digestset/set.go b/vendor/github.com/docker/distribution/digestset/set.go deleted file mode 100644 index 71327dca72..0000000000 --- a/vendor/github.com/docker/distribution/digestset/set.go +++ /dev/null @@ -1,247 +0,0 @@ -package digestset - -import ( - "errors" - "sort" - "strings" - "sync" - - digest "github.com/opencontainers/go-digest" -) - -var ( - // ErrDigestNotFound is used when a matching digest - // could not be found in a set. - ErrDigestNotFound = errors.New("digest not found") - - // ErrDigestAmbiguous is used when multiple digests - // are found in a set. None of the matching digests - // should be considered valid matches. - ErrDigestAmbiguous = errors.New("ambiguous digest string") -) - -// Set is used to hold a unique set of digests which -// may be easily referenced by easily referenced by a string -// representation of the digest as well as short representation. -// The uniqueness of the short representation is based on other -// digests in the set. If digests are omitted from this set, -// collisions in a larger set may not be detected, therefore it -// is important to always do short representation lookups on -// the complete set of digests. To mitigate collisions, an -// appropriately long short code should be used. -type Set struct { - mutex sync.RWMutex - entries digestEntries -} - -// NewSet creates an empty set of digests -// which may have digests added. -func NewSet() *Set { - return &Set{ - entries: digestEntries{}, - } -} - -// checkShortMatch checks whether two digests match as either whole -// values or short values. This function does not test equality, -// rather whether the second value could match against the first -// value. -func checkShortMatch(alg digest.Algorithm, hex, shortAlg, shortHex string) bool { - if len(hex) == len(shortHex) { - if hex != shortHex { - return false - } - if len(shortAlg) > 0 && string(alg) != shortAlg { - return false - } - } else if !strings.HasPrefix(hex, shortHex) { - return false - } else if len(shortAlg) > 0 && string(alg) != shortAlg { - return false - } - return true -} - -// Lookup looks for a digest matching the given string representation. -// If no digests could be found ErrDigestNotFound will be returned -// with an empty digest value. If multiple matches are found -// ErrDigestAmbiguous will be returned with an empty digest value. -func (dst *Set) Lookup(d string) (digest.Digest, error) { - dst.mutex.RLock() - defer dst.mutex.RUnlock() - if len(dst.entries) == 0 { - return "", ErrDigestNotFound - } - var ( - searchFunc func(int) bool - alg digest.Algorithm - hex string - ) - dgst, err := digest.Parse(d) - if err == digest.ErrDigestInvalidFormat { - hex = d - searchFunc = func(i int) bool { - return dst.entries[i].val >= d - } - } else { - hex = dgst.Hex() - alg = dgst.Algorithm() - searchFunc = func(i int) bool { - if dst.entries[i].val == hex { - return dst.entries[i].alg >= alg - } - return dst.entries[i].val >= hex - } - } - idx := sort.Search(len(dst.entries), searchFunc) - if idx == len(dst.entries) || !checkShortMatch(dst.entries[idx].alg, dst.entries[idx].val, string(alg), hex) { - return "", ErrDigestNotFound - } - if dst.entries[idx].alg == alg && dst.entries[idx].val == hex { - return dst.entries[idx].digest, nil - } - if idx+1 < len(dst.entries) && checkShortMatch(dst.entries[idx+1].alg, dst.entries[idx+1].val, string(alg), hex) { - return "", ErrDigestAmbiguous - } - - return dst.entries[idx].digest, nil -} - -// Add adds the given digest to the set. An error will be returned -// if the given digest is invalid. If the digest already exists in the -// set, this operation will be a no-op. -func (dst *Set) Add(d digest.Digest) error { - if err := d.Validate(); err != nil { - return err - } - dst.mutex.Lock() - defer dst.mutex.Unlock() - entry := &digestEntry{alg: d.Algorithm(), val: d.Hex(), digest: d} - searchFunc := func(i int) bool { - if dst.entries[i].val == entry.val { - return dst.entries[i].alg >= entry.alg - } - return dst.entries[i].val >= entry.val - } - idx := sort.Search(len(dst.entries), searchFunc) - if idx == len(dst.entries) { - dst.entries = append(dst.entries, entry) - return nil - } else if dst.entries[idx].digest == d { - return nil - } - - entries := append(dst.entries, nil) - copy(entries[idx+1:], entries[idx:len(entries)-1]) - entries[idx] = entry - dst.entries = entries - return nil -} - -// Remove removes the given digest from the set. An err will be -// returned if the given digest is invalid. If the digest does -// not exist in the set, this operation will be a no-op. -func (dst *Set) Remove(d digest.Digest) error { - if err := d.Validate(); err != nil { - return err - } - dst.mutex.Lock() - defer dst.mutex.Unlock() - entry := &digestEntry{alg: d.Algorithm(), val: d.Hex(), digest: d} - searchFunc := func(i int) bool { - if dst.entries[i].val == entry.val { - return dst.entries[i].alg >= entry.alg - } - return dst.entries[i].val >= entry.val - } - idx := sort.Search(len(dst.entries), searchFunc) - // Not found if idx is after or value at idx is not digest - if idx == len(dst.entries) || dst.entries[idx].digest != d { - return nil - } - - entries := dst.entries - copy(entries[idx:], entries[idx+1:]) - entries = entries[:len(entries)-1] - dst.entries = entries - - return nil -} - -// All returns all the digests in the set -func (dst *Set) All() []digest.Digest { - dst.mutex.RLock() - defer dst.mutex.RUnlock() - retValues := make([]digest.Digest, len(dst.entries)) - for i := range dst.entries { - retValues[i] = dst.entries[i].digest - } - - return retValues -} - -// ShortCodeTable returns a map of Digest to unique short codes. The -// length represents the minimum value, the maximum length may be the -// entire value of digest if uniqueness cannot be achieved without the -// full value. This function will attempt to make short codes as short -// as possible to be unique. -func ShortCodeTable(dst *Set, length int) map[digest.Digest]string { - dst.mutex.RLock() - defer dst.mutex.RUnlock() - m := make(map[digest.Digest]string, len(dst.entries)) - l := length - resetIdx := 0 - for i := 0; i < len(dst.entries); i++ { - var short string - extended := true - for extended { - extended = false - if len(dst.entries[i].val) <= l { - short = dst.entries[i].digest.String() - } else { - short = dst.entries[i].val[:l] - for j := i + 1; j < len(dst.entries); j++ { - if checkShortMatch(dst.entries[j].alg, dst.entries[j].val, "", short) { - if j > resetIdx { - resetIdx = j - } - extended = true - } else { - break - } - } - if extended { - l++ - } - } - } - m[dst.entries[i].digest] = short - if i >= resetIdx { - l = length - } - } - return m -} - -type digestEntry struct { - alg digest.Algorithm - val string - digest digest.Digest -} - -type digestEntries []*digestEntry - -func (d digestEntries) Len() int { - return len(d) -} - -func (d digestEntries) Less(i, j int) bool { - if d[i].val != d[j].val { - return d[i].val < d[j].val - } - return d[i].alg < d[j].alg -} - -func (d digestEntries) Swap(i, j int) { - d[i], d[j] = d[j], d[i] -} diff --git a/vendor/github.com/docker/distribution/doc.go b/vendor/github.com/docker/distribution/doc.go deleted file mode 100644 index bdd8cb708e..0000000000 --- a/vendor/github.com/docker/distribution/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Package distribution will define the interfaces for the components of -// docker distribution. The goal is to allow users to reliably package, ship -// and store content related to docker images. -// -// This is currently a work in progress. More details are available in the -// README.md. -package distribution diff --git a/vendor/github.com/docker/distribution/errors.go b/vendor/github.com/docker/distribution/errors.go deleted file mode 100644 index 020d33258b..0000000000 --- a/vendor/github.com/docker/distribution/errors.go +++ /dev/null @@ -1,115 +0,0 @@ -package distribution - -import ( - "errors" - "fmt" - "strings" - - "github.com/opencontainers/go-digest" -) - -// ErrAccessDenied is returned when an access to a requested resource is -// denied. -var ErrAccessDenied = errors.New("access denied") - -// ErrManifestNotModified is returned when a conditional manifest GetByTag -// returns nil due to the client indicating it has the latest version -var ErrManifestNotModified = errors.New("manifest not modified") - -// ErrUnsupported is returned when an unimplemented or unsupported action is -// performed -var ErrUnsupported = errors.New("operation unsupported") - -// ErrTagUnknown is returned if the given tag is not known by the tag service -type ErrTagUnknown struct { - Tag string -} - -func (err ErrTagUnknown) Error() string { - return fmt.Sprintf("unknown tag=%s", err.Tag) -} - -// ErrRepositoryUnknown is returned if the named repository is not known by -// the registry. -type ErrRepositoryUnknown struct { - Name string -} - -func (err ErrRepositoryUnknown) Error() string { - return fmt.Sprintf("unknown repository name=%s", err.Name) -} - -// ErrRepositoryNameInvalid should be used to denote an invalid repository -// name. Reason may set, indicating the cause of invalidity. -type ErrRepositoryNameInvalid struct { - Name string - Reason error -} - -func (err ErrRepositoryNameInvalid) Error() string { - return fmt.Sprintf("repository name %q invalid: %v", err.Name, err.Reason) -} - -// ErrManifestUnknown is returned if the manifest is not known by the -// registry. -type ErrManifestUnknown struct { - Name string - Tag string -} - -func (err ErrManifestUnknown) Error() string { - return fmt.Sprintf("unknown manifest name=%s tag=%s", err.Name, err.Tag) -} - -// ErrManifestUnknownRevision is returned when a manifest cannot be found by -// revision within a repository. -type ErrManifestUnknownRevision struct { - Name string - Revision digest.Digest -} - -func (err ErrManifestUnknownRevision) Error() string { - return fmt.Sprintf("unknown manifest name=%s revision=%s", err.Name, err.Revision) -} - -// ErrManifestUnverified is returned when the registry is unable to verify -// the manifest. -type ErrManifestUnverified struct{} - -func (ErrManifestUnverified) Error() string { - return "unverified manifest" -} - -// ErrManifestVerification provides a type to collect errors encountered -// during manifest verification. Currently, it accepts errors of all types, -// but it may be narrowed to those involving manifest verification. -type ErrManifestVerification []error - -func (errs ErrManifestVerification) Error() string { - var parts []string - for _, err := range errs { - parts = append(parts, err.Error()) - } - - return fmt.Sprintf("errors verifying manifest: %v", strings.Join(parts, ",")) -} - -// ErrManifestBlobUnknown returned when a referenced blob cannot be found. -type ErrManifestBlobUnknown struct { - Digest digest.Digest -} - -func (err ErrManifestBlobUnknown) Error() string { - return fmt.Sprintf("unknown blob %v on manifest", err.Digest) -} - -// ErrManifestNameInvalid should be used to denote an invalid manifest -// name. Reason may set, indicating the cause of invalidity. -type ErrManifestNameInvalid struct { - Name string - Reason error -} - -func (err ErrManifestNameInvalid) Error() string { - return fmt.Sprintf("manifest name %q invalid: %v", err.Name, err.Reason) -} diff --git a/vendor/github.com/docker/distribution/manifests.go b/vendor/github.com/docker/distribution/manifests.go deleted file mode 100644 index 1816baea1d..0000000000 --- a/vendor/github.com/docker/distribution/manifests.go +++ /dev/null @@ -1,125 +0,0 @@ -package distribution - -import ( - "context" - "fmt" - "mime" - - "github.com/opencontainers/go-digest" -) - -// Manifest represents a registry object specifying a set of -// references and an optional target -type Manifest interface { - // References returns a list of objects which make up this manifest. - // A reference is anything which can be represented by a - // distribution.Descriptor. These can consist of layers, resources or other - // manifests. - // - // While no particular order is required, implementations should return - // them from highest to lowest priority. For example, one might want to - // return the base layer before the top layer. - References() []Descriptor - - // Payload provides the serialized format of the manifest, in addition to - // the media type. - Payload() (mediaType string, payload []byte, err error) -} - -// ManifestBuilder creates a manifest allowing one to include dependencies. -// Instances can be obtained from a version-specific manifest package. Manifest -// specific data is passed into the function which creates the builder. -type ManifestBuilder interface { - // Build creates the manifest from his builder. - Build(ctx context.Context) (Manifest, error) - - // References returns a list of objects which have been added to this - // builder. The dependencies are returned in the order they were added, - // which should be from base to head. - References() []Descriptor - - // AppendReference includes the given object in the manifest after any - // existing dependencies. If the add fails, such as when adding an - // unsupported dependency, an error may be returned. - // - // The destination of the reference is dependent on the manifest type and - // the dependency type. - AppendReference(dependency Describable) error -} - -// ManifestService describes operations on image manifests. -type ManifestService interface { - // Exists returns true if the manifest exists. - Exists(ctx context.Context, dgst digest.Digest) (bool, error) - - // Get retrieves the manifest specified by the given digest - Get(ctx context.Context, dgst digest.Digest, options ...ManifestServiceOption) (Manifest, error) - - // Put creates or updates the given manifest returning the manifest digest - Put(ctx context.Context, manifest Manifest, options ...ManifestServiceOption) (digest.Digest, error) - - // Delete removes the manifest specified by the given digest. Deleting - // a manifest that doesn't exist will return ErrManifestNotFound - Delete(ctx context.Context, dgst digest.Digest) error -} - -// ManifestEnumerator enables iterating over manifests -type ManifestEnumerator interface { - // Enumerate calls ingester for each manifest. - Enumerate(ctx context.Context, ingester func(digest.Digest) error) error -} - -// Describable is an interface for descriptors -type Describable interface { - Descriptor() Descriptor -} - -// ManifestMediaTypes returns the supported media types for manifests. -func ManifestMediaTypes() (mediaTypes []string) { - for t := range mappings { - if t != "" { - mediaTypes = append(mediaTypes, t) - } - } - return -} - -// UnmarshalFunc implements manifest unmarshalling a given MediaType -type UnmarshalFunc func([]byte) (Manifest, Descriptor, error) - -var mappings = make(map[string]UnmarshalFunc, 0) - -// UnmarshalManifest looks up manifest unmarshal functions based on -// MediaType -func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) { - // Need to look up by the actual media type, not the raw contents of - // the header. Strip semicolons and anything following them. - var mediaType string - if ctHeader != "" { - var err error - mediaType, _, err = mime.ParseMediaType(ctHeader) - if err != nil { - return nil, Descriptor{}, err - } - } - - unmarshalFunc, ok := mappings[mediaType] - if !ok { - unmarshalFunc, ok = mappings[""] - if !ok { - return nil, Descriptor{}, fmt.Errorf("unsupported manifest media type and no default available: %s", mediaType) - } - } - - return unmarshalFunc(p) -} - -// RegisterManifestSchema registers an UnmarshalFunc for a given schema type. This -// should be called from specific -func RegisterManifestSchema(mediaType string, u UnmarshalFunc) error { - if _, ok := mappings[mediaType]; ok { - return fmt.Errorf("manifest media type registration would overwrite existing: %s", mediaType) - } - mappings[mediaType] = u - return nil -} diff --git a/vendor/github.com/docker/distribution/metrics/prometheus.go b/vendor/github.com/docker/distribution/metrics/prometheus.go deleted file mode 100644 index b5a5321448..0000000000 --- a/vendor/github.com/docker/distribution/metrics/prometheus.go +++ /dev/null @@ -1,13 +0,0 @@ -package metrics - -import "github.com/docker/go-metrics" - -const ( - // NamespacePrefix is the namespace of prometheus metrics - NamespacePrefix = "registry" -) - -var ( - // StorageNamespace is the prometheus namespace of blob/cache related operations - StorageNamespace = metrics.NewNamespace(NamespacePrefix, "storage", nil) -) diff --git a/vendor/github.com/docker/distribution/reference/helpers.go b/vendor/github.com/docker/distribution/reference/helpers.go deleted file mode 100644 index 978df7eabb..0000000000 --- a/vendor/github.com/docker/distribution/reference/helpers.go +++ /dev/null @@ -1,42 +0,0 @@ -package reference - -import "path" - -// IsNameOnly returns true if reference only contains a repo name. -func IsNameOnly(ref Named) bool { - if _, ok := ref.(NamedTagged); ok { - return false - } - if _, ok := ref.(Canonical); ok { - return false - } - return true -} - -// FamiliarName returns the familiar name string -// for the given named, familiarizing if needed. -func FamiliarName(ref Named) string { - if nn, ok := ref.(normalizedNamed); ok { - return nn.Familiar().Name() - } - return ref.Name() -} - -// FamiliarString returns the familiar string representation -// for the given reference, familiarizing if needed. -func FamiliarString(ref Reference) string { - if nn, ok := ref.(normalizedNamed); ok { - return nn.Familiar().String() - } - return ref.String() -} - -// FamiliarMatch reports whether ref matches the specified pattern. -// See https://godoc.org/path#Match for supported patterns. -func FamiliarMatch(pattern string, ref Reference) (bool, error) { - matched, err := path.Match(pattern, FamiliarString(ref)) - if namedRef, isNamed := ref.(Named); isNamed && !matched { - matched, _ = path.Match(pattern, FamiliarName(namedRef)) - } - return matched, err -} diff --git a/vendor/github.com/docker/distribution/reference/normalize.go b/vendor/github.com/docker/distribution/reference/normalize.go deleted file mode 100644 index 2d71fc5e9f..0000000000 --- a/vendor/github.com/docker/distribution/reference/normalize.go +++ /dev/null @@ -1,170 +0,0 @@ -package reference - -import ( - "errors" - "fmt" - "strings" - - "github.com/docker/distribution/digestset" - "github.com/opencontainers/go-digest" -) - -var ( - legacyDefaultDomain = "index.docker.io" - defaultDomain = "docker.io" - officialRepoName = "library" - defaultTag = "latest" -) - -// normalizedNamed represents a name which has been -// normalized and has a familiar form. A familiar name -// is what is used in Docker UI. An example normalized -// name is "docker.io/library/ubuntu" and corresponding -// familiar name of "ubuntu". -type normalizedNamed interface { - Named - Familiar() Named -} - -// ParseNormalizedNamed parses a string into a named reference -// transforming a familiar name from Docker UI to a fully -// qualified reference. If the value may be an identifier -// use ParseAnyReference. -func ParseNormalizedNamed(s string) (Named, error) { - if ok := anchoredIdentifierRegexp.MatchString(s); ok { - return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s) - } - domain, remainder := splitDockerDomain(s) - var remoteName string - if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 { - remoteName = remainder[:tagSep] - } else { - remoteName = remainder - } - if strings.ToLower(remoteName) != remoteName { - return nil, errors.New("invalid reference format: repository name must be lowercase") - } - - ref, err := Parse(domain + "/" + remainder) - if err != nil { - return nil, err - } - named, isNamed := ref.(Named) - if !isNamed { - return nil, fmt.Errorf("reference %s has no name", ref.String()) - } - return named, nil -} - -// splitDockerDomain splits a repository name to domain and remotename string. -// If no valid domain is found, the default domain is used. Repository name -// needs to be already validated before. -func splitDockerDomain(name string) (domain, remainder string) { - i := strings.IndexRune(name, '/') - if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") { - domain, remainder = defaultDomain, name - } else { - domain, remainder = name[:i], name[i+1:] - } - if domain == legacyDefaultDomain { - domain = defaultDomain - } - if domain == defaultDomain && !strings.ContainsRune(remainder, '/') { - remainder = officialRepoName + "/" + remainder - } - return -} - -// familiarizeName returns a shortened version of the name familiar -// to to the Docker UI. Familiar names have the default domain -// "docker.io" and "library/" repository prefix removed. -// For example, "docker.io/library/redis" will have the familiar -// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp". -// Returns a familiarized named only reference. -func familiarizeName(named namedRepository) repository { - repo := repository{ - domain: named.Domain(), - path: named.Path(), - } - - if repo.domain == defaultDomain { - repo.domain = "" - // Handle official repositories which have the pattern "library/" - if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName { - repo.path = split[1] - } - } - return repo -} - -func (r reference) Familiar() Named { - return reference{ - namedRepository: familiarizeName(r.namedRepository), - tag: r.tag, - digest: r.digest, - } -} - -func (r repository) Familiar() Named { - return familiarizeName(r) -} - -func (t taggedReference) Familiar() Named { - return taggedReference{ - namedRepository: familiarizeName(t.namedRepository), - tag: t.tag, - } -} - -func (c canonicalReference) Familiar() Named { - return canonicalReference{ - namedRepository: familiarizeName(c.namedRepository), - digest: c.digest, - } -} - -// TagNameOnly adds the default tag "latest" to a reference if it only has -// a repo name. -func TagNameOnly(ref Named) Named { - if IsNameOnly(ref) { - namedTagged, err := WithTag(ref, defaultTag) - if err != nil { - // Default tag must be valid, to create a NamedTagged - // type with non-validated input the WithTag function - // should be used instead - panic(err) - } - return namedTagged - } - return ref -} - -// ParseAnyReference parses a reference string as a possible identifier, -// full digest, or familiar name. -func ParseAnyReference(ref string) (Reference, error) { - if ok := anchoredIdentifierRegexp.MatchString(ref); ok { - return digestReference("sha256:" + ref), nil - } - if dgst, err := digest.Parse(ref); err == nil { - return digestReference(dgst), nil - } - - return ParseNormalizedNamed(ref) -} - -// ParseAnyReferenceWithSet parses a reference string as a possible short -// identifier to be matched in a digest set, a full digest, or familiar name. -func ParseAnyReferenceWithSet(ref string, ds *digestset.Set) (Reference, error) { - if ok := anchoredShortIdentifierRegexp.MatchString(ref); ok { - dgst, err := ds.Lookup(ref) - if err == nil { - return digestReference(dgst), nil - } - } else { - if dgst, err := digest.Parse(ref); err == nil { - return digestReference(dgst), nil - } - } - - return ParseNormalizedNamed(ref) -} diff --git a/vendor/github.com/docker/distribution/reference/reference.go b/vendor/github.com/docker/distribution/reference/reference.go deleted file mode 100644 index 2f66cca87a..0000000000 --- a/vendor/github.com/docker/distribution/reference/reference.go +++ /dev/null @@ -1,433 +0,0 @@ -// Package reference provides a general type to represent any way of referencing images within the registry. -// Its main purpose is to abstract tags and digests (content-addressable hash). -// -// Grammar -// -// reference := name [ ":" tag ] [ "@" digest ] -// name := [domain '/'] path-component ['/' path-component]* -// domain := domain-component ['.' domain-component]* [':' port-number] -// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/ -// port-number := /[0-9]+/ -// path-component := alpha-numeric [separator alpha-numeric]* -// alpha-numeric := /[a-z0-9]+/ -// separator := /[_.]|__|[-]*/ -// -// tag := /[\w][\w.-]{0,127}/ -// -// digest := digest-algorithm ":" digest-hex -// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]* -// digest-algorithm-separator := /[+.-_]/ -// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/ -// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value -// -// identifier := /[a-f0-9]{64}/ -// short-identifier := /[a-f0-9]{6,64}/ -package reference - -import ( - "errors" - "fmt" - "strings" - - "github.com/opencontainers/go-digest" -) - -const ( - // NameTotalLengthMax is the maximum total number of characters in a repository name. - NameTotalLengthMax = 255 -) - -var ( - // ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference. - ErrReferenceInvalidFormat = errors.New("invalid reference format") - - // ErrTagInvalidFormat represents an error while trying to parse a string as a tag. - ErrTagInvalidFormat = errors.New("invalid tag format") - - // ErrDigestInvalidFormat represents an error while trying to parse a string as a tag. - ErrDigestInvalidFormat = errors.New("invalid digest format") - - // ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters. - ErrNameContainsUppercase = errors.New("repository name must be lowercase") - - // ErrNameEmpty is returned for empty, invalid repository names. - ErrNameEmpty = errors.New("repository name must have at least one component") - - // ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax. - ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax) - - // ErrNameNotCanonical is returned when a name is not canonical. - ErrNameNotCanonical = errors.New("repository name must be canonical") -) - -// Reference is an opaque object reference identifier that may include -// modifiers such as a hostname, name, tag, and digest. -type Reference interface { - // String returns the full reference - String() string -} - -// Field provides a wrapper type for resolving correct reference types when -// working with encoding. -type Field struct { - reference Reference -} - -// AsField wraps a reference in a Field for encoding. -func AsField(reference Reference) Field { - return Field{reference} -} - -// Reference unwraps the reference type from the field to -// return the Reference object. This object should be -// of the appropriate type to further check for different -// reference types. -func (f Field) Reference() Reference { - return f.reference -} - -// MarshalText serializes the field to byte text which -// is the string of the reference. -func (f Field) MarshalText() (p []byte, err error) { - return []byte(f.reference.String()), nil -} - -// UnmarshalText parses text bytes by invoking the -// reference parser to ensure the appropriately -// typed reference object is wrapped by field. -func (f *Field) UnmarshalText(p []byte) error { - r, err := Parse(string(p)) - if err != nil { - return err - } - - f.reference = r - return nil -} - -// Named is an object with a full name -type Named interface { - Reference - Name() string -} - -// Tagged is an object which has a tag -type Tagged interface { - Reference - Tag() string -} - -// NamedTagged is an object including a name and tag. -type NamedTagged interface { - Named - Tag() string -} - -// Digested is an object which has a digest -// in which it can be referenced by -type Digested interface { - Reference - Digest() digest.Digest -} - -// Canonical reference is an object with a fully unique -// name including a name with domain and digest -type Canonical interface { - Named - Digest() digest.Digest -} - -// namedRepository is a reference to a repository with a name. -// A namedRepository has both domain and path components. -type namedRepository interface { - Named - Domain() string - Path() string -} - -// Domain returns the domain part of the Named reference -func Domain(named Named) string { - if r, ok := named.(namedRepository); ok { - return r.Domain() - } - domain, _ := splitDomain(named.Name()) - return domain -} - -// Path returns the name without the domain part of the Named reference -func Path(named Named) (name string) { - if r, ok := named.(namedRepository); ok { - return r.Path() - } - _, path := splitDomain(named.Name()) - return path -} - -func splitDomain(name string) (string, string) { - match := anchoredNameRegexp.FindStringSubmatch(name) - if len(match) != 3 { - return "", name - } - return match[1], match[2] -} - -// SplitHostname splits a named reference into a -// hostname and name string. If no valid hostname is -// found, the hostname is empty and the full value -// is returned as name -// DEPRECATED: Use Domain or Path -func SplitHostname(named Named) (string, string) { - if r, ok := named.(namedRepository); ok { - return r.Domain(), r.Path() - } - return splitDomain(named.Name()) -} - -// Parse parses s and returns a syntactically valid Reference. -// If an error was encountered it is returned, along with a nil Reference. -// NOTE: Parse will not handle short digests. -func Parse(s string) (Reference, error) { - matches := ReferenceRegexp.FindStringSubmatch(s) - if matches == nil { - if s == "" { - return nil, ErrNameEmpty - } - if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil { - return nil, ErrNameContainsUppercase - } - return nil, ErrReferenceInvalidFormat - } - - if len(matches[1]) > NameTotalLengthMax { - return nil, ErrNameTooLong - } - - var repo repository - - nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1]) - if nameMatch != nil && len(nameMatch) == 3 { - repo.domain = nameMatch[1] - repo.path = nameMatch[2] - } else { - repo.domain = "" - repo.path = matches[1] - } - - ref := reference{ - namedRepository: repo, - tag: matches[2], - } - if matches[3] != "" { - var err error - ref.digest, err = digest.Parse(matches[3]) - if err != nil { - return nil, err - } - } - - r := getBestReferenceType(ref) - if r == nil { - return nil, ErrNameEmpty - } - - return r, nil -} - -// ParseNamed parses s and returns a syntactically valid reference implementing -// the Named interface. The reference must have a name and be in the canonical -// form, otherwise an error is returned. -// If an error was encountered it is returned, along with a nil Reference. -// NOTE: ParseNamed will not handle short digests. -func ParseNamed(s string) (Named, error) { - named, err := ParseNormalizedNamed(s) - if err != nil { - return nil, err - } - if named.String() != s { - return nil, ErrNameNotCanonical - } - return named, nil -} - -// WithName returns a named object representing the given string. If the input -// is invalid ErrReferenceInvalidFormat will be returned. -func WithName(name string) (Named, error) { - if len(name) > NameTotalLengthMax { - return nil, ErrNameTooLong - } - - match := anchoredNameRegexp.FindStringSubmatch(name) - if match == nil || len(match) != 3 { - return nil, ErrReferenceInvalidFormat - } - return repository{ - domain: match[1], - path: match[2], - }, nil -} - -// WithTag combines the name from "name" and the tag from "tag" to form a -// reference incorporating both the name and the tag. -func WithTag(name Named, tag string) (NamedTagged, error) { - if !anchoredTagRegexp.MatchString(tag) { - return nil, ErrTagInvalidFormat - } - var repo repository - if r, ok := name.(namedRepository); ok { - repo.domain = r.Domain() - repo.path = r.Path() - } else { - repo.path = name.Name() - } - if canonical, ok := name.(Canonical); ok { - return reference{ - namedRepository: repo, - tag: tag, - digest: canonical.Digest(), - }, nil - } - return taggedReference{ - namedRepository: repo, - tag: tag, - }, nil -} - -// WithDigest combines the name from "name" and the digest from "digest" to form -// a reference incorporating both the name and the digest. -func WithDigest(name Named, digest digest.Digest) (Canonical, error) { - if !anchoredDigestRegexp.MatchString(digest.String()) { - return nil, ErrDigestInvalidFormat - } - var repo repository - if r, ok := name.(namedRepository); ok { - repo.domain = r.Domain() - repo.path = r.Path() - } else { - repo.path = name.Name() - } - if tagged, ok := name.(Tagged); ok { - return reference{ - namedRepository: repo, - tag: tagged.Tag(), - digest: digest, - }, nil - } - return canonicalReference{ - namedRepository: repo, - digest: digest, - }, nil -} - -// TrimNamed removes any tag or digest from the named reference. -func TrimNamed(ref Named) Named { - domain, path := SplitHostname(ref) - return repository{ - domain: domain, - path: path, - } -} - -func getBestReferenceType(ref reference) Reference { - if ref.Name() == "" { - // Allow digest only references - if ref.digest != "" { - return digestReference(ref.digest) - } - return nil - } - if ref.tag == "" { - if ref.digest != "" { - return canonicalReference{ - namedRepository: ref.namedRepository, - digest: ref.digest, - } - } - return ref.namedRepository - } - if ref.digest == "" { - return taggedReference{ - namedRepository: ref.namedRepository, - tag: ref.tag, - } - } - - return ref -} - -type reference struct { - namedRepository - tag string - digest digest.Digest -} - -func (r reference) String() string { - return r.Name() + ":" + r.tag + "@" + r.digest.String() -} - -func (r reference) Tag() string { - return r.tag -} - -func (r reference) Digest() digest.Digest { - return r.digest -} - -type repository struct { - domain string - path string -} - -func (r repository) String() string { - return r.Name() -} - -func (r repository) Name() string { - if r.domain == "" { - return r.path - } - return r.domain + "/" + r.path -} - -func (r repository) Domain() string { - return r.domain -} - -func (r repository) Path() string { - return r.path -} - -type digestReference digest.Digest - -func (d digestReference) String() string { - return digest.Digest(d).String() -} - -func (d digestReference) Digest() digest.Digest { - return digest.Digest(d) -} - -type taggedReference struct { - namedRepository - tag string -} - -func (t taggedReference) String() string { - return t.Name() + ":" + t.tag -} - -func (t taggedReference) Tag() string { - return t.tag -} - -type canonicalReference struct { - namedRepository - digest digest.Digest -} - -func (c canonicalReference) String() string { - return c.Name() + "@" + c.digest.String() -} - -func (c canonicalReference) Digest() digest.Digest { - return c.digest -} diff --git a/vendor/github.com/docker/distribution/reference/regexp.go b/vendor/github.com/docker/distribution/reference/regexp.go deleted file mode 100644 index 7860349320..0000000000 --- a/vendor/github.com/docker/distribution/reference/regexp.go +++ /dev/null @@ -1,143 +0,0 @@ -package reference - -import "regexp" - -var ( - // alphaNumericRegexp defines the alpha numeric atom, typically a - // component of names. This only allows lower case characters and digits. - alphaNumericRegexp = match(`[a-z0-9]+`) - - // separatorRegexp defines the separators allowed to be embedded in name - // components. This allow one period, one or two underscore and multiple - // dashes. - separatorRegexp = match(`(?:[._]|__|[-]*)`) - - // nameComponentRegexp restricts registry path component names to start - // with at least one letter or number, with following parts able to be - // separated by one period, one or two underscore and multiple dashes. - nameComponentRegexp = expression( - alphaNumericRegexp, - optional(repeated(separatorRegexp, alphaNumericRegexp))) - - // domainComponentRegexp restricts the registry domain component of a - // repository name to start with a component as defined by DomainRegexp - // and followed by an optional port. - domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`) - - // DomainRegexp defines the structure of potential domain components - // that may be part of image names. This is purposely a subset of what is - // allowed by DNS to ensure backwards compatibility with Docker image - // names. - DomainRegexp = expression( - domainComponentRegexp, - optional(repeated(literal(`.`), domainComponentRegexp)), - optional(literal(`:`), match(`[0-9]+`))) - - // TagRegexp matches valid tag names. From docker/docker:graph/tags.go. - TagRegexp = match(`[\w][\w.-]{0,127}`) - - // anchoredTagRegexp matches valid tag names, anchored at the start and - // end of the matched string. - anchoredTagRegexp = anchored(TagRegexp) - - // DigestRegexp matches valid digests. - DigestRegexp = match(`[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`) - - // anchoredDigestRegexp matches valid digests, anchored at the start and - // end of the matched string. - anchoredDigestRegexp = anchored(DigestRegexp) - - // NameRegexp is the format for the name component of references. The - // regexp has capturing groups for the domain and name part omitting - // the separating forward slash from either. - NameRegexp = expression( - optional(DomainRegexp, literal(`/`)), - nameComponentRegexp, - optional(repeated(literal(`/`), nameComponentRegexp))) - - // anchoredNameRegexp is used to parse a name value, capturing the - // domain and trailing components. - anchoredNameRegexp = anchored( - optional(capture(DomainRegexp), literal(`/`)), - capture(nameComponentRegexp, - optional(repeated(literal(`/`), nameComponentRegexp)))) - - // ReferenceRegexp is the full supported format of a reference. The regexp - // is anchored and has capturing groups for name, tag, and digest - // components. - ReferenceRegexp = anchored(capture(NameRegexp), - optional(literal(":"), capture(TagRegexp)), - optional(literal("@"), capture(DigestRegexp))) - - // IdentifierRegexp is the format for string identifier used as a - // content addressable identifier using sha256. These identifiers - // are like digests without the algorithm, since sha256 is used. - IdentifierRegexp = match(`([a-f0-9]{64})`) - - // ShortIdentifierRegexp is the format used to represent a prefix - // of an identifier. A prefix may be used to match a sha256 identifier - // within a list of trusted identifiers. - ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`) - - // anchoredIdentifierRegexp is used to check or match an - // identifier value, anchored at start and end of string. - anchoredIdentifierRegexp = anchored(IdentifierRegexp) - - // anchoredShortIdentifierRegexp is used to check if a value - // is a possible identifier prefix, anchored at start and end - // of string. - anchoredShortIdentifierRegexp = anchored(ShortIdentifierRegexp) -) - -// match compiles the string to a regular expression. -var match = regexp.MustCompile - -// literal compiles s into a literal regular expression, escaping any regexp -// reserved characters. -func literal(s string) *regexp.Regexp { - re := match(regexp.QuoteMeta(s)) - - if _, complete := re.LiteralPrefix(); !complete { - panic("must be a literal") - } - - return re -} - -// expression defines a full expression, where each regular expression must -// follow the previous. -func expression(res ...*regexp.Regexp) *regexp.Regexp { - var s string - for _, re := range res { - s += re.String() - } - - return match(s) -} - -// optional wraps the expression in a non-capturing group and makes the -// production optional. -func optional(res ...*regexp.Regexp) *regexp.Regexp { - return match(group(expression(res...)).String() + `?`) -} - -// repeated wraps the regexp in a non-capturing group to get one or more -// matches. -func repeated(res ...*regexp.Regexp) *regexp.Regexp { - return match(group(expression(res...)).String() + `+`) -} - -// group wraps the regexp in a non-capturing group. -func group(res ...*regexp.Regexp) *regexp.Regexp { - return match(`(?:` + expression(res...).String() + `)`) -} - -// capture wraps the expression in a capturing group. -func capture(res ...*regexp.Regexp) *regexp.Regexp { - return match(`(` + expression(res...).String() + `)`) -} - -// anchored anchors the regular expression by adding start and end delimiters. -func anchored(res ...*regexp.Regexp) *regexp.Regexp { - return match(`^` + expression(res...).String() + `$`) -} diff --git a/vendor/github.com/docker/distribution/registry.go b/vendor/github.com/docker/distribution/registry.go deleted file mode 100644 index a3a80ab884..0000000000 --- a/vendor/github.com/docker/distribution/registry.go +++ /dev/null @@ -1,113 +0,0 @@ -package distribution - -import ( - "context" - - "github.com/docker/distribution/reference" -) - -// Scope defines the set of items that match a namespace. -type Scope interface { - // Contains returns true if the name belongs to the namespace. - Contains(name string) bool -} - -type fullScope struct{} - -func (f fullScope) Contains(string) bool { - return true -} - -// GlobalScope represents the full namespace scope which contains -// all other scopes. -var GlobalScope = Scope(fullScope{}) - -// Namespace represents a collection of repositories, addressable by name. -// Generally, a namespace is backed by a set of one or more services, -// providing facilities such as registry access, trust, and indexing. -type Namespace interface { - // Scope describes the names that can be used with this Namespace. The - // global namespace will have a scope that matches all names. The scope - // effectively provides an identity for the namespace. - Scope() Scope - - // Repository should return a reference to the named repository. The - // registry may or may not have the repository but should always return a - // reference. - Repository(ctx context.Context, name reference.Named) (Repository, error) - - // Repositories fills 'repos' with a lexicographically sorted catalog of repositories - // up to the size of 'repos' and returns the value 'n' for the number of entries - // which were filled. 'last' contains an offset in the catalog, and 'err' will be - // set to io.EOF if there are no more entries to obtain. - Repositories(ctx context.Context, repos []string, last string) (n int, err error) - - // Blobs returns a blob enumerator to access all blobs - Blobs() BlobEnumerator - - // BlobStatter returns a BlobStatter to control - BlobStatter() BlobStatter -} - -// RepositoryEnumerator describes an operation to enumerate repositories -type RepositoryEnumerator interface { - Enumerate(ctx context.Context, ingester func(string) error) error -} - -// ManifestServiceOption is a function argument for Manifest Service methods -type ManifestServiceOption interface { - Apply(ManifestService) error -} - -// WithTag allows a tag to be passed into Put -func WithTag(tag string) ManifestServiceOption { - return WithTagOption{tag} -} - -// WithTagOption holds a tag -type WithTagOption struct{ Tag string } - -// Apply conforms to the ManifestServiceOption interface -func (o WithTagOption) Apply(m ManifestService) error { - // no implementation - return nil -} - -// WithManifestMediaTypes lists the media types the client wishes -// the server to provide. -func WithManifestMediaTypes(mediaTypes []string) ManifestServiceOption { - return WithManifestMediaTypesOption{mediaTypes} -} - -// WithManifestMediaTypesOption holds a list of accepted media types -type WithManifestMediaTypesOption struct{ MediaTypes []string } - -// Apply conforms to the ManifestServiceOption interface -func (o WithManifestMediaTypesOption) Apply(m ManifestService) error { - // no implementation - return nil -} - -// Repository is a named collection of manifests and layers. -type Repository interface { - // Named returns the name of the repository. - Named() reference.Named - - // Manifests returns a reference to this repository's manifest service. - // with the supplied options applied. - Manifests(ctx context.Context, options ...ManifestServiceOption) (ManifestService, error) - - // Blobs returns a reference to this repository's blob service. - Blobs(ctx context.Context) BlobStore - - // TODO(stevvooe): The above BlobStore return can probably be relaxed to - // be a BlobService for use with clients. This will allow such - // implementations to avoid implementing ServeBlob. - - // Tags returns a reference to this repositories tag service - Tags(ctx context.Context) TagService -} - -// TODO(stevvooe): Must add close methods to all these. May want to change the -// way instances are created to better reflect internal dependency -// relationships. diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/errors.go b/vendor/github.com/docker/distribution/registry/api/errcode/errors.go deleted file mode 100644 index 6d9bb4b62a..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/errors.go +++ /dev/null @@ -1,267 +0,0 @@ -package errcode - -import ( - "encoding/json" - "fmt" - "strings" -) - -// ErrorCoder is the base interface for ErrorCode and Error allowing -// users of each to just call ErrorCode to get the real ID of each -type ErrorCoder interface { - ErrorCode() ErrorCode -} - -// ErrorCode represents the error type. The errors are serialized via strings -// and the integer format may change and should *never* be exported. -type ErrorCode int - -var _ error = ErrorCode(0) - -// ErrorCode just returns itself -func (ec ErrorCode) ErrorCode() ErrorCode { - return ec -} - -// Error returns the ID/Value -func (ec ErrorCode) Error() string { - // NOTE(stevvooe): Cannot use message here since it may have unpopulated args. - return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1)) -} - -// Descriptor returns the descriptor for the error code. -func (ec ErrorCode) Descriptor() ErrorDescriptor { - d, ok := errorCodeToDescriptors[ec] - - if !ok { - return ErrorCodeUnknown.Descriptor() - } - - return d -} - -// String returns the canonical identifier for this error code. -func (ec ErrorCode) String() string { - return ec.Descriptor().Value -} - -// Message returned the human-readable error message for this error code. -func (ec ErrorCode) Message() string { - return ec.Descriptor().Message -} - -// MarshalText encodes the receiver into UTF-8-encoded text and returns the -// result. -func (ec ErrorCode) MarshalText() (text []byte, err error) { - return []byte(ec.String()), nil -} - -// UnmarshalText decodes the form generated by MarshalText. -func (ec *ErrorCode) UnmarshalText(text []byte) error { - desc, ok := idToDescriptors[string(text)] - - if !ok { - desc = ErrorCodeUnknown.Descriptor() - } - - *ec = desc.Code - - return nil -} - -// WithMessage creates a new Error struct based on the passed-in info and -// overrides the Message property. -func (ec ErrorCode) WithMessage(message string) Error { - return Error{ - Code: ec, - Message: message, - } -} - -// WithDetail creates a new Error struct based on the passed-in info and -// set the Detail property appropriately -func (ec ErrorCode) WithDetail(detail interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithDetail(detail) -} - -// WithArgs creates a new Error struct and sets the Args slice -func (ec ErrorCode) WithArgs(args ...interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithArgs(args...) -} - -// Error provides a wrapper around ErrorCode with extra Details provided. -type Error struct { - Code ErrorCode `json:"code"` - Message string `json:"message"` - Detail interface{} `json:"detail,omitempty"` - - // TODO(duglin): See if we need an "args" property so we can do the - // variable substitution right before showing the message to the user -} - -var _ error = Error{} - -// ErrorCode returns the ID/Value of this Error -func (e Error) ErrorCode() ErrorCode { - return e.Code -} - -// Error returns a human readable representation of the error. -func (e Error) Error() string { - return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message) -} - -// WithDetail will return a new Error, based on the current one, but with -// some Detail info added -func (e Error) WithDetail(detail interface{}) Error { - return Error{ - Code: e.Code, - Message: e.Message, - Detail: detail, - } -} - -// WithArgs uses the passed-in list of interface{} as the substitution -// variables in the Error's Message string, but returns a new Error -func (e Error) WithArgs(args ...interface{}) Error { - return Error{ - Code: e.Code, - Message: fmt.Sprintf(e.Code.Message(), args...), - Detail: e.Detail, - } -} - -// ErrorDescriptor provides relevant information about a given error code. -type ErrorDescriptor struct { - // Code is the error code that this descriptor describes. - Code ErrorCode - - // Value provides a unique, string key, often captilized with - // underscores, to identify the error code. This value is used as the - // keyed value when serializing api errors. - Value string - - // Message is a short, human readable decription of the error condition - // included in API responses. - Message string - - // Description provides a complete account of the errors purpose, suitable - // for use in documentation. - Description string - - // HTTPStatusCode provides the http status code that is associated with - // this error condition. - HTTPStatusCode int -} - -// ParseErrorCode returns the value by the string error code. -// `ErrorCodeUnknown` will be returned if the error is not known. -func ParseErrorCode(value string) ErrorCode { - ed, ok := idToDescriptors[value] - if ok { - return ed.Code - } - - return ErrorCodeUnknown -} - -// Errors provides the envelope for multiple errors and a few sugar methods -// for use within the application. -type Errors []error - -var _ error = Errors{} - -func (errs Errors) Error() string { - switch len(errs) { - case 0: - return "" - case 1: - return errs[0].Error() - default: - msg := "errors:\n" - for _, err := range errs { - msg += err.Error() + "\n" - } - return msg - } -} - -// Len returns the current number of errors. -func (errs Errors) Len() int { - return len(errs) -} - -// MarshalJSON converts slice of error, ErrorCode or Error into a -// slice of Error - then serializes -func (errs Errors) MarshalJSON() ([]byte, error) { - var tmpErrs struct { - Errors []Error `json:"errors,omitempty"` - } - - for _, daErr := range errs { - var err Error - - switch daErr.(type) { - case ErrorCode: - err = daErr.(ErrorCode).WithDetail(nil) - case Error: - err = daErr.(Error) - default: - err = ErrorCodeUnknown.WithDetail(daErr) - - } - - // If the Error struct was setup and they forgot to set the - // Message field (meaning its "") then grab it from the ErrCode - msg := err.Message - if msg == "" { - msg = err.Code.Message() - } - - tmpErrs.Errors = append(tmpErrs.Errors, Error{ - Code: err.Code, - Message: msg, - Detail: err.Detail, - }) - } - - return json.Marshal(tmpErrs) -} - -// UnmarshalJSON deserializes []Error and then converts it into slice of -// Error or ErrorCode -func (errs *Errors) UnmarshalJSON(data []byte) error { - var tmpErrs struct { - Errors []Error - } - - if err := json.Unmarshal(data, &tmpErrs); err != nil { - return err - } - - var newErrs Errors - for _, daErr := range tmpErrs.Errors { - // If Message is empty or exactly matches the Code's message string - // then just use the Code, no need for a full Error struct - if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) { - // Error's w/o details get converted to ErrorCode - newErrs = append(newErrs, daErr.Code) - } else { - // Error's w/ details are untouched - newErrs = append(newErrs, Error{ - Code: daErr.Code, - Message: daErr.Message, - Detail: daErr.Detail, - }) - } - } - - *errs = newErrs - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/handler.go b/vendor/github.com/docker/distribution/registry/api/errcode/handler.go deleted file mode 100644 index d77e70473e..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/handler.go +++ /dev/null @@ -1,40 +0,0 @@ -package errcode - -import ( - "encoding/json" - "net/http" -) - -// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err -// and sets the content-type header to 'application/json'. It will handle -// ErrorCoder and Errors, and if necessary will create an envelope. -func ServeJSON(w http.ResponseWriter, err error) error { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - var sc int - - switch errs := err.(type) { - case Errors: - if len(errs) < 1 { - break - } - - if err, ok := errs[0].(ErrorCoder); ok { - sc = err.ErrorCode().Descriptor().HTTPStatusCode - } - case ErrorCoder: - sc = errs.ErrorCode().Descriptor().HTTPStatusCode - err = Errors{err} // create an envelope. - default: - // We just have an unhandled error type, so just place in an envelope - // and move along. - err = Errors{err} - } - - if sc == 0 { - sc = http.StatusInternalServerError - } - - w.WriteHeader(sc) - - return json.NewEncoder(w).Encode(err) -} diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/register.go b/vendor/github.com/docker/distribution/registry/api/errcode/register.go deleted file mode 100644 index d1e8826c6d..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/register.go +++ /dev/null @@ -1,138 +0,0 @@ -package errcode - -import ( - "fmt" - "net/http" - "sort" - "sync" -) - -var ( - errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{} - idToDescriptors = map[string]ErrorDescriptor{} - groupToDescriptors = map[string][]ErrorDescriptor{} -) - -var ( - // ErrorCodeUnknown is a generic error that can be used as a last - // resort if there is no situation-specific error message that can be used - ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ - Value: "UNKNOWN", - Message: "unknown error", - Description: `Generic error returned when the error does not have an - API classification.`, - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeUnsupported is returned when an operation is not supported. - ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ - Value: "UNSUPPORTED", - Message: "The operation is unsupported.", - Description: `The operation was unsupported due to a missing - implementation or invalid set of parameters.`, - HTTPStatusCode: http.StatusMethodNotAllowed, - }) - - // ErrorCodeUnauthorized is returned if a request requires - // authentication. - ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ - Value: "UNAUTHORIZED", - Message: "authentication required", - Description: `The access controller was unable to authenticate - the client. Often this will be accompanied by a - Www-Authenticate HTTP response header indicating how to - authenticate.`, - HTTPStatusCode: http.StatusUnauthorized, - }) - - // ErrorCodeDenied is returned if a client does not have sufficient - // permission to perform an action. - ErrorCodeDenied = Register("errcode", ErrorDescriptor{ - Value: "DENIED", - Message: "requested access to the resource is denied", - Description: `The access controller denied access for the - operation on a resource.`, - HTTPStatusCode: http.StatusForbidden, - }) - - // ErrorCodeUnavailable provides a common error to report unavailability - // of a service or endpoint. - ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ - Value: "UNAVAILABLE", - Message: "service unavailable", - Description: "Returned when a service is not available", - HTTPStatusCode: http.StatusServiceUnavailable, - }) - - // ErrorCodeTooManyRequests is returned if a client attempts too many - // times to contact a service endpoint. - ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{ - Value: "TOOMANYREQUESTS", - Message: "too many requests", - Description: `Returned when a client attempts to contact a - service too many times`, - HTTPStatusCode: http.StatusTooManyRequests, - }) -) - -var nextCode = 1000 -var registerLock sync.Mutex - -// Register will make the passed-in error known to the environment and -// return a new ErrorCode -func Register(group string, descriptor ErrorDescriptor) ErrorCode { - registerLock.Lock() - defer registerLock.Unlock() - - descriptor.Code = ErrorCode(nextCode) - - if _, ok := idToDescriptors[descriptor.Value]; ok { - panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value)) - } - if _, ok := errorCodeToDescriptors[descriptor.Code]; ok { - panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code)) - } - - groupToDescriptors[group] = append(groupToDescriptors[group], descriptor) - errorCodeToDescriptors[descriptor.Code] = descriptor - idToDescriptors[descriptor.Value] = descriptor - - nextCode++ - return descriptor.Code -} - -type byValue []ErrorDescriptor - -func (a byValue) Len() int { return len(a) } -func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value } - -// GetGroupNames returns the list of Error group names that are registered -func GetGroupNames() []string { - keys := []string{} - - for k := range groupToDescriptors { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -} - -// GetErrorCodeGroup returns the named group of error descriptors -func GetErrorCodeGroup(name string) []ErrorDescriptor { - desc := groupToDescriptors[name] - sort.Sort(byValue(desc)) - return desc -} - -// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are -// registered, irrespective of what group they're in -func GetErrorAllDescriptors() []ErrorDescriptor { - result := []ErrorDescriptor{} - - for _, group := range GetGroupNames() { - result = append(result, GetErrorCodeGroup(group)...) - } - sort.Sort(byValue(result)) - return result -} diff --git a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go b/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go deleted file mode 100644 index a9616c58ad..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go +++ /dev/null @@ -1,1596 +0,0 @@ -package v2 - -import ( - "net/http" - "regexp" - - "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/api/errcode" - "github.com/opencontainers/go-digest" -) - -var ( - nameParameterDescriptor = ParameterDescriptor{ - Name: "name", - Type: "string", - Format: reference.NameRegexp.String(), - Required: true, - Description: `Name of the target repository.`, - } - - referenceParameterDescriptor = ParameterDescriptor{ - Name: "reference", - Type: "string", - Format: reference.TagRegexp.String(), - Required: true, - Description: `Tag or digest of the target manifest.`, - } - - uuidParameterDescriptor = ParameterDescriptor{ - Name: "uuid", - Type: "opaque", - Required: true, - Description: "A uuid identifying the upload. This field can accept characters that match `[a-zA-Z0-9-_.=]+`.", - } - - digestPathParameter = ParameterDescriptor{ - Name: "digest", - Type: "path", - Required: true, - Format: digest.DigestRegexp.String(), - Description: `Digest of desired blob.`, - } - - hostHeader = ParameterDescriptor{ - Name: "Host", - Type: "string", - Description: "Standard HTTP Host Header. Should be set to the registry host.", - Format: "", - Examples: []string{"registry-1.docker.io"}, - } - - authHeader = ParameterDescriptor{ - Name: "Authorization", - Type: "string", - Description: "An RFC7235 compliant authorization header.", - Format: " ", - Examples: []string{"Bearer dGhpcyBpcyBhIGZha2UgYmVhcmVyIHRva2VuIQ=="}, - } - - authChallengeHeader = ParameterDescriptor{ - Name: "WWW-Authenticate", - Type: "string", - Description: "An RFC7235 compliant authentication challenge header.", - Format: ` realm="", ..."`, - Examples: []string{ - `Bearer realm="https://auth.docker.com/", service="registry.docker.com", scopes="repository:library/ubuntu:pull"`, - }, - } - - contentLengthZeroHeader = ParameterDescriptor{ - Name: "Content-Length", - Description: "The `Content-Length` header must be zero and the body must be empty.", - Type: "integer", - Format: "0", - } - - dockerUploadUUIDHeader = ParameterDescriptor{ - Name: "Docker-Upload-UUID", - Description: "Identifies the docker upload uuid for the current request.", - Type: "uuid", - Format: "", - } - - digestHeader = ParameterDescriptor{ - Name: "Docker-Content-Digest", - Description: "Digest of the targeted content for the request.", - Type: "digest", - Format: "", - } - - linkHeader = ParameterDescriptor{ - Name: "Link", - Type: "link", - Description: "RFC5988 compliant rel='next' with URL to next result set, if available", - Format: `<?n=&last=>; rel="next"`, - } - - paginationParameters = []ParameterDescriptor{ - { - Name: "n", - Type: "integer", - Description: "Limit the number of entries in each response. It not present, all entries will be returned.", - Format: "", - Required: false, - }, - { - Name: "last", - Type: "string", - Description: "Result set will include values lexically after last.", - Format: "", - Required: false, - }, - } - - unauthorizedResponseDescriptor = ResponseDescriptor{ - Name: "Authentication Required", - StatusCode: http.StatusUnauthorized, - Description: "The client is not authenticated.", - Headers: []ParameterDescriptor{ - authChallengeHeader, - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnauthorized, - }, - } - - repositoryNotFoundResponseDescriptor = ResponseDescriptor{ - Name: "No Such Repository Error", - StatusCode: http.StatusNotFound, - Description: "The repository is not known to the registry.", - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameUnknown, - }, - } - - deniedResponseDescriptor = ResponseDescriptor{ - Name: "Access Denied", - StatusCode: http.StatusForbidden, - Description: "The client does not have required access to the repository.", - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeDenied, - }, - } - - tooManyRequestsDescriptor = ResponseDescriptor{ - Name: "Too Many Requests", - StatusCode: http.StatusTooManyRequests, - Description: "The client made too many requests within a time interval.", - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeTooManyRequests, - }, - } -) - -const ( - manifestBody = `{ - "name": , - "tag": , - "fsLayers": [ - { - "blobSum": "" - }, - ... - ] - ], - "history": , - "signature": -}` - - errorsBody = `{ - "errors:" [ - { - "code": , - "message": "", - "detail": ... - }, - ... - ] -}` -) - -// APIDescriptor exports descriptions of the layout of the v2 registry API. -var APIDescriptor = struct { - // RouteDescriptors provides a list of the routes available in the API. - RouteDescriptors []RouteDescriptor -}{ - RouteDescriptors: routeDescriptors, -} - -// RouteDescriptor describes a route specified by name. -type RouteDescriptor struct { - // Name is the name of the route, as specified in RouteNameXXX exports. - // These names a should be considered a unique reference for a route. If - // the route is registered with gorilla, this is the name that will be - // used. - Name string - - // Path is a gorilla/mux-compatible regexp that can be used to match the - // route. For any incoming method and path, only one route descriptor - // should match. - Path string - - // Entity should be a short, human-readalbe description of the object - // targeted by the endpoint. - Entity string - - // Description should provide an accurate overview of the functionality - // provided by the route. - Description string - - // Methods should describe the various HTTP methods that may be used on - // this route, including request and response formats. - Methods []MethodDescriptor -} - -// MethodDescriptor provides a description of the requests that may be -// conducted with the target method. -type MethodDescriptor struct { - - // Method is an HTTP method, such as GET, PUT or POST. - Method string - - // Description should provide an overview of the functionality provided by - // the covered method, suitable for use in documentation. Use of markdown - // here is encouraged. - Description string - - // Requests is a slice of request descriptors enumerating how this - // endpoint may be used. - Requests []RequestDescriptor -} - -// RequestDescriptor covers a particular set of headers and parameters that -// can be carried out with the parent method. Its most helpful to have one -// RequestDescriptor per API use case. -type RequestDescriptor struct { - // Name provides a short identifier for the request, usable as a title or - // to provide quick context for the particular request. - Name string - - // Description should cover the requests purpose, covering any details for - // this particular use case. - Description string - - // Headers describes headers that must be used with the HTTP request. - Headers []ParameterDescriptor - - // PathParameters enumerate the parameterized path components for the - // given request, as defined in the route's regular expression. - PathParameters []ParameterDescriptor - - // QueryParameters provides a list of query parameters for the given - // request. - QueryParameters []ParameterDescriptor - - // Body describes the format of the request body. - Body BodyDescriptor - - // Successes enumerates the possible responses that are considered to be - // the result of a successful request. - Successes []ResponseDescriptor - - // Failures covers the possible failures from this particular request. - Failures []ResponseDescriptor -} - -// ResponseDescriptor describes the components of an API response. -type ResponseDescriptor struct { - // Name provides a short identifier for the response, usable as a title or - // to provide quick context for the particular response. - Name string - - // Description should provide a brief overview of the role of the - // response. - Description string - - // StatusCode specifies the status received by this particular response. - StatusCode int - - // Headers covers any headers that may be returned from the response. - Headers []ParameterDescriptor - - // Fields describes any fields that may be present in the response. - Fields []ParameterDescriptor - - // ErrorCodes enumerates the error codes that may be returned along with - // the response. - ErrorCodes []errcode.ErrorCode - - // Body describes the body of the response, if any. - Body BodyDescriptor -} - -// BodyDescriptor describes a request body and its expected content type. For -// the most part, it should be example json or some placeholder for body -// data in documentation. -type BodyDescriptor struct { - ContentType string - Format string -} - -// ParameterDescriptor describes the format of a request parameter, which may -// be a header, path parameter or query parameter. -type ParameterDescriptor struct { - // Name is the name of the parameter, either of the path component or - // query parameter. - Name string - - // Type specifies the type of the parameter, such as string, integer, etc. - Type string - - // Description provides a human-readable description of the parameter. - Description string - - // Required means the field is required when set. - Required bool - - // Format is a specifying the string format accepted by this parameter. - Format string - - // Regexp is a compiled regular expression that can be used to validate - // the contents of the parameter. - Regexp *regexp.Regexp - - // Examples provides multiple examples for the values that might be valid - // for this parameter. - Examples []string -} - -var routeDescriptors = []RouteDescriptor{ - { - Name: RouteNameBase, - Path: "/v2/", - Entity: "Base", - Description: `Base V2 API route. Typically, this can be used for lightweight version checks and to validate registry authentication.`, - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Check that the endpoint implements Docker Registry API V2.", - Requests: []RequestDescriptor{ - { - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - Successes: []ResponseDescriptor{ - { - Description: "The API implements V2 protocol and is accessible.", - StatusCode: http.StatusOK, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "The registry does not implement the V2 API.", - StatusCode: http.StatusNotFound, - }, - unauthorizedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - }, - }, - { - Name: RouteNameTags, - Path: "/v2/{name:" + reference.NameRegexp.String() + "}/tags/list", - Entity: "Tags", - Description: "Retrieve information about tags.", - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Fetch the tags under the repository identified by `name`.", - Requests: []RequestDescriptor{ - { - Name: "Tags", - Description: "Return all tags for the repository", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - }, - Successes: []ResponseDescriptor{ - { - StatusCode: http.StatusOK, - Description: "A list of tags for the named repository.", - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: `{ - "name": , - "tags": [ - , - ... - ] -}`, - }, - }, - }, - Failures: []ResponseDescriptor{ - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - { - Name: "Tags Paginated", - Description: "Return a portion of the tags for the specified repository.", - PathParameters: []ParameterDescriptor{nameParameterDescriptor}, - QueryParameters: paginationParameters, - Successes: []ResponseDescriptor{ - { - StatusCode: http.StatusOK, - Description: "A list of tags for the named repository.", - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - linkHeader, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: `{ - "name": , - "tags": [ - , - ... - ], -}`, - }, - }, - }, - Failures: []ResponseDescriptor{ - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - }, - }, - { - Name: RouteNameManifest, - Path: "/v2/{name:" + reference.NameRegexp.String() + "}/manifests/{reference:" + reference.TagRegexp.String() + "|" + digest.DigestRegexp.String() + "}", - Entity: "Manifest", - Description: "Create, update, delete and retrieve manifests.", - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Fetch the manifest identified by `name` and `reference` where `reference` can be a tag or digest. A `HEAD` request can also be issued to this endpoint to obtain resource information without receiving all data.", - Requests: []RequestDescriptor{ - { - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - referenceParameterDescriptor, - }, - Successes: []ResponseDescriptor{ - { - Description: "The manifest identified by `name` and `reference`. The contents can be used to identify and resolve resources required to run the specified image.", - StatusCode: http.StatusOK, - Headers: []ParameterDescriptor{ - digestHeader, - }, - Body: BodyDescriptor{ - ContentType: "", - Format: manifestBody, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "The name or reference was invalid.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeTagInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - { - Method: "PUT", - Description: "Put the manifest identified by `name` and `reference` where `reference` can be a tag or digest.", - Requests: []RequestDescriptor{ - { - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - referenceParameterDescriptor, - }, - Body: BodyDescriptor{ - ContentType: "", - Format: manifestBody, - }, - Successes: []ResponseDescriptor{ - { - Description: "The manifest has been accepted by the registry and is stored under the specified `name` and `tag`.", - StatusCode: http.StatusCreated, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Description: "The canonical location url of the uploaded manifest.", - Format: "", - }, - contentLengthZeroHeader, - digestHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Manifest", - Description: "The received manifest was invalid in some way, as described by the error codes. The client should resolve the issue and retry the request.", - StatusCode: http.StatusBadRequest, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeTagInvalid, - ErrorCodeManifestInvalid, - ErrorCodeManifestUnverified, - ErrorCodeBlobUnknown, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - { - Name: "Missing Layer(s)", - Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: `{ - "errors:" [{ - "code": "BLOB_UNKNOWN", - "message": "blob unknown to registry", - "detail": { - "digest": "" - } - }, - ... - ] -}`, - }, - }, - { - Name: "Not allowed", - Description: "Manifest put is not allowed because the registry is configured as a pull-through cache or for some other reason", - StatusCode: http.StatusMethodNotAllowed, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnsupported, - }, - }, - }, - }, - }, - }, - { - Method: "DELETE", - Description: "Delete the manifest identified by `name` and `reference`. Note that a manifest can _only_ be deleted by `digest`.", - Requests: []RequestDescriptor{ - { - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - referenceParameterDescriptor, - }, - Successes: []ResponseDescriptor{ - { - StatusCode: http.StatusAccepted, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Name or Reference", - Description: "The specified `name` or `reference` were invalid and the delete was unable to proceed.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeTagInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - { - Name: "Unknown Manifest", - Description: "The specified `name` or `reference` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest was already deleted if this response is returned.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameUnknown, - ErrorCodeManifestUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Name: "Not allowed", - Description: "Manifest delete is not allowed because the registry is configured as a pull-through cache or `delete` has been disabled.", - StatusCode: http.StatusMethodNotAllowed, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnsupported, - }, - }, - }, - }, - }, - }, - }, - }, - - { - Name: RouteNameBlob, - Path: "/v2/{name:" + reference.NameRegexp.String() + "}/blobs/{digest:" + digest.DigestRegexp.String() + "}", - Entity: "Blob", - Description: "Operations on blobs identified by `name` and `digest`. Used to fetch or delete layers by digest.", - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Retrieve the blob from the registry identified by `digest`. A `HEAD` request can also be issued to this endpoint to obtain resource information without receiving all data.", - Requests: []RequestDescriptor{ - { - Name: "Fetch Blob", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - digestPathParameter, - }, - Successes: []ResponseDescriptor{ - { - Description: "The blob identified by `digest` is available. The blob content will be present in the body of the request.", - StatusCode: http.StatusOK, - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "The length of the requested blob content.", - Format: "", - }, - digestHeader, - }, - Body: BodyDescriptor{ - ContentType: "application/octet-stream", - Format: "", - }, - }, - { - Description: "The blob identified by `digest` is available at the provided location.", - StatusCode: http.StatusTemporaryRedirect, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Description: "The location where the layer should be accessible.", - Format: "", - }, - digestHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeDigestInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The blob, identified by `name` and `digest`, is unknown to the registry.", - StatusCode: http.StatusNotFound, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameUnknown, - ErrorCodeBlobUnknown, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - { - Name: "Fetch Blob Part", - Description: "This endpoint may also support RFC7233 compliant range requests. Support can be detected by issuing a HEAD request. If the header `Accept-Range: bytes` is returned, range requests can be used to fetch partial content.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - { - Name: "Range", - Type: "string", - Description: "HTTP Range header specifying blob chunk.", - Format: "bytes=-", - }, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - digestPathParameter, - }, - Successes: []ResponseDescriptor{ - { - Description: "The blob identified by `digest` is available. The specified chunk of blob content will be present in the body of the request.", - StatusCode: http.StatusPartialContent, - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "The length of the requested blob chunk.", - Format: "", - }, - { - Name: "Content-Range", - Type: "byte range", - Description: "Content range of blob chunk.", - Format: "bytes -/", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/octet-stream", - Format: "", - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeDigestInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameUnknown, - ErrorCodeBlobUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The range specification cannot be satisfied for the requested content. This can happen when the range is not formatted correctly or if the range is outside of the valid size of the content.", - StatusCode: http.StatusRequestedRangeNotSatisfiable, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - { - Method: "DELETE", - Description: "Delete the blob identified by `name` and `digest`", - Requests: []RequestDescriptor{ - { - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - digestPathParameter, - }, - Successes: []ResponseDescriptor{ - { - StatusCode: http.StatusAccepted, - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "0", - Format: "0", - }, - digestHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Name or Digest", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - }, - }, - { - Description: "The blob, identified by `name` and `digest`, is unknown to the registry.", - StatusCode: http.StatusNotFound, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameUnknown, - ErrorCodeBlobUnknown, - }, - }, - { - Description: "Blob delete is not allowed because the registry is configured as a pull-through cache or `delete` has been disabled", - StatusCode: http.StatusMethodNotAllowed, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnsupported, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - - // TODO(stevvooe): We may want to add a PUT request here to - // kickoff an upload of a blob, integrated with the blob upload - // API. - }, - }, - - { - Name: RouteNameBlobUpload, - Path: "/v2/{name:" + reference.NameRegexp.String() + "}/blobs/uploads/", - Entity: "Initiate Blob Upload", - Description: "Initiate a blob upload. This endpoint can be used to create resumable uploads or monolithic uploads.", - Methods: []MethodDescriptor{ - { - Method: "POST", - Description: "Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the `digest` parameter is present, the request body will be used to complete the upload in a single request.", - Requests: []RequestDescriptor{ - { - Name: "Initiate Monolithic Blob Upload", - Description: "Upload a blob identified by the `digest` parameter in single request. This upload will not be resumable unless a recoverable error is returned.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - { - Name: "Content-Length", - Type: "integer", - Format: "", - }, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - }, - QueryParameters: []ParameterDescriptor{ - { - Name: "digest", - Type: "query", - Format: "", - Regexp: digest.DigestRegexp, - Description: `Digest of uploaded blob. If present, the upload will be completed, in a single request, with contents of the request body as the resulting blob.`, - }, - }, - Body: BodyDescriptor{ - ContentType: "application/octect-stream", - Format: "", - }, - Successes: []ResponseDescriptor{ - { - Description: "The blob has been created in the registry and is available at the provided location.", - StatusCode: http.StatusCreated, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Format: "", - }, - contentLengthZeroHeader, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Name or Digest", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - }, - }, - { - Name: "Not allowed", - Description: "Blob upload is not allowed because the registry is configured as a pull-through cache or for some other reason", - StatusCode: http.StatusMethodNotAllowed, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnsupported, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - { - Name: "Initiate Resumable Blob Upload", - Description: "Initiate a resumable blob upload with an empty request body.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - contentLengthZeroHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - }, - Successes: []ResponseDescriptor{ - { - Description: "The upload has been created. The `Location` header must be used to complete the upload. The response should be identical to a `GET` request on the contents of the returned `Location` header.", - StatusCode: http.StatusAccepted, - Headers: []ParameterDescriptor{ - contentLengthZeroHeader, - { - Name: "Location", - Type: "url", - Format: "/v2//blobs/uploads/", - Description: "The location of the created upload. Clients should use the contents verbatim to complete the upload, adding parameters where required.", - }, - { - Name: "Range", - Format: "0-0", - Description: "Range header indicating the progress of the upload. When starting an upload, it will return an empty range, since no content has been received.", - }, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Name or Digest", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - { - Name: "Mount Blob", - Description: "Mount a blob identified by the `mount` parameter from another repository.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - contentLengthZeroHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - }, - QueryParameters: []ParameterDescriptor{ - { - Name: "mount", - Type: "query", - Format: "", - Regexp: digest.DigestRegexp, - Description: `Digest of blob to mount from the source repository.`, - }, - { - Name: "from", - Type: "query", - Format: "", - Regexp: reference.NameRegexp, - Description: `Name of the source repository.`, - }, - }, - Successes: []ResponseDescriptor{ - { - Description: "The blob has been mounted in the repository and is available at the provided location.", - StatusCode: http.StatusCreated, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Format: "", - }, - contentLengthZeroHeader, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Name: "Invalid Name or Digest", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - }, - }, - { - Name: "Not allowed", - Description: "Blob mount is not allowed because the registry is configured as a pull-through cache or for some other reason", - StatusCode: http.StatusMethodNotAllowed, - ErrorCodes: []errcode.ErrorCode{ - errcode.ErrorCodeUnsupported, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - }, - }, - - { - Name: RouteNameBlobUploadChunk, - Path: "/v2/{name:" + reference.NameRegexp.String() + "}/blobs/uploads/{uuid:[a-zA-Z0-9-_.=]+}", - Entity: "Blob Upload", - Description: "Interact with blob uploads. Clients should never assemble URLs for this endpoint and should only take it through the `Location` header on related API requests. The `Location` header and its parameters should be preserved by clients, using the latest value returned via upload related API calls.", - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Retrieve status of upload identified by `uuid`. The primary purpose of this endpoint is to resolve the current status of a resumable upload.", - Requests: []RequestDescriptor{ - { - Description: "Retrieve the progress of the current upload, as reported by the `Range` header.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - uuidParameterDescriptor, - }, - Successes: []ResponseDescriptor{ - { - Name: "Upload Progress", - Description: "The upload is known and in progress. The last received offset is available in the `Range` header.", - StatusCode: http.StatusNoContent, - Headers: []ParameterDescriptor{ - { - Name: "Range", - Type: "header", - Format: "0-", - Description: "Range indicating the current progress of the upload.", - }, - contentLengthZeroHeader, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was an error processing the upload and it must be restarted.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - ErrorCodeBlobUploadInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The upload is unknown to the registry. The upload must be restarted.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUploadUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - { - Method: "PATCH", - Description: "Upload a chunk of data for the specified upload.", - Requests: []RequestDescriptor{ - { - Name: "Stream upload", - Description: "Upload a stream of data to upload without completing the upload.", - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - uuidParameterDescriptor, - }, - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - }, - Body: BodyDescriptor{ - ContentType: "application/octet-stream", - Format: "", - }, - Successes: []ResponseDescriptor{ - { - Name: "Data Accepted", - Description: "The stream of data has been accepted and the current progress is available in the range header. The updated upload location is available in the `Location` header.", - StatusCode: http.StatusNoContent, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Format: "/v2//blobs/uploads/", - Description: "The location of the upload. Clients should assume this changes after each request. Clients should use the contents verbatim to complete the upload, adding parameters where required.", - }, - { - Name: "Range", - Type: "header", - Format: "0-", - Description: "Range indicating the current progress of the upload.", - }, - contentLengthZeroHeader, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was an error processing the upload and it must be restarted.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - ErrorCodeBlobUploadInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The upload is unknown to the registry. The upload must be restarted.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUploadUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - { - Name: "Chunked upload", - Description: "Upload a chunk of data to specified upload without completing the upload. The data will be uploaded to the specified Content Range.", - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - uuidParameterDescriptor, - }, - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - { - Name: "Content-Range", - Type: "header", - Format: "-", - Required: true, - Description: "Range of bytes identifying the desired block of content represented by the body. Start must the end offset retrieved via status check plus one. Note that this is a non-standard use of the `Content-Range` header.", - }, - { - Name: "Content-Length", - Type: "integer", - Format: "", - Description: "Length of the chunk being uploaded, corresponding the length of the request body.", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/octet-stream", - Format: "", - }, - Successes: []ResponseDescriptor{ - { - Name: "Chunk Accepted", - Description: "The chunk of data has been accepted and the current progress is available in the range header. The updated upload location is available in the `Location` header.", - StatusCode: http.StatusNoContent, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Format: "/v2//blobs/uploads/", - Description: "The location of the upload. Clients should assume this changes after each request. Clients should use the contents verbatim to complete the upload, adding parameters where required.", - }, - { - Name: "Range", - Type: "header", - Format: "0-", - Description: "Range indicating the current progress of the upload.", - }, - contentLengthZeroHeader, - dockerUploadUUIDHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was an error processing the upload and it must be restarted.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - ErrorCodeBlobUploadInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The upload is unknown to the registry. The upload must be restarted.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUploadUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The `Content-Range` specification cannot be accepted, either because it does not overlap with the current progress or it is invalid.", - StatusCode: http.StatusRequestedRangeNotSatisfiable, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - { - Method: "PUT", - Description: "Complete the upload specified by `uuid`, optionally appending the body as the final chunk.", - Requests: []RequestDescriptor{ - { - Description: "Complete the upload, providing all the data in the body, if necessary. A request without a body will just complete the upload with previously uploaded content.", - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - { - Name: "Content-Length", - Type: "integer", - Format: "", - Description: "Length of the data being uploaded, corresponding to the length of the request body. May be zero if no data is provided.", - }, - }, - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - uuidParameterDescriptor, - }, - QueryParameters: []ParameterDescriptor{ - { - Name: "digest", - Type: "string", - Format: "", - Regexp: digest.DigestRegexp, - Required: true, - Description: `Digest of uploaded blob.`, - }, - }, - Body: BodyDescriptor{ - ContentType: "application/octet-stream", - Format: "", - }, - Successes: []ResponseDescriptor{ - { - Name: "Upload Complete", - Description: "The upload has been completed and accepted by the registry. The canonical location will be available in the `Location` header.", - StatusCode: http.StatusNoContent, - Headers: []ParameterDescriptor{ - { - Name: "Location", - Type: "url", - Format: "", - Description: "The canonical location of the blob for retrieval", - }, - { - Name: "Content-Range", - Type: "header", - Format: "-", - Description: "Range of bytes identifying the desired block of content represented by the body. Start must match the end of offset retrieved via status check. Note that this is a non-standard use of the `Content-Range` header.", - }, - contentLengthZeroHeader, - digestHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "There was an error processing the upload and it must be restarted.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeDigestInvalid, - ErrorCodeNameInvalid, - ErrorCodeBlobUploadInvalid, - errcode.ErrorCodeUnsupported, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The upload is unknown to the registry. The upload must be restarted.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUploadUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - { - Method: "DELETE", - Description: "Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout.", - Requests: []RequestDescriptor{ - { - Description: "Cancel the upload specified by `uuid`.", - PathParameters: []ParameterDescriptor{ - nameParameterDescriptor, - uuidParameterDescriptor, - }, - Headers: []ParameterDescriptor{ - hostHeader, - authHeader, - contentLengthZeroHeader, - }, - Successes: []ResponseDescriptor{ - { - Name: "Upload Deleted", - Description: "The upload has been successfully deleted.", - StatusCode: http.StatusNoContent, - Headers: []ParameterDescriptor{ - contentLengthZeroHeader, - }, - }, - }, - Failures: []ResponseDescriptor{ - { - Description: "An error was encountered processing the delete. The client may ignore this error.", - StatusCode: http.StatusBadRequest, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeNameInvalid, - ErrorCodeBlobUploadInvalid, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - { - Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.", - StatusCode: http.StatusNotFound, - ErrorCodes: []errcode.ErrorCode{ - ErrorCodeBlobUploadUnknown, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: errorsBody, - }, - }, - unauthorizedResponseDescriptor, - repositoryNotFoundResponseDescriptor, - deniedResponseDescriptor, - tooManyRequestsDescriptor, - }, - }, - }, - }, - }, - }, - { - Name: RouteNameCatalog, - Path: "/v2/_catalog", - Entity: "Catalog", - Description: "List a set of available repositories in the local registry cluster. Does not provide any indication of what may be available upstream. Applications can only determine if a repository is available but not if it is not available.", - Methods: []MethodDescriptor{ - { - Method: "GET", - Description: "Retrieve a sorted, json list of repositories available in the registry.", - Requests: []RequestDescriptor{ - { - Name: "Catalog Fetch", - Description: "Request an unabridged list of repositories available. The implementation may impose a maximum limit and return a partial set with pagination links.", - Successes: []ResponseDescriptor{ - { - Description: "Returns the unabridged list of repositories as a json response.", - StatusCode: http.StatusOK, - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - }, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: `{ - "repositories": [ - , - ... - ] -}`, - }, - }, - }, - }, - { - Name: "Catalog Fetch Paginated", - Description: "Return the specified portion of repositories.", - QueryParameters: paginationParameters, - Successes: []ResponseDescriptor{ - { - StatusCode: http.StatusOK, - Body: BodyDescriptor{ - ContentType: "application/json; charset=utf-8", - Format: `{ - "repositories": [ - , - ... - ] - "next": "?last=&n=" -}`, - }, - Headers: []ParameterDescriptor{ - { - Name: "Content-Length", - Type: "integer", - Description: "Length of the JSON response body.", - Format: "", - }, - linkHeader, - }, - }, - }, - }, - }, - }, - }, - }, -} - -var routeDescriptorsMap map[string]RouteDescriptor - -func init() { - routeDescriptorsMap = make(map[string]RouteDescriptor, len(routeDescriptors)) - - for _, descriptor := range routeDescriptors { - routeDescriptorsMap[descriptor.Name] = descriptor - } -} diff --git a/vendor/github.com/docker/distribution/registry/api/v2/doc.go b/vendor/github.com/docker/distribution/registry/api/v2/doc.go deleted file mode 100644 index cde0119594..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Package v2 describes routes, urls and the error codes used in the Docker -// Registry JSON HTTP API V2. In addition to declarations, descriptors are -// provided for routes and error codes that can be used for implementation and -// automatically generating documentation. -// -// Definitions here are considered to be locked down for the V2 registry api. -// Any changes must be considered carefully and should not proceed without a -// change proposal in docker core. -package v2 diff --git a/vendor/github.com/docker/distribution/registry/api/v2/errors.go b/vendor/github.com/docker/distribution/registry/api/v2/errors.go deleted file mode 100644 index 97d6923aa0..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/errors.go +++ /dev/null @@ -1,136 +0,0 @@ -package v2 - -import ( - "net/http" - - "github.com/docker/distribution/registry/api/errcode" -) - -const errGroup = "registry.api.v2" - -var ( - // ErrorCodeDigestInvalid is returned when uploading a blob if the - // provided digest does not match the blob contents. - ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "DIGEST_INVALID", - Message: "provided digest did not match uploaded content", - Description: `When a blob is uploaded, the registry will check that - the content matches the digest provided by the client. The error may - include a detail structure with the key "digest", including the - invalid digest string. This error may also be returned when a manifest - includes an invalid layer digest.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeSizeInvalid is returned when uploading a blob if the provided - ErrorCodeSizeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "SIZE_INVALID", - Message: "provided length did not match content length", - Description: `When a layer is uploaded, the provided size will be - checked against the uploaded content. If they do not match, this error - will be returned.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeNameInvalid is returned when the name in the manifest does not - // match the provided name. - ErrorCodeNameInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NAME_INVALID", - Message: "invalid repository name", - Description: `Invalid repository name encountered either during - manifest validation or any API operation.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeTagInvalid is returned when the tag in the manifest does not - // match the provided tag. - ErrorCodeTagInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "TAG_INVALID", - Message: "manifest tag did not match URI", - Description: `During a manifest upload, if the tag in the manifest - does not match the uri tag, this error will be returned.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeNameUnknown when the repository name is not known. - ErrorCodeNameUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "NAME_UNKNOWN", - Message: "repository name not known to registry", - Description: `This is returned if the name used during an operation is - unknown to the registry.`, - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeManifestUnknown returned when image manifest is unknown. - ErrorCodeManifestUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MANIFEST_UNKNOWN", - Message: "manifest unknown", - Description: `This error is returned when the manifest, identified by - name and tag is unknown to the repository.`, - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeManifestInvalid returned when an image manifest is invalid, - // typically during a PUT operation. This error encompasses all errors - // encountered during manifest validation that aren't signature errors. - ErrorCodeManifestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MANIFEST_INVALID", - Message: "manifest invalid", - Description: `During upload, manifests undergo several checks ensuring - validity. If those checks fail, this error may be returned, unless a - more specific error is included. The detail will contain information - the failed validation.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeManifestUnverified is returned when the manifest fails - // signature verification. - ErrorCodeManifestUnverified = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MANIFEST_UNVERIFIED", - Message: "manifest failed signature verification", - Description: `During manifest upload, if the manifest fails signature - verification, this error will be returned.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeManifestBlobUnknown is returned when a manifest blob is - // unknown to the registry. - ErrorCodeManifestBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MANIFEST_BLOB_UNKNOWN", - Message: "blob unknown to registry", - Description: `This error may be returned when a manifest blob is - unknown to the registry.`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorCodeBlobUnknown is returned when a blob is unknown to the - // registry. This can happen when the manifest references a nonexistent - // layer or the result is not found by a blob fetch. - ErrorCodeBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BLOB_UNKNOWN", - Message: "blob unknown to registry", - Description: `This error may be returned when a blob is unknown to the - registry in a specified repository. This can be returned with a - standard get or if a manifest references an unknown layer during - upload.`, - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeBlobUploadUnknown is returned when an upload is unknown. - ErrorCodeBlobUploadUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BLOB_UPLOAD_UNKNOWN", - Message: "blob upload unknown to registry", - Description: `If a blob upload has been cancelled or was never - started, this error code may be returned.`, - HTTPStatusCode: http.StatusNotFound, - }) - - // ErrorCodeBlobUploadInvalid is returned when an upload is invalid. - ErrorCodeBlobUploadInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BLOB_UPLOAD_INVALID", - Message: "blob upload invalid", - Description: `The blob upload encountered an error and can no - longer proceed.`, - HTTPStatusCode: http.StatusNotFound, - }) -) diff --git a/vendor/github.com/docker/distribution/registry/api/v2/headerparser.go b/vendor/github.com/docker/distribution/registry/api/v2/headerparser.go deleted file mode 100644 index 9bc41a3a64..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/headerparser.go +++ /dev/null @@ -1,161 +0,0 @@ -package v2 - -import ( - "fmt" - "regexp" - "strings" - "unicode" -) - -var ( - // according to rfc7230 - reToken = regexp.MustCompile(`^[^"(),/:;<=>?@[\]{}[:space:][:cntrl:]]+`) - reQuotedValue = regexp.MustCompile(`^[^\\"]+`) - reEscapedCharacter = regexp.MustCompile(`^[[:blank:][:graph:]]`) -) - -// parseForwardedHeader is a benevolent parser of Forwarded header defined in rfc7239. The header contains -// a comma-separated list of forwarding key-value pairs. Each list element is set by single proxy. The -// function parses only the first element of the list, which is set by the very first proxy. It returns a map -// of corresponding key-value pairs and an unparsed slice of the input string. -// -// Examples of Forwarded header values: -// -// 1. Forwarded: For=192.0.2.43; Proto=https,For="[2001:db8:cafe::17]",For=unknown -// 2. Forwarded: for="192.0.2.43:443"; host="registry.example.org", for="10.10.05.40:80" -// -// The first will be parsed into {"for": "192.0.2.43", "proto": "https"} while the second into -// {"for": "192.0.2.43:443", "host": "registry.example.org"}. -func parseForwardedHeader(forwarded string) (map[string]string, string, error) { - // Following are states of forwarded header parser. Any state could transition to a failure. - const ( - // terminating state; can transition to Parameter - stateElement = iota - // terminating state; can transition to KeyValueDelimiter - stateParameter - // can transition to Value - stateKeyValueDelimiter - // can transition to one of { QuotedValue, PairEnd } - stateValue - // can transition to one of { EscapedCharacter, PairEnd } - stateQuotedValue - // can transition to one of { QuotedValue } - stateEscapedCharacter - // terminating state; can transition to one of { Parameter, Element } - statePairEnd - ) - - var ( - parameter string - value string - parse = forwarded[:] - res = map[string]string{} - state = stateElement - ) - -Loop: - for { - // skip spaces unless in quoted value - if state != stateQuotedValue && state != stateEscapedCharacter { - parse = strings.TrimLeftFunc(parse, unicode.IsSpace) - } - - if len(parse) == 0 { - if state != stateElement && state != statePairEnd && state != stateParameter { - return nil, parse, fmt.Errorf("unexpected end of input") - } - // terminating - break - } - - switch state { - // terminate at list element delimiter - case stateElement: - if parse[0] == ',' { - parse = parse[1:] - break Loop - } - state = stateParameter - - // parse parameter (the key of key-value pair) - case stateParameter: - match := reToken.FindString(parse) - if len(match) == 0 { - return nil, parse, fmt.Errorf("failed to parse token at position %d", len(forwarded)-len(parse)) - } - parameter = strings.ToLower(match) - parse = parse[len(match):] - state = stateKeyValueDelimiter - - // parse '=' - case stateKeyValueDelimiter: - if parse[0] != '=' { - return nil, parse, fmt.Errorf("expected '=', not '%c' at position %d", parse[0], len(forwarded)-len(parse)) - } - parse = parse[1:] - state = stateValue - - // parse value or quoted value - case stateValue: - if parse[0] == '"' { - parse = parse[1:] - state = stateQuotedValue - } else { - value = reToken.FindString(parse) - if len(value) == 0 { - return nil, parse, fmt.Errorf("failed to parse value at position %d", len(forwarded)-len(parse)) - } - if _, exists := res[parameter]; exists { - return nil, parse, fmt.Errorf("duplicate parameter %q at position %d", parameter, len(forwarded)-len(parse)) - } - res[parameter] = value - parse = parse[len(value):] - value = "" - state = statePairEnd - } - - // parse a part of quoted value until the first backslash - case stateQuotedValue: - match := reQuotedValue.FindString(parse) - value += match - parse = parse[len(match):] - switch { - case len(parse) == 0: - return nil, parse, fmt.Errorf("unterminated quoted string") - case parse[0] == '"': - res[parameter] = value - value = "" - parse = parse[1:] - state = statePairEnd - case parse[0] == '\\': - parse = parse[1:] - state = stateEscapedCharacter - } - - // parse escaped character in a quoted string, ignore the backslash - // transition back to QuotedValue state - case stateEscapedCharacter: - c := reEscapedCharacter.FindString(parse) - if len(c) == 0 { - return nil, parse, fmt.Errorf("invalid escape sequence at position %d", len(forwarded)-len(parse)-1) - } - value += c - parse = parse[1:] - state = stateQuotedValue - - // expect either a new key-value pair, new list or end of input - case statePairEnd: - switch parse[0] { - case ';': - parse = parse[1:] - state = stateParameter - case ',': - state = stateElement - default: - return nil, parse, fmt.Errorf("expected ',' or ';', not %c at position %d", parse[0], len(forwarded)-len(parse)) - } - } - } - - return res, parse, nil -} diff --git a/vendor/github.com/docker/distribution/registry/api/v2/routes.go b/vendor/github.com/docker/distribution/registry/api/v2/routes.go deleted file mode 100644 index 5b80d5be76..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/routes.go +++ /dev/null @@ -1,49 +0,0 @@ -package v2 - -import "github.com/gorilla/mux" - -// The following are definitions of the name under which all V2 routes are -// registered. These symbols can be used to look up a route based on the name. -const ( - RouteNameBase = "base" - RouteNameManifest = "manifest" - RouteNameTags = "tags" - RouteNameBlob = "blob" - RouteNameBlobUpload = "blob-upload" - RouteNameBlobUploadChunk = "blob-upload-chunk" - RouteNameCatalog = "catalog" -) - -var allEndpoints = []string{ - RouteNameManifest, - RouteNameCatalog, - RouteNameTags, - RouteNameBlob, - RouteNameBlobUpload, - RouteNameBlobUploadChunk, -} - -// Router builds a gorilla router with named routes for the various API -// methods. This can be used directly by both server implementations and -// clients. -func Router() *mux.Router { - return RouterWithPrefix("") -} - -// RouterWithPrefix builds a gorilla router with a configured prefix -// on all routes. -func RouterWithPrefix(prefix string) *mux.Router { - rootRouter := mux.NewRouter() - router := rootRouter - if prefix != "" { - router = router.PathPrefix(prefix).Subrouter() - } - - router.StrictSlash(true) - - for _, descriptor := range routeDescriptors { - router.Path(descriptor.Path).Name(descriptor.Name) - } - - return rootRouter -} diff --git a/vendor/github.com/docker/distribution/registry/api/v2/urls.go b/vendor/github.com/docker/distribution/registry/api/v2/urls.go deleted file mode 100644 index 1337bdb127..0000000000 --- a/vendor/github.com/docker/distribution/registry/api/v2/urls.go +++ /dev/null @@ -1,266 +0,0 @@ -package v2 - -import ( - "fmt" - "net/http" - "net/url" - "strings" - - "github.com/docker/distribution/reference" - "github.com/gorilla/mux" -) - -// URLBuilder creates registry API urls from a single base endpoint. It can be -// used to create urls for use in a registry client or server. -// -// All urls will be created from the given base, including the api version. -// For example, if a root of "/foo/" is provided, urls generated will be fall -// under "/foo/v2/...". Most application will only provide a schema, host and -// port, such as "https://localhost:5000/". -type URLBuilder struct { - root *url.URL // url root (ie http://localhost/) - router *mux.Router - relative bool -} - -// NewURLBuilder creates a URLBuilder with provided root url object. -func NewURLBuilder(root *url.URL, relative bool) *URLBuilder { - return &URLBuilder{ - root: root, - router: Router(), - relative: relative, - } -} - -// NewURLBuilderFromString workes identically to NewURLBuilder except it takes -// a string argument for the root, returning an error if it is not a valid -// url. -func NewURLBuilderFromString(root string, relative bool) (*URLBuilder, error) { - u, err := url.Parse(root) - if err != nil { - return nil, err - } - - return NewURLBuilder(u, relative), nil -} - -// NewURLBuilderFromRequest uses information from an *http.Request to -// construct the root url. -func NewURLBuilderFromRequest(r *http.Request, relative bool) *URLBuilder { - var ( - scheme = "http" - host = r.Host - ) - - if r.TLS != nil { - scheme = "https" - } else if len(r.URL.Scheme) > 0 { - scheme = r.URL.Scheme - } - - // Handle fowarded headers - // Prefer "Forwarded" header as defined by rfc7239 if given - // see https://tools.ietf.org/html/rfc7239 - if forwarded := r.Header.Get("Forwarded"); len(forwarded) > 0 { - forwardedHeader, _, err := parseForwardedHeader(forwarded) - if err == nil { - if fproto := forwardedHeader["proto"]; len(fproto) > 0 { - scheme = fproto - } - if fhost := forwardedHeader["host"]; len(fhost) > 0 { - host = fhost - } - } - } else { - if forwardedProto := r.Header.Get("X-Forwarded-Proto"); len(forwardedProto) > 0 { - scheme = forwardedProto - } - if forwardedHost := r.Header.Get("X-Forwarded-Host"); len(forwardedHost) > 0 { - // According to the Apache mod_proxy docs, X-Forwarded-Host can be a - // comma-separated list of hosts, to which each proxy appends the - // requested host. We want to grab the first from this comma-separated - // list. - hosts := strings.SplitN(forwardedHost, ",", 2) - host = strings.TrimSpace(hosts[0]) - } - } - - basePath := routeDescriptorsMap[RouteNameBase].Path - - requestPath := r.URL.Path - index := strings.Index(requestPath, basePath) - - u := &url.URL{ - Scheme: scheme, - Host: host, - } - - if index > 0 { - // N.B. index+1 is important because we want to include the trailing / - u.Path = requestPath[0 : index+1] - } - - return NewURLBuilder(u, relative) -} - -// BuildBaseURL constructs a base url for the API, typically just "/v2/". -func (ub *URLBuilder) BuildBaseURL() (string, error) { - route := ub.cloneRoute(RouteNameBase) - - baseURL, err := route.URL() - if err != nil { - return "", err - } - - return baseURL.String(), nil -} - -// BuildCatalogURL constructs a url get a catalog of repositories -func (ub *URLBuilder) BuildCatalogURL(values ...url.Values) (string, error) { - route := ub.cloneRoute(RouteNameCatalog) - - catalogURL, err := route.URL() - if err != nil { - return "", err - } - - return appendValuesURL(catalogURL, values...).String(), nil -} - -// BuildTagsURL constructs a url to list the tags in the named repository. -func (ub *URLBuilder) BuildTagsURL(name reference.Named) (string, error) { - route := ub.cloneRoute(RouteNameTags) - - tagsURL, err := route.URL("name", name.Name()) - if err != nil { - return "", err - } - - return tagsURL.String(), nil -} - -// BuildManifestURL constructs a url for the manifest identified by name and -// reference. The argument reference may be either a tag or digest. -func (ub *URLBuilder) BuildManifestURL(ref reference.Named) (string, error) { - route := ub.cloneRoute(RouteNameManifest) - - tagOrDigest := "" - switch v := ref.(type) { - case reference.Tagged: - tagOrDigest = v.Tag() - case reference.Digested: - tagOrDigest = v.Digest().String() - default: - return "", fmt.Errorf("reference must have a tag or digest") - } - - manifestURL, err := route.URL("name", ref.Name(), "reference", tagOrDigest) - if err != nil { - return "", err - } - - return manifestURL.String(), nil -} - -// BuildBlobURL constructs the url for the blob identified by name and dgst. -func (ub *URLBuilder) BuildBlobURL(ref reference.Canonical) (string, error) { - route := ub.cloneRoute(RouteNameBlob) - - layerURL, err := route.URL("name", ref.Name(), "digest", ref.Digest().String()) - if err != nil { - return "", err - } - - return layerURL.String(), nil -} - -// BuildBlobUploadURL constructs a url to begin a blob upload in the -// repository identified by name. -func (ub *URLBuilder) BuildBlobUploadURL(name reference.Named, values ...url.Values) (string, error) { - route := ub.cloneRoute(RouteNameBlobUpload) - - uploadURL, err := route.URL("name", name.Name()) - if err != nil { - return "", err - } - - return appendValuesURL(uploadURL, values...).String(), nil -} - -// BuildBlobUploadChunkURL constructs a url for the upload identified by uuid, -// including any url values. This should generally not be used by clients, as -// this url is provided by server implementations during the blob upload -// process. -func (ub *URLBuilder) BuildBlobUploadChunkURL(name reference.Named, uuid string, values ...url.Values) (string, error) { - route := ub.cloneRoute(RouteNameBlobUploadChunk) - - uploadURL, err := route.URL("name", name.Name(), "uuid", uuid) - if err != nil { - return "", err - } - - return appendValuesURL(uploadURL, values...).String(), nil -} - -// clondedRoute returns a clone of the named route from the router. Routes -// must be cloned to avoid modifying them during url generation. -func (ub *URLBuilder) cloneRoute(name string) clonedRoute { - route := new(mux.Route) - root := new(url.URL) - - *route = *ub.router.GetRoute(name) // clone the route - *root = *ub.root - - return clonedRoute{Route: route, root: root, relative: ub.relative} -} - -type clonedRoute struct { - *mux.Route - root *url.URL - relative bool -} - -func (cr clonedRoute) URL(pairs ...string) (*url.URL, error) { - routeURL, err := cr.Route.URL(pairs...) - if err != nil { - return nil, err - } - - if cr.relative { - return routeURL, nil - } - - if routeURL.Scheme == "" && routeURL.User == nil && routeURL.Host == "" { - routeURL.Path = routeURL.Path[1:] - } - - url := cr.root.ResolveReference(routeURL) - url.Scheme = cr.root.Scheme - return url, nil -} - -// appendValuesURL appends the parameters to the url. -func appendValuesURL(u *url.URL, values ...url.Values) *url.URL { - merged := u.Query() - - for _, v := range values { - for k, vv := range v { - merged[k] = append(merged[k], vv...) - } - } - - u.RawQuery = merged.Encode() - return u -} - -// appendValues appends the parameters to the url. Panics if the string is not -// a url. -func appendValues(u string, values ...url.Values) string { - up, err := url.Parse(u) - - if err != nil { - panic(err) // should never happen - } - - return appendValuesURL(up, values...).String() -} diff --git a/vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go b/vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go deleted file mode 100644 index 2c3ebe1653..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go +++ /dev/null @@ -1,27 +0,0 @@ -package challenge - -import ( - "net/url" - "strings" -) - -// FROM: https://golang.org/src/net/http/http.go -// Given a string of the form "host", "host:port", or "[ipv6::address]:port", -// return true if the string includes a port. -func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } - -// FROM: http://golang.org/src/net/http/transport.go -var portMap = map[string]string{ - "http": "80", - "https": "443", -} - -// canonicalAddr returns url.Host but always with a ":port" suffix -// FROM: http://golang.org/src/net/http/transport.go -func canonicalAddr(url *url.URL) string { - addr := url.Host - if !hasPort(addr) { - return addr + ":" + portMap[url.Scheme] - } - return addr -} diff --git a/vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go b/vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go deleted file mode 100644 index 6e3f1ccc41..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go +++ /dev/null @@ -1,237 +0,0 @@ -package challenge - -import ( - "fmt" - "net/http" - "net/url" - "strings" - "sync" -) - -// Challenge carries information from a WWW-Authenticate response header. -// See RFC 2617. -type Challenge struct { - // Scheme is the auth-scheme according to RFC 2617 - Scheme string - - // Parameters are the auth-params according to RFC 2617 - Parameters map[string]string -} - -// Manager manages the challenges for endpoints. -// The challenges are pulled out of HTTP responses. Only -// responses which expect challenges should be added to -// the manager, since a non-unauthorized request will be -// viewed as not requiring challenges. -type Manager interface { - // GetChallenges returns the challenges for the given - // endpoint URL. - GetChallenges(endpoint url.URL) ([]Challenge, error) - - // AddResponse adds the response to the challenge - // manager. The challenges will be parsed out of - // the WWW-Authenicate headers and added to the - // URL which was produced the response. If the - // response was authorized, any challenges for the - // endpoint will be cleared. - AddResponse(resp *http.Response) error -} - -// NewSimpleManager returns an instance of -// Manger which only maps endpoints to challenges -// based on the responses which have been added the -// manager. The simple manager will make no attempt to -// perform requests on the endpoints or cache the responses -// to a backend. -func NewSimpleManager() Manager { - return &simpleManager{ - Challenges: make(map[string][]Challenge), - } -} - -type simpleManager struct { - sync.RWMutex - Challenges map[string][]Challenge -} - -func normalizeURL(endpoint *url.URL) { - endpoint.Host = strings.ToLower(endpoint.Host) - endpoint.Host = canonicalAddr(endpoint) -} - -func (m *simpleManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { - normalizeURL(&endpoint) - - m.RLock() - defer m.RUnlock() - challenges := m.Challenges[endpoint.String()] - return challenges, nil -} - -func (m *simpleManager) AddResponse(resp *http.Response) error { - challenges := ResponseChallenges(resp) - if resp.Request == nil { - return fmt.Errorf("missing request reference") - } - urlCopy := url.URL{ - Path: resp.Request.URL.Path, - Host: resp.Request.URL.Host, - Scheme: resp.Request.URL.Scheme, - } - normalizeURL(&urlCopy) - - m.Lock() - defer m.Unlock() - m.Challenges[urlCopy.String()] = challenges - return nil -} - -// Octet types from RFC 2616. -type octetType byte - -var octetTypes [256]octetType - -const ( - isToken octetType = 1 << iota - isSpace -) - -func init() { - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t octetType - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { - t |= isSpace - } - if isChar && !isCtl && !isSeparator { - t |= isToken - } - octetTypes[c] = t - } -} - -// ResponseChallenges returns a list of authorization challenges -// for the given http Response. Challenges are only checked if -// the response status code was a 401. -func ResponseChallenges(resp *http.Response) []Challenge { - if resp.StatusCode == http.StatusUnauthorized { - // Parse the WWW-Authenticate Header and store the challenges - // on this endpoint object. - return parseAuthHeader(resp.Header) - } - - return nil -} - -func parseAuthHeader(header http.Header) []Challenge { - challenges := []Challenge{} - for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] { - v, p := parseValueAndParams(h) - if v != "" { - challenges = append(challenges, Challenge{Scheme: v, Parameters: p}) - } - } - return challenges -} - -func parseValueAndParams(header string) (value string, params map[string]string) { - params = make(map[string]string) - value, s := expectToken(header) - if value == "" { - return - } - value = strings.ToLower(value) - s = "," + skipSpace(s) - for strings.HasPrefix(s, ",") { - var pkey string - pkey, s = expectToken(skipSpace(s[1:])) - if pkey == "" { - return - } - if !strings.HasPrefix(s, "=") { - return - } - var pvalue string - pvalue, s = expectTokenOrQuoted(s[1:]) - if pvalue == "" { - return - } - pkey = strings.ToLower(pkey) - params[pkey] = pvalue - s = skipSpace(s) - } - return -} - -func skipSpace(s string) (rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpace == 0 { - break - } - } - return s[i:] -} - -func expectToken(s string) (token, rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isToken == 0 { - break - } - } - return s[:i], s[i:] -} - -func expectTokenOrQuoted(s string) (value string, rest string) { - if !strings.HasPrefix(s, "\"") { - return expectToken(s) - } - s = s[1:] - for i := 0; i < len(s); i++ { - switch s[i] { - case '"': - return s[:i], s[i+1:] - case '\\': - p := make([]byte, len(s)-1) - j := copy(p, s[:i]) - escape := true - for i = i + 1; i < len(s); i++ { - b := s[i] - switch { - case escape: - escape = false - p[j] = b - j++ - case b == '\\': - escape = true - case b == '"': - return string(p[:j]), s[i+1:] - default: - p[j] = b - j++ - } - } - return "", "" - } - } - return "", "" -} diff --git a/vendor/github.com/docker/distribution/registry/client/blob_writer.go b/vendor/github.com/docker/distribution/registry/client/blob_writer.go deleted file mode 100644 index 695bf852f1..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/blob_writer.go +++ /dev/null @@ -1,162 +0,0 @@ -package client - -import ( - "bytes" - "context" - "fmt" - "io" - "io/ioutil" - "net/http" - "time" - - "github.com/docker/distribution" -) - -type httpBlobUpload struct { - statter distribution.BlobStatter - client *http.Client - - uuid string - startedAt time.Time - - location string // always the last value of the location header. - offset int64 - closed bool -} - -func (hbu *httpBlobUpload) Reader() (io.ReadCloser, error) { - panic("Not implemented") -} - -func (hbu *httpBlobUpload) handleErrorResponse(resp *http.Response) error { - if resp.StatusCode == http.StatusNotFound { - return distribution.ErrBlobUploadUnknown - } - return HandleErrorResponse(resp) -} - -func (hbu *httpBlobUpload) ReadFrom(r io.Reader) (n int64, err error) { - req, err := http.NewRequest("PATCH", hbu.location, ioutil.NopCloser(r)) - if err != nil { - return 0, err - } - defer req.Body.Close() - - resp, err := hbu.client.Do(req) - if err != nil { - return 0, err - } - - if !SuccessStatus(resp.StatusCode) { - return 0, hbu.handleErrorResponse(resp) - } - - hbu.uuid = resp.Header.Get("Docker-Upload-UUID") - hbu.location, err = sanitizeLocation(resp.Header.Get("Location"), hbu.location) - if err != nil { - return 0, err - } - rng := resp.Header.Get("Range") - var start, end int64 - if n, err := fmt.Sscanf(rng, "%d-%d", &start, &end); err != nil { - return 0, err - } else if n != 2 || end < start { - return 0, fmt.Errorf("bad range format: %s", rng) - } - - return (end - start + 1), nil - -} - -func (hbu *httpBlobUpload) Write(p []byte) (n int, err error) { - req, err := http.NewRequest("PATCH", hbu.location, bytes.NewReader(p)) - if err != nil { - return 0, err - } - req.Header.Set("Content-Range", fmt.Sprintf("%d-%d", hbu.offset, hbu.offset+int64(len(p)-1))) - req.Header.Set("Content-Length", fmt.Sprintf("%d", len(p))) - req.Header.Set("Content-Type", "application/octet-stream") - - resp, err := hbu.client.Do(req) - if err != nil { - return 0, err - } - - if !SuccessStatus(resp.StatusCode) { - return 0, hbu.handleErrorResponse(resp) - } - - hbu.uuid = resp.Header.Get("Docker-Upload-UUID") - hbu.location, err = sanitizeLocation(resp.Header.Get("Location"), hbu.location) - if err != nil { - return 0, err - } - rng := resp.Header.Get("Range") - var start, end int - if n, err := fmt.Sscanf(rng, "%d-%d", &start, &end); err != nil { - return 0, err - } else if n != 2 || end < start { - return 0, fmt.Errorf("bad range format: %s", rng) - } - - return (end - start + 1), nil - -} - -func (hbu *httpBlobUpload) Size() int64 { - return hbu.offset -} - -func (hbu *httpBlobUpload) ID() string { - return hbu.uuid -} - -func (hbu *httpBlobUpload) StartedAt() time.Time { - return hbu.startedAt -} - -func (hbu *httpBlobUpload) Commit(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) { - // TODO(dmcgowan): Check if already finished, if so just fetch - req, err := http.NewRequest("PUT", hbu.location, nil) - if err != nil { - return distribution.Descriptor{}, err - } - - values := req.URL.Query() - values.Set("digest", desc.Digest.String()) - req.URL.RawQuery = values.Encode() - - resp, err := hbu.client.Do(req) - if err != nil { - return distribution.Descriptor{}, err - } - defer resp.Body.Close() - - if !SuccessStatus(resp.StatusCode) { - return distribution.Descriptor{}, hbu.handleErrorResponse(resp) - } - - return hbu.statter.Stat(ctx, desc.Digest) -} - -func (hbu *httpBlobUpload) Cancel(ctx context.Context) error { - req, err := http.NewRequest("DELETE", hbu.location, nil) - if err != nil { - return err - } - resp, err := hbu.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode == http.StatusNotFound || SuccessStatus(resp.StatusCode) { - return nil - } - return hbu.handleErrorResponse(resp) -} - -func (hbu *httpBlobUpload) Close() error { - hbu.closed = true - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/client/errors.go b/vendor/github.com/docker/distribution/registry/client/errors.go deleted file mode 100644 index 52d49d5d29..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/errors.go +++ /dev/null @@ -1,139 +0,0 @@ -package client - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/client/auth/challenge" -) - -// ErrNoErrorsInBody is returned when an HTTP response body parses to an empty -// errcode.Errors slice. -var ErrNoErrorsInBody = errors.New("no error details found in HTTP response body") - -// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is -// returned when making a registry api call. -type UnexpectedHTTPStatusError struct { - Status string -} - -func (e *UnexpectedHTTPStatusError) Error() string { - return fmt.Sprintf("received unexpected HTTP status: %s", e.Status) -} - -// UnexpectedHTTPResponseError is returned when an expected HTTP status code -// is returned, but the content was unexpected and failed to be parsed. -type UnexpectedHTTPResponseError struct { - ParseErr error - StatusCode int - Response []byte -} - -func (e *UnexpectedHTTPResponseError) Error() string { - return fmt.Sprintf("error parsing HTTP %d response body: %s: %q", e.StatusCode, e.ParseErr.Error(), string(e.Response)) -} - -func parseHTTPErrorResponse(statusCode int, r io.Reader) error { - var errors errcode.Errors - body, err := ioutil.ReadAll(r) - if err != nil { - return err - } - - // For backward compatibility, handle irregularly formatted - // messages that contain a "details" field. - var detailsErr struct { - Details string `json:"details"` - } - err = json.Unmarshal(body, &detailsErr) - if err == nil && detailsErr.Details != "" { - switch statusCode { - case http.StatusUnauthorized: - return errcode.ErrorCodeUnauthorized.WithMessage(detailsErr.Details) - case http.StatusTooManyRequests: - return errcode.ErrorCodeTooManyRequests.WithMessage(detailsErr.Details) - default: - return errcode.ErrorCodeUnknown.WithMessage(detailsErr.Details) - } - } - - if err := json.Unmarshal(body, &errors); err != nil { - return &UnexpectedHTTPResponseError{ - ParseErr: err, - StatusCode: statusCode, - Response: body, - } - } - - if len(errors) == 0 { - // If there was no error specified in the body, return - // UnexpectedHTTPResponseError. - return &UnexpectedHTTPResponseError{ - ParseErr: ErrNoErrorsInBody, - StatusCode: statusCode, - Response: body, - } - } - - return errors -} - -func makeErrorList(err error) []error { - if errL, ok := err.(errcode.Errors); ok { - return []error(errL) - } - return []error{err} -} - -func mergeErrors(err1, err2 error) error { - return errcode.Errors(append(makeErrorList(err1), makeErrorList(err2)...)) -} - -// HandleErrorResponse returns error parsed from HTTP response for an -// unsuccessful HTTP response code (in the range 400 - 499 inclusive). An -// UnexpectedHTTPStatusError returned for response code outside of expected -// range. -func HandleErrorResponse(resp *http.Response) error { - if resp.StatusCode >= 400 && resp.StatusCode < 500 { - // Check for OAuth errors within the `WWW-Authenticate` header first - // See https://tools.ietf.org/html/rfc6750#section-3 - for _, c := range challenge.ResponseChallenges(resp) { - if c.Scheme == "bearer" { - var err errcode.Error - // codes defined at https://tools.ietf.org/html/rfc6750#section-3.1 - switch c.Parameters["error"] { - case "invalid_token": - err.Code = errcode.ErrorCodeUnauthorized - case "insufficient_scope": - err.Code = errcode.ErrorCodeDenied - default: - continue - } - if description := c.Parameters["error_description"]; description != "" { - err.Message = description - } else { - err.Message = err.Code.Message() - } - - return mergeErrors(err, parseHTTPErrorResponse(resp.StatusCode, resp.Body)) - } - } - err := parseHTTPErrorResponse(resp.StatusCode, resp.Body) - if uErr, ok := err.(*UnexpectedHTTPResponseError); ok && resp.StatusCode == 401 { - return errcode.ErrorCodeUnauthorized.WithDetail(uErr.Response) - } - return err - } - return &UnexpectedHTTPStatusError{Status: resp.Status} -} - -// SuccessStatus returns true if the argument is a successful HTTP response -// code (in the range 200 - 399 inclusive). -func SuccessStatus(status int) bool { - return status >= 200 && status <= 399 -} diff --git a/vendor/github.com/docker/distribution/registry/client/repository.go b/vendor/github.com/docker/distribution/registry/client/repository.go deleted file mode 100644 index d8e2c795d9..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/repository.go +++ /dev/null @@ -1,869 +0,0 @@ -package client - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "github.com/docker/distribution" - "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/api/v2" - "github.com/docker/distribution/registry/client/transport" - "github.com/docker/distribution/registry/storage/cache" - "github.com/docker/distribution/registry/storage/cache/memory" - "github.com/opencontainers/go-digest" -) - -// Registry provides an interface for calling Repositories, which returns a catalog of repositories. -type Registry interface { - Repositories(ctx context.Context, repos []string, last string) (n int, err error) -} - -// checkHTTPRedirect is a callback that can manipulate redirected HTTP -// requests. It is used to preserve Accept and Range headers. -func checkHTTPRedirect(req *http.Request, via []*http.Request) error { - if len(via) >= 10 { - return errors.New("stopped after 10 redirects") - } - - if len(via) > 0 { - for headerName, headerVals := range via[0].Header { - if headerName != "Accept" && headerName != "Range" { - continue - } - for _, val := range headerVals { - // Don't add to redirected request if redirected - // request already has a header with the same - // name and value. - hasValue := false - for _, existingVal := range req.Header[headerName] { - if existingVal == val { - hasValue = true - break - } - } - if !hasValue { - req.Header.Add(headerName, val) - } - } - } - } - - return nil -} - -// NewRegistry creates a registry namespace which can be used to get a listing of repositories -func NewRegistry(baseURL string, transport http.RoundTripper) (Registry, error) { - ub, err := v2.NewURLBuilderFromString(baseURL, false) - if err != nil { - return nil, err - } - - client := &http.Client{ - Transport: transport, - Timeout: 1 * time.Minute, - CheckRedirect: checkHTTPRedirect, - } - - return ®istry{ - client: client, - ub: ub, - }, nil -} - -type registry struct { - client *http.Client - ub *v2.URLBuilder - context context.Context -} - -// Repositories returns a lexigraphically sorted catalog given a base URL. The 'entries' slice will be filled up to the size -// of the slice, starting at the value provided in 'last'. The number of entries will be returned along with io.EOF if there -// are no more entries -func (r *registry) Repositories(ctx context.Context, entries []string, last string) (int, error) { - var numFilled int - var returnErr error - - values := buildCatalogValues(len(entries), last) - u, err := r.ub.BuildCatalogURL(values) - if err != nil { - return 0, err - } - - resp, err := r.client.Get(u) - if err != nil { - return 0, err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - var ctlg struct { - Repositories []string `json:"repositories"` - } - decoder := json.NewDecoder(resp.Body) - - if err := decoder.Decode(&ctlg); err != nil { - return 0, err - } - - for cnt := range ctlg.Repositories { - entries[cnt] = ctlg.Repositories[cnt] - } - numFilled = len(ctlg.Repositories) - - link := resp.Header.Get("Link") - if link == "" { - returnErr = io.EOF - } - } else { - return 0, HandleErrorResponse(resp) - } - - return numFilled, returnErr -} - -// NewRepository creates a new Repository for the given repository name and base URL. -func NewRepository(name reference.Named, baseURL string, transport http.RoundTripper) (distribution.Repository, error) { - ub, err := v2.NewURLBuilderFromString(baseURL, false) - if err != nil { - return nil, err - } - - client := &http.Client{ - Transport: transport, - CheckRedirect: checkHTTPRedirect, - // TODO(dmcgowan): create cookie jar - } - - return &repository{ - client: client, - ub: ub, - name: name, - }, nil -} - -type repository struct { - client *http.Client - ub *v2.URLBuilder - context context.Context - name reference.Named -} - -func (r *repository) Named() reference.Named { - return r.name -} - -func (r *repository) Blobs(ctx context.Context) distribution.BlobStore { - statter := &blobStatter{ - name: r.name, - ub: r.ub, - client: r.client, - } - return &blobs{ - name: r.name, - ub: r.ub, - client: r.client, - statter: cache.NewCachedBlobStatter(memory.NewInMemoryBlobDescriptorCacheProvider(), statter), - } -} - -func (r *repository) Manifests(ctx context.Context, options ...distribution.ManifestServiceOption) (distribution.ManifestService, error) { - // todo(richardscothern): options should be sent over the wire - return &manifests{ - name: r.name, - ub: r.ub, - client: r.client, - etags: make(map[string]string), - }, nil -} - -func (r *repository) Tags(ctx context.Context) distribution.TagService { - return &tags{ - client: r.client, - ub: r.ub, - name: r.Named(), - } -} - -// tags implements remote tagging operations. -type tags struct { - client *http.Client - ub *v2.URLBuilder - name reference.Named -} - -// All returns all tags -func (t *tags) All(ctx context.Context) ([]string, error) { - var tags []string - - listURLStr, err := t.ub.BuildTagsURL(t.name) - if err != nil { - return tags, err - } - - listURL, err := url.Parse(listURLStr) - if err != nil { - return tags, err - } - - for { - resp, err := t.client.Get(listURL.String()) - if err != nil { - return tags, err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return tags, err - } - - tagsResponse := struct { - Tags []string `json:"tags"` - }{} - if err := json.Unmarshal(b, &tagsResponse); err != nil { - return tags, err - } - tags = append(tags, tagsResponse.Tags...) - if link := resp.Header.Get("Link"); link != "" { - linkURLStr := strings.Trim(strings.Split(link, ";")[0], "<>") - linkURL, err := url.Parse(linkURLStr) - if err != nil { - return tags, err - } - - listURL = listURL.ResolveReference(linkURL) - } else { - return tags, nil - } - } else { - return tags, HandleErrorResponse(resp) - } - } -} - -func descriptorFromResponse(response *http.Response) (distribution.Descriptor, error) { - desc := distribution.Descriptor{} - headers := response.Header - - ctHeader := headers.Get("Content-Type") - if ctHeader == "" { - return distribution.Descriptor{}, errors.New("missing or empty Content-Type header") - } - desc.MediaType = ctHeader - - digestHeader := headers.Get("Docker-Content-Digest") - if digestHeader == "" { - bytes, err := ioutil.ReadAll(response.Body) - if err != nil { - return distribution.Descriptor{}, err - } - _, desc, err := distribution.UnmarshalManifest(ctHeader, bytes) - if err != nil { - return distribution.Descriptor{}, err - } - return desc, nil - } - - dgst, err := digest.Parse(digestHeader) - if err != nil { - return distribution.Descriptor{}, err - } - desc.Digest = dgst - - lengthHeader := headers.Get("Content-Length") - if lengthHeader == "" { - return distribution.Descriptor{}, errors.New("missing or empty Content-Length header") - } - length, err := strconv.ParseInt(lengthHeader, 10, 64) - if err != nil { - return distribution.Descriptor{}, err - } - desc.Size = length - - return desc, nil - -} - -// Get issues a HEAD request for a Manifest against its named endpoint in order -// to construct a descriptor for the tag. If the registry doesn't support HEADing -// a manifest, fallback to GET. -func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, error) { - ref, err := reference.WithTag(t.name, tag) - if err != nil { - return distribution.Descriptor{}, err - } - u, err := t.ub.BuildManifestURL(ref) - if err != nil { - return distribution.Descriptor{}, err - } - - newRequest := func(method string) (*http.Response, error) { - req, err := http.NewRequest(method, u, nil) - if err != nil { - return nil, err - } - - for _, t := range distribution.ManifestMediaTypes() { - req.Header.Add("Accept", t) - } - resp, err := t.client.Do(req) - return resp, err - } - - resp, err := newRequest("HEAD") - if err != nil { - return distribution.Descriptor{}, err - } - defer resp.Body.Close() - - switch { - case resp.StatusCode >= 200 && resp.StatusCode < 400 && len(resp.Header.Get("Docker-Content-Digest")) > 0: - // if the response is a success AND a Docker-Content-Digest can be retrieved from the headers - return descriptorFromResponse(resp) - default: - // if the response is an error - there will be no body to decode. - // Issue a GET request: - // - for data from a server that does not handle HEAD - // - to get error details in case of a failure - resp, err = newRequest("GET") - if err != nil { - return distribution.Descriptor{}, err - } - defer resp.Body.Close() - - if resp.StatusCode >= 200 && resp.StatusCode < 400 { - return descriptorFromResponse(resp) - } - return distribution.Descriptor{}, HandleErrorResponse(resp) - } -} - -func (t *tags) Lookup(ctx context.Context, digest distribution.Descriptor) ([]string, error) { - panic("not implemented") -} - -func (t *tags) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error { - panic("not implemented") -} - -func (t *tags) Untag(ctx context.Context, tag string) error { - panic("not implemented") -} - -type manifests struct { - name reference.Named - ub *v2.URLBuilder - client *http.Client - etags map[string]string -} - -func (ms *manifests) Exists(ctx context.Context, dgst digest.Digest) (bool, error) { - ref, err := reference.WithDigest(ms.name, dgst) - if err != nil { - return false, err - } - u, err := ms.ub.BuildManifestURL(ref) - if err != nil { - return false, err - } - - resp, err := ms.client.Head(u) - if err != nil { - return false, err - } - - if SuccessStatus(resp.StatusCode) { - return true, nil - } else if resp.StatusCode == http.StatusNotFound { - return false, nil - } - return false, HandleErrorResponse(resp) -} - -// AddEtagToTag allows a client to supply an eTag to Get which will be -// used for a conditional HTTP request. If the eTag matches, a nil manifest -// and ErrManifestNotModified error will be returned. etag is automatically -// quoted when added to this map. -func AddEtagToTag(tag, etag string) distribution.ManifestServiceOption { - return etagOption{tag, etag} -} - -type etagOption struct{ tag, etag string } - -func (o etagOption) Apply(ms distribution.ManifestService) error { - if ms, ok := ms.(*manifests); ok { - ms.etags[o.tag] = fmt.Sprintf(`"%s"`, o.etag) - return nil - } - return fmt.Errorf("etag options is a client-only option") -} - -// ReturnContentDigest allows a client to set a the content digest on -// a successful request from the 'Docker-Content-Digest' header. This -// returned digest is represents the digest which the registry uses -// to refer to the content and can be used to delete the content. -func ReturnContentDigest(dgst *digest.Digest) distribution.ManifestServiceOption { - return contentDigestOption{dgst} -} - -type contentDigestOption struct{ digest *digest.Digest } - -func (o contentDigestOption) Apply(ms distribution.ManifestService) error { - return nil -} - -func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) { - var ( - digestOrTag string - ref reference.Named - err error - contentDgst *digest.Digest - mediaTypes []string - ) - - for _, option := range options { - switch opt := option.(type) { - case distribution.WithTagOption: - digestOrTag = opt.Tag - ref, err = reference.WithTag(ms.name, opt.Tag) - if err != nil { - return nil, err - } - case contentDigestOption: - contentDgst = opt.digest - case distribution.WithManifestMediaTypesOption: - mediaTypes = opt.MediaTypes - default: - err := option.Apply(ms) - if err != nil { - return nil, err - } - } - } - - if digestOrTag == "" { - digestOrTag = dgst.String() - ref, err = reference.WithDigest(ms.name, dgst) - if err != nil { - return nil, err - } - } - - if len(mediaTypes) == 0 { - mediaTypes = distribution.ManifestMediaTypes() - } - - u, err := ms.ub.BuildManifestURL(ref) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", u, nil) - if err != nil { - return nil, err - } - - for _, t := range mediaTypes { - req.Header.Add("Accept", t) - } - - if _, ok := ms.etags[digestOrTag]; ok { - req.Header.Set("If-None-Match", ms.etags[digestOrTag]) - } - - resp, err := ms.client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - if resp.StatusCode == http.StatusNotModified { - return nil, distribution.ErrManifestNotModified - } else if SuccessStatus(resp.StatusCode) { - if contentDgst != nil { - dgst, err := digest.Parse(resp.Header.Get("Docker-Content-Digest")) - if err == nil { - *contentDgst = dgst - } - } - mt := resp.Header.Get("Content-Type") - body, err := ioutil.ReadAll(resp.Body) - - if err != nil { - return nil, err - } - m, _, err := distribution.UnmarshalManifest(mt, body) - if err != nil { - return nil, err - } - return m, nil - } - return nil, HandleErrorResponse(resp) -} - -// Put puts a manifest. A tag can be specified using an options parameter which uses some shared state to hold the -// tag name in order to build the correct upload URL. -func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) { - ref := ms.name - var tagged bool - - for _, option := range options { - if opt, ok := option.(distribution.WithTagOption); ok { - var err error - ref, err = reference.WithTag(ref, opt.Tag) - if err != nil { - return "", err - } - tagged = true - } else { - err := option.Apply(ms) - if err != nil { - return "", err - } - } - } - mediaType, p, err := m.Payload() - if err != nil { - return "", err - } - - if !tagged { - // generate a canonical digest and Put by digest - _, d, err := distribution.UnmarshalManifest(mediaType, p) - if err != nil { - return "", err - } - ref, err = reference.WithDigest(ref, d.Digest) - if err != nil { - return "", err - } - } - - manifestURL, err := ms.ub.BuildManifestURL(ref) - if err != nil { - return "", err - } - - putRequest, err := http.NewRequest("PUT", manifestURL, bytes.NewReader(p)) - if err != nil { - return "", err - } - - putRequest.Header.Set("Content-Type", mediaType) - - resp, err := ms.client.Do(putRequest) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - dgstHeader := resp.Header.Get("Docker-Content-Digest") - dgst, err := digest.Parse(dgstHeader) - if err != nil { - return "", err - } - - return dgst, nil - } - - return "", HandleErrorResponse(resp) -} - -func (ms *manifests) Delete(ctx context.Context, dgst digest.Digest) error { - ref, err := reference.WithDigest(ms.name, dgst) - if err != nil { - return err - } - u, err := ms.ub.BuildManifestURL(ref) - if err != nil { - return err - } - req, err := http.NewRequest("DELETE", u, nil) - if err != nil { - return err - } - - resp, err := ms.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - return nil - } - return HandleErrorResponse(resp) -} - -// todo(richardscothern): Restore interface and implementation with merge of #1050 -/*func (ms *manifests) Enumerate(ctx context.Context, manifests []distribution.Manifest, last distribution.Manifest) (n int, err error) { - panic("not supported") -}*/ - -type blobs struct { - name reference.Named - ub *v2.URLBuilder - client *http.Client - - statter distribution.BlobDescriptorService - distribution.BlobDeleter -} - -func sanitizeLocation(location, base string) (string, error) { - baseURL, err := url.Parse(base) - if err != nil { - return "", err - } - - locationURL, err := url.Parse(location) - if err != nil { - return "", err - } - - return baseURL.ResolveReference(locationURL).String(), nil -} - -func (bs *blobs) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - return bs.statter.Stat(ctx, dgst) - -} - -func (bs *blobs) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) { - reader, err := bs.Open(ctx, dgst) - if err != nil { - return nil, err - } - defer reader.Close() - - return ioutil.ReadAll(reader) -} - -func (bs *blobs) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) { - ref, err := reference.WithDigest(bs.name, dgst) - if err != nil { - return nil, err - } - blobURL, err := bs.ub.BuildBlobURL(ref) - if err != nil { - return nil, err - } - - return transport.NewHTTPReadSeeker(bs.client, blobURL, - func(resp *http.Response) error { - if resp.StatusCode == http.StatusNotFound { - return distribution.ErrBlobUnknown - } - return HandleErrorResponse(resp) - }), nil -} - -func (bs *blobs) ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error { - panic("not implemented") -} - -func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) { - writer, err := bs.Create(ctx) - if err != nil { - return distribution.Descriptor{}, err - } - dgstr := digest.Canonical.Digester() - n, err := io.Copy(writer, io.TeeReader(bytes.NewReader(p), dgstr.Hash())) - if err != nil { - return distribution.Descriptor{}, err - } - if n < int64(len(p)) { - return distribution.Descriptor{}, fmt.Errorf("short copy: wrote %d of %d", n, len(p)) - } - - desc := distribution.Descriptor{ - MediaType: mediaType, - Size: int64(len(p)), - Digest: dgstr.Digest(), - } - - return writer.Commit(ctx, desc) -} - -type optionFunc func(interface{}) error - -func (f optionFunc) Apply(v interface{}) error { - return f(v) -} - -// WithMountFrom returns a BlobCreateOption which designates that the blob should be -// mounted from the given canonical reference. -func WithMountFrom(ref reference.Canonical) distribution.BlobCreateOption { - return optionFunc(func(v interface{}) error { - opts, ok := v.(*distribution.CreateOptions) - if !ok { - return fmt.Errorf("unexpected options type: %T", v) - } - - opts.Mount.ShouldMount = true - opts.Mount.From = ref - - return nil - }) -} - -func (bs *blobs) Create(ctx context.Context, options ...distribution.BlobCreateOption) (distribution.BlobWriter, error) { - var opts distribution.CreateOptions - - for _, option := range options { - err := option.Apply(&opts) - if err != nil { - return nil, err - } - } - - var values []url.Values - - if opts.Mount.ShouldMount { - values = append(values, url.Values{"from": {opts.Mount.From.Name()}, "mount": {opts.Mount.From.Digest().String()}}) - } - - u, err := bs.ub.BuildBlobUploadURL(bs.name, values...) - if err != nil { - return nil, err - } - - resp, err := bs.client.Post(u, "", nil) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - switch resp.StatusCode { - case http.StatusCreated: - desc, err := bs.statter.Stat(ctx, opts.Mount.From.Digest()) - if err != nil { - return nil, err - } - return nil, distribution.ErrBlobMounted{From: opts.Mount.From, Descriptor: desc} - case http.StatusAccepted: - // TODO(dmcgowan): Check for invalid UUID - uuid := resp.Header.Get("Docker-Upload-UUID") - location, err := sanitizeLocation(resp.Header.Get("Location"), u) - if err != nil { - return nil, err - } - - return &httpBlobUpload{ - statter: bs.statter, - client: bs.client, - uuid: uuid, - startedAt: time.Now(), - location: location, - }, nil - default: - return nil, HandleErrorResponse(resp) - } -} - -func (bs *blobs) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) { - panic("not implemented") -} - -func (bs *blobs) Delete(ctx context.Context, dgst digest.Digest) error { - return bs.statter.Clear(ctx, dgst) -} - -type blobStatter struct { - name reference.Named - ub *v2.URLBuilder - client *http.Client -} - -func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - ref, err := reference.WithDigest(bs.name, dgst) - if err != nil { - return distribution.Descriptor{}, err - } - u, err := bs.ub.BuildBlobURL(ref) - if err != nil { - return distribution.Descriptor{}, err - } - - resp, err := bs.client.Head(u) - if err != nil { - return distribution.Descriptor{}, err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - lengthHeader := resp.Header.Get("Content-Length") - if lengthHeader == "" { - return distribution.Descriptor{}, fmt.Errorf("missing content-length header for request: %s", u) - } - - length, err := strconv.ParseInt(lengthHeader, 10, 64) - if err != nil { - return distribution.Descriptor{}, fmt.Errorf("error parsing content-length: %v", err) - } - - return distribution.Descriptor{ - MediaType: resp.Header.Get("Content-Type"), - Size: length, - Digest: dgst, - }, nil - } else if resp.StatusCode == http.StatusNotFound { - return distribution.Descriptor{}, distribution.ErrBlobUnknown - } - return distribution.Descriptor{}, HandleErrorResponse(resp) -} - -func buildCatalogValues(maxEntries int, last string) url.Values { - values := url.Values{} - - if maxEntries > 0 { - values.Add("n", strconv.Itoa(maxEntries)) - } - - if last != "" { - values.Add("last", last) - } - - return values -} - -func (bs *blobStatter) Clear(ctx context.Context, dgst digest.Digest) error { - ref, err := reference.WithDigest(bs.name, dgst) - if err != nil { - return err - } - blobURL, err := bs.ub.BuildBlobURL(ref) - if err != nil { - return err - } - - req, err := http.NewRequest("DELETE", blobURL, nil) - if err != nil { - return err - } - - resp, err := bs.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - return nil - } - return HandleErrorResponse(resp) -} - -func (bs *blobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/client/transport/http_reader.go b/vendor/github.com/docker/distribution/registry/client/transport/http_reader.go deleted file mode 100644 index e5ff09d756..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/transport/http_reader.go +++ /dev/null @@ -1,251 +0,0 @@ -package transport - -import ( - "errors" - "fmt" - "io" - "net/http" - "os" - "regexp" - "strconv" -) - -var ( - contentRangeRegexp = regexp.MustCompile(`bytes ([0-9]+)-([0-9]+)/([0-9]+|\\*)`) - - // ErrWrongCodeForByteRange is returned if the client sends a request - // with a Range header but the server returns a 2xx or 3xx code other - // than 206 Partial Content. - ErrWrongCodeForByteRange = errors.New("expected HTTP 206 from byte range request") -) - -// ReadSeekCloser combines io.ReadSeeker with io.Closer. -type ReadSeekCloser interface { - io.ReadSeeker - io.Closer -} - -// NewHTTPReadSeeker handles reading from an HTTP endpoint using a GET -// request. When seeking and starting a read from a non-zero offset -// the a "Range" header will be added which sets the offset. -// TODO(dmcgowan): Move this into a separate utility package -func NewHTTPReadSeeker(client *http.Client, url string, errorHandler func(*http.Response) error) ReadSeekCloser { - return &httpReadSeeker{ - client: client, - url: url, - errorHandler: errorHandler, - } -} - -type httpReadSeeker struct { - client *http.Client - url string - - // errorHandler creates an error from an unsuccessful HTTP response. - // This allows the error to be created with the HTTP response body - // without leaking the body through a returned error. - errorHandler func(*http.Response) error - - size int64 - - // rc is the remote read closer. - rc io.ReadCloser - // readerOffset tracks the offset as of the last read. - readerOffset int64 - // seekOffset allows Seek to override the offset. Seek changes - // seekOffset instead of changing readOffset directly so that - // connection resets can be delayed and possibly avoided if the - // seek is undone (i.e. seeking to the end and then back to the - // beginning). - seekOffset int64 - err error -} - -func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) { - if hrs.err != nil { - return 0, hrs.err - } - - // If we sought to a different position, we need to reset the - // connection. This logic is here instead of Seek so that if - // a seek is undone before the next read, the connection doesn't - // need to be closed and reopened. A common example of this is - // seeking to the end to determine the length, and then seeking - // back to the original position. - if hrs.readerOffset != hrs.seekOffset { - hrs.reset() - } - - hrs.readerOffset = hrs.seekOffset - - rd, err := hrs.reader() - if err != nil { - return 0, err - } - - n, err = rd.Read(p) - hrs.seekOffset += int64(n) - hrs.readerOffset += int64(n) - - return n, err -} - -func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) { - if hrs.err != nil { - return 0, hrs.err - } - - lastReaderOffset := hrs.readerOffset - - if whence == os.SEEK_SET && hrs.rc == nil { - // If no request has been made yet, and we are seeking to an - // absolute position, set the read offset as well to avoid an - // unnecessary request. - hrs.readerOffset = offset - } - - _, err := hrs.reader() - if err != nil { - hrs.readerOffset = lastReaderOffset - return 0, err - } - - newOffset := hrs.seekOffset - - switch whence { - case os.SEEK_CUR: - newOffset += offset - case os.SEEK_END: - if hrs.size < 0 { - return 0, errors.New("content length not known") - } - newOffset = hrs.size + offset - case os.SEEK_SET: - newOffset = offset - } - - if newOffset < 0 { - err = errors.New("cannot seek to negative position") - } else { - hrs.seekOffset = newOffset - } - - return hrs.seekOffset, err -} - -func (hrs *httpReadSeeker) Close() error { - if hrs.err != nil { - return hrs.err - } - - // close and release reader chain - if hrs.rc != nil { - hrs.rc.Close() - } - - hrs.rc = nil - - hrs.err = errors.New("httpLayer: closed") - - return nil -} - -func (hrs *httpReadSeeker) reset() { - if hrs.err != nil { - return - } - if hrs.rc != nil { - hrs.rc.Close() - hrs.rc = nil - } -} - -func (hrs *httpReadSeeker) reader() (io.Reader, error) { - if hrs.err != nil { - return nil, hrs.err - } - - if hrs.rc != nil { - return hrs.rc, nil - } - - req, err := http.NewRequest("GET", hrs.url, nil) - if err != nil { - return nil, err - } - - if hrs.readerOffset > 0 { - // If we are at different offset, issue a range request from there. - req.Header.Add("Range", fmt.Sprintf("bytes=%d-", hrs.readerOffset)) - // TODO: get context in here - // context.GetLogger(hrs.context).Infof("Range: %s", req.Header.Get("Range")) - } - - req.Header.Add("Accept-Encoding", "identity") - resp, err := hrs.client.Do(req) - if err != nil { - return nil, err - } - - // Normally would use client.SuccessStatus, but that would be a cyclic - // import - if resp.StatusCode >= 200 && resp.StatusCode <= 399 { - if hrs.readerOffset > 0 { - if resp.StatusCode != http.StatusPartialContent { - return nil, ErrWrongCodeForByteRange - } - - contentRange := resp.Header.Get("Content-Range") - if contentRange == "" { - return nil, errors.New("no Content-Range header found in HTTP 206 response") - } - - submatches := contentRangeRegexp.FindStringSubmatch(contentRange) - if len(submatches) < 4 { - return nil, fmt.Errorf("could not parse Content-Range header: %s", contentRange) - } - - startByte, err := strconv.ParseUint(submatches[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("could not parse start of range in Content-Range header: %s", contentRange) - } - - if startByte != uint64(hrs.readerOffset) { - return nil, fmt.Errorf("received Content-Range starting at offset %d instead of requested %d", startByte, hrs.readerOffset) - } - - endByte, err := strconv.ParseUint(submatches[2], 10, 64) - if err != nil { - return nil, fmt.Errorf("could not parse end of range in Content-Range header: %s", contentRange) - } - - if submatches[3] == "*" { - hrs.size = -1 - } else { - size, err := strconv.ParseUint(submatches[3], 10, 64) - if err != nil { - return nil, fmt.Errorf("could not parse total size in Content-Range header: %s", contentRange) - } - - if endByte+1 != size { - return nil, fmt.Errorf("range in Content-Range stops before the end of the content: %s", contentRange) - } - - hrs.size = int64(size) - } - } else if resp.StatusCode == http.StatusOK { - hrs.size = resp.ContentLength - } else { - hrs.size = -1 - } - hrs.rc = resp.Body - } else { - defer resp.Body.Close() - if hrs.errorHandler != nil { - return nil, hrs.errorHandler(resp) - } - return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status) - } - - return hrs.rc, nil -} diff --git a/vendor/github.com/docker/distribution/registry/client/transport/transport.go b/vendor/github.com/docker/distribution/registry/client/transport/transport.go deleted file mode 100644 index 30e45fab0f..0000000000 --- a/vendor/github.com/docker/distribution/registry/client/transport/transport.go +++ /dev/null @@ -1,147 +0,0 @@ -package transport - -import ( - "io" - "net/http" - "sync" -) - -// RequestModifier represents an object which will do an inplace -// modification of an HTTP request. -type RequestModifier interface { - ModifyRequest(*http.Request) error -} - -type headerModifier http.Header - -// NewHeaderRequestModifier returns a new RequestModifier which will -// add the given headers to a request. -func NewHeaderRequestModifier(header http.Header) RequestModifier { - return headerModifier(header) -} - -func (h headerModifier) ModifyRequest(req *http.Request) error { - for k, s := range http.Header(h) { - req.Header[k] = append(req.Header[k], s...) - } - - return nil -} - -// NewTransport creates a new transport which will apply modifiers to -// the request on a RoundTrip call. -func NewTransport(base http.RoundTripper, modifiers ...RequestModifier) http.RoundTripper { - return &transport{ - Modifiers: modifiers, - Base: base, - } -} - -// transport is an http.RoundTripper that makes HTTP requests after -// copying and modifying the request -type transport struct { - Modifiers []RequestModifier - Base http.RoundTripper - - mu sync.Mutex // guards modReq - modReq map[*http.Request]*http.Request // original -> modified -} - -// RoundTrip authorizes and authenticates the request with an -// access token. If no token exists or token is expired, -// tries to refresh/fetch a new token. -func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { - req2 := cloneRequest(req) - for _, modifier := range t.Modifiers { - if err := modifier.ModifyRequest(req2); err != nil { - return nil, err - } - } - - t.setModReq(req, req2) - res, err := t.base().RoundTrip(req2) - if err != nil { - t.setModReq(req, nil) - return nil, err - } - res.Body = &onEOFReader{ - rc: res.Body, - fn: func() { t.setModReq(req, nil) }, - } - return res, nil -} - -// CancelRequest cancels an in-flight request by closing its connection. -func (t *transport) CancelRequest(req *http.Request) { - type canceler interface { - CancelRequest(*http.Request) - } - if cr, ok := t.base().(canceler); ok { - t.mu.Lock() - modReq := t.modReq[req] - delete(t.modReq, req) - t.mu.Unlock() - cr.CancelRequest(modReq) - } -} - -func (t *transport) base() http.RoundTripper { - if t.Base != nil { - return t.Base - } - return http.DefaultTransport -} - -func (t *transport) setModReq(orig, mod *http.Request) { - t.mu.Lock() - defer t.mu.Unlock() - if t.modReq == nil { - t.modReq = make(map[*http.Request]*http.Request) - } - if mod == nil { - delete(t.modReq, orig) - } else { - t.modReq[orig] = mod - } -} - -// cloneRequest returns a clone of the provided *http.Request. -// The clone is a shallow copy of the struct and its Header map. -func cloneRequest(r *http.Request) *http.Request { - // shallow copy of the struct - r2 := new(http.Request) - *r2 = *r - // deep copy of the Header - r2.Header = make(http.Header, len(r.Header)) - for k, s := range r.Header { - r2.Header[k] = append([]string(nil), s...) - } - - return r2 -} - -type onEOFReader struct { - rc io.ReadCloser - fn func() -} - -func (r *onEOFReader) Read(p []byte) (n int, err error) { - n, err = r.rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -func (r *onEOFReader) Close() error { - err := r.rc.Close() - r.runFunc() - return err -} - -func (r *onEOFReader) runFunc() { - if fn := r.fn; fn != nil { - fn() - r.fn = nil - } -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cache.go b/vendor/github.com/docker/distribution/registry/storage/cache/cache.go deleted file mode 100644 index 10a3909197..0000000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/cache.go +++ /dev/null @@ -1,35 +0,0 @@ -// Package cache provides facilities to speed up access to the storage -// backend. -package cache - -import ( - "fmt" - - "github.com/docker/distribution" -) - -// BlobDescriptorCacheProvider provides repository scoped -// BlobDescriptorService cache instances and a global descriptor cache. -type BlobDescriptorCacheProvider interface { - distribution.BlobDescriptorService - - RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) -} - -// ValidateDescriptor provides a helper function to ensure that caches have -// common criteria for admitting descriptors. -func ValidateDescriptor(desc distribution.Descriptor) error { - if err := desc.Digest.Validate(); err != nil { - return err - } - - if desc.Size < 0 { - return fmt.Errorf("cache: invalid length in descriptor: %v < 0", desc.Size) - } - - if desc.MediaType == "" { - return fmt.Errorf("cache: empty mediatype on descriptor: %v", desc) - } - - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go b/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go deleted file mode 100644 index ac4c452117..0000000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go +++ /dev/null @@ -1,129 +0,0 @@ -package cache - -import ( - "context" - - "github.com/docker/distribution" - prometheus "github.com/docker/distribution/metrics" - "github.com/opencontainers/go-digest" -) - -// Metrics is used to hold metric counters -// related to the number of times a cache was -// hit or missed. -type Metrics struct { - Requests uint64 - Hits uint64 - Misses uint64 -} - -// Logger can be provided on the MetricsTracker to log errors. -// -// Usually, this is just a proxy to dcontext.GetLogger. -type Logger interface { - Errorf(format string, args ...interface{}) -} - -// MetricsTracker represents a metric tracker -// which simply counts the number of hits and misses. -type MetricsTracker interface { - Hit() - Miss() - Metrics() Metrics - Logger(context.Context) Logger -} - -type cachedBlobStatter struct { - cache distribution.BlobDescriptorService - backend distribution.BlobDescriptorService - tracker MetricsTracker -} - -var ( - // cacheCount is the number of total cache request received/hits/misses - cacheCount = prometheus.StorageNamespace.NewLabeledCounter("cache", "The number of cache request received", "type") -) - -// NewCachedBlobStatter creates a new statter which prefers a cache and -// falls back to a backend. -func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService) distribution.BlobDescriptorService { - return &cachedBlobStatter{ - cache: cache, - backend: backend, - } -} - -// NewCachedBlobStatterWithMetrics creates a new statter which prefers a cache and -// falls back to a backend. Hits and misses will send to the tracker. -func NewCachedBlobStatterWithMetrics(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService, tracker MetricsTracker) distribution.BlobStatter { - return &cachedBlobStatter{ - cache: cache, - backend: backend, - tracker: tracker, - } -} - -func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - cacheCount.WithValues("Request").Inc(1) - desc, err := cbds.cache.Stat(ctx, dgst) - if err != nil { - if err != distribution.ErrBlobUnknown { - logErrorf(ctx, cbds.tracker, "error retrieving descriptor from cache: %v", err) - } - - goto fallback - } - cacheCount.WithValues("Hit").Inc(1) - if cbds.tracker != nil { - cbds.tracker.Hit() - } - return desc, nil -fallback: - cacheCount.WithValues("Miss").Inc(1) - if cbds.tracker != nil { - cbds.tracker.Miss() - } - desc, err = cbds.backend.Stat(ctx, dgst) - if err != nil { - return desc, err - } - - if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil { - logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err) - } - - return desc, err - -} - -func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) error { - err := cbds.cache.Clear(ctx, dgst) - if err != nil { - return err - } - - err = cbds.backend.Clear(ctx, dgst) - if err != nil { - return err - } - return nil -} - -func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil { - logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err) - } - return nil -} - -func logErrorf(ctx context.Context, tracker MetricsTracker, format string, args ...interface{}) { - if tracker == nil { - return - } - - logger := tracker.Logger(ctx) - if logger == nil { - return - } - logger.Errorf(format, args...) -} diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go b/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go deleted file mode 100644 index 42d94d9bde..0000000000 --- a/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go +++ /dev/null @@ -1,179 +0,0 @@ -package memory - -import ( - "context" - "sync" - - "github.com/docker/distribution" - "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/storage/cache" - "github.com/opencontainers/go-digest" -) - -type inMemoryBlobDescriptorCacheProvider struct { - global *mapBlobDescriptorCache - repositories map[string]*mapBlobDescriptorCache - mu sync.RWMutex -} - -// NewInMemoryBlobDescriptorCacheProvider returns a new mapped-based cache for -// storing blob descriptor data. -func NewInMemoryBlobDescriptorCacheProvider() cache.BlobDescriptorCacheProvider { - return &inMemoryBlobDescriptorCacheProvider{ - global: newMapBlobDescriptorCache(), - repositories: make(map[string]*mapBlobDescriptorCache), - } -} - -func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { - if _, err := reference.ParseNormalizedNamed(repo); err != nil { - return nil, err - } - - imbdcp.mu.RLock() - defer imbdcp.mu.RUnlock() - - return &repositoryScopedInMemoryBlobDescriptorCache{ - repo: repo, - parent: imbdcp, - repository: imbdcp.repositories[repo], - }, nil -} - -func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - return imbdcp.global.Stat(ctx, dgst) -} - -func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dgst digest.Digest) error { - return imbdcp.global.Clear(ctx, dgst) -} - -func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - _, err := imbdcp.Stat(ctx, dgst) - if err == distribution.ErrBlobUnknown { - - if dgst.Algorithm() != desc.Digest.Algorithm() && dgst != desc.Digest { - // if the digests differ, set the other canonical mapping - if err := imbdcp.global.SetDescriptor(ctx, desc.Digest, desc); err != nil { - return err - } - } - - // unknown, just set it - return imbdcp.global.SetDescriptor(ctx, dgst, desc) - } - - // we already know it, do nothing - return err -} - -// repositoryScopedInMemoryBlobDescriptorCache provides the request scoped -// repository cache. Instances are not thread-safe but the delegated -// operations are. -type repositoryScopedInMemoryBlobDescriptorCache struct { - repo string - parent *inMemoryBlobDescriptorCacheProvider // allows lazy allocation of repo's map - repository *mapBlobDescriptorCache -} - -func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - rsimbdcp.parent.mu.Lock() - repo := rsimbdcp.repository - rsimbdcp.parent.mu.Unlock() - - if repo == nil { - return distribution.Descriptor{}, distribution.ErrBlobUnknown - } - - return repo.Stat(ctx, dgst) -} - -func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error { - rsimbdcp.parent.mu.Lock() - repo := rsimbdcp.repository - rsimbdcp.parent.mu.Unlock() - - if repo == nil { - return distribution.ErrBlobUnknown - } - - return repo.Clear(ctx, dgst) -} - -func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - rsimbdcp.parent.mu.Lock() - repo := rsimbdcp.repository - if repo == nil { - // allocate map since we are setting it now. - var ok bool - // have to read back value since we may have allocated elsewhere. - repo, ok = rsimbdcp.parent.repositories[rsimbdcp.repo] - if !ok { - repo = newMapBlobDescriptorCache() - rsimbdcp.parent.repositories[rsimbdcp.repo] = repo - } - rsimbdcp.repository = repo - } - rsimbdcp.parent.mu.Unlock() - - if err := repo.SetDescriptor(ctx, dgst, desc); err != nil { - return err - } - - return rsimbdcp.parent.SetDescriptor(ctx, dgst, desc) -} - -// mapBlobDescriptorCache provides a simple map-based implementation of the -// descriptor cache. -type mapBlobDescriptorCache struct { - descriptors map[digest.Digest]distribution.Descriptor - mu sync.RWMutex -} - -var _ distribution.BlobDescriptorService = &mapBlobDescriptorCache{} - -func newMapBlobDescriptorCache() *mapBlobDescriptorCache { - return &mapBlobDescriptorCache{ - descriptors: make(map[digest.Digest]distribution.Descriptor), - } -} - -func (mbdc *mapBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { - if err := dgst.Validate(); err != nil { - return distribution.Descriptor{}, err - } - - mbdc.mu.RLock() - defer mbdc.mu.RUnlock() - - desc, ok := mbdc.descriptors[dgst] - if !ok { - return distribution.Descriptor{}, distribution.ErrBlobUnknown - } - - return desc, nil -} - -func (mbdc *mapBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error { - mbdc.mu.Lock() - defer mbdc.mu.Unlock() - - delete(mbdc.descriptors, dgst) - return nil -} - -func (mbdc *mapBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error { - if err := dgst.Validate(); err != nil { - return err - } - - if err := cache.ValidateDescriptor(desc); err != nil { - return err - } - - mbdc.mu.Lock() - defer mbdc.mu.Unlock() - - mbdc.descriptors[dgst] = desc - return nil -} diff --git a/vendor/github.com/docker/distribution/tags.go b/vendor/github.com/docker/distribution/tags.go deleted file mode 100644 index f22df2b850..0000000000 --- a/vendor/github.com/docker/distribution/tags.go +++ /dev/null @@ -1,27 +0,0 @@ -package distribution - -import ( - "context" -) - -// TagService provides access to information about tagged objects. -type TagService interface { - // Get retrieves the descriptor identified by the tag. Some - // implementations may differentiate between "trusted" tags and - // "untrusted" tags. If a tag is "untrusted", the mapping will be returned - // as an ErrTagUntrusted error, with the target descriptor. - Get(ctx context.Context, tag string) (Descriptor, error) - - // Tag associates the tag with the provided descriptor, updating the - // current association, if needed. - Tag(ctx context.Context, tag string, desc Descriptor) error - - // Untag removes the given tag association - Untag(ctx context.Context, tag string) error - - // All returns the set of tags managed by this tag service - All(ctx context.Context) ([]string, error) - - // Lookup returns the set of tags referencing the given digest. - Lookup(ctx context.Context, digest Descriptor) ([]string, error) -} diff --git a/vendor/github.com/docker/docker-credential-helpers/LICENSE b/vendor/github.com/docker/docker-credential-helpers/LICENSE deleted file mode 100644 index 1ea555e2af..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2016 David Calavera - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/docker/docker-credential-helpers/client/client.go b/vendor/github.com/docker/docker-credential-helpers/client/client.go deleted file mode 100644 index d1d0434cb5..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/client/client.go +++ /dev/null @@ -1,121 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - - "github.com/docker/docker-credential-helpers/credentials" -) - -// isValidCredsMessage checks if 'msg' contains invalid credentials error message. -// It returns whether the logs are free of invalid credentials errors and the error if it isn't. -// error values can be errCredentialsMissingServerURL or errCredentialsMissingUsername. -func isValidCredsMessage(msg string) error { - if credentials.IsCredentialsMissingServerURLMessage(msg) { - return credentials.NewErrCredentialsMissingServerURL() - } - - if credentials.IsCredentialsMissingUsernameMessage(msg) { - return credentials.NewErrCredentialsMissingUsername() - } - - return nil -} - -// Store uses an external program to save credentials. -func Store(program ProgramFunc, creds *credentials.Credentials) error { - cmd := program("store") - - buffer := new(bytes.Buffer) - if err := json.NewEncoder(buffer).Encode(creds); err != nil { - return err - } - cmd.Input(buffer) - - out, err := cmd.Output() - if err != nil { - t := strings.TrimSpace(string(out)) - - if isValidErr := isValidCredsMessage(t); isValidErr != nil { - err = isValidErr - } - - return fmt.Errorf("error storing credentials - err: %v, out: `%s`", err, t) - } - - return nil -} - -// Get executes an external program to get the credentials from a native store. -func Get(program ProgramFunc, serverURL string) (*credentials.Credentials, error) { - cmd := program("get") - cmd.Input(strings.NewReader(serverURL)) - - out, err := cmd.Output() - if err != nil { - t := strings.TrimSpace(string(out)) - - if credentials.IsErrCredentialsNotFoundMessage(t) { - return nil, credentials.NewErrCredentialsNotFound() - } - - if isValidErr := isValidCredsMessage(t); isValidErr != nil { - err = isValidErr - } - - return nil, fmt.Errorf("error getting credentials - err: %v, out: `%s`", err, t) - } - - resp := &credentials.Credentials{ - ServerURL: serverURL, - } - - if err := json.NewDecoder(bytes.NewReader(out)).Decode(resp); err != nil { - return nil, err - } - - return resp, nil -} - -// Erase executes a program to remove the server credentials from the native store. -func Erase(program ProgramFunc, serverURL string) error { - cmd := program("erase") - cmd.Input(strings.NewReader(serverURL)) - out, err := cmd.Output() - if err != nil { - t := strings.TrimSpace(string(out)) - - if isValidErr := isValidCredsMessage(t); isValidErr != nil { - err = isValidErr - } - - return fmt.Errorf("error erasing credentials - err: %v, out: `%s`", err, t) - } - - return nil -} - -// List executes a program to list server credentials in the native store. -func List(program ProgramFunc) (map[string]string, error) { - cmd := program("list") - cmd.Input(strings.NewReader("unused")) - out, err := cmd.Output() - if err != nil { - t := strings.TrimSpace(string(out)) - - if isValidErr := isValidCredsMessage(t); isValidErr != nil { - err = isValidErr - } - - return nil, fmt.Errorf("error listing credentials - err: %v, out: `%s`", err, t) - } - - var resp map[string]string - if err = json.NewDecoder(bytes.NewReader(out)).Decode(&resp); err != nil { - return nil, err - } - - return resp, nil -} diff --git a/vendor/github.com/docker/docker-credential-helpers/client/command.go b/vendor/github.com/docker/docker-credential-helpers/client/command.go deleted file mode 100644 index 8da3343065..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/client/command.go +++ /dev/null @@ -1,56 +0,0 @@ -package client - -import ( - "fmt" - "io" - "os" - "os/exec" -) - -// Program is an interface to execute external programs. -type Program interface { - Output() ([]byte, error) - Input(in io.Reader) -} - -// ProgramFunc is a type of function that initializes programs based on arguments. -type ProgramFunc func(args ...string) Program - -// NewShellProgramFunc creates programs that are executed in a Shell. -func NewShellProgramFunc(name string) ProgramFunc { - return NewShellProgramFuncWithEnv(name, nil) -} - -// NewShellProgramFuncWithEnv creates programs that are executed in a Shell with environment variables -func NewShellProgramFuncWithEnv(name string, env *map[string]string) ProgramFunc { - return func(args ...string) Program { - return &Shell{cmd: createProgramCmdRedirectErr(name, args, env)} - } -} - -func createProgramCmdRedirectErr(commandName string, args []string, env *map[string]string) *exec.Cmd { - programCmd := exec.Command(commandName, args...) - programCmd.Env = os.Environ() - if env != nil { - for k, v := range *env { - programCmd.Env = append(programCmd.Env, fmt.Sprintf("%s=%s", k, v)) - } - } - programCmd.Stderr = os.Stderr - return programCmd -} - -// Shell invokes shell commands to talk with a remote credentials helper. -type Shell struct { - cmd *exec.Cmd -} - -// Output returns responses from the remote credentials helper. -func (s *Shell) Output() ([]byte, error) { - return s.cmd.Output() -} - -// Input sets the input to send to a remote credentials helper. -func (s *Shell) Input(in io.Reader) { - s.cmd.Stdin = in -} diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go b/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go deleted file mode 100644 index da8b594e7f..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go +++ /dev/null @@ -1,186 +0,0 @@ -package credentials - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "io" - "os" - "strings" -) - -// Credentials holds the information shared between docker and the credentials store. -type Credentials struct { - ServerURL string - Username string - Secret string -} - -// isValid checks the integrity of Credentials object such that no credentials lack -// a server URL or a username. -// It returns whether the credentials are valid and the error if it isn't. -// error values can be errCredentialsMissingServerURL or errCredentialsMissingUsername -func (c *Credentials) isValid() (bool, error) { - if len(c.ServerURL) == 0 { - return false, NewErrCredentialsMissingServerURL() - } - - if len(c.Username) == 0 { - return false, NewErrCredentialsMissingUsername() - } - - return true, nil -} - -// CredsLabel holds the way Docker credentials should be labeled as such in credentials stores that allow labelling. -// That label allows to filter out non-Docker credentials too at lookup/search in macOS keychain, -// Windows credentials manager and Linux libsecret. Default value is "Docker Credentials" -var CredsLabel = "Docker Credentials" - -// SetCredsLabel is a simple setter for CredsLabel -func SetCredsLabel(label string) { - CredsLabel = label -} - -// Serve initializes the credentials helper and parses the action argument. -// This function is designed to be called from a command line interface. -// It uses os.Args[1] as the key for the action. -// It uses os.Stdin as input and os.Stdout as output. -// This function terminates the program with os.Exit(1) if there is an error. -func Serve(helper Helper) { - var err error - if len(os.Args) != 2 { - err = fmt.Errorf("Usage: %s ", os.Args[0]) - } - - if err == nil { - err = HandleCommand(helper, os.Args[1], os.Stdin, os.Stdout) - } - - if err != nil { - fmt.Fprintf(os.Stdout, "%v\n", err) - os.Exit(1) - } -} - -// HandleCommand uses a helper and a key to run a credential action. -func HandleCommand(helper Helper, key string, in io.Reader, out io.Writer) error { - switch key { - case "store": - return Store(helper, in) - case "get": - return Get(helper, in, out) - case "erase": - return Erase(helper, in) - case "list": - return List(helper, out) - case "version": - return PrintVersion(out) - } - return fmt.Errorf("Unknown credential action `%s`", key) -} - -// Store uses a helper and an input reader to save credentials. -// The reader must contain the JSON serialization of a Credentials struct. -func Store(helper Helper, reader io.Reader) error { - scanner := bufio.NewScanner(reader) - - buffer := new(bytes.Buffer) - for scanner.Scan() { - buffer.Write(scanner.Bytes()) - } - - if err := scanner.Err(); err != nil && err != io.EOF { - return err - } - - var creds Credentials - if err := json.NewDecoder(buffer).Decode(&creds); err != nil { - return err - } - - if ok, err := creds.isValid(); !ok { - return err - } - - return helper.Add(&creds) -} - -// Get retrieves the credentials for a given server url. -// The reader must contain the server URL to search. -// The writer is used to write the JSON serialization of the credentials. -func Get(helper Helper, reader io.Reader, writer io.Writer) error { - scanner := bufio.NewScanner(reader) - - buffer := new(bytes.Buffer) - for scanner.Scan() { - buffer.Write(scanner.Bytes()) - } - - if err := scanner.Err(); err != nil && err != io.EOF { - return err - } - - serverURL := strings.TrimSpace(buffer.String()) - if len(serverURL) == 0 { - return NewErrCredentialsMissingServerURL() - } - - username, secret, err := helper.Get(serverURL) - if err != nil { - return err - } - - resp := Credentials{ - ServerURL: serverURL, - Username: username, - Secret: secret, - } - - buffer.Reset() - if err := json.NewEncoder(buffer).Encode(resp); err != nil { - return err - } - - fmt.Fprint(writer, buffer.String()) - return nil -} - -// Erase removes credentials from the store. -// The reader must contain the server URL to remove. -func Erase(helper Helper, reader io.Reader) error { - scanner := bufio.NewScanner(reader) - - buffer := new(bytes.Buffer) - for scanner.Scan() { - buffer.Write(scanner.Bytes()) - } - - if err := scanner.Err(); err != nil && err != io.EOF { - return err - } - - serverURL := strings.TrimSpace(buffer.String()) - if len(serverURL) == 0 { - return NewErrCredentialsMissingServerURL() - } - - return helper.Delete(serverURL) -} - -//List returns all the serverURLs of keys in -//the OS store as a list of strings -func List(helper Helper, writer io.Writer) error { - accts, err := helper.List() - if err != nil { - return err - } - return json.NewEncoder(writer).Encode(accts) -} - -//PrintVersion outputs the current version. -func PrintVersion(writer io.Writer) error { - fmt.Fprintln(writer, Version) - return nil -} diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/error.go b/vendor/github.com/docker/docker-credential-helpers/credentials/error.go deleted file mode 100644 index fe6a5aef45..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/error.go +++ /dev/null @@ -1,102 +0,0 @@ -package credentials - -const ( - // ErrCredentialsNotFound standardizes the not found error, so every helper returns - // the same message and docker can handle it properly. - errCredentialsNotFoundMessage = "credentials not found in native keychain" - - // ErrCredentialsMissingServerURL and ErrCredentialsMissingUsername standardize - // invalid credentials or credentials management operations - errCredentialsMissingServerURLMessage = "no credentials server URL" - errCredentialsMissingUsernameMessage = "no credentials username" -) - -// errCredentialsNotFound represents an error -// raised when credentials are not in the store. -type errCredentialsNotFound struct{} - -// Error returns the standard error message -// for when the credentials are not in the store. -func (errCredentialsNotFound) Error() string { - return errCredentialsNotFoundMessage -} - -// NewErrCredentialsNotFound creates a new error -// for when the credentials are not in the store. -func NewErrCredentialsNotFound() error { - return errCredentialsNotFound{} -} - -// IsErrCredentialsNotFound returns true if the error -// was caused by not having a set of credentials in a store. -func IsErrCredentialsNotFound(err error) bool { - _, ok := err.(errCredentialsNotFound) - return ok -} - -// IsErrCredentialsNotFoundMessage returns true if the error -// was caused by not having a set of credentials in a store. -// -// This function helps to check messages returned by an -// external program via its standard output. -func IsErrCredentialsNotFoundMessage(err string) bool { - return err == errCredentialsNotFoundMessage -} - -// errCredentialsMissingServerURL represents an error raised -// when the credentials object has no server URL or when no -// server URL is provided to a credentials operation requiring -// one. -type errCredentialsMissingServerURL struct{} - -func (errCredentialsMissingServerURL) Error() string { - return errCredentialsMissingServerURLMessage -} - -// errCredentialsMissingUsername represents an error raised -// when the credentials object has no username or when no -// username is provided to a credentials operation requiring -// one. -type errCredentialsMissingUsername struct{} - -func (errCredentialsMissingUsername) Error() string { - return errCredentialsMissingUsernameMessage -} - -// NewErrCredentialsMissingServerURL creates a new error for -// errCredentialsMissingServerURL. -func NewErrCredentialsMissingServerURL() error { - return errCredentialsMissingServerURL{} -} - -// NewErrCredentialsMissingUsername creates a new error for -// errCredentialsMissingUsername. -func NewErrCredentialsMissingUsername() error { - return errCredentialsMissingUsername{} -} - -// IsCredentialsMissingServerURL returns true if the error -// was an errCredentialsMissingServerURL. -func IsCredentialsMissingServerURL(err error) bool { - _, ok := err.(errCredentialsMissingServerURL) - return ok -} - -// IsCredentialsMissingServerURLMessage checks for an -// errCredentialsMissingServerURL in the error message. -func IsCredentialsMissingServerURLMessage(err string) bool { - return err == errCredentialsMissingServerURLMessage -} - -// IsCredentialsMissingUsername returns true if the error -// was an errCredentialsMissingUsername. -func IsCredentialsMissingUsername(err error) bool { - _, ok := err.(errCredentialsMissingUsername) - return ok -} - -// IsCredentialsMissingUsernameMessage checks for an -// errCredentialsMissingUsername in the error message. -func IsCredentialsMissingUsernameMessage(err string) bool { - return err == errCredentialsMissingUsernameMessage -} diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/helper.go b/vendor/github.com/docker/docker-credential-helpers/credentials/helper.go deleted file mode 100644 index 135acd254d..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/helper.go +++ /dev/null @@ -1,14 +0,0 @@ -package credentials - -// Helper is the interface a credentials store helper must implement. -type Helper interface { - // Add appends credentials to the store. - Add(*Credentials) error - // Delete removes credentials from the store. - Delete(serverURL string) error - // Get retrieves credentials from the store. - // It returns username and secret as strings. - Get(serverURL string) (string, string, error) - // List returns the stored serverURLs and their associated usernames. - List() (map[string]string, error) -} diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go b/vendor/github.com/docker/docker-credential-helpers/credentials/version.go deleted file mode 100644 index 033a5fee55..0000000000 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go +++ /dev/null @@ -1,4 +0,0 @@ -package credentials - -// Version holds a string describing the current version -const Version = "0.6.0" diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go deleted file mode 100644 index 97a92f8b78..0000000000 --- a/vendor/github.com/docker/docker/api/common.go +++ /dev/null @@ -1,11 +0,0 @@ -package api // import "github.com/docker/docker/api" - -// Common constants for daemon and client. -const ( - // DefaultVersion of Current REST API - DefaultVersion string = "1.36" - - // NoBaseImageSpecifier is the symbol used by the FROM - // command to specify that no base image is to be used. - NoBaseImageSpecifier string = "scratch" -) diff --git a/vendor/github.com/docker/docker/api/common_unix.go b/vendor/github.com/docker/docker/api/common_unix.go deleted file mode 100644 index af1a541646..0000000000 --- a/vendor/github.com/docker/docker/api/common_unix.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !windows - -package api // import "github.com/docker/docker/api" - -// MinVersion represents Minimum REST API version supported -const MinVersion string = "1.12" diff --git a/vendor/github.com/docker/docker/api/common_windows.go b/vendor/github.com/docker/docker/api/common_windows.go deleted file mode 100644 index 590ba5479b..0000000000 --- a/vendor/github.com/docker/docker/api/common_windows.go +++ /dev/null @@ -1,8 +0,0 @@ -package api // import "github.com/docker/docker/api" - -// MinVersion represents Minimum REST API version supported -// Technically the first daemon API version released on Windows is v1.25 in -// engine version 1.13. However, some clients are explicitly using downlevel -// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive. -// Hence also allowing 1.24 on Windows. -const MinVersion string = "1.24" diff --git a/vendor/github.com/docker/docker/api/types/auth.go b/vendor/github.com/docker/docker/api/types/auth.go deleted file mode 100644 index ddf15bb182..0000000000 --- a/vendor/github.com/docker/docker/api/types/auth.go +++ /dev/null @@ -1,22 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -// AuthConfig contains authorization information for connecting to a Registry -type AuthConfig struct { - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Auth string `json:"auth,omitempty"` - - // Email is an optional value associated with the username. - // This field is deprecated and will be removed in a later - // version of docker. - Email string `json:"email,omitempty"` - - ServerAddress string `json:"serveraddress,omitempty"` - - // IdentityToken is used to authenticate the user and get - // an access token for the registry. - IdentityToken string `json:"identitytoken,omitempty"` - - // RegistryToken is a bearer token to be sent to a registry - RegistryToken string `json:"registrytoken,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go deleted file mode 100644 index 18b36d592b..0000000000 --- a/vendor/github.com/docker/docker/api/types/client.go +++ /dev/null @@ -1,390 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "bufio" - "io" - "net" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - units "github.com/docker/go-units" -) - -// CheckpointCreateOptions holds parameters to create a checkpoint from a container -type CheckpointCreateOptions struct { - CheckpointID string - CheckpointDir string - Exit bool -} - -// CheckpointListOptions holds parameters to list checkpoints for a container -type CheckpointListOptions struct { - CheckpointDir string -} - -// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container -type CheckpointDeleteOptions struct { - CheckpointID string - CheckpointDir string -} - -// ContainerAttachOptions holds parameters to attach to a container. -type ContainerAttachOptions struct { - Stream bool - Stdin bool - Stdout bool - Stderr bool - DetachKeys string - Logs bool -} - -// ContainerCommitOptions holds parameters to commit changes into a container. -type ContainerCommitOptions struct { - Reference string - Comment string - Author string - Changes []string - Pause bool - Config *container.Config -} - -// ContainerExecInspect holds information returned by exec inspect. -type ContainerExecInspect struct { - ExecID string - ContainerID string - Running bool - ExitCode int - Pid int -} - -// ContainerListOptions holds parameters to list containers with. -type ContainerListOptions struct { - Quiet bool - Size bool - All bool - Latest bool - Since string - Before string - Limit int - Filters filters.Args -} - -// ContainerLogsOptions holds parameters to filter logs with. -type ContainerLogsOptions struct { - ShowStdout bool - ShowStderr bool - Since string - Until string - Timestamps bool - Follow bool - Tail string - Details bool -} - -// ContainerRemoveOptions holds parameters to remove containers. -type ContainerRemoveOptions struct { - RemoveVolumes bool - RemoveLinks bool - Force bool -} - -// ContainerStartOptions holds parameters to start containers. -type ContainerStartOptions struct { - CheckpointID string - CheckpointDir string -} - -// CopyToContainerOptions holds information -// about files to copy into a container -type CopyToContainerOptions struct { - AllowOverwriteDirWithFile bool - CopyUIDGID bool -} - -// EventsOptions holds parameters to filter events with. -type EventsOptions struct { - Since string - Until string - Filters filters.Args -} - -// NetworkListOptions holds parameters to filter the list of networks with. -type NetworkListOptions struct { - Filters filters.Args -} - -// HijackedResponse holds connection information for a hijacked request. -type HijackedResponse struct { - Conn net.Conn - Reader *bufio.Reader -} - -// Close closes the hijacked connection and reader. -func (h *HijackedResponse) Close() { - h.Conn.Close() -} - -// CloseWriter is an interface that implements structs -// that close input streams to prevent from writing. -type CloseWriter interface { - CloseWrite() error -} - -// CloseWrite closes a readWriter for writing. -func (h *HijackedResponse) CloseWrite() error { - if conn, ok := h.Conn.(CloseWriter); ok { - return conn.CloseWrite() - } - return nil -} - -// ImageBuildOptions holds the information -// necessary to build images. -type ImageBuildOptions struct { - Tags []string - SuppressOutput bool - RemoteContext string - NoCache bool - Remove bool - ForceRemove bool - PullParent bool - Isolation container.Isolation - CPUSetCPUs string - CPUSetMems string - CPUShares int64 - CPUQuota int64 - CPUPeriod int64 - Memory int64 - MemorySwap int64 - CgroupParent string - NetworkMode string - ShmSize int64 - Dockerfile string - Ulimits []*units.Ulimit - // BuildArgs needs to be a *string instead of just a string so that - // we can tell the difference between "" (empty string) and no value - // at all (nil). See the parsing of buildArgs in - // api/server/router/build/build_routes.go for even more info. - BuildArgs map[string]*string - AuthConfigs map[string]AuthConfig - Context io.Reader - Labels map[string]string - // squash the resulting image's layers to the parent - // preserves the original image and creates a new one from the parent with all - // the changes applied to a single layer - Squash bool - // CacheFrom specifies images that are used for matching cache. Images - // specified here do not need to have a valid parent chain to match cache. - CacheFrom []string - SecurityOpt []string - ExtraHosts []string // List of extra hosts - Target string - SessionID string - Platform string -} - -// ImageBuildResponse holds information -// returned by a server after building -// an image. -type ImageBuildResponse struct { - Body io.ReadCloser - OSType string -} - -// ImageCreateOptions holds information to create images. -type ImageCreateOptions struct { - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry. - Platform string // Platform is the target platform of the image if it needs to be pulled from the registry. -} - -// ImageImportSource holds source information for ImageImport -type ImageImportSource struct { - Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this. - SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute. -} - -// ImageImportOptions holds information to import images from the client host. -type ImageImportOptions struct { - Tag string // Tag is the name to tag this image with. This attribute is deprecated. - Message string // Message is the message to tag the image with - Changes []string // Changes are the raw changes to apply to this image - Platform string // Platform is the target platform of the image -} - -// ImageListOptions holds parameters to filter the list of images with. -type ImageListOptions struct { - All bool - Filters filters.Args -} - -// ImageLoadResponse returns information to the client about a load process. -type ImageLoadResponse struct { - // Body must be closed to avoid a resource leak - Body io.ReadCloser - JSON bool -} - -// ImagePullOptions holds information to pull images. -type ImagePullOptions struct { - All bool - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry - PrivilegeFunc RequestPrivilegeFunc - Platform string -} - -// RequestPrivilegeFunc is a function interface that -// clients can supply to retry operations after -// getting an authorization error. -// This function returns the registry authentication -// header value in base 64 format, or an error -// if the privilege request fails. -type RequestPrivilegeFunc func() (string, error) - -//ImagePushOptions holds information to push images. -type ImagePushOptions ImagePullOptions - -// ImageRemoveOptions holds parameters to remove images. -type ImageRemoveOptions struct { - Force bool - PruneChildren bool -} - -// ImageSearchOptions holds parameters to search images with. -type ImageSearchOptions struct { - RegistryAuth string - PrivilegeFunc RequestPrivilegeFunc - Filters filters.Args - Limit int -} - -// ResizeOptions holds parameters to resize a tty. -// It can be used to resize container ttys and -// exec process ttys too. -type ResizeOptions struct { - Height uint - Width uint -} - -// NodeListOptions holds parameters to list nodes with. -type NodeListOptions struct { - Filters filters.Args -} - -// NodeRemoveOptions holds parameters to remove nodes with. -type NodeRemoveOptions struct { - Force bool -} - -// ServiceCreateOptions contains the options to use when creating a service. -type ServiceCreateOptions struct { - // EncodedRegistryAuth is the encoded registry authorization credentials to - // use when updating the service. - // - // This field follows the format of the X-Registry-Auth header. - EncodedRegistryAuth string - - // QueryRegistry indicates whether the service update requires - // contacting a registry. A registry may be contacted to retrieve - // the image digest and manifest, which in turn can be used to update - // platform or other information about the service. - QueryRegistry bool -} - -// ServiceCreateResponse contains the information returned to a client -// on the creation of a new service. -type ServiceCreateResponse struct { - // ID is the ID of the created service. - ID string - // Warnings is a set of non-fatal warning messages to pass on to the user. - Warnings []string `json:",omitempty"` -} - -// Values for RegistryAuthFrom in ServiceUpdateOptions -const ( - RegistryAuthFromSpec = "spec" - RegistryAuthFromPreviousSpec = "previous-spec" -) - -// ServiceUpdateOptions contains the options to be used for updating services. -type ServiceUpdateOptions struct { - // EncodedRegistryAuth is the encoded registry authorization credentials to - // use when updating the service. - // - // This field follows the format of the X-Registry-Auth header. - EncodedRegistryAuth string - - // TODO(stevvooe): Consider moving the version parameter of ServiceUpdate - // into this field. While it does open API users up to racy writes, most - // users may not need that level of consistency in practice. - - // RegistryAuthFrom specifies where to find the registry authorization - // credentials if they are not given in EncodedRegistryAuth. Valid - // values are "spec" and "previous-spec". - RegistryAuthFrom string - - // Rollback indicates whether a server-side rollback should be - // performed. When this is set, the provided spec will be ignored. - // The valid values are "previous" and "none". An empty value is the - // same as "none". - Rollback string - - // QueryRegistry indicates whether the service update requires - // contacting a registry. A registry may be contacted to retrieve - // the image digest and manifest, which in turn can be used to update - // platform or other information about the service. - QueryRegistry bool -} - -// ServiceListOptions holds parameters to list services with. -type ServiceListOptions struct { - Filters filters.Args -} - -// ServiceInspectOptions holds parameters related to the "service inspect" -// operation. -type ServiceInspectOptions struct { - InsertDefaults bool -} - -// TaskListOptions holds parameters to list tasks with. -type TaskListOptions struct { - Filters filters.Args -} - -// PluginRemoveOptions holds parameters to remove plugins. -type PluginRemoveOptions struct { - Force bool -} - -// PluginEnableOptions holds parameters to enable plugins. -type PluginEnableOptions struct { - Timeout int -} - -// PluginDisableOptions holds parameters to disable plugins. -type PluginDisableOptions struct { - Force bool -} - -// PluginInstallOptions holds parameters to install a plugin. -type PluginInstallOptions struct { - Disabled bool - AcceptAllPermissions bool - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry - RemoteRef string // RemoteRef is the plugin name on the registry - PrivilegeFunc RequestPrivilegeFunc - AcceptPermissionsFunc func(PluginPrivileges) (bool, error) - Args []string -} - -// SwarmUnlockKeyResponse contains the response for Engine API: -// GET /swarm/unlockkey -type SwarmUnlockKeyResponse struct { - // UnlockKey is the unlock key in ASCII-armored format. - UnlockKey string -} - -// PluginCreateOptions hold all options to plugin create. -type PluginCreateOptions struct { - RepoName string -} diff --git a/vendor/github.com/docker/docker/api/types/configs.go b/vendor/github.com/docker/docker/api/types/configs.go deleted file mode 100644 index f6537a27f2..0000000000 --- a/vendor/github.com/docker/docker/api/types/configs.go +++ /dev/null @@ -1,57 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" -) - -// configs holds structs used for internal communication between the -// frontend (such as an http server) and the backend (such as the -// docker daemon). - -// ContainerCreateConfig is the parameter set to ContainerCreate() -type ContainerCreateConfig struct { - Name string - Config *container.Config - HostConfig *container.HostConfig - NetworkingConfig *network.NetworkingConfig - AdjustCPUShares bool -} - -// ContainerRmConfig holds arguments for the container remove -// operation. This struct is used to tell the backend what operations -// to perform. -type ContainerRmConfig struct { - ForceRemove, RemoveVolume, RemoveLink bool -} - -// ExecConfig is a small subset of the Config struct that holds the configuration -// for the exec feature of docker. -type ExecConfig struct { - User string // User that will run the command - Privileged bool // Is the container in privileged mode - Tty bool // Attach standard streams to a tty. - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStderr bool // Attach the standard error - AttachStdout bool // Attach the standard output - Detach bool // Execute in detach mode - DetachKeys string // Escape keys for detach - Env []string // Environment variables - WorkingDir string // Working directory - Cmd []string // Execution commands and args -} - -// PluginRmConfig holds arguments for plugin remove. -type PluginRmConfig struct { - ForceRemove bool -} - -// PluginEnableConfig holds arguments for plugin enable -type PluginEnableConfig struct { - Timeout int -} - -// PluginDisableConfig holds arguments for plugin disable. -type PluginDisableConfig struct { - ForceDisable bool -} diff --git a/vendor/github.com/docker/docker/api/types/error_response.go b/vendor/github.com/docker/docker/api/types/error_response.go deleted file mode 100644 index dc942d9d9e..0000000000 --- a/vendor/github.com/docker/docker/api/types/error_response.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ErrorResponse Represents an error. -// swagger:model ErrorResponse -type ErrorResponse struct { - - // The error message. - // Required: true - Message string `json:"message"` -} diff --git a/vendor/github.com/docker/docker/api/types/events/events.go b/vendor/github.com/docker/docker/api/types/events/events.go deleted file mode 100644 index 027c6edb72..0000000000 --- a/vendor/github.com/docker/docker/api/types/events/events.go +++ /dev/null @@ -1,52 +0,0 @@ -package events // import "github.com/docker/docker/api/types/events" - -const ( - // ContainerEventType is the event type that containers generate - ContainerEventType = "container" - // DaemonEventType is the event type that daemon generate - DaemonEventType = "daemon" - // ImageEventType is the event type that images generate - ImageEventType = "image" - // NetworkEventType is the event type that networks generate - NetworkEventType = "network" - // PluginEventType is the event type that plugins generate - PluginEventType = "plugin" - // VolumeEventType is the event type that volumes generate - VolumeEventType = "volume" - // ServiceEventType is the event type that services generate - ServiceEventType = "service" - // NodeEventType is the event type that nodes generate - NodeEventType = "node" - // SecretEventType is the event type that secrets generate - SecretEventType = "secret" - // ConfigEventType is the event type that configs generate - ConfigEventType = "config" -) - -// Actor describes something that generates events, -// like a container, or a network, or a volume. -// It has a defined name and a set or attributes. -// The container attributes are its labels, other actors -// can generate these attributes from other properties. -type Actor struct { - ID string - Attributes map[string]string -} - -// Message represents the information an event contains -type Message struct { - // Deprecated information from JSONMessage. - // With data only in container events. - Status string `json:"status,omitempty"` - ID string `json:"id,omitempty"` - From string `json:"from,omitempty"` - - Type string - Action string - Actor Actor - // Engine events are local scope. Cluster events are swarm scope. - Scope string `json:"scope,omitempty"` - - Time int64 `json:"time,omitempty"` - TimeNano int64 `json:"timeNano,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go deleted file mode 100644 index a41e3d8d96..0000000000 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ /dev/null @@ -1,350 +0,0 @@ -/*Package filters provides tools for encoding a mapping of keys to a set of -multiple values. -*/ -package filters // import "github.com/docker/docker/api/types/filters" - -import ( - "encoding/json" - "errors" - "regexp" - "strings" - - "github.com/docker/docker/api/types/versions" -) - -// Args stores a mapping of keys to a set of multiple values. -type Args struct { - fields map[string]map[string]bool -} - -// KeyValuePair are used to initialize a new Args -type KeyValuePair struct { - Key string - Value string -} - -// Arg creates a new KeyValuePair for initializing Args -func Arg(key, value string) KeyValuePair { - return KeyValuePair{Key: key, Value: value} -} - -// NewArgs returns a new Args populated with the initial args -func NewArgs(initialArgs ...KeyValuePair) Args { - args := Args{fields: map[string]map[string]bool{}} - for _, arg := range initialArgs { - args.Add(arg.Key, arg.Value) - } - return args -} - -// ParseFlag parses a key=value string and adds it to an Args. -// -// Deprecated: Use Args.Add() -func ParseFlag(arg string, prev Args) (Args, error) { - filters := prev - if len(arg) == 0 { - return filters, nil - } - - if !strings.Contains(arg, "=") { - return filters, ErrBadFormat - } - - f := strings.SplitN(arg, "=", 2) - - name := strings.ToLower(strings.TrimSpace(f[0])) - value := strings.TrimSpace(f[1]) - - filters.Add(name, value) - - return filters, nil -} - -// ErrBadFormat is an error returned when a filter is not in the form key=value -// -// Deprecated: this error will be removed in a future version -var ErrBadFormat = errors.New("bad format of filter (expected name=value)") - -// ToParam encodes the Args as args JSON encoded string -// -// Deprecated: use ToJSON -func ToParam(a Args) (string, error) { - return ToJSON(a) -} - -// MarshalJSON returns a JSON byte representation of the Args -func (args Args) MarshalJSON() ([]byte, error) { - if len(args.fields) == 0 { - return []byte{}, nil - } - return json.Marshal(args.fields) -} - -// ToJSON returns the Args as a JSON encoded string -func ToJSON(a Args) (string, error) { - if a.Len() == 0 { - return "", nil - } - buf, err := json.Marshal(a) - return string(buf), err -} - -// ToParamWithVersion encodes Args as a JSON string. If version is less than 1.22 -// then the encoded format will use an older legacy format where the values are a -// list of strings, instead of a set. -// -// Deprecated: Use ToJSON -func ToParamWithVersion(version string, a Args) (string, error) { - if a.Len() == 0 { - return "", nil - } - - if version != "" && versions.LessThan(version, "1.22") { - buf, err := json.Marshal(convertArgsToSlice(a.fields)) - return string(buf), err - } - - return ToJSON(a) -} - -// FromParam decodes a JSON encoded string into Args -// -// Deprecated: use FromJSON -func FromParam(p string) (Args, error) { - return FromJSON(p) -} - -// FromJSON decodes a JSON encoded string into Args -func FromJSON(p string) (Args, error) { - args := NewArgs() - - if p == "" { - return args, nil - } - - raw := []byte(p) - err := json.Unmarshal(raw, &args) - if err == nil { - return args, nil - } - - // Fallback to parsing arguments in the legacy slice format - deprecated := map[string][]string{} - if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil { - return args, err - } - - args.fields = deprecatedArgs(deprecated) - return args, nil -} - -// UnmarshalJSON populates the Args from JSON encode bytes -func (args Args) UnmarshalJSON(raw []byte) error { - if len(raw) == 0 { - return nil - } - return json.Unmarshal(raw, &args.fields) -} - -// Get returns the list of values associated with the key -func (args Args) Get(key string) []string { - values := args.fields[key] - if values == nil { - return make([]string, 0) - } - slice := make([]string, 0, len(values)) - for key := range values { - slice = append(slice, key) - } - return slice -} - -// Add a new value to the set of values -func (args Args) Add(key, value string) { - if _, ok := args.fields[key]; ok { - args.fields[key][value] = true - } else { - args.fields[key] = map[string]bool{value: true} - } -} - -// Del removes a value from the set -func (args Args) Del(key, value string) { - if _, ok := args.fields[key]; ok { - delete(args.fields[key], value) - if len(args.fields[key]) == 0 { - delete(args.fields, key) - } - } -} - -// Len returns the number of keys in the mapping -func (args Args) Len() int { - return len(args.fields) -} - -// MatchKVList returns true if all the pairs in sources exist as key=value -// pairs in the mapping at key, or if there are no values at key. -func (args Args) MatchKVList(key string, sources map[string]string) bool { - fieldValues := args.fields[key] - - //do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - - if len(sources) == 0 { - return false - } - - for value := range fieldValues { - testKV := strings.SplitN(value, "=", 2) - - v, ok := sources[testKV[0]] - if !ok { - return false - } - if len(testKV) == 2 && testKV[1] != v { - return false - } - } - - return true -} - -// Match returns true if any of the values at key match the source string -func (args Args) Match(field, source string) bool { - if args.ExactMatch(field, source) { - return true - } - - fieldValues := args.fields[field] - for name2match := range fieldValues { - match, err := regexp.MatchString(name2match, source) - if err != nil { - continue - } - if match { - return true - } - } - return false -} - -// ExactMatch returns true if the source matches exactly one of the values. -func (args Args) ExactMatch(key, source string) bool { - fieldValues, ok := args.fields[key] - //do not filter if there is no filter set or cannot determine filter - if !ok || len(fieldValues) == 0 { - return true - } - - // try to match full name value to avoid O(N) regular expression matching - return fieldValues[source] -} - -// UniqueExactMatch returns true if there is only one value and the source -// matches exactly the value. -func (args Args) UniqueExactMatch(key, source string) bool { - fieldValues := args.fields[key] - //do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - if len(args.fields[key]) != 1 { - return false - } - - // try to match full name value to avoid O(N) regular expression matching - return fieldValues[source] -} - -// FuzzyMatch returns true if the source matches exactly one value, or the -// source has one of the values as a prefix. -func (args Args) FuzzyMatch(key, source string) bool { - if args.ExactMatch(key, source) { - return true - } - - fieldValues := args.fields[key] - for prefix := range fieldValues { - if strings.HasPrefix(source, prefix) { - return true - } - } - return false -} - -// Include returns true if the key exists in the mapping -// -// Deprecated: use Contains -func (args Args) Include(field string) bool { - _, ok := args.fields[field] - return ok -} - -// Contains returns true if the key exists in the mapping -func (args Args) Contains(field string) bool { - _, ok := args.fields[field] - return ok -} - -type invalidFilter string - -func (e invalidFilter) Error() string { - return "Invalid filter '" + string(e) + "'" -} - -func (invalidFilter) InvalidParameter() {} - -// Validate compared the set of accepted keys against the keys in the mapping. -// An error is returned if any mapping keys are not in the accepted set. -func (args Args) Validate(accepted map[string]bool) error { - for name := range args.fields { - if !accepted[name] { - return invalidFilter(name) - } - } - return nil -} - -// WalkValues iterates over the list of values for a key in the mapping and calls -// op() for each value. If op returns an error the iteration stops and the -// error is returned. -func (args Args) WalkValues(field string, op func(value string) error) error { - if _, ok := args.fields[field]; !ok { - return nil - } - for v := range args.fields[field] { - if err := op(v); err != nil { - return err - } - } - return nil -} - -func deprecatedArgs(d map[string][]string) map[string]map[string]bool { - m := map[string]map[string]bool{} - for k, v := range d { - values := map[string]bool{} - for _, vv := range v { - values[vv] = true - } - m[k] = values - } - return m -} - -func convertArgsToSlice(f map[string]map[string]bool) map[string][]string { - m := map[string][]string{} - for k, v := range f { - values := []string{} - for kk := range v { - if v[kk] { - values = append(values, kk) - } - } - m[k] = values - } - return m -} diff --git a/vendor/github.com/docker/docker/api/types/graph_driver_data.go b/vendor/github.com/docker/docker/api/types/graph_driver_data.go deleted file mode 100644 index 4d9bf1c62c..0000000000 --- a/vendor/github.com/docker/docker/api/types/graph_driver_data.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// GraphDriverData Information about a container's graph driver. -// swagger:model GraphDriverData -type GraphDriverData struct { - - // data - // Required: true - Data map[string]string `json:"Data"` - - // name - // Required: true - Name string `json:"Name"` -} diff --git a/vendor/github.com/docker/docker/api/types/id_response.go b/vendor/github.com/docker/docker/api/types/id_response.go deleted file mode 100644 index 7592d2f8b1..0000000000 --- a/vendor/github.com/docker/docker/api/types/id_response.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// IDResponse Response to an API call that returns just an Id -// swagger:model IdResponse -type IDResponse struct { - - // The id of the newly created object. - // Required: true - ID string `json:"Id"` -} diff --git a/vendor/github.com/docker/docker/api/types/image/image_history.go b/vendor/github.com/docker/docker/api/types/image/image_history.go deleted file mode 100644 index d6b354bcdf..0000000000 --- a/vendor/github.com/docker/docker/api/types/image/image_history.go +++ /dev/null @@ -1,37 +0,0 @@ -package image - -// ---------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE -// This file was generated by `swagger generate operation` -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// HistoryResponseItem individual image layer information in response to ImageHistory operation -// swagger:model HistoryResponseItem -type HistoryResponseItem struct { - - // comment - // Required: true - Comment string `json:"Comment"` - - // created - // Required: true - Created int64 `json:"Created"` - - // created by - // Required: true - CreatedBy string `json:"CreatedBy"` - - // Id - // Required: true - ID string `json:"Id"` - - // size - // Required: true - Size int64 `json:"Size"` - - // tags - // Required: true - Tags []string `json:"Tags"` -} diff --git a/vendor/github.com/docker/docker/api/types/image_delete_response_item.go b/vendor/github.com/docker/docker/api/types/image_delete_response_item.go deleted file mode 100644 index b9a65a0d8e..0000000000 --- a/vendor/github.com/docker/docker/api/types/image_delete_response_item.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ImageDeleteResponseItem image delete response item -// swagger:model ImageDeleteResponseItem -type ImageDeleteResponseItem struct { - - // The image ID of an image that was deleted - Deleted string `json:"Deleted,omitempty"` - - // The image ID of an image that was untagged - Untagged string `json:"Untagged,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/image_summary.go b/vendor/github.com/docker/docker/api/types/image_summary.go deleted file mode 100644 index e145b3dcfc..0000000000 --- a/vendor/github.com/docker/docker/api/types/image_summary.go +++ /dev/null @@ -1,49 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ImageSummary image summary -// swagger:model ImageSummary -type ImageSummary struct { - - // containers - // Required: true - Containers int64 `json:"Containers"` - - // created - // Required: true - Created int64 `json:"Created"` - - // Id - // Required: true - ID string `json:"Id"` - - // labels - // Required: true - Labels map[string]string `json:"Labels"` - - // parent Id - // Required: true - ParentID string `json:"ParentId"` - - // repo digests - // Required: true - RepoDigests []string `json:"RepoDigests"` - - // repo tags - // Required: true - RepoTags []string `json:"RepoTags"` - - // shared size - // Required: true - SharedSize int64 `json:"SharedSize"` - - // size - // Required: true - Size int64 `json:"Size"` - - // virtual size - // Required: true - VirtualSize int64 `json:"VirtualSize"` -} diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go deleted file mode 100644 index 761d0b34f2..0000000000 --- a/vendor/github.com/docker/docker/api/types/network/network.go +++ /dev/null @@ -1,108 +0,0 @@ -package network // import "github.com/docker/docker/api/types/network" - -// Address represents an IP address -type Address struct { - Addr string - PrefixLen int -} - -// IPAM represents IP Address Management -type IPAM struct { - Driver string - Options map[string]string //Per network IPAM driver options - Config []IPAMConfig -} - -// IPAMConfig represents IPAM configurations -type IPAMConfig struct { - Subnet string `json:",omitempty"` - IPRange string `json:",omitempty"` - Gateway string `json:",omitempty"` - AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"` -} - -// EndpointIPAMConfig represents IPAM configurations for the endpoint -type EndpointIPAMConfig struct { - IPv4Address string `json:",omitempty"` - IPv6Address string `json:",omitempty"` - LinkLocalIPs []string `json:",omitempty"` -} - -// Copy makes a copy of the endpoint ipam config -func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig { - cfgCopy := *cfg - cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs)) - cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...) - return &cfgCopy -} - -// PeerInfo represents one peer of an overlay network -type PeerInfo struct { - Name string - IP string -} - -// EndpointSettings stores the network endpoint details -type EndpointSettings struct { - // Configurations - IPAMConfig *EndpointIPAMConfig - Links []string - Aliases []string - // Operational data - NetworkID string - EndpointID string - Gateway string - IPAddress string - IPPrefixLen int - IPv6Gateway string - GlobalIPv6Address string - GlobalIPv6PrefixLen int - MacAddress string - DriverOpts map[string]string -} - -// Task carries the information about one backend task -type Task struct { - Name string - EndpointID string - EndpointIP string - Info map[string]string -} - -// ServiceInfo represents service parameters with the list of service's tasks -type ServiceInfo struct { - VIP string - Ports []string - LocalLBIndex int - Tasks []Task -} - -// Copy makes a deep copy of `EndpointSettings` -func (es *EndpointSettings) Copy() *EndpointSettings { - epCopy := *es - if es.IPAMConfig != nil { - epCopy.IPAMConfig = es.IPAMConfig.Copy() - } - - if es.Links != nil { - links := make([]string, 0, len(es.Links)) - epCopy.Links = append(links, es.Links...) - } - - if es.Aliases != nil { - aliases := make([]string, 0, len(es.Aliases)) - epCopy.Aliases = append(aliases, es.Aliases...) - } - return &epCopy -} - -// NetworkingConfig represents the container's networking configuration for each of its interfaces -// Carries the networking configs specified in the `docker run` and `docker network connect` commands -type NetworkingConfig struct { - EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network -} - -// ConfigReference specifies the source which provides a network's configuration -type ConfigReference struct { - Network string -} diff --git a/vendor/github.com/docker/docker/api/types/plugin.go b/vendor/github.com/docker/docker/api/types/plugin.go deleted file mode 100644 index cab333e01a..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin.go +++ /dev/null @@ -1,200 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Plugin A plugin for the Engine API -// swagger:model Plugin -type Plugin struct { - - // config - // Required: true - Config PluginConfig `json:"Config"` - - // True if the plugin is running. False if the plugin is not running, only installed. - // Required: true - Enabled bool `json:"Enabled"` - - // Id - ID string `json:"Id,omitempty"` - - // name - // Required: true - Name string `json:"Name"` - - // plugin remote reference used to push/pull the plugin - PluginReference string `json:"PluginReference,omitempty"` - - // settings - // Required: true - Settings PluginSettings `json:"Settings"` -} - -// PluginConfig The config of a plugin. -// swagger:model PluginConfig -type PluginConfig struct { - - // args - // Required: true - Args PluginConfigArgs `json:"Args"` - - // description - // Required: true - Description string `json:"Description"` - - // Docker Version used to create the plugin - DockerVersion string `json:"DockerVersion,omitempty"` - - // documentation - // Required: true - Documentation string `json:"Documentation"` - - // entrypoint - // Required: true - Entrypoint []string `json:"Entrypoint"` - - // env - // Required: true - Env []PluginEnv `json:"Env"` - - // interface - // Required: true - Interface PluginConfigInterface `json:"Interface"` - - // ipc host - // Required: true - IpcHost bool `json:"IpcHost"` - - // linux - // Required: true - Linux PluginConfigLinux `json:"Linux"` - - // mounts - // Required: true - Mounts []PluginMount `json:"Mounts"` - - // network - // Required: true - Network PluginConfigNetwork `json:"Network"` - - // pid host - // Required: true - PidHost bool `json:"PidHost"` - - // propagated mount - // Required: true - PropagatedMount string `json:"PropagatedMount"` - - // user - User PluginConfigUser `json:"User,omitempty"` - - // work dir - // Required: true - WorkDir string `json:"WorkDir"` - - // rootfs - Rootfs *PluginConfigRootfs `json:"rootfs,omitempty"` -} - -// PluginConfigArgs plugin config args -// swagger:model PluginConfigArgs -type PluginConfigArgs struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // value - // Required: true - Value []string `json:"Value"` -} - -// PluginConfigInterface The interface between Docker and the plugin -// swagger:model PluginConfigInterface -type PluginConfigInterface struct { - - // socket - // Required: true - Socket string `json:"Socket"` - - // types - // Required: true - Types []PluginInterfaceType `json:"Types"` -} - -// PluginConfigLinux plugin config linux -// swagger:model PluginConfigLinux -type PluginConfigLinux struct { - - // allow all devices - // Required: true - AllowAllDevices bool `json:"AllowAllDevices"` - - // capabilities - // Required: true - Capabilities []string `json:"Capabilities"` - - // devices - // Required: true - Devices []PluginDevice `json:"Devices"` -} - -// PluginConfigNetwork plugin config network -// swagger:model PluginConfigNetwork -type PluginConfigNetwork struct { - - // type - // Required: true - Type string `json:"Type"` -} - -// PluginConfigRootfs plugin config rootfs -// swagger:model PluginConfigRootfs -type PluginConfigRootfs struct { - - // diff ids - DiffIds []string `json:"diff_ids"` - - // type - Type string `json:"type,omitempty"` -} - -// PluginConfigUser plugin config user -// swagger:model PluginConfigUser -type PluginConfigUser struct { - - // g ID - GID uint32 `json:"GID,omitempty"` - - // UID - UID uint32 `json:"UID,omitempty"` -} - -// PluginSettings Settings that can be modified by users. -// swagger:model PluginSettings -type PluginSettings struct { - - // args - // Required: true - Args []string `json:"Args"` - - // devices - // Required: true - Devices []PluginDevice `json:"Devices"` - - // env - // Required: true - Env []string `json:"Env"` - - // mounts - // Required: true - Mounts []PluginMount `json:"Mounts"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_device.go b/vendor/github.com/docker/docker/api/types/plugin_device.go deleted file mode 100644 index 5699010675..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_device.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginDevice plugin device -// swagger:model PluginDevice -type PluginDevice struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // path - // Required: true - Path *string `json:"Path"` - - // settable - // Required: true - Settable []string `json:"Settable"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_env.go b/vendor/github.com/docker/docker/api/types/plugin_env.go deleted file mode 100644 index 32962dc2eb..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_env.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginEnv plugin env -// swagger:model PluginEnv -type PluginEnv struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // value - // Required: true - Value *string `json:"Value"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_interface_type.go b/vendor/github.com/docker/docker/api/types/plugin_interface_type.go deleted file mode 100644 index c82f204e87..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_interface_type.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginInterfaceType plugin interface type -// swagger:model PluginInterfaceType -type PluginInterfaceType struct { - - // capability - // Required: true - Capability string `json:"Capability"` - - // prefix - // Required: true - Prefix string `json:"Prefix"` - - // version - // Required: true - Version string `json:"Version"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_mount.go b/vendor/github.com/docker/docker/api/types/plugin_mount.go deleted file mode 100644 index 5c031cf8b5..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_mount.go +++ /dev/null @@ -1,37 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginMount plugin mount -// swagger:model PluginMount -type PluginMount struct { - - // description - // Required: true - Description string `json:"Description"` - - // destination - // Required: true - Destination string `json:"Destination"` - - // name - // Required: true - Name string `json:"Name"` - - // options - // Required: true - Options []string `json:"Options"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // source - // Required: true - Source *string `json:"Source"` - - // type - // Required: true - Type string `json:"Type"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_responses.go b/vendor/github.com/docker/docker/api/types/plugin_responses.go deleted file mode 100644 index 60d1fb5ad8..0000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_responses.go +++ /dev/null @@ -1,71 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "encoding/json" - "fmt" - "sort" -) - -// PluginsListResponse contains the response for the Engine API -type PluginsListResponse []*Plugin - -// UnmarshalJSON implements json.Unmarshaler for PluginInterfaceType -func (t *PluginInterfaceType) UnmarshalJSON(p []byte) error { - versionIndex := len(p) - prefixIndex := 0 - if len(p) < 2 || p[0] != '"' || p[len(p)-1] != '"' { - return fmt.Errorf("%q is not a plugin interface type", p) - } - p = p[1 : len(p)-1] -loop: - for i, b := range p { - switch b { - case '.': - prefixIndex = i - case '/': - versionIndex = i - break loop - } - } - t.Prefix = string(p[:prefixIndex]) - t.Capability = string(p[prefixIndex+1 : versionIndex]) - if versionIndex < len(p) { - t.Version = string(p[versionIndex+1:]) - } - return nil -} - -// MarshalJSON implements json.Marshaler for PluginInterfaceType -func (t *PluginInterfaceType) MarshalJSON() ([]byte, error) { - return json.Marshal(t.String()) -} - -// String implements fmt.Stringer for PluginInterfaceType -func (t PluginInterfaceType) String() string { - return fmt.Sprintf("%s.%s/%s", t.Prefix, t.Capability, t.Version) -} - -// PluginPrivilege describes a permission the user has to accept -// upon installing a plugin. -type PluginPrivilege struct { - Name string - Description string - Value []string -} - -// PluginPrivileges is a list of PluginPrivilege -type PluginPrivileges []PluginPrivilege - -func (s PluginPrivileges) Len() int { - return len(s) -} - -func (s PluginPrivileges) Less(i, j int) bool { - return s[i].Name < s[j].Name -} - -func (s PluginPrivileges) Swap(i, j int) { - sort.Strings(s[i].Value) - sort.Strings(s[j].Value) - s[i], s[j] = s[j], s[i] -} diff --git a/vendor/github.com/docker/docker/api/types/port.go b/vendor/github.com/docker/docker/api/types/port.go deleted file mode 100644 index ad52d46d56..0000000000 --- a/vendor/github.com/docker/docker/api/types/port.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Port An open port on a container -// swagger:model Port -type Port struct { - - // IP - IP string `json:"IP,omitempty"` - - // Port on the container - // Required: true - PrivatePort uint16 `json:"PrivatePort"` - - // Port exposed on the host - PublicPort uint16 `json:"PublicPort,omitempty"` - - // type - // Required: true - Type string `json:"Type"` -} diff --git a/vendor/github.com/docker/docker/api/types/registry/authenticate.go b/vendor/github.com/docker/docker/api/types/registry/authenticate.go deleted file mode 100644 index f0a2113e40..0000000000 --- a/vendor/github.com/docker/docker/api/types/registry/authenticate.go +++ /dev/null @@ -1,21 +0,0 @@ -package registry // import "github.com/docker/docker/api/types/registry" - -// ---------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE -// This file was generated by `swagger generate operation` -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// AuthenticateOKBody authenticate o k body -// swagger:model AuthenticateOKBody -type AuthenticateOKBody struct { - - // An opaque token used to authenticate a user after a successful login - // Required: true - IdentityToken string `json:"IdentityToken"` - - // The status of the authentication - // Required: true - Status string `json:"Status"` -} diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go deleted file mode 100644 index 8789ad3b32..0000000000 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ /dev/null @@ -1,119 +0,0 @@ -package registry // import "github.com/docker/docker/api/types/registry" - -import ( - "encoding/json" - "net" - - "github.com/opencontainers/image-spec/specs-go/v1" -) - -// ServiceConfig stores daemon registry services configuration. -type ServiceConfig struct { - AllowNondistributableArtifactsCIDRs []*NetIPNet - AllowNondistributableArtifactsHostnames []string - InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` - IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` - Mirrors []string -} - -// NetIPNet is the net.IPNet type, which can be marshalled and -// unmarshalled to JSON -type NetIPNet net.IPNet - -// String returns the CIDR notation of ipnet -func (ipnet *NetIPNet) String() string { - return (*net.IPNet)(ipnet).String() -} - -// MarshalJSON returns the JSON representation of the IPNet -func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) { - return json.Marshal((*net.IPNet)(ipnet).String()) -} - -// UnmarshalJSON sets the IPNet from a byte array of JSON -func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) { - var ipnetStr string - if err = json.Unmarshal(b, &ipnetStr); err == nil { - var cidr *net.IPNet - if _, cidr, err = net.ParseCIDR(ipnetStr); err == nil { - *ipnet = NetIPNet(*cidr) - } - } - return -} - -// IndexInfo contains information about a registry -// -// RepositoryInfo Examples: -// { -// "Index" : { -// "Name" : "docker.io", -// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"], -// "Secure" : true, -// "Official" : true, -// }, -// "RemoteName" : "library/debian", -// "LocalName" : "debian", -// "CanonicalName" : "docker.io/debian" -// "Official" : true, -// } -// -// { -// "Index" : { -// "Name" : "127.0.0.1:5000", -// "Mirrors" : [], -// "Secure" : false, -// "Official" : false, -// }, -// "RemoteName" : "user/repo", -// "LocalName" : "127.0.0.1:5000/user/repo", -// "CanonicalName" : "127.0.0.1:5000/user/repo", -// "Official" : false, -// } -type IndexInfo struct { - // Name is the name of the registry, such as "docker.io" - Name string - // Mirrors is a list of mirrors, expressed as URIs - Mirrors []string - // Secure is set to false if the registry is part of the list of - // insecure registries. Insecure registries accept HTTP and/or accept - // HTTPS with certificates from unknown CAs. - Secure bool - // Official indicates whether this is an official registry - Official bool -} - -// SearchResult describes a search result returned from a registry -type SearchResult struct { - // StarCount indicates the number of stars this repository has - StarCount int `json:"star_count"` - // IsOfficial is true if the result is from an official repository. - IsOfficial bool `json:"is_official"` - // Name is the name of the repository - Name string `json:"name"` - // IsAutomated indicates whether the result is automated - IsAutomated bool `json:"is_automated"` - // Description is a textual description of the repository - Description string `json:"description"` -} - -// SearchResults lists a collection search results returned from a registry -type SearchResults struct { - // Query contains the query string that generated the search results - Query string `json:"query"` - // NumResults indicates the number of results the query returned - NumResults int `json:"num_results"` - // Results is a slice containing the actual results for the search - Results []SearchResult `json:"results"` -} - -// DistributionInspect describes the result obtained from contacting the -// registry to retrieve image metadata -type DistributionInspect struct { - // Descriptor contains information about the manifest, including - // the content addressable digest - Descriptor v1.Descriptor - // Platforms contains the list of platforms supported by the image, - // obtained by parsing the manifest - Platforms []v1.Platform -} diff --git a/vendor/github.com/docker/docker/api/types/seccomp.go b/vendor/github.com/docker/docker/api/types/seccomp.go deleted file mode 100644 index 67a41e1a89..0000000000 --- a/vendor/github.com/docker/docker/api/types/seccomp.go +++ /dev/null @@ -1,93 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -// Seccomp represents the config for a seccomp profile for syscall restriction. -type Seccomp struct { - DefaultAction Action `json:"defaultAction"` - // Architectures is kept to maintain backward compatibility with the old - // seccomp profile. - Architectures []Arch `json:"architectures,omitempty"` - ArchMap []Architecture `json:"archMap,omitempty"` - Syscalls []*Syscall `json:"syscalls"` -} - -// Architecture is used to represent a specific architecture -// and its sub-architectures -type Architecture struct { - Arch Arch `json:"architecture"` - SubArches []Arch `json:"subArchitectures"` -} - -// Arch used for architectures -type Arch string - -// Additional architectures permitted to be used for system calls -// By default only the native architecture of the kernel is permitted -const ( - ArchX86 Arch = "SCMP_ARCH_X86" - ArchX86_64 Arch = "SCMP_ARCH_X86_64" - ArchX32 Arch = "SCMP_ARCH_X32" - ArchARM Arch = "SCMP_ARCH_ARM" - ArchAARCH64 Arch = "SCMP_ARCH_AARCH64" - ArchMIPS Arch = "SCMP_ARCH_MIPS" - ArchMIPS64 Arch = "SCMP_ARCH_MIPS64" - ArchMIPS64N32 Arch = "SCMP_ARCH_MIPS64N32" - ArchMIPSEL Arch = "SCMP_ARCH_MIPSEL" - ArchMIPSEL64 Arch = "SCMP_ARCH_MIPSEL64" - ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32" - ArchPPC Arch = "SCMP_ARCH_PPC" - ArchPPC64 Arch = "SCMP_ARCH_PPC64" - ArchPPC64LE Arch = "SCMP_ARCH_PPC64LE" - ArchS390 Arch = "SCMP_ARCH_S390" - ArchS390X Arch = "SCMP_ARCH_S390X" -) - -// Action taken upon Seccomp rule match -type Action string - -// Define actions for Seccomp rules -const ( - ActKill Action = "SCMP_ACT_KILL" - ActTrap Action = "SCMP_ACT_TRAP" - ActErrno Action = "SCMP_ACT_ERRNO" - ActTrace Action = "SCMP_ACT_TRACE" - ActAllow Action = "SCMP_ACT_ALLOW" -) - -// Operator used to match syscall arguments in Seccomp -type Operator string - -// Define operators for syscall arguments in Seccomp -const ( - OpNotEqual Operator = "SCMP_CMP_NE" - OpLessThan Operator = "SCMP_CMP_LT" - OpLessEqual Operator = "SCMP_CMP_LE" - OpEqualTo Operator = "SCMP_CMP_EQ" - OpGreaterEqual Operator = "SCMP_CMP_GE" - OpGreaterThan Operator = "SCMP_CMP_GT" - OpMaskedEqual Operator = "SCMP_CMP_MASKED_EQ" -) - -// Arg used for matching specific syscall arguments in Seccomp -type Arg struct { - Index uint `json:"index"` - Value uint64 `json:"value"` - ValueTwo uint64 `json:"valueTwo"` - Op Operator `json:"op"` -} - -// Filter is used to conditionally apply Seccomp rules -type Filter struct { - Caps []string `json:"caps,omitempty"` - Arches []string `json:"arches,omitempty"` -} - -// Syscall is used to match a group of syscalls in Seccomp -type Syscall struct { - Name string `json:"name,omitempty"` - Names []string `json:"names,omitempty"` - Action Action `json:"action"` - Args []*Arg `json:"args"` - Comment string `json:"comment"` - Includes Filter `json:"includes"` - Excludes Filter `json:"excludes"` -} diff --git a/vendor/github.com/docker/docker/api/types/service_update_response.go b/vendor/github.com/docker/docker/api/types/service_update_response.go deleted file mode 100644 index 74ea64b1bb..0000000000 --- a/vendor/github.com/docker/docker/api/types/service_update_response.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ServiceUpdateResponse service update response -// swagger:model ServiceUpdateResponse -type ServiceUpdateResponse struct { - - // Optional warning messages - Warnings []string `json:"Warnings"` -} diff --git a/vendor/github.com/docker/docker/api/types/stats.go b/vendor/github.com/docker/docker/api/types/stats.go deleted file mode 100644 index 60175c0613..0000000000 --- a/vendor/github.com/docker/docker/api/types/stats.go +++ /dev/null @@ -1,181 +0,0 @@ -// Package types is used for API stability in the types and response to the -// consumers of the API stats endpoint. -package types // import "github.com/docker/docker/api/types" - -import "time" - -// ThrottlingData stores CPU throttling stats of one running container. -// Not used on Windows. -type ThrottlingData struct { - // Number of periods with throttling active - Periods uint64 `json:"periods"` - // Number of periods when the container hits its throttling limit. - ThrottledPeriods uint64 `json:"throttled_periods"` - // Aggregate time the container was throttled for in nanoseconds. - ThrottledTime uint64 `json:"throttled_time"` -} - -// CPUUsage stores All CPU stats aggregated since container inception. -type CPUUsage struct { - // Total CPU time consumed. - // Units: nanoseconds (Linux) - // Units: 100's of nanoseconds (Windows) - TotalUsage uint64 `json:"total_usage"` - - // Total CPU time consumed per core (Linux). Not used on Windows. - // Units: nanoseconds. - PercpuUsage []uint64 `json:"percpu_usage,omitempty"` - - // Time spent by tasks of the cgroup in kernel mode (Linux). - // Time spent by all container processes in kernel mode (Windows). - // Units: nanoseconds (Linux). - // Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers. - UsageInKernelmode uint64 `json:"usage_in_kernelmode"` - - // Time spent by tasks of the cgroup in user mode (Linux). - // Time spent by all container processes in user mode (Windows). - // Units: nanoseconds (Linux). - // Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers - UsageInUsermode uint64 `json:"usage_in_usermode"` -} - -// CPUStats aggregates and wraps all CPU related info of container -type CPUStats struct { - // CPU Usage. Linux and Windows. - CPUUsage CPUUsage `json:"cpu_usage"` - - // System Usage. Linux only. - SystemUsage uint64 `json:"system_cpu_usage,omitempty"` - - // Online CPUs. Linux only. - OnlineCPUs uint32 `json:"online_cpus,omitempty"` - - // Throttling Data. Linux only. - ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` -} - -// MemoryStats aggregates all memory stats since container inception on Linux. -// Windows returns stats for commit and private working set only. -type MemoryStats struct { - // Linux Memory Stats - - // current res_counter usage for memory - Usage uint64 `json:"usage,omitempty"` - // maximum usage ever recorded. - MaxUsage uint64 `json:"max_usage,omitempty"` - // TODO(vishh): Export these as stronger types. - // all the stats exported via memory.stat. - Stats map[string]uint64 `json:"stats,omitempty"` - // number of times memory usage hits limits. - Failcnt uint64 `json:"failcnt,omitempty"` - Limit uint64 `json:"limit,omitempty"` - - // Windows Memory Stats - // See https://technet.microsoft.com/en-us/magazine/ff382715.aspx - - // committed bytes - Commit uint64 `json:"commitbytes,omitempty"` - // peak committed bytes - CommitPeak uint64 `json:"commitpeakbytes,omitempty"` - // private working set - PrivateWorkingSet uint64 `json:"privateworkingset,omitempty"` -} - -// BlkioStatEntry is one small entity to store a piece of Blkio stats -// Not used on Windows. -type BlkioStatEntry struct { - Major uint64 `json:"major"` - Minor uint64 `json:"minor"` - Op string `json:"op"` - Value uint64 `json:"value"` -} - -// BlkioStats stores All IO service stats for data read and write. -// This is a Linux specific structure as the differences between expressing -// block I/O on Windows and Linux are sufficiently significant to make -// little sense attempting to morph into a combined structure. -type BlkioStats struct { - // number of bytes transferred to and from the block device - IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"` - IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"` - IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"` - IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"` - IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"` - IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"` - IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"` - SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"` -} - -// StorageStats is the disk I/O stats for read/write on Windows. -type StorageStats struct { - ReadCountNormalized uint64 `json:"read_count_normalized,omitempty"` - ReadSizeBytes uint64 `json:"read_size_bytes,omitempty"` - WriteCountNormalized uint64 `json:"write_count_normalized,omitempty"` - WriteSizeBytes uint64 `json:"write_size_bytes,omitempty"` -} - -// NetworkStats aggregates the network stats of one container -type NetworkStats struct { - // Bytes received. Windows and Linux. - RxBytes uint64 `json:"rx_bytes"` - // Packets received. Windows and Linux. - RxPackets uint64 `json:"rx_packets"` - // Received errors. Not used on Windows. Note that we dont `omitempty` this - // field as it is expected in the >=v1.21 API stats structure. - RxErrors uint64 `json:"rx_errors"` - // Incoming packets dropped. Windows and Linux. - RxDropped uint64 `json:"rx_dropped"` - // Bytes sent. Windows and Linux. - TxBytes uint64 `json:"tx_bytes"` - // Packets sent. Windows and Linux. - TxPackets uint64 `json:"tx_packets"` - // Sent errors. Not used on Windows. Note that we dont `omitempty` this - // field as it is expected in the >=v1.21 API stats structure. - TxErrors uint64 `json:"tx_errors"` - // Outgoing packets dropped. Windows and Linux. - TxDropped uint64 `json:"tx_dropped"` - // Endpoint ID. Not used on Linux. - EndpointID string `json:"endpoint_id,omitempty"` - // Instance ID. Not used on Linux. - InstanceID string `json:"instance_id,omitempty"` -} - -// PidsStats contains the stats of a container's pids -type PidsStats struct { - // Current is the number of pids in the cgroup - Current uint64 `json:"current,omitempty"` - // Limit is the hard limit on the number of pids in the cgroup. - // A "Limit" of 0 means that there is no limit. - Limit uint64 `json:"limit,omitempty"` -} - -// Stats is Ultimate struct aggregating all types of stats of one container -type Stats struct { - // Common stats - Read time.Time `json:"read"` - PreRead time.Time `json:"preread"` - - // Linux specific stats, not populated on Windows. - PidsStats PidsStats `json:"pids_stats,omitempty"` - BlkioStats BlkioStats `json:"blkio_stats,omitempty"` - - // Windows specific stats, not populated on Linux. - NumProcs uint32 `json:"num_procs"` - StorageStats StorageStats `json:"storage_stats,omitempty"` - - // Shared stats - CPUStats CPUStats `json:"cpu_stats,omitempty"` - PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" - MemoryStats MemoryStats `json:"memory_stats,omitempty"` -} - -// StatsJSON is newly used Networks -type StatsJSON struct { - Stats - - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - - // Networks request version >=1.21 - Networks map[string]NetworkStats `json:"networks,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/common.go b/vendor/github.com/docker/docker/api/types/swarm/common.go deleted file mode 100644 index ef020f458b..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/common.go +++ /dev/null @@ -1,40 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "time" - -// Version represents the internal object version. -type Version struct { - Index uint64 `json:",omitempty"` -} - -// Meta is a base object inherited by most of the other once. -type Meta struct { - Version Version `json:",omitempty"` - CreatedAt time.Time `json:",omitempty"` - UpdatedAt time.Time `json:",omitempty"` -} - -// Annotations represents how to describe an object. -type Annotations struct { - Name string `json:",omitempty"` - Labels map[string]string `json:"Labels"` -} - -// Driver represents a driver (network, logging, secrets backend). -type Driver struct { - Name string `json:",omitempty"` - Options map[string]string `json:",omitempty"` -} - -// TLSInfo represents the TLS information about what CA certificate is trusted, -// and who the issuer for a TLS certificate is -type TLSInfo struct { - // TrustRoot is the trusted CA root certificate in PEM format - TrustRoot string `json:",omitempty"` - - // CertIssuer is the raw subject bytes of the issuer - CertIssuerSubject []byte `json:",omitempty"` - - // CertIssuerPublicKey is the raw public key bytes of the issuer - CertIssuerPublicKey []byte `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/config.go b/vendor/github.com/docker/docker/api/types/swarm/config.go deleted file mode 100644 index c1fdf3b3e4..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/config.go +++ /dev/null @@ -1,31 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "os" - -// Config represents a config. -type Config struct { - ID string - Meta - Spec ConfigSpec -} - -// ConfigSpec represents a config specification from a config in swarm -type ConfigSpec struct { - Annotations - Data []byte `json:",omitempty"` -} - -// ConfigReferenceFileTarget is a file target in a config reference -type ConfigReferenceFileTarget struct { - Name string - UID string - GID string - Mode os.FileMode -} - -// ConfigReference is a reference to a config in swarm -type ConfigReference struct { - File *ConfigReferenceFileTarget - ConfigID string - ConfigName string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/container.go b/vendor/github.com/docker/docker/api/types/swarm/container.go deleted file mode 100644 index 0041653c9d..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/container.go +++ /dev/null @@ -1,73 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "time" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/mount" -) - -// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf) -// Detailed documentation is available in: -// http://man7.org/linux/man-pages/man5/resolv.conf.5.html -// `nameserver`, `search`, `options` have been supported. -// TODO: `domain` is not supported yet. -type DNSConfig struct { - // Nameservers specifies the IP addresses of the name servers - Nameservers []string `json:",omitempty"` - // Search specifies the search list for host-name lookup - Search []string `json:",omitempty"` - // Options allows certain internal resolver variables to be modified - Options []string `json:",omitempty"` -} - -// SELinuxContext contains the SELinux labels of the container. -type SELinuxContext struct { - Disable bool - - User string - Role string - Type string - Level string -} - -// CredentialSpec for managed service account (Windows only) -type CredentialSpec struct { - File string - Registry string -} - -// Privileges defines the security options for the container. -type Privileges struct { - CredentialSpec *CredentialSpec - SELinuxContext *SELinuxContext -} - -// ContainerSpec represents the spec of a container. -type ContainerSpec struct { - Image string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Command []string `json:",omitempty"` - Args []string `json:",omitempty"` - Hostname string `json:",omitempty"` - Env []string `json:",omitempty"` - Dir string `json:",omitempty"` - User string `json:",omitempty"` - Groups []string `json:",omitempty"` - Privileges *Privileges `json:",omitempty"` - StopSignal string `json:",omitempty"` - TTY bool `json:",omitempty"` - OpenStdin bool `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Mounts []mount.Mount `json:",omitempty"` - StopGracePeriod *time.Duration `json:",omitempty"` - Healthcheck *container.HealthConfig `json:",omitempty"` - // The format of extra hosts on swarmkit is specified in: - // http://man7.org/linux/man-pages/man5/hosts.5.html - // IP_address canonical_hostname [aliases...] - Hosts []string `json:",omitempty"` - DNSConfig *DNSConfig `json:",omitempty"` - Secrets []*SecretReference `json:",omitempty"` - Configs []*ConfigReference `json:",omitempty"` - Isolation container.Isolation `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/network.go b/vendor/github.com/docker/docker/api/types/swarm/network.go deleted file mode 100644 index fd9b1a52c2..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/network.go +++ /dev/null @@ -1,119 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "github.com/docker/docker/api/types/network" -) - -// Endpoint represents an endpoint. -type Endpoint struct { - Spec EndpointSpec `json:",omitempty"` - Ports []PortConfig `json:",omitempty"` - VirtualIPs []EndpointVirtualIP `json:",omitempty"` -} - -// EndpointSpec represents the spec of an endpoint. -type EndpointSpec struct { - Mode ResolutionMode `json:",omitempty"` - Ports []PortConfig `json:",omitempty"` -} - -// ResolutionMode represents a resolution mode. -type ResolutionMode string - -const ( - // ResolutionModeVIP VIP - ResolutionModeVIP ResolutionMode = "vip" - // ResolutionModeDNSRR DNSRR - ResolutionModeDNSRR ResolutionMode = "dnsrr" -) - -// PortConfig represents the config of a port. -type PortConfig struct { - Name string `json:",omitempty"` - Protocol PortConfigProtocol `json:",omitempty"` - // TargetPort is the port inside the container - TargetPort uint32 `json:",omitempty"` - // PublishedPort is the port on the swarm hosts - PublishedPort uint32 `json:",omitempty"` - // PublishMode is the mode in which port is published - PublishMode PortConfigPublishMode `json:",omitempty"` -} - -// PortConfigPublishMode represents the mode in which the port is to -// be published. -type PortConfigPublishMode string - -const ( - // PortConfigPublishModeIngress is used for ports published - // for ingress load balancing using routing mesh. - PortConfigPublishModeIngress PortConfigPublishMode = "ingress" - // PortConfigPublishModeHost is used for ports published - // for direct host level access on the host where the task is running. - PortConfigPublishModeHost PortConfigPublishMode = "host" -) - -// PortConfigProtocol represents the protocol of a port. -type PortConfigProtocol string - -const ( - // TODO(stevvooe): These should be used generally, not just for PortConfig. - - // PortConfigProtocolTCP TCP - PortConfigProtocolTCP PortConfigProtocol = "tcp" - // PortConfigProtocolUDP UDP - PortConfigProtocolUDP PortConfigProtocol = "udp" -) - -// EndpointVirtualIP represents the virtual ip of a port. -type EndpointVirtualIP struct { - NetworkID string `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// Network represents a network. -type Network struct { - ID string - Meta - Spec NetworkSpec `json:",omitempty"` - DriverState Driver `json:",omitempty"` - IPAMOptions *IPAMOptions `json:",omitempty"` -} - -// NetworkSpec represents the spec of a network. -type NetworkSpec struct { - Annotations - DriverConfiguration *Driver `json:",omitempty"` - IPv6Enabled bool `json:",omitempty"` - Internal bool `json:",omitempty"` - Attachable bool `json:",omitempty"` - Ingress bool `json:",omitempty"` - IPAMOptions *IPAMOptions `json:",omitempty"` - ConfigFrom *network.ConfigReference `json:",omitempty"` - Scope string `json:",omitempty"` -} - -// NetworkAttachmentConfig represents the configuration of a network attachment. -type NetworkAttachmentConfig struct { - Target string `json:",omitempty"` - Aliases []string `json:",omitempty"` - DriverOpts map[string]string `json:",omitempty"` -} - -// NetworkAttachment represents a network attachment. -type NetworkAttachment struct { - Network Network `json:",omitempty"` - Addresses []string `json:",omitempty"` -} - -// IPAMOptions represents ipam options. -type IPAMOptions struct { - Driver Driver `json:",omitempty"` - Configs []IPAMConfig `json:",omitempty"` -} - -// IPAMConfig represents ipam configuration. -type IPAMConfig struct { - Subnet string `json:",omitempty"` - Range string `json:",omitempty"` - Gateway string `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/node.go b/vendor/github.com/docker/docker/api/types/swarm/node.go deleted file mode 100644 index 1e30f5fa10..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/node.go +++ /dev/null @@ -1,115 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -// Node represents a node. -type Node struct { - ID string - Meta - // Spec defines the desired state of the node as specified by the user. - // The system will honor this and will *never* modify it. - Spec NodeSpec `json:",omitempty"` - // Description encapsulates the properties of the Node as reported by the - // agent. - Description NodeDescription `json:",omitempty"` - // Status provides the current status of the node, as seen by the manager. - Status NodeStatus `json:",omitempty"` - // ManagerStatus provides the current status of the node's manager - // component, if the node is a manager. - ManagerStatus *ManagerStatus `json:",omitempty"` -} - -// NodeSpec represents the spec of a node. -type NodeSpec struct { - Annotations - Role NodeRole `json:",omitempty"` - Availability NodeAvailability `json:",omitempty"` -} - -// NodeRole represents the role of a node. -type NodeRole string - -const ( - // NodeRoleWorker WORKER - NodeRoleWorker NodeRole = "worker" - // NodeRoleManager MANAGER - NodeRoleManager NodeRole = "manager" -) - -// NodeAvailability represents the availability of a node. -type NodeAvailability string - -const ( - // NodeAvailabilityActive ACTIVE - NodeAvailabilityActive NodeAvailability = "active" - // NodeAvailabilityPause PAUSE - NodeAvailabilityPause NodeAvailability = "pause" - // NodeAvailabilityDrain DRAIN - NodeAvailabilityDrain NodeAvailability = "drain" -) - -// NodeDescription represents the description of a node. -type NodeDescription struct { - Hostname string `json:",omitempty"` - Platform Platform `json:",omitempty"` - Resources Resources `json:",omitempty"` - Engine EngineDescription `json:",omitempty"` - TLSInfo TLSInfo `json:",omitempty"` -} - -// Platform represents the platform (Arch/OS). -type Platform struct { - Architecture string `json:",omitempty"` - OS string `json:",omitempty"` -} - -// EngineDescription represents the description of an engine. -type EngineDescription struct { - EngineVersion string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Plugins []PluginDescription `json:",omitempty"` -} - -// PluginDescription represents the description of an engine plugin. -type PluginDescription struct { - Type string `json:",omitempty"` - Name string `json:",omitempty"` -} - -// NodeStatus represents the status of a node. -type NodeStatus struct { - State NodeState `json:",omitempty"` - Message string `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// Reachability represents the reachability of a node. -type Reachability string - -const ( - // ReachabilityUnknown UNKNOWN - ReachabilityUnknown Reachability = "unknown" - // ReachabilityUnreachable UNREACHABLE - ReachabilityUnreachable Reachability = "unreachable" - // ReachabilityReachable REACHABLE - ReachabilityReachable Reachability = "reachable" -) - -// ManagerStatus represents the status of a manager. -type ManagerStatus struct { - Leader bool `json:",omitempty"` - Reachability Reachability `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// NodeState represents the state of a node. -type NodeState string - -const ( - // NodeStateUnknown UNKNOWN - NodeStateUnknown NodeState = "unknown" - // NodeStateDown DOWN - NodeStateDown NodeState = "down" - // NodeStateReady READY - NodeStateReady NodeState = "ready" - // NodeStateDisconnected DISCONNECTED - NodeStateDisconnected NodeState = "disconnected" -) diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime.go b/vendor/github.com/docker/docker/api/types/swarm/runtime.go deleted file mode 100644 index 81b5f4cfd9..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime.go +++ /dev/null @@ -1,19 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -// RuntimeType is the type of runtime used for the TaskSpec -type RuntimeType string - -// RuntimeURL is the proto type url -type RuntimeURL string - -const ( - // RuntimeContainer is the container based runtime - RuntimeContainer RuntimeType = "container" - // RuntimePlugin is the plugin based runtime - RuntimePlugin RuntimeType = "plugin" - - // RuntimeURLContainer is the proto url for the container type - RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer" - // RuntimeURLPlugin is the proto url for the plugin type - RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin" -) diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go b/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go deleted file mode 100644 index 98c2806c31..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go +++ /dev/null @@ -1,3 +0,0 @@ -//go:generate protoc -I . --gogofast_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto - -package runtime // import "github.com/docker/docker/api/types/swarm/runtime" diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go deleted file mode 100644 index 1fdc9b0436..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go +++ /dev/null @@ -1,712 +0,0 @@ -// Code generated by protoc-gen-gogo. -// source: plugin.proto -// DO NOT EDIT! - -/* - Package runtime is a generated protocol buffer package. - - It is generated from these files: - plugin.proto - - It has these top-level messages: - PluginSpec - PluginPrivilege -*/ -package runtime - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package - -// PluginSpec defines the base payload which clients can specify for creating -// a service with the plugin runtime. -type PluginSpec struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"` - Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"` - Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"` -} - -func (m *PluginSpec) Reset() { *m = PluginSpec{} } -func (m *PluginSpec) String() string { return proto.CompactTextString(m) } -func (*PluginSpec) ProtoMessage() {} -func (*PluginSpec) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} } - -func (m *PluginSpec) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *PluginSpec) GetRemote() string { - if m != nil { - return m.Remote - } - return "" -} - -func (m *PluginSpec) GetPrivileges() []*PluginPrivilege { - if m != nil { - return m.Privileges - } - return nil -} - -func (m *PluginSpec) GetDisabled() bool { - if m != nil { - return m.Disabled - } - return false -} - -// PluginPrivilege describes a permission the user has to accept -// upon installing a plugin. -type PluginPrivilege struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Value []string `protobuf:"bytes,3,rep,name=value" json:"value,omitempty"` -} - -func (m *PluginPrivilege) Reset() { *m = PluginPrivilege{} } -func (m *PluginPrivilege) String() string { return proto.CompactTextString(m) } -func (*PluginPrivilege) ProtoMessage() {} -func (*PluginPrivilege) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{1} } - -func (m *PluginPrivilege) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *PluginPrivilege) GetDescription() string { - if m != nil { - return m.Description - } - return "" -} - -func (m *PluginPrivilege) GetValue() []string { - if m != nil { - return m.Value - } - return nil -} - -func init() { - proto.RegisterType((*PluginSpec)(nil), "PluginSpec") - proto.RegisterType((*PluginPrivilege)(nil), "PluginPrivilege") -} -func (m *PluginSpec) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Name) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - } - if len(m.Remote) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Remote))) - i += copy(dAtA[i:], m.Remote) - } - if len(m.Privileges) > 0 { - for _, msg := range m.Privileges { - dAtA[i] = 0x1a - i++ - i = encodeVarintPlugin(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n - } - } - if m.Disabled { - dAtA[i] = 0x20 - i++ - if m.Disabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } - return i, nil -} - -func (m *PluginPrivilege) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Name) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - } - if len(m.Description) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) - } - if len(m.Value) > 0 { - for _, s := range m.Value { - dAtA[i] = 0x1a - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - return i, nil -} - -func encodeFixed64Plugin(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Plugin(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} -func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *PluginSpec) Size() (n int) { - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - l = len(m.Remote) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - if len(m.Privileges) > 0 { - for _, e := range m.Privileges { - l = e.Size() - n += 1 + l + sovPlugin(uint64(l)) - } - } - if m.Disabled { - n += 2 - } - return n -} - -func (m *PluginPrivilege) Size() (n int) { - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - if len(m.Value) > 0 { - for _, s := range m.Value { - l = len(s) - n += 1 + l + sovPlugin(uint64(l)) - } - } - return n -} - -func sovPlugin(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozPlugin(x uint64) (n int) { - return sovPlugin(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *PluginSpec) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PluginSpec: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PluginSpec: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Remote", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Remote = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Privileges", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Privileges = append(m.Privileges, &PluginPrivilege{}) - if err := m.Privileges[len(m.Privileges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Disabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Disabled = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipPlugin(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthPlugin - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PluginPrivilege) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PluginPrivilege: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PluginPrivilege: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = append(m.Value, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipPlugin(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthPlugin - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipPlugin(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthPlugin - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipPlugin(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow") -) - -func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) } - -var fileDescriptorPlugin = []byte{ - // 196 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d, - 0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x6a, 0x63, 0xe4, 0xe2, 0x0a, 0x00, 0x0b, - 0x04, 0x17, 0xa4, 0x26, 0x0b, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, - 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x45, 0xa9, 0xb9, 0xf9, 0x25, 0xa9, 0x12, - 0x4c, 0x60, 0x51, 0x28, 0x4f, 0xc8, 0x80, 0x8b, 0xab, 0xa0, 0x28, 0xb3, 0x2c, 0x33, 0x27, 0x35, - 0x3d, 0xb5, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x40, 0x0f, 0x62, 0x58, 0x00, 0x4c, - 0x22, 0x08, 0x49, 0x8d, 0x90, 0x14, 0x17, 0x47, 0x4a, 0x66, 0x71, 0x62, 0x52, 0x4e, 0x6a, 0x8a, - 0x04, 0x8b, 0x02, 0xa3, 0x06, 0x47, 0x10, 0x9c, 0xaf, 0x14, 0xcb, 0xc5, 0x8f, 0xa6, 0x15, 0xab, - 0x63, 0x14, 0xb8, 0xb8, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a, 0x32, 0xf3, 0xf3, 0xa0, - 0x2e, 0x42, 0x16, 0x12, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x05, 0xbb, 0x88, 0x33, - 0x08, 0xc2, 0x71, 0xe2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, - 0x18, 0x93, 0xd8, 0xc0, 0x9e, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x84, 0xad, 0x79, - 0x0c, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/secret.go b/vendor/github.com/docker/docker/api/types/swarm/secret.go deleted file mode 100644 index cfba1141d8..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/secret.go +++ /dev/null @@ -1,32 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "os" - -// Secret represents a secret. -type Secret struct { - ID string - Meta - Spec SecretSpec -} - -// SecretSpec represents a secret specification from a secret in swarm -type SecretSpec struct { - Annotations - Data []byte `json:",omitempty"` - Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store -} - -// SecretReferenceFileTarget is a file target in a secret reference -type SecretReferenceFileTarget struct { - Name string - UID string - GID string - Mode os.FileMode -} - -// SecretReference is a reference to a secret in swarm -type SecretReference struct { - File *SecretReferenceFileTarget - SecretID string - SecretName string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/service.go b/vendor/github.com/docker/docker/api/types/swarm/service.go deleted file mode 100644 index abf192e759..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/service.go +++ /dev/null @@ -1,124 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "time" - -// Service represents a service. -type Service struct { - ID string - Meta - Spec ServiceSpec `json:",omitempty"` - PreviousSpec *ServiceSpec `json:",omitempty"` - Endpoint Endpoint `json:",omitempty"` - UpdateStatus *UpdateStatus `json:",omitempty"` -} - -// ServiceSpec represents the spec of a service. -type ServiceSpec struct { - Annotations - - // TaskTemplate defines how the service should construct new tasks when - // orchestrating this service. - TaskTemplate TaskSpec `json:",omitempty"` - Mode ServiceMode `json:",omitempty"` - UpdateConfig *UpdateConfig `json:",omitempty"` - RollbackConfig *UpdateConfig `json:",omitempty"` - - // Networks field in ServiceSpec is deprecated. The - // same field in TaskSpec should be used instead. - // This field will be removed in a future release. - Networks []NetworkAttachmentConfig `json:",omitempty"` - EndpointSpec *EndpointSpec `json:",omitempty"` -} - -// ServiceMode represents the mode of a service. -type ServiceMode struct { - Replicated *ReplicatedService `json:",omitempty"` - Global *GlobalService `json:",omitempty"` -} - -// UpdateState is the state of a service update. -type UpdateState string - -const ( - // UpdateStateUpdating is the updating state. - UpdateStateUpdating UpdateState = "updating" - // UpdateStatePaused is the paused state. - UpdateStatePaused UpdateState = "paused" - // UpdateStateCompleted is the completed state. - UpdateStateCompleted UpdateState = "completed" - // UpdateStateRollbackStarted is the state with a rollback in progress. - UpdateStateRollbackStarted UpdateState = "rollback_started" - // UpdateStateRollbackPaused is the state with a rollback in progress. - UpdateStateRollbackPaused UpdateState = "rollback_paused" - // UpdateStateRollbackCompleted is the state with a rollback in progress. - UpdateStateRollbackCompleted UpdateState = "rollback_completed" -) - -// UpdateStatus reports the status of a service update. -type UpdateStatus struct { - State UpdateState `json:",omitempty"` - StartedAt *time.Time `json:",omitempty"` - CompletedAt *time.Time `json:",omitempty"` - Message string `json:",omitempty"` -} - -// ReplicatedService is a kind of ServiceMode. -type ReplicatedService struct { - Replicas *uint64 `json:",omitempty"` -} - -// GlobalService is a kind of ServiceMode. -type GlobalService struct{} - -const ( - // UpdateFailureActionPause PAUSE - UpdateFailureActionPause = "pause" - // UpdateFailureActionContinue CONTINUE - UpdateFailureActionContinue = "continue" - // UpdateFailureActionRollback ROLLBACK - UpdateFailureActionRollback = "rollback" - - // UpdateOrderStopFirst STOP_FIRST - UpdateOrderStopFirst = "stop-first" - // UpdateOrderStartFirst START_FIRST - UpdateOrderStartFirst = "start-first" -) - -// UpdateConfig represents the update configuration. -type UpdateConfig struct { - // Maximum number of tasks to be updated in one iteration. - // 0 means unlimited parallelism. - Parallelism uint64 - - // Amount of time between updates. - Delay time.Duration `json:",omitempty"` - - // FailureAction is the action to take when an update failures. - FailureAction string `json:",omitempty"` - - // Monitor indicates how long to monitor a task for failure after it is - // created. If the task fails by ending up in one of the states - // REJECTED, COMPLETED, or FAILED, within Monitor from its creation, - // this counts as a failure. If it fails after Monitor, it does not - // count as a failure. If Monitor is unspecified, a default value will - // be used. - Monitor time.Duration `json:",omitempty"` - - // MaxFailureRatio is the fraction of tasks that may fail during - // an update before the failure action is invoked. Any task created by - // the current update which ends up in one of the states REJECTED, - // COMPLETED or FAILED within Monitor from its creation counts as a - // failure. The number of failures is divided by the number of tasks - // being updated, and if this fraction is greater than - // MaxFailureRatio, the failure action is invoked. - // - // If the failure action is CONTINUE, there is no effect. - // If the failure action is PAUSE, no more tasks will be updated until - // another update is started. - MaxFailureRatio float32 - - // Order indicates the order of operations when rolling out an updated - // task. Either the old task is shut down before the new task is - // started, or the new task is started before the old task is shut down. - Order string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go deleted file mode 100644 index 1b111d725b..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go +++ /dev/null @@ -1,217 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "time" - -// ClusterInfo represents info about the cluster for outputting in "info" -// it contains the same information as "Swarm", but without the JoinTokens -type ClusterInfo struct { - ID string - Meta - Spec Spec - TLSInfo TLSInfo - RootRotationInProgress bool -} - -// Swarm represents a swarm. -type Swarm struct { - ClusterInfo - JoinTokens JoinTokens -} - -// JoinTokens contains the tokens workers and managers need to join the swarm. -type JoinTokens struct { - // Worker is the join token workers may use to join the swarm. - Worker string - // Manager is the join token managers may use to join the swarm. - Manager string -} - -// Spec represents the spec of a swarm. -type Spec struct { - Annotations - - Orchestration OrchestrationConfig `json:",omitempty"` - Raft RaftConfig `json:",omitempty"` - Dispatcher DispatcherConfig `json:",omitempty"` - CAConfig CAConfig `json:",omitempty"` - TaskDefaults TaskDefaults `json:",omitempty"` - EncryptionConfig EncryptionConfig `json:",omitempty"` -} - -// OrchestrationConfig represents orchestration configuration. -type OrchestrationConfig struct { - // TaskHistoryRetentionLimit is the number of historic tasks to keep per instance or - // node. If negative, never remove completed or failed tasks. - TaskHistoryRetentionLimit *int64 `json:",omitempty"` -} - -// TaskDefaults parameterizes cluster-level task creation with default values. -type TaskDefaults struct { - // LogDriver selects the log driver to use for tasks created in the - // orchestrator if unspecified by a service. - // - // Updating this value will only have an affect on new tasks. Old tasks - // will continue use their previously configured log driver until - // recreated. - LogDriver *Driver `json:",omitempty"` -} - -// EncryptionConfig controls at-rest encryption of data and keys. -type EncryptionConfig struct { - // AutoLockManagers specifies whether or not managers TLS keys and raft data - // should be encrypted at rest in such a way that they must be unlocked - // before the manager node starts up again. - AutoLockManagers bool -} - -// RaftConfig represents raft configuration. -type RaftConfig struct { - // SnapshotInterval is the number of log entries between snapshots. - SnapshotInterval uint64 `json:",omitempty"` - - // KeepOldSnapshots is the number of snapshots to keep beyond the - // current snapshot. - KeepOldSnapshots *uint64 `json:",omitempty"` - - // LogEntriesForSlowFollowers is the number of log entries to keep - // around to sync up slow followers after a snapshot is created. - LogEntriesForSlowFollowers uint64 `json:",omitempty"` - - // ElectionTick is the number of ticks that a follower will wait for a message - // from the leader before becoming a candidate and starting an election. - // ElectionTick must be greater than HeartbeatTick. - // - // A tick currently defaults to one second, so these translate directly to - // seconds currently, but this is NOT guaranteed. - ElectionTick int - - // HeartbeatTick is the number of ticks between heartbeats. Every - // HeartbeatTick ticks, the leader will send a heartbeat to the - // followers. - // - // A tick currently defaults to one second, so these translate directly to - // seconds currently, but this is NOT guaranteed. - HeartbeatTick int -} - -// DispatcherConfig represents dispatcher configuration. -type DispatcherConfig struct { - // HeartbeatPeriod defines how often agent should send heartbeats to - // dispatcher. - HeartbeatPeriod time.Duration `json:",omitempty"` -} - -// CAConfig represents CA configuration. -type CAConfig struct { - // NodeCertExpiry is the duration certificates should be issued for - NodeCertExpiry time.Duration `json:",omitempty"` - - // ExternalCAs is a list of CAs to which a manager node will make - // certificate signing requests for node certificates. - ExternalCAs []*ExternalCA `json:",omitempty"` - - // SigningCACert and SigningCAKey specify the desired signing root CA and - // root CA key for the swarm. When inspecting the cluster, the key will - // be redacted. - SigningCACert string `json:",omitempty"` - SigningCAKey string `json:",omitempty"` - - // If this value changes, and there is no specified signing cert and key, - // then the swarm is forced to generate a new root certificate ane key. - ForceRotate uint64 `json:",omitempty"` -} - -// ExternalCAProtocol represents type of external CA. -type ExternalCAProtocol string - -// ExternalCAProtocolCFSSL CFSSL -const ExternalCAProtocolCFSSL ExternalCAProtocol = "cfssl" - -// ExternalCA defines external CA to be used by the cluster. -type ExternalCA struct { - // Protocol is the protocol used by this external CA. - Protocol ExternalCAProtocol - - // URL is the URL where the external CA can be reached. - URL string - - // Options is a set of additional key/value pairs whose interpretation - // depends on the specified CA type. - Options map[string]string `json:",omitempty"` - - // CACert specifies which root CA is used by this external CA. This certificate must - // be in PEM format. - CACert string -} - -// InitRequest is the request used to init a swarm. -type InitRequest struct { - ListenAddr string - AdvertiseAddr string - DataPathAddr string - ForceNewCluster bool - Spec Spec - AutoLockManagers bool - Availability NodeAvailability -} - -// JoinRequest is the request used to join a swarm. -type JoinRequest struct { - ListenAddr string - AdvertiseAddr string - DataPathAddr string - RemoteAddrs []string - JoinToken string // accept by secret - Availability NodeAvailability -} - -// UnlockRequest is the request used to unlock a swarm. -type UnlockRequest struct { - // UnlockKey is the unlock key in ASCII-armored format. - UnlockKey string -} - -// LocalNodeState represents the state of the local node. -type LocalNodeState string - -const ( - // LocalNodeStateInactive INACTIVE - LocalNodeStateInactive LocalNodeState = "inactive" - // LocalNodeStatePending PENDING - LocalNodeStatePending LocalNodeState = "pending" - // LocalNodeStateActive ACTIVE - LocalNodeStateActive LocalNodeState = "active" - // LocalNodeStateError ERROR - LocalNodeStateError LocalNodeState = "error" - // LocalNodeStateLocked LOCKED - LocalNodeStateLocked LocalNodeState = "locked" -) - -// Info represents generic information about swarm. -type Info struct { - NodeID string - NodeAddr string - - LocalNodeState LocalNodeState - ControlAvailable bool - Error string - - RemoteManagers []Peer - Nodes int `json:",omitempty"` - Managers int `json:",omitempty"` - - Cluster *ClusterInfo `json:",omitempty"` -} - -// Peer represents a peer. -type Peer struct { - NodeID string - Addr string -} - -// UpdateFlags contains flags for SwarmUpdate. -type UpdateFlags struct { - RotateWorkerToken bool - RotateManagerToken bool - RotateManagerUnlockKey bool -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/task.go b/vendor/github.com/docker/docker/api/types/swarm/task.go deleted file mode 100644 index 5c2bc492e4..0000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/task.go +++ /dev/null @@ -1,188 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "time" - - "github.com/docker/docker/api/types/swarm/runtime" -) - -// TaskState represents the state of a task. -type TaskState string - -const ( - // TaskStateNew NEW - TaskStateNew TaskState = "new" - // TaskStateAllocated ALLOCATED - TaskStateAllocated TaskState = "allocated" - // TaskStatePending PENDING - TaskStatePending TaskState = "pending" - // TaskStateAssigned ASSIGNED - TaskStateAssigned TaskState = "assigned" - // TaskStateAccepted ACCEPTED - TaskStateAccepted TaskState = "accepted" - // TaskStatePreparing PREPARING - TaskStatePreparing TaskState = "preparing" - // TaskStateReady READY - TaskStateReady TaskState = "ready" - // TaskStateStarting STARTING - TaskStateStarting TaskState = "starting" - // TaskStateRunning RUNNING - TaskStateRunning TaskState = "running" - // TaskStateComplete COMPLETE - TaskStateComplete TaskState = "complete" - // TaskStateShutdown SHUTDOWN - TaskStateShutdown TaskState = "shutdown" - // TaskStateFailed FAILED - TaskStateFailed TaskState = "failed" - // TaskStateRejected REJECTED - TaskStateRejected TaskState = "rejected" - // TaskStateRemove REMOVE - TaskStateRemove TaskState = "remove" - // TaskStateOrphaned ORPHANED - TaskStateOrphaned TaskState = "orphaned" -) - -// Task represents a task. -type Task struct { - ID string - Meta - Annotations - - Spec TaskSpec `json:",omitempty"` - ServiceID string `json:",omitempty"` - Slot int `json:",omitempty"` - NodeID string `json:",omitempty"` - Status TaskStatus `json:",omitempty"` - DesiredState TaskState `json:",omitempty"` - NetworksAttachments []NetworkAttachment `json:",omitempty"` - GenericResources []GenericResource `json:",omitempty"` -} - -// TaskSpec represents the spec of a task. -type TaskSpec struct { - // ContainerSpec and PluginSpec are mutually exclusive. - // PluginSpec will only be used when the `Runtime` field is set to `plugin` - ContainerSpec *ContainerSpec `json:",omitempty"` - PluginSpec *runtime.PluginSpec `json:",omitempty"` - - Resources *ResourceRequirements `json:",omitempty"` - RestartPolicy *RestartPolicy `json:",omitempty"` - Placement *Placement `json:",omitempty"` - Networks []NetworkAttachmentConfig `json:",omitempty"` - - // LogDriver specifies the LogDriver to use for tasks created from this - // spec. If not present, the one on cluster default on swarm.Spec will be - // used, finally falling back to the engine default if not specified. - LogDriver *Driver `json:",omitempty"` - - // ForceUpdate is a counter that triggers an update even if no relevant - // parameters have been changed. - ForceUpdate uint64 - - Runtime RuntimeType `json:",omitempty"` -} - -// Resources represents resources (CPU/Memory). -type Resources struct { - NanoCPUs int64 `json:",omitempty"` - MemoryBytes int64 `json:",omitempty"` - GenericResources []GenericResource `json:",omitempty"` -} - -// GenericResource represents a "user defined" resource which can -// be either an integer (e.g: SSD=3) or a string (e.g: SSD=sda1) -type GenericResource struct { - NamedResourceSpec *NamedGenericResource `json:",omitempty"` - DiscreteResourceSpec *DiscreteGenericResource `json:",omitempty"` -} - -// NamedGenericResource represents a "user defined" resource which is defined -// as a string. -// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) -// Value is used to identify the resource (GPU="UUID-1", FPGA="/dev/sdb5", ...) -type NamedGenericResource struct { - Kind string `json:",omitempty"` - Value string `json:",omitempty"` -} - -// DiscreteGenericResource represents a "user defined" resource which is defined -// as an integer -// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) -// Value is used to count the resource (SSD=5, HDD=3, ...) -type DiscreteGenericResource struct { - Kind string `json:",omitempty"` - Value int64 `json:",omitempty"` -} - -// ResourceRequirements represents resources requirements. -type ResourceRequirements struct { - Limits *Resources `json:",omitempty"` - Reservations *Resources `json:",omitempty"` -} - -// Placement represents orchestration parameters. -type Placement struct { - Constraints []string `json:",omitempty"` - Preferences []PlacementPreference `json:",omitempty"` - - // Platforms stores all the platforms that the image can run on. - // This field is used in the platform filter for scheduling. If empty, - // then the platform filter is off, meaning there are no scheduling restrictions. - Platforms []Platform `json:",omitempty"` -} - -// PlacementPreference provides a way to make the scheduler aware of factors -// such as topology. -type PlacementPreference struct { - Spread *SpreadOver -} - -// SpreadOver is a scheduling preference that instructs the scheduler to spread -// tasks evenly over groups of nodes identified by labels. -type SpreadOver struct { - // label descriptor, such as engine.labels.az - SpreadDescriptor string -} - -// RestartPolicy represents the restart policy. -type RestartPolicy struct { - Condition RestartPolicyCondition `json:",omitempty"` - Delay *time.Duration `json:",omitempty"` - MaxAttempts *uint64 `json:",omitempty"` - Window *time.Duration `json:",omitempty"` -} - -// RestartPolicyCondition represents when to restart. -type RestartPolicyCondition string - -const ( - // RestartPolicyConditionNone NONE - RestartPolicyConditionNone RestartPolicyCondition = "none" - // RestartPolicyConditionOnFailure ON_FAILURE - RestartPolicyConditionOnFailure RestartPolicyCondition = "on-failure" - // RestartPolicyConditionAny ANY - RestartPolicyConditionAny RestartPolicyCondition = "any" -) - -// TaskStatus represents the status of a task. -type TaskStatus struct { - Timestamp time.Time `json:",omitempty"` - State TaskState `json:",omitempty"` - Message string `json:",omitempty"` - Err string `json:",omitempty"` - ContainerStatus *ContainerStatus `json:",omitempty"` - PortStatus PortStatus `json:",omitempty"` -} - -// ContainerStatus represents the status of a container. -type ContainerStatus struct { - ContainerID string - PID int - ExitCode int -} - -// PortStatus represents the port status of a task's host ports whose -// service has published host ports -type PortStatus struct { - Ports []PortConfig `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/time/duration_convert.go b/vendor/github.com/docker/docker/api/types/time/duration_convert.go deleted file mode 100644 index 84b6f07322..0000000000 --- a/vendor/github.com/docker/docker/api/types/time/duration_convert.go +++ /dev/null @@ -1,12 +0,0 @@ -package time // import "github.com/docker/docker/api/types/time" - -import ( - "strconv" - "time" -) - -// DurationToSecondsString converts the specified duration to the number -// seconds it represents, formatted as a string. -func DurationToSecondsString(duration time.Duration) string { - return strconv.FormatFloat(duration.Seconds(), 'f', 0, 64) -} diff --git a/vendor/github.com/docker/docker/api/types/time/timestamp.go b/vendor/github.com/docker/docker/api/types/time/timestamp.go deleted file mode 100644 index 8d573accb1..0000000000 --- a/vendor/github.com/docker/docker/api/types/time/timestamp.go +++ /dev/null @@ -1,122 +0,0 @@ -package time // import "github.com/docker/docker/api/types/time" - -import ( - "fmt" - "math" - "strconv" - "strings" - "time" -) - -// These are additional predefined layouts for use in Time.Format and Time.Parse -// with --since and --until parameters for `docker logs` and `docker events` -const ( - rFC3339Local = "2006-01-02T15:04:05" // RFC3339 with local timezone - rFC3339NanoLocal = "2006-01-02T15:04:05.999999999" // RFC3339Nano with local timezone - dateWithZone = "2006-01-02Z07:00" // RFC3339 with time at 00:00:00 - dateLocal = "2006-01-02" // RFC3339 with local timezone and time at 00:00:00 -) - -// GetTimestamp tries to parse given string as golang duration, -// then RFC3339 time and finally as a Unix timestamp. If -// any of these were successful, it returns a Unix timestamp -// as string otherwise returns the given value back. -// In case of duration input, the returned timestamp is computed -// as the given reference time minus the amount of the duration. -func GetTimestamp(value string, reference time.Time) (string, error) { - if d, err := time.ParseDuration(value); value != "0" && err == nil { - return strconv.FormatInt(reference.Add(-d).Unix(), 10), nil - } - - var format string - // if the string has a Z or a + or three dashes use parse otherwise use parseinlocation - parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3) - - if strings.Contains(value, ".") { - if parseInLocation { - format = rFC3339NanoLocal - } else { - format = time.RFC3339Nano - } - } else if strings.Contains(value, "T") { - // we want the number of colons in the T portion of the timestamp - tcolons := strings.Count(value, ":") - // if parseInLocation is off and we have a +/- zone offset (not Z) then - // there will be an extra colon in the input for the tz offset subtract that - // colon from the tcolons count - if !parseInLocation && !strings.ContainsAny(value, "zZ") && tcolons > 0 { - tcolons-- - } - if parseInLocation { - switch tcolons { - case 0: - format = "2006-01-02T15" - case 1: - format = "2006-01-02T15:04" - default: - format = rFC3339Local - } - } else { - switch tcolons { - case 0: - format = "2006-01-02T15Z07:00" - case 1: - format = "2006-01-02T15:04Z07:00" - default: - format = time.RFC3339 - } - } - } else if parseInLocation { - format = dateLocal - } else { - format = dateWithZone - } - - var t time.Time - var err error - - if parseInLocation { - t, err = time.ParseInLocation(format, value, time.FixedZone(reference.Zone())) - } else { - t, err = time.Parse(format, value) - } - - if err != nil { - // if there is a `-` then it's an RFC3339 like timestamp otherwise assume unixtimestamp - if strings.Contains(value, "-") { - return "", err // was probably an RFC3339 like timestamp but the parser failed with an error - } - return value, nil // unixtimestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server) - } - - return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil -} - -// ParseTimestamps returns seconds and nanoseconds from a timestamp that has the -// format "%d.%09d", time.Unix(), int64(time.Nanosecond())) -// if the incoming nanosecond portion is longer or shorter than 9 digits it is -// converted to nanoseconds. The expectation is that the seconds and -// seconds will be used to create a time variable. For example: -// seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0) -// if err == nil since := time.Unix(seconds, nanoseconds) -// returns seconds as def(aultSeconds) if value == "" -func ParseTimestamps(value string, def int64) (int64, int64, error) { - if value == "" { - return def, 0, nil - } - sa := strings.SplitN(value, ".", 2) - s, err := strconv.ParseInt(sa[0], 10, 64) - if err != nil { - return s, 0, err - } - if len(sa) != 2 { - return s, 0, nil - } - n, err := strconv.ParseInt(sa[1], 10, 64) - if err != nil { - return s, n, err - } - // should already be in nanoseconds but just in case convert n to nanoseconds - n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1])))) - return s, n, nil -} diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go deleted file mode 100644 index 729f4eb6c4..0000000000 --- a/vendor/github.com/docker/docker/api/types/types.go +++ /dev/null @@ -1,587 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "errors" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/go-connections/nat" -) - -// RootFS returns Image's RootFS description including the layer IDs. -type RootFS struct { - Type string - Layers []string `json:",omitempty"` - BaseLayer string `json:",omitempty"` -} - -// ImageInspect contains response of Engine API: -// GET "/images/{name:.*}/json" -type ImageInspect struct { - ID string `json:"Id"` - RepoTags []string - RepoDigests []string - Parent string - Comment string - Created string - Container string - ContainerConfig *container.Config - DockerVersion string - Author string - Config *container.Config - Architecture string - Os string - OsVersion string `json:",omitempty"` - Size int64 - VirtualSize int64 - GraphDriver GraphDriverData - RootFS RootFS - Metadata ImageMetadata -} - -// ImageMetadata contains engine-local data about the image -type ImageMetadata struct { - LastTagTime time.Time `json:",omitempty"` -} - -// Container contains response of Engine API: -// GET "/containers/json" -type Container struct { - ID string `json:"Id"` - Names []string - Image string - ImageID string - Command string - Created int64 - Ports []Port - SizeRw int64 `json:",omitempty"` - SizeRootFs int64 `json:",omitempty"` - Labels map[string]string - State string - Status string - HostConfig struct { - NetworkMode string `json:",omitempty"` - } - NetworkSettings *SummaryNetworkSettings - Mounts []MountPoint -} - -// CopyConfig contains request body of Engine API: -// POST "/containers/"+containerID+"/copy" -type CopyConfig struct { - Resource string -} - -// ContainerPathStat is used to encode the header from -// GET "/containers/{name:.*}/archive" -// "Name" is the file or directory name. -type ContainerPathStat struct { - Name string `json:"name"` - Size int64 `json:"size"` - Mode os.FileMode `json:"mode"` - Mtime time.Time `json:"mtime"` - LinkTarget string `json:"linkTarget"` -} - -// ContainerStats contains response of Engine API: -// GET "/stats" -type ContainerStats struct { - Body io.ReadCloser `json:"body"` - OSType string `json:"ostype"` -} - -// Ping contains response of Engine API: -// GET "/_ping" -type Ping struct { - APIVersion string - OSType string - Experimental bool -} - -// ComponentVersion describes the version information for a specific component. -type ComponentVersion struct { - Name string - Version string - Details map[string]string `json:",omitempty"` -} - -// Version contains response of Engine API: -// GET "/version" -type Version struct { - Platform struct{ Name string } `json:",omitempty"` - Components []ComponentVersion `json:",omitempty"` - - // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility - - Version string - APIVersion string `json:"ApiVersion"` - MinAPIVersion string `json:"MinAPIVersion,omitempty"` - GitCommit string - GoVersion string - Os string - Arch string - KernelVersion string `json:",omitempty"` - Experimental bool `json:",omitempty"` - BuildTime string `json:",omitempty"` -} - -// Commit holds the Git-commit (SHA1) that a binary was built from, as reported -// in the version-string of external tools, such as containerd, or runC. -type Commit struct { - ID string // ID is the actual commit ID of external tool. - Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time. -} - -// Info contains response of Engine API: -// GET "/info" -type Info struct { - ID string - Containers int - ContainersRunning int - ContainersPaused int - ContainersStopped int - Images int - Driver string - DriverStatus [][2]string - SystemStatus [][2]string - Plugins PluginsInfo - MemoryLimit bool - SwapLimit bool - KernelMemory bool - CPUCfsPeriod bool `json:"CpuCfsPeriod"` - CPUCfsQuota bool `json:"CpuCfsQuota"` - CPUShares bool - CPUSet bool - IPv4Forwarding bool - BridgeNfIptables bool - BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` - Debug bool - NFd int - OomKillDisable bool - NGoroutines int - SystemTime string - LoggingDriver string - CgroupDriver string - NEventsListener int - KernelVersion string - OperatingSystem string - OSType string - Architecture string - IndexServerAddress string - RegistryConfig *registry.ServiceConfig - NCPU int - MemTotal int64 - GenericResources []swarm.GenericResource - DockerRootDir string - HTTPProxy string `json:"HttpProxy"` - HTTPSProxy string `json:"HttpsProxy"` - NoProxy string - Name string - Labels []string - ExperimentalBuild bool - ServerVersion string - ClusterStore string - ClusterAdvertise string - Runtimes map[string]Runtime - DefaultRuntime string - Swarm swarm.Info - // LiveRestoreEnabled determines whether containers should be kept - // running when the daemon is shutdown or upon daemon start if - // running containers are detected - LiveRestoreEnabled bool - Isolation container.Isolation - InitBinary string - ContainerdCommit Commit - RuncCommit Commit - InitCommit Commit - SecurityOptions []string -} - -// KeyValue holds a key/value pair -type KeyValue struct { - Key, Value string -} - -// SecurityOpt contains the name and options of a security option -type SecurityOpt struct { - Name string - Options []KeyValue -} - -// DecodeSecurityOptions decodes a security options string slice to a type safe -// SecurityOpt -func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) { - so := []SecurityOpt{} - for _, opt := range opts { - // support output from a < 1.13 docker daemon - if !strings.Contains(opt, "=") { - so = append(so, SecurityOpt{Name: opt}) - continue - } - secopt := SecurityOpt{} - split := strings.Split(opt, ",") - for _, s := range split { - kv := strings.SplitN(s, "=", 2) - if len(kv) != 2 { - return nil, fmt.Errorf("invalid security option %q", s) - } - if kv[0] == "" || kv[1] == "" { - return nil, errors.New("invalid empty security option") - } - if kv[0] == "name" { - secopt.Name = kv[1] - continue - } - secopt.Options = append(secopt.Options, KeyValue{Key: kv[0], Value: kv[1]}) - } - so = append(so, secopt) - } - return so, nil -} - -// PluginsInfo is a temp struct holding Plugins name -// registered with docker daemon. It is used by Info struct -type PluginsInfo struct { - // List of Volume plugins registered - Volume []string - // List of Network plugins registered - Network []string - // List of Authorization plugins registered - Authorization []string - // List of Log plugins registered - Log []string -} - -// ExecStartCheck is a temp struct used by execStart -// Config fields is part of ExecConfig in runconfig package -type ExecStartCheck struct { - // ExecStart will first check if it's detached - Detach bool - // Check if there's a tty - Tty bool -} - -// HealthcheckResult stores information about a single run of a healthcheck probe -type HealthcheckResult struct { - Start time.Time // Start is the time this check started - End time.Time // End is the time this check ended - ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe - Output string // Output from last check -} - -// Health states -const ( - NoHealthcheck = "none" // Indicates there is no healthcheck - Starting = "starting" // Starting indicates that the container is not yet ready - Healthy = "healthy" // Healthy indicates that the container is running correctly - Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem -) - -// Health stores information about the container's healthcheck results -type Health struct { - Status string // Status is one of Starting, Healthy or Unhealthy - FailingStreak int // FailingStreak is the number of consecutive failures - Log []*HealthcheckResult // Log contains the last few results (oldest first) -} - -// ContainerState stores container's running state -// it's part of ContainerJSONBase and will return by "inspect" command -type ContainerState struct { - Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead" - Running bool - Paused bool - Restarting bool - OOMKilled bool - Dead bool - Pid int - ExitCode int - Error string - StartedAt string - FinishedAt string - Health *Health `json:",omitempty"` -} - -// ContainerNode stores information about the node that a container -// is running on. It's only available in Docker Swarm -type ContainerNode struct { - ID string - IPAddress string `json:"IP"` - Addr string - Name string - Cpus int - Memory int64 - Labels map[string]string -} - -// ContainerJSONBase contains response of Engine API: -// GET "/containers/{name:.*}/json" -type ContainerJSONBase struct { - ID string `json:"Id"` - Created string - Path string - Args []string - State *ContainerState - Image string - ResolvConfPath string - HostnamePath string - HostsPath string - LogPath string - Node *ContainerNode `json:",omitempty"` - Name string - RestartCount int - Driver string - Platform string - MountLabel string - ProcessLabel string - AppArmorProfile string - ExecIDs []string - HostConfig *container.HostConfig - GraphDriver GraphDriverData - SizeRw *int64 `json:",omitempty"` - SizeRootFs *int64 `json:",omitempty"` -} - -// ContainerJSON is newly used struct along with MountPoint -type ContainerJSON struct { - *ContainerJSONBase - Mounts []MountPoint - Config *container.Config - NetworkSettings *NetworkSettings -} - -// NetworkSettings exposes the network settings in the api -type NetworkSettings struct { - NetworkSettingsBase - DefaultNetworkSettings - Networks map[string]*network.EndpointSettings -} - -// SummaryNetworkSettings provides a summary of container's networks -// in /containers/json -type SummaryNetworkSettings struct { - Networks map[string]*network.EndpointSettings -} - -// NetworkSettingsBase holds basic information about networks -type NetworkSettingsBase struct { - Bridge string // Bridge is the Bridge name the network uses(e.g. `docker0`) - SandboxID string // SandboxID uniquely represents a container's network stack - HairpinMode bool // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface - LinkLocalIPv6Address string // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix - LinkLocalIPv6PrefixLen int // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address - Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port - SandboxKey string // SandboxKey identifies the sandbox - SecondaryIPAddresses []network.Address - SecondaryIPv6Addresses []network.Address -} - -// DefaultNetworkSettings holds network information -// during the 2 release deprecation period. -// It will be removed in Docker 1.11. -type DefaultNetworkSettings struct { - EndpointID string // EndpointID uniquely represents a service endpoint in a Sandbox - Gateway string // Gateway holds the gateway address for the network - GlobalIPv6Address string // GlobalIPv6Address holds network's global IPv6 address - GlobalIPv6PrefixLen int // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address - IPAddress string // IPAddress holds the IPv4 address for the network - IPPrefixLen int // IPPrefixLen represents mask length of network's IPv4 address - IPv6Gateway string // IPv6Gateway holds gateway address specific for IPv6 - MacAddress string // MacAddress holds the MAC address for the network -} - -// MountPoint represents a mount point configuration inside the container. -// This is used for reporting the mountpoints in use by a container. -type MountPoint struct { - Type mount.Type `json:",omitempty"` - Name string `json:",omitempty"` - Source string - Destination string - Driver string `json:",omitempty"` - Mode string - RW bool - Propagation mount.Propagation -} - -// NetworkResource is the body of the "get network" http response message -type NetworkResource struct { - Name string // Name is the requested name of the network - ID string `json:"Id"` // ID uniquely identifies a network on a single machine - Created time.Time // Created is the time the network created - Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level) - Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`) - EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6 - IPAM network.IPAM // IPAM is the network's IP Address Management - Internal bool // Internal represents if the network is used internal only - Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. - Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster. - ConfigFrom network.ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network. - ConfigOnly bool // ConfigOnly networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services. - Containers map[string]EndpointResource // Containers contains endpoints belonging to the network - Options map[string]string // Options holds the network specific options to use for when creating the network - Labels map[string]string // Labels holds metadata specific to the network being created - Peers []network.PeerInfo `json:",omitempty"` // List of peer nodes for an overlay network - Services map[string]network.ServiceInfo `json:",omitempty"` -} - -// EndpointResource contains network resources allocated and used for a container in a network -type EndpointResource struct { - Name string - EndpointID string - MacAddress string - IPv4Address string - IPv6Address string -} - -// NetworkCreate is the expected body of the "create network" http request message -type NetworkCreate struct { - // Check for networks with duplicate names. - // Network is primarily keyed based on a random ID and not on the name. - // Network name is strictly a user-friendly alias to the network - // which is uniquely identified using ID. - // And there is no guaranteed way to check for duplicates. - // Option CheckDuplicate is there to provide a best effort checking of any networks - // which has the same name but it is not guaranteed to catch all name collisions. - CheckDuplicate bool - Driver string - Scope string - EnableIPv6 bool - IPAM *network.IPAM - Internal bool - Attachable bool - Ingress bool - ConfigOnly bool - ConfigFrom *network.ConfigReference - Options map[string]string - Labels map[string]string -} - -// NetworkCreateRequest is the request message sent to the server for network create call. -type NetworkCreateRequest struct { - NetworkCreate - Name string -} - -// NetworkCreateResponse is the response message sent by the server for network create call -type NetworkCreateResponse struct { - ID string `json:"Id"` - Warning string -} - -// NetworkConnect represents the data to be used to connect a container to the network -type NetworkConnect struct { - Container string - EndpointConfig *network.EndpointSettings `json:",omitempty"` -} - -// NetworkDisconnect represents the data to be used to disconnect a container from the network -type NetworkDisconnect struct { - Container string - Force bool -} - -// NetworkInspectOptions holds parameters to inspect network -type NetworkInspectOptions struct { - Scope string - Verbose bool -} - -// Checkpoint represents the details of a checkpoint -type Checkpoint struct { - Name string // Name is the name of the checkpoint -} - -// Runtime describes an OCI runtime -type Runtime struct { - Path string `json:"path"` - Args []string `json:"runtimeArgs,omitempty"` -} - -// DiskUsage contains response of Engine API: -// GET "/system/df" -type DiskUsage struct { - LayersSize int64 - Images []*ImageSummary - Containers []*Container - Volumes []*Volume - BuilderSize int64 -} - -// ContainersPruneReport contains the response for Engine API: -// POST "/containers/prune" -type ContainersPruneReport struct { - ContainersDeleted []string - SpaceReclaimed uint64 -} - -// VolumesPruneReport contains the response for Engine API: -// POST "/volumes/prune" -type VolumesPruneReport struct { - VolumesDeleted []string - SpaceReclaimed uint64 -} - -// ImagesPruneReport contains the response for Engine API: -// POST "/images/prune" -type ImagesPruneReport struct { - ImagesDeleted []ImageDeleteResponseItem - SpaceReclaimed uint64 -} - -// BuildCachePruneReport contains the response for Engine API: -// POST "/build/prune" -type BuildCachePruneReport struct { - SpaceReclaimed uint64 -} - -// NetworksPruneReport contains the response for Engine API: -// POST "/networks/prune" -type NetworksPruneReport struct { - NetworksDeleted []string -} - -// SecretCreateResponse contains the information returned to a client -// on the creation of a new secret. -type SecretCreateResponse struct { - // ID is the id of the created secret. - ID string -} - -// SecretListOptions holds parameters to list secrets -type SecretListOptions struct { - Filters filters.Args -} - -// ConfigCreateResponse contains the information returned to a client -// on the creation of a new config. -type ConfigCreateResponse struct { - // ID is the id of the created config. - ID string -} - -// ConfigListOptions holds parameters to list configs -type ConfigListOptions struct { - Filters filters.Args -} - -// PushResult contains the tag, manifest digest, and manifest size from the -// push. It's used to signal this information to the trust code in the client -// so it can sign the manifest if necessary. -type PushResult struct { - Tag string - Digest string - Size int -} - -// BuildResult contains the image id of a successful build -type BuildResult struct { - ID string -} diff --git a/vendor/github.com/docker/docker/api/types/versions/compare.go b/vendor/github.com/docker/docker/api/types/versions/compare.go deleted file mode 100644 index 8ccb0aa92e..0000000000 --- a/vendor/github.com/docker/docker/api/types/versions/compare.go +++ /dev/null @@ -1,62 +0,0 @@ -package versions // import "github.com/docker/docker/api/types/versions" - -import ( - "strconv" - "strings" -) - -// compare compares two version strings -// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise. -func compare(v1, v2 string) int { - var ( - currTab = strings.Split(v1, ".") - otherTab = strings.Split(v2, ".") - ) - - max := len(currTab) - if len(otherTab) > max { - max = len(otherTab) - } - for i := 0; i < max; i++ { - var currInt, otherInt int - - if len(currTab) > i { - currInt, _ = strconv.Atoi(currTab[i]) - } - if len(otherTab) > i { - otherInt, _ = strconv.Atoi(otherTab[i]) - } - if currInt > otherInt { - return 1 - } - if otherInt > currInt { - return -1 - } - } - return 0 -} - -// LessThan checks if a version is less than another -func LessThan(v, other string) bool { - return compare(v, other) == -1 -} - -// LessThanOrEqualTo checks if a version is less than or equal to another -func LessThanOrEqualTo(v, other string) bool { - return compare(v, other) <= 0 -} - -// GreaterThan checks if a version is greater than another -func GreaterThan(v, other string) bool { - return compare(v, other) == 1 -} - -// GreaterThanOrEqualTo checks if a version is greater than or equal to another -func GreaterThanOrEqualTo(v, other string) bool { - return compare(v, other) >= 0 -} - -// Equal checks if a version is equal to another -func Equal(v, other string) bool { - return compare(v, other) == 0 -} diff --git a/vendor/github.com/docker/docker/api/types/volume.go b/vendor/github.com/docker/docker/api/types/volume.go deleted file mode 100644 index b5ee96a500..0000000000 --- a/vendor/github.com/docker/docker/api/types/volume.go +++ /dev/null @@ -1,69 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Volume volume -// swagger:model Volume -type Volume struct { - - // Date/Time the volume was created. - CreatedAt string `json:"CreatedAt,omitempty"` - - // Name of the volume driver used by the volume. - // Required: true - Driver string `json:"Driver"` - - // User-defined key/value metadata. - // Required: true - Labels map[string]string `json:"Labels"` - - // Mount path of the volume on the host. - // Required: true - Mountpoint string `json:"Mountpoint"` - - // Name of the volume. - // Required: true - Name string `json:"Name"` - - // The driver specific options used when creating the volume. - // Required: true - Options map[string]string `json:"Options"` - - // The level at which the volume exists. Either `global` for cluster-wide, or `local` for machine level. - // Required: true - Scope string `json:"Scope"` - - // Low-level details about the volume, provided by the volume driver. - // Details are returned as a map with key/value pairs: - // `{"key":"value","key2":"value2"}`. - // - // The `Status` field is optional, and is omitted if the volume driver - // does not support this feature. - // - Status map[string]interface{} `json:"Status,omitempty"` - - // usage data - UsageData *VolumeUsageData `json:"UsageData,omitempty"` -} - -// VolumeUsageData Usage details about the volume. This information is used by the -// `GET /system/df` endpoint, and omitted in other endpoints. -// -// swagger:model VolumeUsageData -type VolumeUsageData struct { - - // The number of containers referencing this volume. This field - // is set to `-1` if the reference-count is not available. - // - // Required: true - RefCount int64 `json:"RefCount"` - - // Amount of disk space used by the volume (in bytes). This information - // is only available for volumes created with the `"local"` volume - // driver. For volumes created with other volume drivers, this field - // is set to `-1` ("not available") - // - // Required: true - Size int64 `json:"Size"` -} diff --git a/vendor/github.com/docker/docker/api/types/volume/volumes_create.go b/vendor/github.com/docker/docker/api/types/volume/volumes_create.go deleted file mode 100644 index b2dd3a419d..0000000000 --- a/vendor/github.com/docker/docker/api/types/volume/volumes_create.go +++ /dev/null @@ -1,29 +0,0 @@ -package volume // import "github.com/docker/docker/api/types/volume" - -// ---------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE -// This file was generated by `swagger generate operation` -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// VolumesCreateBody volumes create body -// swagger:model VolumesCreateBody -type VolumesCreateBody struct { - - // Name of the volume driver to use. - // Required: true - Driver string `json:"Driver"` - - // A mapping of driver options and values. These options are passed directly to the driver and are driver specific. - // Required: true - DriverOpts map[string]string `json:"DriverOpts"` - - // User-defined key/value metadata. - // Required: true - Labels map[string]string `json:"Labels"` - - // The new volume's name. If not specified, Docker generates a name. - // Required: true - Name string `json:"Name"` -} diff --git a/vendor/github.com/docker/docker/api/types/volume/volumes_list.go b/vendor/github.com/docker/docker/api/types/volume/volumes_list.go deleted file mode 100644 index e071ca08fc..0000000000 --- a/vendor/github.com/docker/docker/api/types/volume/volumes_list.go +++ /dev/null @@ -1,23 +0,0 @@ -package volume // import "github.com/docker/docker/api/types/volume" - -// ---------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE -// This file was generated by `swagger generate operation` -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -import "github.com/docker/docker/api/types" - -// VolumesListOKBody volumes list o k body -// swagger:model VolumesListOKBody -type VolumesListOKBody struct { - - // List of volumes - // Required: true - Volumes []*types.Volume `json:"Volumes"` - - // Warnings that occurred when fetching the list of volumes - // Required: true - Warnings []string `json:"Warnings"` -} diff --git a/vendor/github.com/docker/docker/client/build_prune.go b/vendor/github.com/docker/docker/client/build_prune.go deleted file mode 100644 index 3ad07ccb85..0000000000 --- a/vendor/github.com/docker/docker/client/build_prune.go +++ /dev/null @@ -1,30 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// BuildCachePrune requests the daemon to delete unused cache data -func (cli *Client) BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) { - if err := cli.NewVersionError("1.31", "build prune"); err != nil { - return nil, err - } - - report := types.BuildCachePruneReport{} - - serverResp, err := cli.post(ctx, "/build/prune", nil, nil, nil) - if err != nil { - return nil, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return nil, fmt.Errorf("Error retrieving disk usage: %v", err) - } - - return &report, nil -} diff --git a/vendor/github.com/docker/docker/client/checkpoint_create.go b/vendor/github.com/docker/docker/client/checkpoint_create.go deleted file mode 100644 index 6441ed2501..0000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_create.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// CheckpointCreate creates a checkpoint from the given container with the given name -func (cli *Client) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error { - resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/checkpoint_delete.go b/vendor/github.com/docker/docker/client/checkpoint_delete.go deleted file mode 100644 index 5b97c35c6b..0000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_delete.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// CheckpointDelete deletes the checkpoint with the given name from the given container -func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options types.CheckpointDeleteOptions) error { - query := url.Values{} - if options.CheckpointDir != "" { - query.Set("dir", options.CheckpointDir) - } - - resp, err := cli.delete(ctx, "/containers/"+containerID+"/checkpoints/"+options.CheckpointID, query, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/checkpoint_list.go b/vendor/github.com/docker/docker/client/checkpoint_list.go deleted file mode 100644 index 8ba1ddff7f..0000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_list.go +++ /dev/null @@ -1,28 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// CheckpointList returns the checkpoints of the given container in the docker host -func (cli *Client) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) { - var checkpoints []types.Checkpoint - - query := url.Values{} - if options.CheckpointDir != "" { - query.Set("dir", options.CheckpointDir) - } - - resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) - if err != nil { - return checkpoints, wrapResponseError(err, resp, "container", container) - } - - err = json.NewDecoder(resp.body).Decode(&checkpoints) - ensureReaderClosed(resp) - return checkpoints, err -} diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go deleted file mode 100644 index 6ce0cdba1f..0000000000 --- a/vendor/github.com/docker/docker/client/client.go +++ /dev/null @@ -1,383 +0,0 @@ -/* -Package client is a Go client for the Docker Engine API. - -For more information about the Engine API, see the documentation: -https://docs.docker.com/engine/reference/api/ - -Usage - -You use the library by creating a client object and calling methods on it. The -client can be created either from environment variables with NewEnvClient, or -configured manually with NewClient. - -For example, to list running containers (the equivalent of "docker ps"): - - package main - - import ( - "context" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - ) - - func main() { - cli, err := client.NewEnvClient() - if err != nil { - panic(err) - } - - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) - if err != nil { - panic(err) - } - - for _, container := range containers { - fmt.Printf("%s %s\n", container.ID[:10], container.Image) - } - } - -*/ -package client // import "github.com/docker/docker/client" - -import ( - "errors" - "fmt" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strings" - - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "golang.org/x/net/context" -) - -// ErrRedirect is the error returned by checkRedirect when the request is non-GET. -var ErrRedirect = errors.New("unexpected redirect in response") - -// Client is the API client that performs all operations -// against a docker server. -type Client struct { - // scheme sets the scheme for the client - scheme string - // host holds the server address to connect to - host string - // proto holds the client protocol i.e. unix. - proto string - // addr holds the client address. - addr string - // basePath holds the path to prepend to the requests. - basePath string - // client used to send and receive http requests. - client *http.Client - // version of the server to talk to. - version string - // custom http headers configured by users. - customHTTPHeaders map[string]string - // manualOverride is set to true when the version was set by users. - manualOverride bool -} - -// CheckRedirect specifies the policy for dealing with redirect responses: -// If the request is non-GET return `ErrRedirect`. Otherwise use the last response. -// -// Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308) in the client . -// The Docker client (and by extension docker API client) can be made to to send a request -// like POST /containers//start where what would normally be in the name section of the URL is empty. -// This triggers an HTTP 301 from the daemon. -// In go 1.8 this 301 will be converted to a GET request, and ends up getting a 404 from the daemon. -// This behavior change manifests in the client in that before the 301 was not followed and -// the client did not generate an error, but now results in a message like Error response from daemon: page not found. -func CheckRedirect(req *http.Request, via []*http.Request) error { - if via[0].Method == http.MethodGet { - return http.ErrUseLastResponse - } - return ErrRedirect -} - -// NewEnvClient initializes a new API client based on environment variables. -// Use DOCKER_HOST to set the url to the docker server. -// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest. -// Use DOCKER_CERT_PATH to load the TLS certificates from. -// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default. -// deprecated: use NewClientWithOpts(FromEnv) -func NewEnvClient() (*Client, error) { - return NewClientWithOpts(FromEnv) -} - -// FromEnv enhance the default client with values from environment variables -func FromEnv(c *Client) error { - var httpClient *http.Client - if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { - options := tlsconfig.Options{ - CAFile: filepath.Join(dockerCertPath, "ca.pem"), - CertFile: filepath.Join(dockerCertPath, "cert.pem"), - KeyFile: filepath.Join(dockerCertPath, "key.pem"), - InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "", - } - tlsc, err := tlsconfig.Client(options) - if err != nil { - return err - } - - httpClient = &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsc, - }, - CheckRedirect: CheckRedirect, - } - WithHTTPClient(httpClient)(c) - } - - host := os.Getenv("DOCKER_HOST") - if host != "" { - // WithHost will create an API client if it doesn't exist - if err := WithHost(host)(c); err != nil { - return err - } - } - version := os.Getenv("DOCKER_API_VERSION") - if version != "" { - c.version = version - c.manualOverride = true - } - return nil -} - -// WithVersion overrides the client version with the specified one -func WithVersion(version string) func(*Client) error { - return func(c *Client) error { - c.version = version - return nil - } -} - -// WithHost overrides the client host with the specified one, creating a new -// http client if one doesn't exist -func WithHost(host string) func(*Client) error { - return func(c *Client) error { - hostURL, err := ParseHostURL(host) - if err != nil { - return err - } - c.host = host - c.proto = hostURL.Scheme - c.addr = hostURL.Host - c.basePath = hostURL.Path - if c.client == nil { - client, err := defaultHTTPClient(host) - if err != nil { - return err - } - return WithHTTPClient(client)(c) - } - if transport, ok := c.client.Transport.(*http.Transport); ok { - return sockets.ConfigureTransport(transport, c.proto, c.addr) - } - return fmt.Errorf("cannot apply host to http transport") - } -} - -// WithHTTPClient overrides the client http client with the specified one -func WithHTTPClient(client *http.Client) func(*Client) error { - return func(c *Client) error { - if client != nil { - c.client = client - } - return nil - } -} - -// WithHTTPHeaders overrides the client default http headers -func WithHTTPHeaders(headers map[string]string) func(*Client) error { - return func(c *Client) error { - c.customHTTPHeaders = headers - return nil - } -} - -// NewClientWithOpts initializes a new API client with default values. It takes functors -// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))` -// It also initializes the custom http headers to add to each request. -// -// It won't send any version information if the version number is empty. It is -// highly recommended that you set a version or your client may break if the -// server is upgraded. -func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) { - client, err := defaultHTTPClient(DefaultDockerHost) - if err != nil { - return nil, err - } - c := &Client{ - host: DefaultDockerHost, - version: api.DefaultVersion, - scheme: "http", - client: client, - proto: defaultProto, - addr: defaultAddr, - } - - for _, op := range ops { - if err := op(c); err != nil { - return nil, err - } - } - - if _, ok := c.client.Transport.(http.RoundTripper); !ok { - return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport) - } - tlsConfig := resolveTLSConfig(c.client.Transport) - if tlsConfig != nil { - // TODO(stevvooe): This isn't really the right way to write clients in Go. - // `NewClient` should probably only take an `*http.Client` and work from there. - // Unfortunately, the model of having a host-ish/url-thingy as the connection - // string has us confusing protocol and transport layers. We continue doing - // this to avoid breaking existing clients but this should be addressed. - c.scheme = "https" - } - - return c, nil -} - -func defaultHTTPClient(host string) (*http.Client, error) { - url, err := ParseHostURL(host) - if err != nil { - return nil, err - } - transport := new(http.Transport) - sockets.ConfigureTransport(transport, url.Scheme, url.Host) - return &http.Client{ - Transport: transport, - CheckRedirect: CheckRedirect, - }, nil -} - -// NewClient initializes a new API client for the given host and API version. -// It uses the given http client as transport. -// It also initializes the custom http headers to add to each request. -// -// It won't send any version information if the version number is empty. It is -// highly recommended that you set a version or your client may break if the -// server is upgraded. -// deprecated: use NewClientWithOpts -func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { - return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders)) -} - -// Close the transport used by the client -func (cli *Client) Close() error { - if t, ok := cli.client.Transport.(*http.Transport); ok { - t.CloseIdleConnections() - } - return nil -} - -// getAPIPath returns the versioned request path to call the api. -// It appends the query parameters to the path if they are not empty. -func (cli *Client) getAPIPath(p string, query url.Values) string { - var apiPath string - if cli.version != "" { - v := strings.TrimPrefix(cli.version, "v") - apiPath = path.Join(cli.basePath, "/v"+v, p) - } else { - apiPath = path.Join(cli.basePath, p) - } - return (&url.URL{Path: apiPath, RawQuery: query.Encode()}).String() -} - -// ClientVersion returns the API version used by this client. -func (cli *Client) ClientVersion() string { - return cli.version -} - -// NegotiateAPIVersion queries the API and updates the version to match the -// API version. Any errors are silently ignored. -func (cli *Client) NegotiateAPIVersion(ctx context.Context) { - ping, _ := cli.Ping(ctx) - cli.NegotiateAPIVersionPing(ping) -} - -// NegotiateAPIVersionPing updates the client version to match the Ping.APIVersion -// if the ping version is less than the default version. -func (cli *Client) NegotiateAPIVersionPing(p types.Ping) { - if cli.manualOverride { - return - } - - // try the latest version before versioning headers existed - if p.APIVersion == "" { - p.APIVersion = "1.24" - } - - // if the client is not initialized with a version, start with the latest supported version - if cli.version == "" { - cli.version = api.DefaultVersion - } - - // if server version is lower than the client version, downgrade - if versions.LessThan(p.APIVersion, cli.version) { - cli.version = p.APIVersion - } -} - -// DaemonHost returns the host address used by the client -func (cli *Client) DaemonHost() string { - return cli.host -} - -// ParseHost parses a url string, validates the strings is a host url, and returns -// the parsed host as: protocol, address, and base path -// Deprecated: use ParseHostURL -func ParseHost(host string) (string, string, string, error) { - hostURL, err := ParseHostURL(host) - if err != nil { - return "", "", "", err - } - return hostURL.Scheme, hostURL.Host, hostURL.Path, nil -} - -// ParseHostURL parses a url string, validates the string is a host url, and -// returns the parsed URL -func ParseHostURL(host string) (*url.URL, error) { - protoAddrParts := strings.SplitN(host, "://", 2) - if len(protoAddrParts) == 1 { - return nil, fmt.Errorf("unable to parse docker host `%s`", host) - } - - var basePath string - proto, addr := protoAddrParts[0], protoAddrParts[1] - if proto == "tcp" { - parsed, err := url.Parse("tcp://" + addr) - if err != nil { - return nil, err - } - addr = parsed.Host - basePath = parsed.Path - } - return &url.URL{ - Scheme: proto, - Host: addr, - Path: basePath, - }, nil -} - -// CustomHTTPHeaders returns the custom http headers stored by the client. -func (cli *Client) CustomHTTPHeaders() map[string]string { - m := make(map[string]string) - for k, v := range cli.customHTTPHeaders { - m[k] = v - } - return m -} - -// SetCustomHTTPHeaders that will be set on every HTTP request made by the client. -func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) { - cli.customHTTPHeaders = headers -} diff --git a/vendor/github.com/docker/docker/client/client_unix.go b/vendor/github.com/docker/docker/client/client_unix.go deleted file mode 100644 index 3d24470ba3..0000000000 --- a/vendor/github.com/docker/docker/client/client_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build linux freebsd openbsd darwin - -package client // import "github.com/docker/docker/client" - -// DefaultDockerHost defines os specific default if DOCKER_HOST is unset -const DefaultDockerHost = "unix:///var/run/docker.sock" - -const defaultProto = "unix" -const defaultAddr = "/var/run/docker.sock" diff --git a/vendor/github.com/docker/docker/client/client_windows.go b/vendor/github.com/docker/docker/client/client_windows.go deleted file mode 100644 index c649e54412..0000000000 --- a/vendor/github.com/docker/docker/client/client_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -package client // import "github.com/docker/docker/client" - -// DefaultDockerHost defines os specific default if DOCKER_HOST is unset -const DefaultDockerHost = "npipe:////./pipe/docker_engine" - -const defaultProto = "npipe" -const defaultAddr = "//./pipe/docker_engine" diff --git a/vendor/github.com/docker/docker/client/config_create.go b/vendor/github.com/docker/docker/client/config_create.go deleted file mode 100644 index b6d15b70e4..0000000000 --- a/vendor/github.com/docker/docker/client/config_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ConfigCreate creates a new Config. -func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - var response types.ConfigCreateResponse - if err := cli.NewVersionError("1.30", "config create"); err != nil { - return response, err - } - resp, err := cli.post(ctx, "/configs/create", nil, config, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/config_inspect.go b/vendor/github.com/docker/docker/client/config_inspect.go deleted file mode 100644 index b49fdf568a..0000000000 --- a/vendor/github.com/docker/docker/client/config_inspect.go +++ /dev/null @@ -1,33 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ConfigInspectWithRaw returns the config information with raw data -func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { - if err := cli.NewVersionError("1.30", "config inspect"); err != nil { - return swarm.Config{}, nil, err - } - resp, err := cli.get(ctx, "/configs/"+id, nil, nil) - if err != nil { - return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) - } - defer ensureReaderClosed(resp) - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return swarm.Config{}, nil, err - } - - var config swarm.Config - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&config) - - return config, body, err -} diff --git a/vendor/github.com/docker/docker/client/config_list.go b/vendor/github.com/docker/docker/client/config_list.go deleted file mode 100644 index b9d2632f6a..0000000000 --- a/vendor/github.com/docker/docker/client/config_list.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ConfigList returns the list of configs. -func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) { - if err := cli.NewVersionError("1.30", "config list"); err != nil { - return nil, err - } - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/configs", query, nil) - if err != nil { - return nil, err - } - - var configs []swarm.Config - err = json.NewDecoder(resp.body).Decode(&configs) - ensureReaderClosed(resp) - return configs, err -} diff --git a/vendor/github.com/docker/docker/client/config_remove.go b/vendor/github.com/docker/docker/client/config_remove.go deleted file mode 100644 index 9c8f293f3e..0000000000 --- a/vendor/github.com/docker/docker/client/config_remove.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// ConfigRemove removes a Config. -func (cli *Client) ConfigRemove(ctx context.Context, id string) error { - if err := cli.NewVersionError("1.30", "config remove"); err != nil { - return err - } - resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "config", id) -} diff --git a/vendor/github.com/docker/docker/client/config_update.go b/vendor/github.com/docker/docker/client/config_update.go deleted file mode 100644 index 6b24024cd1..0000000000 --- a/vendor/github.com/docker/docker/client/config_update.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ConfigUpdate attempts to update a Config -func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error { - if err := cli.NewVersionError("1.30", "config update"); err != nil { - return err - } - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_attach.go b/vendor/github.com/docker/docker/client/container_attach.go deleted file mode 100644 index 1a2a431975..0000000000 --- a/vendor/github.com/docker/docker/client/container_attach.go +++ /dev/null @@ -1,57 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerAttach attaches a connection to a container in the server. -// It returns a types.HijackedConnection with the hijacked connection -// and the a reader to get output. It's up to the called to close -// the hijacked connection by calling types.HijackedResponse.Close. -// -// The stream format on the response will be in one of two formats: -// -// If the container is using a TTY, there is only a single stream (stdout), and -// data is copied directly from the container output stream, no extra -// multiplexing or headers. -// -// If the container is *not* using a TTY, streams for stdout and stderr are -// multiplexed. -// The format of the multiplexed stream is as follows: -// -// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} -// -// STREAM_TYPE can be 1 for stdout and 2 for stderr -// -// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian. -// This is the size of OUTPUT. -// -// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this -// stream. -func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) { - query := url.Values{} - if options.Stream { - query.Set("stream", "1") - } - if options.Stdin { - query.Set("stdin", "1") - } - if options.Stdout { - query.Set("stdout", "1") - } - if options.Stderr { - query.Set("stderr", "1") - } - if options.DetachKeys != "" { - query.Set("detachKeys", options.DetachKeys) - } - if options.Logs { - query.Set("logs", "1") - } - - headers := map[string][]string{"Content-Type": {"text/plain"}} - return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/container_commit.go b/vendor/github.com/docker/docker/client/container_commit.go deleted file mode 100644 index 95219beb17..0000000000 --- a/vendor/github.com/docker/docker/client/container_commit.go +++ /dev/null @@ -1,55 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "errors" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerCommit applies changes into a container and creates a new tagged image. -func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) { - var repository, tag string - if options.Reference != "" { - ref, err := reference.ParseNormalizedNamed(options.Reference) - if err != nil { - return types.IDResponse{}, err - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return types.IDResponse{}, errors.New("refusing to create a tag with a digest reference") - } - ref = reference.TagNameOnly(ref) - - if tagged, ok := ref.(reference.Tagged); ok { - tag = tagged.Tag() - } - repository = reference.FamiliarName(ref) - } - - query := url.Values{} - query.Set("container", container) - query.Set("repo", repository) - query.Set("tag", tag) - query.Set("comment", options.Comment) - query.Set("author", options.Author) - for _, change := range options.Changes { - query.Add("changes", change) - } - if !options.Pause { - query.Set("pause", "0") - } - - var response types.IDResponse - resp, err := cli.post(ctx, "/commit", query, options.Config, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_copy.go b/vendor/github.com/docker/docker/client/container_copy.go deleted file mode 100644 index 036298c17c..0000000000 --- a/vendor/github.com/docker/docker/client/container_copy.go +++ /dev/null @@ -1,102 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "path/filepath" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" -) - -// ContainerStatPath returns Stat information about a path inside the container filesystem. -func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) { - query := url.Values{} - query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. - - urlStr := "/containers/" + containerID + "/archive" - response, err := cli.head(ctx, urlStr, query, nil) - if err != nil { - return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path) - } - defer ensureReaderClosed(response) - return getContainerPathStatFromHeader(response.header) -} - -// CopyToContainer copies content into the container filesystem. -// Note that `content` must be a Reader for a TAR archive -func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options types.CopyToContainerOptions) error { - query := url.Values{} - query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API. - // Do not allow for an existing directory to be overwritten by a non-directory and vice versa. - if !options.AllowOverwriteDirWithFile { - query.Set("noOverwriteDirNonDir", "true") - } - - if options.CopyUIDGID { - query.Set("copyUIDGID", "true") - } - - apiPath := "/containers/" + containerID + "/archive" - - response, err := cli.putRaw(ctx, apiPath, query, content, nil) - if err != nil { - return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) - } - defer ensureReaderClosed(response) - - if response.statusCode != http.StatusOK { - return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - return nil -} - -// CopyFromContainer gets the content from the container and returns it as a Reader -// for a TAR archive to manipulate it in the host. It's up to the caller to close the reader. -func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) { - query := make(url.Values, 1) - query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. - - apiPath := "/containers/" + containerID + "/archive" - response, err := cli.get(ctx, apiPath, query, nil) - if err != nil { - return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath) - } - - if response.statusCode != http.StatusOK { - return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - // In order to get the copy behavior right, we need to know information - // about both the source and the destination. The response headers include - // stat info about the source that we can use in deciding exactly how to - // copy it locally. Along with the stat info about the local destination, - // we have everything we need to handle the multiple possibilities there - // can be when copying a file/dir from one location to another file/dir. - stat, err := getContainerPathStatFromHeader(response.header) - if err != nil { - return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err) - } - return response.body, stat, err -} - -func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) { - var stat types.ContainerPathStat - - encodedStat := header.Get("X-Docker-Container-Path-Stat") - statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat)) - - err := json.NewDecoder(statDecoder).Decode(&stat) - if err != nil { - err = fmt.Errorf("unable to decode container path stat header: %s", err) - } - - return stat, err -} diff --git a/vendor/github.com/docker/docker/client/container_create.go b/vendor/github.com/docker/docker/client/container_create.go deleted file mode 100644 index 0af82a19ec..0000000000 --- a/vendor/github.com/docker/docker/client/container_create.go +++ /dev/null @@ -1,56 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - "strings" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/versions" - "golang.org/x/net/context" -) - -type configWrapper struct { - *container.Config - HostConfig *container.HostConfig - NetworkingConfig *network.NetworkingConfig -} - -// ContainerCreate creates a new container based in the given configuration. -// It can be associated with a name, but it's not mandatory. -func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) { - var response container.ContainerCreateCreatedBody - - if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil { - return response, err - } - - // When using API 1.24 and under, the client is responsible for removing the container - if hostConfig != nil && versions.LessThan(cli.ClientVersion(), "1.25") { - hostConfig.AutoRemove = false - } - - query := url.Values{} - if containerName != "" { - query.Set("name", containerName) - } - - body := configWrapper{ - Config: config, - HostConfig: hostConfig, - NetworkingConfig: networkingConfig, - } - - serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) - if err != nil { - if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") { - return response, objectNotFoundError{object: "image", id: config.Image} - } - return response, err - } - - err = json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_diff.go b/vendor/github.com/docker/docker/client/container_diff.go deleted file mode 100644 index f03ebf1da3..0000000000 --- a/vendor/github.com/docker/docker/client/container_diff.go +++ /dev/null @@ -1,23 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/container" - "golang.org/x/net/context" -) - -// ContainerDiff shows differences in a container filesystem since it was started. -func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.ContainerChangeResponseItem, error) { - var changes []container.ContainerChangeResponseItem - - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) - if err != nil { - return changes, err - } - - err = json.NewDecoder(serverResp.body).Decode(&changes) - ensureReaderClosed(serverResp) - return changes, err -} diff --git a/vendor/github.com/docker/docker/client/container_exec.go b/vendor/github.com/docker/docker/client/container_exec.go deleted file mode 100644 index 59db8a90fb..0000000000 --- a/vendor/github.com/docker/docker/client/container_exec.go +++ /dev/null @@ -1,54 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) { - var response types.IDResponse - - if err := cli.NewVersionError("1.25", "env"); len(config.Env) != 0 && err != nil { - return response, err - } - - resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) - if err != nil { - return response, err - } - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} - -// ContainerExecStart starts an exec process already created in the docker host. -func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error { - resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil) - ensureReaderClosed(resp) - return err -} - -// ContainerExecAttach attaches a connection to an exec process in the server. -// It returns a types.HijackedConnection with the hijacked connection -// and the a reader to get output. It's up to the called to close -// the hijacked connection by calling types.HijackedResponse.Close. -func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) { - headers := map[string][]string{"Content-Type": {"application/json"}} - return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers) -} - -// ContainerExecInspect returns information about a specific exec process on the docker host. -func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) { - var response types.ContainerExecInspect - resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_export.go b/vendor/github.com/docker/docker/client/container_export.go deleted file mode 100644 index f4c2bee368..0000000000 --- a/vendor/github.com/docker/docker/client/container_export.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - - "golang.org/x/net/context" -) - -// ContainerExport retrieves the raw contents of a container -// and returns them as an io.ReadCloser. It's up to the caller -// to close the stream. -func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) { - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil) - if err != nil { - return nil, err - } - - return serverResp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/container_inspect.go b/vendor/github.com/docker/docker/client/container_inspect.go deleted file mode 100644 index 1ec45e823f..0000000000 --- a/vendor/github.com/docker/docker/client/container_inspect.go +++ /dev/null @@ -1,47 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerInspect returns the container information. -func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) - if err != nil { - return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) - } - - var response types.ContainerJSON - err = json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} - -// ContainerInspectWithRaw returns the container information and its raw representation. -func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) { - query := url.Values{} - if getSize { - query.Set("size", "1") - } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) - if err != nil { - return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) - } - defer ensureReaderClosed(serverResp) - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return types.ContainerJSON{}, nil, err - } - - var response types.ContainerJSON - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/container_kill.go b/vendor/github.com/docker/docker/client/container_kill.go deleted file mode 100644 index c5a9fe75b2..0000000000 --- a/vendor/github.com/docker/docker/client/container_kill.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "golang.org/x/net/context" -) - -// ContainerKill terminates the container process but does not remove the container from the docker host. -func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error { - query := url.Values{} - query.Set("signal", signal) - - resp, err := cli.post(ctx, "/containers/"+containerID+"/kill", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_list.go b/vendor/github.com/docker/docker/client/container_list.go deleted file mode 100644 index cd2e13835b..0000000000 --- a/vendor/github.com/docker/docker/client/container_list.go +++ /dev/null @@ -1,56 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// ContainerList returns the list of containers in the docker host. -func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) { - query := url.Values{} - - if options.All { - query.Set("all", "1") - } - - if options.Limit != -1 { - query.Set("limit", strconv.Itoa(options.Limit)) - } - - if options.Since != "" { - query.Set("since", options.Since) - } - - if options.Before != "" { - query.Set("before", options.Before) - } - - if options.Size { - query.Set("size", "1") - } - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) - - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/containers/json", query, nil) - if err != nil { - return nil, err - } - - var containers []types.Container - err = json.NewDecoder(resp.body).Decode(&containers) - ensureReaderClosed(resp) - return containers, err -} diff --git a/vendor/github.com/docker/docker/client/container_logs.go b/vendor/github.com/docker/docker/client/container_logs.go deleted file mode 100644 index 01d88a322f..0000000000 --- a/vendor/github.com/docker/docker/client/container_logs.go +++ /dev/null @@ -1,80 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" -) - -// ContainerLogs returns the logs generated by a container in an io.ReadCloser. -// It's up to the caller to close the stream. -// -// The stream format on the response will be in one of two formats: -// -// If the container is using a TTY, there is only a single stream (stdout), and -// data is copied directly from the container output stream, no extra -// multiplexing or headers. -// -// If the container is *not* using a TTY, streams for stdout and stderr are -// multiplexed. -// The format of the multiplexed stream is as follows: -// -// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} -// -// STREAM_TYPE can be 1 for stdout and 2 for stderr -// -// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian. -// This is the size of OUTPUT. -// -// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this -// stream. -func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Until != "" { - ts, err := timetypes.GetTimestamp(options.Until, time.Now()) - if err != nil { - return nil, err - } - query.Set("until", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) - if err != nil { - return nil, wrapResponseError(err, resp, "container", container) - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/container_pause.go b/vendor/github.com/docker/docker/client/container_pause.go deleted file mode 100644 index fa0a9011a3..0000000000 --- a/vendor/github.com/docker/docker/client/container_pause.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// ContainerPause pauses the main process of a given container without terminating it. -func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { - resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_prune.go b/vendor/github.com/docker/docker/client/container_prune.go deleted file mode 100644 index 4129841d49..0000000000 --- a/vendor/github.com/docker/docker/client/container_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// ContainersPrune requests the daemon to delete unused data -func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) { - var report types.ContainersPruneReport - - if err := cli.NewVersionError("1.25", "container prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) - if err != nil { - return report, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving disk usage: %v", err) - } - - return report, nil -} diff --git a/vendor/github.com/docker/docker/client/container_remove.go b/vendor/github.com/docker/docker/client/container_remove.go deleted file mode 100644 index c782914319..0000000000 --- a/vendor/github.com/docker/docker/client/container_remove.go +++ /dev/null @@ -1,27 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerRemove kills and removes a container from the docker host. -func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error { - query := url.Values{} - if options.RemoveVolumes { - query.Set("v", "1") - } - if options.RemoveLinks { - query.Set("link", "1") - } - - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "container", containerID) -} diff --git a/vendor/github.com/docker/docker/client/container_rename.go b/vendor/github.com/docker/docker/client/container_rename.go deleted file mode 100644 index ad43e398d5..0000000000 --- a/vendor/github.com/docker/docker/client/container_rename.go +++ /dev/null @@ -1,16 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "golang.org/x/net/context" -) - -// ContainerRename changes the name of a given container. -func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error { - query := url.Values{} - query.Set("name", newContainerName) - resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_resize.go b/vendor/github.com/docker/docker/client/container_resize.go deleted file mode 100644 index 8f1244e228..0000000000 --- a/vendor/github.com/docker/docker/client/container_resize.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerResize changes the size of the tty for a container. -func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error { - return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width) -} - -// ContainerExecResize changes the size of the tty for an exec process running inside a container. -func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error { - return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width) -} - -func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error { - query := url.Values{} - query.Set("h", strconv.Itoa(int(height))) - query.Set("w", strconv.Itoa(int(width))) - - resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_restart.go b/vendor/github.com/docker/docker/client/container_restart.go deleted file mode 100644 index 8c8085dcf2..0000000000 --- a/vendor/github.com/docker/docker/client/container_restart.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "time" - - timetypes "github.com/docker/docker/api/types/time" - "golang.org/x/net/context" -) - -// ContainerRestart stops and starts a container again. -// It makes the daemon to wait for the container to be up again for -// a specific amount of time, given the timeout. -func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout *time.Duration) error { - query := url.Values{} - if timeout != nil { - query.Set("t", timetypes.DurationToSecondsString(*timeout)) - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_start.go b/vendor/github.com/docker/docker/client/container_start.go deleted file mode 100644 index d06b637003..0000000000 --- a/vendor/github.com/docker/docker/client/container_start.go +++ /dev/null @@ -1,24 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" -) - -// ContainerStart sends a request to the docker daemon to start a container. -func (cli *Client) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error { - query := url.Values{} - if len(options.CheckpointID) != 0 { - query.Set("checkpoint", options.CheckpointID) - } - if len(options.CheckpointDir) != 0 { - query.Set("checkpoint-dir", options.CheckpointDir) - } - - resp, err := cli.post(ctx, "/containers/"+containerID+"/start", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_stats.go b/vendor/github.com/docker/docker/client/container_stats.go deleted file mode 100644 index a7a2b8ec35..0000000000 --- a/vendor/github.com/docker/docker/client/container_stats.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ContainerStats returns near realtime stats for a given container. -// It's up to the caller to close the io.ReadCloser returned. -func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (types.ContainerStats, error) { - query := url.Values{} - query.Set("stream", "0") - if stream { - query.Set("stream", "1") - } - - resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil) - if err != nil { - return types.ContainerStats{}, err - } - - osType := getDockerOS(resp.header.Get("Server")) - return types.ContainerStats{Body: resp.body, OSType: osType}, err -} diff --git a/vendor/github.com/docker/docker/client/container_stop.go b/vendor/github.com/docker/docker/client/container_stop.go deleted file mode 100644 index ca316666a9..0000000000 --- a/vendor/github.com/docker/docker/client/container_stop.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "time" - - timetypes "github.com/docker/docker/api/types/time" - "golang.org/x/net/context" -) - -// ContainerStop stops a container without terminating the process. -// The process is blocked until the container stops or the timeout expires. -func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error { - query := url.Values{} - if timeout != nil { - query.Set("t", timetypes.DurationToSecondsString(*timeout)) - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_top.go b/vendor/github.com/docker/docker/client/container_top.go deleted file mode 100644 index 55841ce998..0000000000 --- a/vendor/github.com/docker/docker/client/container_top.go +++ /dev/null @@ -1,28 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - "strings" - - "github.com/docker/docker/api/types/container" - "golang.org/x/net/context" -) - -// ContainerTop shows process information from within a container. -func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.ContainerTopOKBody, error) { - var response container.ContainerTopOKBody - query := url.Values{} - if len(arguments) > 0 { - query.Set("ps_args", strings.Join(arguments, " ")) - } - - resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_unpause.go b/vendor/github.com/docker/docker/client/container_unpause.go deleted file mode 100644 index b75fb0c31e..0000000000 --- a/vendor/github.com/docker/docker/client/container_unpause.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// ContainerUnpause resumes the process execution within a container -func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { - resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_update.go b/vendor/github.com/docker/docker/client/container_update.go deleted file mode 100644 index 218ec90fd9..0000000000 --- a/vendor/github.com/docker/docker/client/container_update.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types/container" - "golang.org/x/net/context" -) - -// ContainerUpdate updates resources of a container -func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { - var response container.ContainerUpdateOKBody - serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(serverResp.body).Decode(&response) - - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_wait.go b/vendor/github.com/docker/docker/client/container_wait.go deleted file mode 100644 index 87b0dc1afd..0000000000 --- a/vendor/github.com/docker/docker/client/container_wait.go +++ /dev/null @@ -1,84 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/versions" -) - -// ContainerWait waits until the specified container is in a certain state -// indicated by the given condition, either "not-running" (default), -// "next-exit", or "removed". -// -// If this client's API version is before 1.30, condition is ignored and -// ContainerWait will return immediately with the two channels, as the server -// will wait as if the condition were "not-running". -// -// If this client's API version is at least 1.30, ContainerWait blocks until -// the request has been acknowledged by the server (with a response header), -// then returns two channels on which the caller can wait for the exit status -// of the container or an error if there was a problem either beginning the -// wait request or in getting the response. This allows the caller to -// synchronize ContainerWait with other calls, such as specifying a -// "next-exit" condition before issuing a ContainerStart request. -func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) { - if versions.LessThan(cli.ClientVersion(), "1.30") { - return cli.legacyContainerWait(ctx, containerID) - } - - resultC := make(chan container.ContainerWaitOKBody) - errC := make(chan error, 1) - - query := url.Values{} - query.Set("condition", string(condition)) - - resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", query, nil, nil) - if err != nil { - defer ensureReaderClosed(resp) - errC <- err - return resultC, errC - } - - go func() { - defer ensureReaderClosed(resp) - var res container.ContainerWaitOKBody - if err := json.NewDecoder(resp.body).Decode(&res); err != nil { - errC <- err - return - } - - resultC <- res - }() - - return resultC, errC -} - -// legacyContainerWait returns immediately and doesn't have an option to wait -// until the container is removed. -func (cli *Client) legacyContainerWait(ctx context.Context, containerID string) (<-chan container.ContainerWaitOKBody, <-chan error) { - resultC := make(chan container.ContainerWaitOKBody) - errC := make(chan error) - - go func() { - resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil) - if err != nil { - errC <- err - return - } - defer ensureReaderClosed(resp) - - var res container.ContainerWaitOKBody - if err := json.NewDecoder(resp.body).Decode(&res); err != nil { - errC <- err - return - } - - resultC <- res - }() - - return resultC, errC -} diff --git a/vendor/github.com/docker/docker/client/disk_usage.go b/vendor/github.com/docker/docker/client/disk_usage.go deleted file mode 100644 index 831fd40e62..0000000000 --- a/vendor/github.com/docker/docker/client/disk_usage.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// DiskUsage requests the current data usage from the daemon -func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) { - var du types.DiskUsage - - serverResp, err := cli.get(ctx, "/system/df", nil, nil) - if err != nil { - return du, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil { - return du, fmt.Errorf("Error retrieving disk usage: %v", err) - } - - return du, nil -} diff --git a/vendor/github.com/docker/docker/client/distribution_inspect.go b/vendor/github.com/docker/docker/client/distribution_inspect.go deleted file mode 100644 index 5f55945c41..0000000000 --- a/vendor/github.com/docker/docker/client/distribution_inspect.go +++ /dev/null @@ -1,35 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - registrytypes "github.com/docker/docker/api/types/registry" - "golang.org/x/net/context" -) - -// DistributionInspect returns the image digest with full Manifest -func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) { - // Contact the registry to retrieve digest and platform information - var distributionInspect registrytypes.DistributionInspect - - if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil { - return distributionInspect, err - } - var headers map[string][]string - - if encodedRegistryAuth != "" { - headers = map[string][]string{ - "X-Registry-Auth": {encodedRegistryAuth}, - } - } - - resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers) - if err != nil { - return distributionInspect, err - } - - err = json.NewDecoder(resp.body).Decode(&distributionInspect) - ensureReaderClosed(resp) - return distributionInspect, err -} diff --git a/vendor/github.com/docker/docker/client/errors.go b/vendor/github.com/docker/docker/client/errors.go deleted file mode 100644 index 05c1246276..0000000000 --- a/vendor/github.com/docker/docker/client/errors.go +++ /dev/null @@ -1,133 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "fmt" - - "net/http" - - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" -) - -// errConnectionFailed implements an error returned when connection failed. -type errConnectionFailed struct { - host string -} - -// Error returns a string representation of an errConnectionFailed -func (err errConnectionFailed) Error() string { - if err.host == "" { - return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?" - } - return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host) -} - -// IsErrConnectionFailed returns true if the error is caused by connection failed. -func IsErrConnectionFailed(err error) bool { - _, ok := errors.Cause(err).(errConnectionFailed) - return ok -} - -// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed. -func ErrorConnectionFailed(host string) error { - return errConnectionFailed{host: host} -} - -type notFound interface { - error - NotFound() bool // Is the error a NotFound error -} - -// IsErrNotFound returns true if the error is a NotFound error, which is returned -// by the API when some object is not found. -func IsErrNotFound(err error) bool { - te, ok := err.(notFound) - return ok && te.NotFound() -} - -type objectNotFoundError struct { - object string - id string -} - -func (e objectNotFoundError) NotFound() bool { - return true -} - -func (e objectNotFoundError) Error() string { - return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) -} - -func wrapResponseError(err error, resp serverResponse, object, id string) error { - switch { - case err == nil: - return nil - case resp.statusCode == http.StatusNotFound: - return objectNotFoundError{object: object, id: id} - case resp.statusCode == http.StatusNotImplemented: - return notImplementedError{message: err.Error()} - default: - return err - } -} - -// unauthorizedError represents an authorization error in a remote registry. -type unauthorizedError struct { - cause error -} - -// Error returns a string representation of an unauthorizedError -func (u unauthorizedError) Error() string { - return u.cause.Error() -} - -// IsErrUnauthorized returns true if the error is caused -// when a remote registry authentication fails -func IsErrUnauthorized(err error) bool { - _, ok := err.(unauthorizedError) - return ok -} - -type pluginPermissionDenied struct { - name string -} - -func (e pluginPermissionDenied) Error() string { - return "Permission denied while installing plugin " + e.name -} - -// IsErrPluginPermissionDenied returns true if the error is caused -// when a user denies a plugin's permissions -func IsErrPluginPermissionDenied(err error) bool { - _, ok := err.(pluginPermissionDenied) - return ok -} - -type notImplementedError struct { - message string -} - -func (e notImplementedError) Error() string { - return e.message -} - -func (e notImplementedError) NotImplemented() bool { - return true -} - -// IsErrNotImplemented returns true if the error is a NotImplemented error. -// This is returned by the API when a requested feature has not been -// implemented. -func IsErrNotImplemented(err error) bool { - te, ok := err.(notImplementedError) - return ok && te.NotImplemented() -} - -// NewVersionError returns an error if the APIVersion required -// if less than the current supported version -func (cli *Client) NewVersionError(APIrequired, feature string) error { - if cli.version != "" && versions.LessThan(cli.version, APIrequired) { - return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version) - } - return nil -} diff --git a/vendor/github.com/docker/docker/client/events.go b/vendor/github.com/docker/docker/client/events.go deleted file mode 100644 index d5d4dd8ac2..0000000000 --- a/vendor/github.com/docker/docker/client/events.go +++ /dev/null @@ -1,102 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - timetypes "github.com/docker/docker/api/types/time" -) - -// Events returns a stream of events in the daemon. It's up to the caller to close the stream -// by cancelling the context. Once the stream has been completely read an io.EOF error will -// be sent over the error channel. If an error is sent all processing will be stopped. It's up -// to the caller to reopen the stream in the event of an error by reinvoking this method. -func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) { - - messages := make(chan events.Message) - errs := make(chan error, 1) - - started := make(chan struct{}) - go func() { - defer close(errs) - - query, err := buildEventsQueryParams(cli.version, options) - if err != nil { - close(started) - errs <- err - return - } - - resp, err := cli.get(ctx, "/events", query, nil) - if err != nil { - close(started) - errs <- err - return - } - defer resp.body.Close() - - decoder := json.NewDecoder(resp.body) - - close(started) - for { - select { - case <-ctx.Done(): - errs <- ctx.Err() - return - default: - var event events.Message - if err := decoder.Decode(&event); err != nil { - errs <- err - return - } - - select { - case messages <- event: - case <-ctx.Done(): - errs <- ctx.Err() - return - } - } - } - }() - <-started - - return messages, errs -} - -func buildEventsQueryParams(cliVersion string, options types.EventsOptions) (url.Values, error) { - query := url.Values{} - ref := time.Now() - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, ref) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Until != "" { - ts, err := timetypes.GetTimestamp(options.Until, ref) - if err != nil { - return nil, err - } - query.Set("until", ts) - } - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cliVersion, options.Filters) - if err != nil { - return nil, err - } - query.Set("filters", filterJSON) - } - - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go deleted file mode 100644 index 628adfda65..0000000000 --- a/vendor/github.com/docker/docker/client/hijack.go +++ /dev/null @@ -1,207 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bufio" - "crypto/tls" - "fmt" - "net" - "net/http" - "net/http/httputil" - "net/url" - "strings" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/go-connections/sockets" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// tlsClientCon holds tls information and a dialed connection. -type tlsClientCon struct { - *tls.Conn - rawConn net.Conn -} - -func (c *tlsClientCon) CloseWrite() error { - // Go standard tls.Conn doesn't provide the CloseWrite() method so we do it - // on its underlying connection. - if conn, ok := c.rawConn.(types.CloseWriter); ok { - return conn.CloseWrite() - } - return nil -} - -// postHijacked sends a POST request and hijacks the connection. -func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) { - bodyEncoded, err := encodeData(body) - if err != nil { - return types.HijackedResponse{}, err - } - - apiPath := cli.getAPIPath(path, query) - req, err := http.NewRequest("POST", apiPath, bodyEncoded) - if err != nil { - return types.HijackedResponse{}, err - } - req = cli.addHeaders(req, headers) - - conn, err := cli.setupHijackConn(req, "tcp") - if err != nil { - return types.HijackedResponse{}, err - } - - return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err -} - -func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) { - return tlsDialWithDialer(new(net.Dialer), network, addr, config) -} - -// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in -// order to return our custom tlsClientCon struct which holds both the tls.Conn -// object _and_ its underlying raw connection. The rationale for this is that -// we need to be able to close the write end of the connection when attaching, -// which tls.Conn does not provide. -func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) { - // We want the Timeout and Deadline values from dialer to cover the - // whole process: TCP connection and TLS handshake. This means that we - // also need to start our own timers now. - timeout := dialer.Timeout - - if !dialer.Deadline.IsZero() { - deadlineTimeout := time.Until(dialer.Deadline) - if timeout == 0 || deadlineTimeout < timeout { - timeout = deadlineTimeout - } - } - - var errChannel chan error - - if timeout != 0 { - errChannel = make(chan error, 2) - time.AfterFunc(timeout, func() { - errChannel <- errors.New("") - }) - } - - proxyDialer, err := sockets.DialerFromEnvironment(dialer) - if err != nil { - return nil, err - } - - rawConn, err := proxyDialer.Dial(network, addr) - if err != nil { - return nil, err - } - // When we set up a TCP connection for hijack, there could be long periods - // of inactivity (a long running command with no output) that in certain - // network setups may cause ECONNTIMEOUT, leaving the client in an unknown - // state. Setting TCP KeepAlive on the socket connection will prohibit - // ECONNTIMEOUT unless the socket connection truly is broken - if tcpConn, ok := rawConn.(*net.TCPConn); ok { - tcpConn.SetKeepAlive(true) - tcpConn.SetKeepAlivePeriod(30 * time.Second) - } - - colonPos := strings.LastIndex(addr, ":") - if colonPos == -1 { - colonPos = len(addr) - } - hostname := addr[:colonPos] - - // If no ServerName is set, infer the ServerName - // from the hostname we're connecting to. - if config.ServerName == "" { - // Make a copy to avoid polluting argument or default. - config = tlsConfigClone(config) - config.ServerName = hostname - } - - conn := tls.Client(rawConn, config) - - if timeout == 0 { - err = conn.Handshake() - } else { - go func() { - errChannel <- conn.Handshake() - }() - - err = <-errChannel - } - - if err != nil { - rawConn.Close() - return nil, err - } - - // This is Docker difference with standard's crypto/tls package: returned a - // wrapper which holds both the TLS and raw connections. - return &tlsClientCon{conn, rawConn}, nil -} - -func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { - if tlsConfig != nil && proto != "unix" && proto != "npipe" { - // Notice this isn't Go standard's tls.Dial function - return tlsDial(proto, addr, tlsConfig) - } - if proto == "npipe" { - return sockets.DialPipe(addr, 32*time.Second) - } - return net.Dial(proto, addr) -} - -func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, error) { - req.Host = cli.addr - req.Header.Set("Connection", "Upgrade") - req.Header.Set("Upgrade", proto) - - conn, err := dial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport)) - if err != nil { - return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") - } - - // When we set up a TCP connection for hijack, there could be long periods - // of inactivity (a long running command with no output) that in certain - // network setups may cause ECONNTIMEOUT, leaving the client in an unknown - // state. Setting TCP KeepAlive on the socket connection will prohibit - // ECONNTIMEOUT unless the socket connection truly is broken - if tcpConn, ok := conn.(*net.TCPConn); ok { - tcpConn.SetKeepAlive(true) - tcpConn.SetKeepAlivePeriod(30 * time.Second) - } - - clientconn := httputil.NewClientConn(conn, nil) - defer clientconn.Close() - - // Server hijacks the connection, error 'connection closed' expected - resp, err := clientconn.Do(req) - if err != httputil.ErrPersistEOF { - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusSwitchingProtocols { - resp.Body.Close() - return nil, fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode) - } - } - - c, br := clientconn.Hijack() - if br.Buffered() > 0 { - // If there is buffered content, wrap the connection - c = &hijackedConn{c, br} - } else { - br.Reset(nil) - } - - return c, nil -} - -type hijackedConn struct { - net.Conn - r *bufio.Reader -} - -func (c *hijackedConn) Read(b []byte) (int, error) { - return c.r.Read(b) -} diff --git a/vendor/github.com/docker/docker/client/image_build.go b/vendor/github.com/docker/docker/client/image_build.go deleted file mode 100644 index 97c9301c82..0000000000 --- a/vendor/github.com/docker/docker/client/image_build.go +++ /dev/null @@ -1,138 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/base64" - "encoding/json" - "io" - "net/http" - "net/url" - "strconv" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" -) - -// ImageBuild sends request to the daemon to build images. -// The Body in the response implement an io.ReadCloser and it's up to the caller to -// close it. -func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - query, err := cli.imageBuildOptionsToQuery(options) - if err != nil { - return types.ImageBuildResponse{}, err - } - - headers := http.Header(make(map[string][]string)) - buf, err := json.Marshal(options.AuthConfigs) - if err != nil { - return types.ImageBuildResponse{}, err - } - headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) - - if options.Platform != "" { - if err := cli.NewVersionError("1.32", "platform"); err != nil { - return types.ImageBuildResponse{}, err - } - query.Set("platform", options.Platform) - } - headers.Set("Content-Type", "application/x-tar") - - serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) - if err != nil { - return types.ImageBuildResponse{}, err - } - - osType := getDockerOS(serverResp.header.Get("Server")) - - return types.ImageBuildResponse{ - Body: serverResp.body, - OSType: osType, - }, nil -} - -func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) { - query := url.Values{ - "t": options.Tags, - "securityopt": options.SecurityOpt, - "extrahosts": options.ExtraHosts, - } - if options.SuppressOutput { - query.Set("q", "1") - } - if options.RemoteContext != "" { - query.Set("remote", options.RemoteContext) - } - if options.NoCache { - query.Set("nocache", "1") - } - if options.Remove { - query.Set("rm", "1") - } else { - query.Set("rm", "0") - } - - if options.ForceRemove { - query.Set("forcerm", "1") - } - - if options.PullParent { - query.Set("pull", "1") - } - - if options.Squash { - if err := cli.NewVersionError("1.25", "squash"); err != nil { - return query, err - } - query.Set("squash", "1") - } - - if !container.Isolation.IsDefault(options.Isolation) { - query.Set("isolation", string(options.Isolation)) - } - - query.Set("cpusetcpus", options.CPUSetCPUs) - query.Set("networkmode", options.NetworkMode) - query.Set("cpusetmems", options.CPUSetMems) - query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10)) - query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10)) - query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10)) - query.Set("memory", strconv.FormatInt(options.Memory, 10)) - query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10)) - query.Set("cgroupparent", options.CgroupParent) - query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10)) - query.Set("dockerfile", options.Dockerfile) - query.Set("target", options.Target) - - ulimitsJSON, err := json.Marshal(options.Ulimits) - if err != nil { - return query, err - } - query.Set("ulimits", string(ulimitsJSON)) - - buildArgsJSON, err := json.Marshal(options.BuildArgs) - if err != nil { - return query, err - } - query.Set("buildargs", string(buildArgsJSON)) - - labelsJSON, err := json.Marshal(options.Labels) - if err != nil { - return query, err - } - query.Set("labels", string(labelsJSON)) - - cacheFromJSON, err := json.Marshal(options.CacheFrom) - if err != nil { - return query, err - } - query.Set("cachefrom", string(cacheFromJSON)) - if options.SessionID != "" { - query.Set("session", options.SessionID) - } - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/image_create.go b/vendor/github.com/docker/docker/client/image_create.go deleted file mode 100644 index fe237508b1..0000000000 --- a/vendor/github.com/docker/docker/client/image_create.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImageCreate creates a new image based in the parent options. -// It returns the JSON content in the response body. -func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(parentReference) - if err != nil { - return nil, err - } - - query := url.Values{} - query.Set("fromImage", reference.FamiliarName(ref)) - query.Set("tag", getAPITagFromNamedRef(ref)) - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/images/create", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_history.go b/vendor/github.com/docker/docker/client/image_history.go deleted file mode 100644 index cf74723a03..0000000000 --- a/vendor/github.com/docker/docker/client/image_history.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/image" - "golang.org/x/net/context" -) - -// ImageHistory returns the changes in an image in history format. -func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) { - var history []image.HistoryResponseItem - serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil) - if err != nil { - return history, err - } - - err = json.NewDecoder(serverResp.body).Decode(&history) - ensureReaderClosed(serverResp) - return history, err -} diff --git a/vendor/github.com/docker/docker/client/image_import.go b/vendor/github.com/docker/docker/client/image_import.go deleted file mode 100644 index dddbf9c629..0000000000 --- a/vendor/github.com/docker/docker/client/image_import.go +++ /dev/null @@ -1,41 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImageImport creates a new image based in the source options. -// It returns the JSON content in the response body. -func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - if ref != "" { - //Check if the given image name can be resolved - if _, err := reference.ParseNormalizedNamed(ref); err != nil { - return nil, err - } - } - - query := url.Values{} - query.Set("fromSrc", source.SourceName) - query.Set("repo", ref) - query.Set("tag", options.Tag) - query.Set("message", options.Message) - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - for _, change := range options.Changes { - query.Add("changes", change) - } - - resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/image_inspect.go b/vendor/github.com/docker/docker/client/image_inspect.go deleted file mode 100644 index 75057bf324..0000000000 --- a/vendor/github.com/docker/docker/client/image_inspect.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ImageInspectWithRaw returns the image information and its raw representation. -func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { - serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) - if err != nil { - return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID) - } - defer ensureReaderClosed(serverResp) - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return types.ImageInspect{}, nil, err - } - - var response types.ImageInspect - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/image_list.go b/vendor/github.com/docker/docker/client/image_list.go deleted file mode 100644 index 1e84a962da..0000000000 --- a/vendor/github.com/docker/docker/client/image_list.go +++ /dev/null @@ -1,45 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/versions" - "golang.org/x/net/context" -) - -// ImageList returns a list of images in the docker host. -func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) { - var images []types.ImageSummary - query := url.Values{} - - optionFilters := options.Filters - referenceFilters := optionFilters.Get("reference") - if versions.LessThan(cli.version, "1.25") && len(referenceFilters) > 0 { - query.Set("filter", referenceFilters[0]) - for _, filterValue := range referenceFilters { - optionFilters.Del("reference", filterValue) - } - } - if optionFilters.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cli.version, optionFilters) - if err != nil { - return images, err - } - query.Set("filters", filterJSON) - } - if options.All { - query.Set("all", "1") - } - - serverResp, err := cli.get(ctx, "/images/json", query, nil) - if err != nil { - return images, err - } - - err = json.NewDecoder(serverResp.body).Decode(&images) - ensureReaderClosed(serverResp) - return images, err -} diff --git a/vendor/github.com/docker/docker/client/image_load.go b/vendor/github.com/docker/docker/client/image_load.go deleted file mode 100644 index 411567c0c9..0000000000 --- a/vendor/github.com/docker/docker/client/image_load.go +++ /dev/null @@ -1,30 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" -) - -// ImageLoad loads an image in the docker host from the client host. -// It's up to the caller to close the io.ReadCloser in the -// ImageLoadResponse returned by this function. -func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - v := url.Values{} - v.Set("quiet", "0") - if quiet { - v.Set("quiet", "1") - } - headers := map[string][]string{"Content-Type": {"application/x-tar"}} - resp, err := cli.postRaw(ctx, "/images/load", v, input, headers) - if err != nil { - return types.ImageLoadResponse{}, err - } - return types.ImageLoadResponse{ - Body: resp.body, - JSON: resp.header.Get("Content-Type") == "application/json", - }, nil -} diff --git a/vendor/github.com/docker/docker/client/image_prune.go b/vendor/github.com/docker/docker/client/image_prune.go deleted file mode 100644 index 32ea9098c3..0000000000 --- a/vendor/github.com/docker/docker/client/image_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// ImagesPrune requests the daemon to delete unused data -func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) { - var report types.ImagesPruneReport - - if err := cli.NewVersionError("1.25", "image prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) - if err != nil { - return report, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving disk usage: %v", err) - } - - return report, nil -} diff --git a/vendor/github.com/docker/docker/client/image_pull.go b/vendor/github.com/docker/docker/client/image_pull.go deleted file mode 100644 index ee5923a8f6..0000000000 --- a/vendor/github.com/docker/docker/client/image_pull.go +++ /dev/null @@ -1,65 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImagePull requests the docker host to pull an image from a remote registry. -// It executes the privileged function if the operation is unauthorized -// and it tries one more time. -// It's up to the caller to handle the io.ReadCloser and close it properly. -// -// FIXME(vdemeester): there is currently used in a few way in docker/docker -// - if not in trusted content, ref is used to pass the whole reference, and tag is empty -// - if in trusted content, ref is used to pass the reference name, and tag for the digest -func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(refStr) - if err != nil { - return nil, err - } - - query := url.Values{} - query.Set("fromImage", reference.FamiliarName(ref)) - if !options.All { - query.Set("tag", getAPITagFromNamedRef(ref)) - } - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - - resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) - if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return nil, privilegeErr - } - resp, err = cli.tryImageCreate(ctx, query, newAuthHeader) - } - if err != nil { - return nil, err - } - return resp.body, nil -} - -// getAPITagFromNamedRef returns a tag from the specified reference. -// This function is necessary as long as the docker "server" api expects -// digests to be sent as tags and makes a distinction between the name -// and tag/digest part of a reference. -func getAPITagFromNamedRef(ref reference.Named) string { - if digested, ok := ref.(reference.Digested); ok { - return digested.Digest().String() - } - ref = reference.TagNameOnly(ref) - if tagged, ok := ref.(reference.Tagged); ok { - return tagged.Tag() - } - return "" -} diff --git a/vendor/github.com/docker/docker/client/image_push.go b/vendor/github.com/docker/docker/client/image_push.go deleted file mode 100644 index 6fcc1626ec..0000000000 --- a/vendor/github.com/docker/docker/client/image_push.go +++ /dev/null @@ -1,56 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "errors" - "io" - "net/http" - "net/url" - - "golang.org/x/net/context" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImagePush requests the docker host to push an image to a remote registry. -// It executes the privileged function if the operation is unauthorized -// and it tries one more time. -// It's up to the caller to handle the io.ReadCloser and close it properly. -func (cli *Client) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(image) - if err != nil { - return nil, err - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return nil, errors.New("cannot push a digest reference") - } - - tag := "" - name := reference.FamiliarName(ref) - - if nameTaggedRef, isNamedTagged := ref.(reference.NamedTagged); isNamedTagged { - tag = nameTaggedRef.Tag() - } - - query := url.Values{} - query.Set("tag", tag) - - resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth) - if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return nil, privilegeErr - } - resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader) - } - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_remove.go b/vendor/github.com/docker/docker/client/image_remove.go deleted file mode 100644 index 6d222a5077..0000000000 --- a/vendor/github.com/docker/docker/client/image_remove.go +++ /dev/null @@ -1,31 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ImageRemove removes an image from the docker host. -func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - query := url.Values{} - - if options.Force { - query.Set("force", "1") - } - if !options.PruneChildren { - query.Set("noprune", "1") - } - - var dels []types.ImageDeleteResponseItem - resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) - if err != nil { - return dels, wrapResponseError(err, resp, "image", imageID) - } - - err = json.NewDecoder(resp.body).Decode(&dels) - ensureReaderClosed(resp) - return dels, err -} diff --git a/vendor/github.com/docker/docker/client/image_save.go b/vendor/github.com/docker/docker/client/image_save.go deleted file mode 100644 index a919615966..0000000000 --- a/vendor/github.com/docker/docker/client/image_save.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - - "golang.org/x/net/context" -) - -// ImageSave retrieves one or more images from the docker host as an io.ReadCloser. -// It's up to the caller to store the images and close the stream. -func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) { - query := url.Values{ - "names": imageIDs, - } - - resp, err := cli.get(ctx, "/images/get", query, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/image_search.go b/vendor/github.com/docker/docker/client/image_search.go deleted file mode 100644 index ba5072ad59..0000000000 --- a/vendor/github.com/docker/docker/client/image_search.go +++ /dev/null @@ -1,51 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - "net/http" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/registry" - "golang.org/x/net/context" -) - -// ImageSearch makes the docker host to search by a term in a remote registry. -// The list of results is not sorted in any fashion. -func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) { - var results []registry.SearchResult - query := url.Values{} - query.Set("term", term) - query.Set("limit", fmt.Sprintf("%d", options.Limit)) - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return results, err - } - query.Set("filters", filterJSON) - } - - resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) - if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return results, privilegeErr - } - resp, err = cli.tryImageSearch(ctx, query, newAuthHeader) - } - if err != nil { - return results, err - } - - err = json.NewDecoder(resp.body).Decode(&results) - ensureReaderClosed(resp) - return results, err -} - -func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.get(ctx, "/images/search", query, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_tag.go b/vendor/github.com/docker/docker/client/image_tag.go deleted file mode 100644 index 4399a3e9aa..0000000000 --- a/vendor/github.com/docker/docker/client/image_tag.go +++ /dev/null @@ -1,37 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/distribution/reference" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// ImageTag tags an image in the docker host -func (cli *Client) ImageTag(ctx context.Context, source, target string) error { - if _, err := reference.ParseAnyReference(source); err != nil { - return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", source) - } - - ref, err := reference.ParseNormalizedNamed(target) - if err != nil { - return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", target) - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return errors.New("refusing to create a tag with a digest reference") - } - - ref = reference.TagNameOnly(ref) - - query := url.Values{} - query.Set("repo", reference.FamiliarName(ref)) - if tagged, ok := ref.(reference.Tagged); ok { - query.Set("tag", tagged.Tag()) - } - - resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/info.go b/vendor/github.com/docker/docker/client/info.go deleted file mode 100644 index 3f6746c942..0000000000 --- a/vendor/github.com/docker/docker/client/info.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// Info returns information about the docker server. -func (cli *Client) Info(ctx context.Context) (types.Info, error) { - var info types.Info - serverResp, err := cli.get(ctx, "/info", url.Values{}, nil) - if err != nil { - return info, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil { - return info, fmt.Errorf("Error reading remote info: %v", err) - } - - return info, nil -} diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/interface.go deleted file mode 100644 index e928e647a7..0000000000 --- a/vendor/github.com/docker/docker/client/interface.go +++ /dev/null @@ -1,194 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net" - "time" - - "github.com/docker/docker/api/types" - containertypes "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/swarm" - volumetypes "github.com/docker/docker/api/types/volume" - "golang.org/x/net/context" -) - -// CommonAPIClient is the common methods between stable and experimental versions of APIClient. -type CommonAPIClient interface { - ConfigAPIClient - ContainerAPIClient - DistributionAPIClient - ImageAPIClient - NodeAPIClient - NetworkAPIClient - PluginAPIClient - ServiceAPIClient - SwarmAPIClient - SecretAPIClient - SystemAPIClient - VolumeAPIClient - ClientVersion() string - DaemonHost() string - ServerVersion(ctx context.Context) (types.Version, error) - NegotiateAPIVersion(ctx context.Context) - NegotiateAPIVersionPing(types.Ping) - DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) -} - -// ContainerAPIClient defines API client methods for the containers -type ContainerAPIClient interface { - ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) - ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) - ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, containerName string) (containertypes.ContainerCreateCreatedBody, error) - ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, error) - ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) - ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) - ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) - ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error - ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error - ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) - ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) - ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error) - ContainerKill(ctx context.Context, container, signal string) error - ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) - ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) - ContainerPause(ctx context.Context, container string) error - ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error - ContainerRename(ctx context.Context, container, newContainerName string) error - ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error - ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error - ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error) - ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error) - ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error - ContainerStop(ctx context.Context, container string, timeout *time.Duration) error - ContainerTop(ctx context.Context, container string, arguments []string) (containertypes.ContainerTopOKBody, error) - ContainerUnpause(ctx context.Context, container string) error - ContainerUpdate(ctx context.Context, container string, updateConfig containertypes.UpdateConfig) (containertypes.ContainerUpdateOKBody, error) - ContainerWait(ctx context.Context, container string, condition containertypes.WaitCondition) (<-chan containertypes.ContainerWaitOKBody, <-chan error) - CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) - CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error - ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) -} - -// DistributionAPIClient defines API client methods for the registry -type DistributionAPIClient interface { - DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error) -} - -// ImageAPIClient defines API client methods for the images -type ImageAPIClient interface { - ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) - BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) - ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) - ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) - ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) - ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) - ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) - ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) - ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) - ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) - ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) - ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) - ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) - ImageTag(ctx context.Context, image, ref string) error - ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error) -} - -// NetworkAPIClient defines API client methods for the networks -type NetworkAPIClient interface { - NetworkConnect(ctx context.Context, network, container string, config *networktypes.EndpointSettings) error - NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) - NetworkDisconnect(ctx context.Context, network, container string, force bool) error - NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error) - NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) - NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) - NetworkRemove(ctx context.Context, network string) error - NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) -} - -// NodeAPIClient defines API client methods for the nodes -type NodeAPIClient interface { - NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) - NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) - NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error - NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error -} - -// PluginAPIClient defines API client methods for the plugins -type PluginAPIClient interface { - PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) - PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error - PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error - PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error - PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) - PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) - PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) - PluginSet(ctx context.Context, name string, args []string) error - PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) - PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error -} - -// ServiceAPIClient defines API client methods for the services -type ServiceAPIClient interface { - ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) - ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) - ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) - ServiceRemove(ctx context.Context, serviceID string) error - ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) - TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error) - TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) - TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) -} - -// SwarmAPIClient defines API client methods for the swarm -type SwarmAPIClient interface { - SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) - SwarmJoin(ctx context.Context, req swarm.JoinRequest) error - SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) - SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error - SwarmLeave(ctx context.Context, force bool) error - SwarmInspect(ctx context.Context) (swarm.Swarm, error) - SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error -} - -// SystemAPIClient defines API client methods for the system -type SystemAPIClient interface { - Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) - Info(ctx context.Context) (types.Info, error) - RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) - DiskUsage(ctx context.Context) (types.DiskUsage, error) - Ping(ctx context.Context) (types.Ping, error) -} - -// VolumeAPIClient defines API client methods for the volumes -type VolumeAPIClient interface { - VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error) - VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) - VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) - VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error) - VolumeRemove(ctx context.Context, volumeID string, force bool) error - VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error) -} - -// SecretAPIClient defines API client methods for secrets -type SecretAPIClient interface { - SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) - SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) - SecretRemove(ctx context.Context, id string) error - SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) - SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error -} - -// ConfigAPIClient defines API client methods for configs -type ConfigAPIClient interface { - ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) - ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) - ConfigRemove(ctx context.Context, id string) error - ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error) - ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error -} diff --git a/vendor/github.com/docker/docker/client/interface_experimental.go b/vendor/github.com/docker/docker/client/interface_experimental.go deleted file mode 100644 index 236c1d6ca6..0000000000 --- a/vendor/github.com/docker/docker/client/interface_experimental.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -type apiClientExperimental interface { - CheckpointAPIClient -} - -// CheckpointAPIClient defines API client methods for the checkpoints -type CheckpointAPIClient interface { - CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error - CheckpointDelete(ctx context.Context, container string, options types.CheckpointDeleteOptions) error - CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) -} diff --git a/vendor/github.com/docker/docker/client/interface_stable.go b/vendor/github.com/docker/docker/client/interface_stable.go deleted file mode 100644 index 5502cd7426..0000000000 --- a/vendor/github.com/docker/docker/client/interface_stable.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -// APIClient is an interface that clients that talk with a docker server must implement. -type APIClient interface { - CommonAPIClient - apiClientExperimental -} - -// Ensure that Client always implements APIClient. -var _ APIClient = &Client{} diff --git a/vendor/github.com/docker/docker/client/login.go b/vendor/github.com/docker/docker/client/login.go deleted file mode 100644 index fefb101ade..0000000000 --- a/vendor/github.com/docker/docker/client/login.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/http" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/registry" - "golang.org/x/net/context" -) - -// RegistryLogin authenticates the docker server with a given docker registry. -// It returns unauthorizedError when the authentication fails. -func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { - resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) - - if resp.statusCode == http.StatusUnauthorized { - return registry.AuthenticateOKBody{}, unauthorizedError{err} - } - if err != nil { - return registry.AuthenticateOKBody{}, err - } - - var response registry.AuthenticateOKBody - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/network_connect.go b/vendor/github.com/docker/docker/client/network_connect.go deleted file mode 100644 index af4a61659b..0000000000 --- a/vendor/github.com/docker/docker/client/network_connect.go +++ /dev/null @@ -1,18 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" - "golang.org/x/net/context" -) - -// NetworkConnect connects a container to an existent network in the docker host. -func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error { - nc := types.NetworkConnect{ - Container: containerID, - EndpointConfig: config, - } - resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/network_create.go b/vendor/github.com/docker/docker/client/network_create.go deleted file mode 100644 index fa1d301a4c..0000000000 --- a/vendor/github.com/docker/docker/client/network_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// NetworkCreate creates a new network in the docker host. -func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { - networkCreateRequest := types.NetworkCreateRequest{ - NetworkCreate: options, - Name: name, - } - var response types.NetworkCreateResponse - serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) - if err != nil { - return response, err - } - - json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/network_disconnect.go b/vendor/github.com/docker/docker/client/network_disconnect.go deleted file mode 100644 index 5fc75a9412..0000000000 --- a/vendor/github.com/docker/docker/client/network_disconnect.go +++ /dev/null @@ -1,14 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// NetworkDisconnect disconnects a container from an existent network in the docker host. -func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error { - nd := types.NetworkDisconnect{Container: containerID, Force: force} - resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/network_inspect.go b/vendor/github.com/docker/docker/client/network_inspect.go deleted file mode 100644 index 3308f18ded..0000000000 --- a/vendor/github.com/docker/docker/client/network_inspect.go +++ /dev/null @@ -1,46 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// NetworkInspect returns the information for a specific network configured in the docker host. -func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, error) { - networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID, options) - return networkResource, err -} - -// NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation. -func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) { - var ( - networkResource types.NetworkResource - resp serverResponse - err error - ) - query := url.Values{} - if options.Verbose { - query.Set("verbose", "true") - } - if options.Scope != "" { - query.Set("scope", options.Scope) - } - resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) - if err != nil { - return networkResource, nil, wrapResponseError(err, resp, "network", networkID) - } - defer ensureReaderClosed(resp) - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return networkResource, nil, err - } - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&networkResource) - return networkResource, body, err -} diff --git a/vendor/github.com/docker/docker/client/network_list.go b/vendor/github.com/docker/docker/client/network_list.go deleted file mode 100644 index 9b424285eb..0000000000 --- a/vendor/github.com/docker/docker/client/network_list.go +++ /dev/null @@ -1,31 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// NetworkList returns the list of networks configured in the docker host. -func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - query := url.Values{} - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - var networkResources []types.NetworkResource - resp, err := cli.get(ctx, "/networks", query, nil) - if err != nil { - return networkResources, err - } - err = json.NewDecoder(resp.body).Decode(&networkResources) - ensureReaderClosed(resp) - return networkResources, err -} diff --git a/vendor/github.com/docker/docker/client/network_prune.go b/vendor/github.com/docker/docker/client/network_prune.go deleted file mode 100644 index d546f0c304..0000000000 --- a/vendor/github.com/docker/docker/client/network_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// NetworksPrune requests the daemon to delete unused networks -func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) { - var report types.NetworksPruneReport - - if err := cli.NewVersionError("1.25", "network prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) - if err != nil { - return report, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving network prune report: %v", err) - } - - return report, nil -} diff --git a/vendor/github.com/docker/docker/client/network_remove.go b/vendor/github.com/docker/docker/client/network_remove.go deleted file mode 100644 index c99de10c83..0000000000 --- a/vendor/github.com/docker/docker/client/network_remove.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// NetworkRemove removes an existent network from the docker host. -func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { - resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "network", networkID) -} diff --git a/vendor/github.com/docker/docker/client/node_inspect.go b/vendor/github.com/docker/docker/client/node_inspect.go deleted file mode 100644 index 454db9f17b..0000000000 --- a/vendor/github.com/docker/docker/client/node_inspect.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// NodeInspectWithRaw returns the node information. -func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { - serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) - if err != nil { - return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) - } - defer ensureReaderClosed(serverResp) - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Node{}, nil, err - } - - var response swarm.Node - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/node_list.go b/vendor/github.com/docker/docker/client/node_list.go deleted file mode 100644 index c613ad2197..0000000000 --- a/vendor/github.com/docker/docker/client/node_list.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// NodeList returns the list of nodes. -func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/nodes", query, nil) - if err != nil { - return nil, err - } - - var nodes []swarm.Node - err = json.NewDecoder(resp.body).Decode(&nodes) - ensureReaderClosed(resp) - return nodes, err -} diff --git a/vendor/github.com/docker/docker/client/node_remove.go b/vendor/github.com/docker/docker/client/node_remove.go deleted file mode 100644 index 7c1a757d31..0000000000 --- a/vendor/github.com/docker/docker/client/node_remove.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - - "golang.org/x/net/context" -) - -// NodeRemove removes a Node. -func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "node", nodeID) -} diff --git a/vendor/github.com/docker/docker/client/node_update.go b/vendor/github.com/docker/docker/client/node_update.go deleted file mode 100644 index 0b528a4703..0000000000 --- a/vendor/github.com/docker/docker/client/node_update.go +++ /dev/null @@ -1,18 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// NodeUpdate updates a Node. -func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, node, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/ping.go b/vendor/github.com/docker/docker/client/ping.go deleted file mode 100644 index e2366276da..0000000000 --- a/vendor/github.com/docker/docker/client/ping.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "path" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// Ping pings the server and returns the value of the "Docker-Experimental", "OS-Type" & "API-Version" headers -func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { - var ping types.Ping - req, err := cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil) - if err != nil { - return ping, err - } - serverResp, err := cli.doRequest(ctx, req) - if err != nil { - return ping, err - } - defer ensureReaderClosed(serverResp) - - if serverResp.header != nil { - ping.APIVersion = serverResp.header.Get("API-Version") - - if serverResp.header.Get("Docker-Experimental") == "true" { - ping.Experimental = true - } - ping.OSType = serverResp.header.Get("OSType") - } - return ping, cli.checkResponseErr(serverResp) -} diff --git a/vendor/github.com/docker/docker/client/plugin_create.go b/vendor/github.com/docker/docker/client/plugin_create.go deleted file mode 100644 index 51ef9c9945..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_create.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/http" - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// PluginCreate creates a plugin -func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error { - headers := http.Header(make(map[string][]string)) - headers.Set("Content-Type", "application/x-tar") - - query := url.Values{} - query.Set("name", createOptions.RepoName) - - resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers) - if err != nil { - return err - } - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_disable.go b/vendor/github.com/docker/docker/client/plugin_disable.go deleted file mode 100644 index 8d8c41d226..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_disable.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// PluginDisable disables a plugin -func (cli *Client) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - resp, err := cli.post(ctx, "/plugins/"+name+"/disable", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_enable.go b/vendor/github.com/docker/docker/client/plugin_enable.go deleted file mode 100644 index 1f0f8f7340..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_enable.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// PluginEnable enables a plugin -func (cli *Client) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error { - query := url.Values{} - query.Set("timeout", strconv.Itoa(options.Timeout)) - - resp, err := cli.post(ctx, "/plugins/"+name+"/enable", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go deleted file mode 100644 index 8957a805ec..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_inspect.go +++ /dev/null @@ -1,28 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// PluginInspectWithRaw inspects an existing plugin -func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { - resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) - if err != nil { - return nil, nil, wrapResponseError(err, resp, "plugin", name) - } - - defer ensureReaderClosed(resp) - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return nil, nil, err - } - var p types.Plugin - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&p) - return &p, body, err -} diff --git a/vendor/github.com/docker/docker/client/plugin_install.go b/vendor/github.com/docker/docker/client/plugin_install.go deleted file mode 100644 index ae04387d5d..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_install.go +++ /dev/null @@ -1,113 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "io" - "net/http" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// PluginInstall installs a plugin -func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { - query := url.Values{} - if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil { - return nil, errors.Wrap(err, "invalid remote reference") - } - query.Set("remote", options.RemoteRef) - - privileges, err := cli.checkPluginPermissions(ctx, query, options) - if err != nil { - return nil, err - } - - // set name for plugin pull, if empty should default to remote reference - query.Set("name", name) - - resp, err := cli.tryPluginPull(ctx, query, privileges, options.RegistryAuth) - if err != nil { - return nil, err - } - - name = resp.header.Get("Docker-Plugin-Name") - - pr, pw := io.Pipe() - go func() { // todo: the client should probably be designed more around the actual api - _, err := io.Copy(pw, resp.body) - if err != nil { - pw.CloseWithError(err) - return - } - defer func() { - if err != nil { - delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil) - ensureReaderClosed(delResp) - } - }() - if len(options.Args) > 0 { - if err := cli.PluginSet(ctx, name, options.Args); err != nil { - pw.CloseWithError(err) - return - } - } - - if options.Disabled { - pw.Close() - return - } - - enableErr := cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0}) - pw.CloseWithError(enableErr) - }() - return pr, nil -} - -func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.get(ctx, "/plugins/privileges", query, headers) -} - -func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/plugins/pull", query, privileges, headers) -} - -func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) { - resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) - if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { - // todo: do inspect before to check existing name before checking privileges - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - ensureReaderClosed(resp) - return nil, privilegeErr - } - options.RegistryAuth = newAuthHeader - resp, err = cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) - } - if err != nil { - ensureReaderClosed(resp) - return nil, err - } - - var privileges types.PluginPrivileges - if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil { - ensureReaderClosed(resp) - return nil, err - } - ensureReaderClosed(resp) - - if !options.AcceptAllPermissions && options.AcceptPermissionsFunc != nil && len(privileges) > 0 { - accept, err := options.AcceptPermissionsFunc(privileges) - if err != nil { - return nil, err - } - if !accept { - return nil, pluginPermissionDenied{options.RemoteRef} - } - } - return privileges, nil -} diff --git a/vendor/github.com/docker/docker/client/plugin_list.go b/vendor/github.com/docker/docker/client/plugin_list.go deleted file mode 100644 index e49876621d..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_list.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// PluginList returns the installed plugins -func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) { - var plugins types.PluginsListResponse - query := url.Values{} - - if filter.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cli.version, filter) - if err != nil { - return plugins, err - } - query.Set("filters", filterJSON) - } - resp, err := cli.get(ctx, "/plugins", query, nil) - if err != nil { - return plugins, wrapResponseError(err, resp, "plugin", "") - } - - err = json.NewDecoder(resp.body).Decode(&plugins) - ensureReaderClosed(resp) - return plugins, err -} diff --git a/vendor/github.com/docker/docker/client/plugin_push.go b/vendor/github.com/docker/docker/client/plugin_push.go deleted file mode 100644 index 33b38d843c..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_push.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - - "golang.org/x/net/context" -) - -// PluginPush pushes a plugin to a registry -func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/plugin_remove.go b/vendor/github.com/docker/docker/client/plugin_remove.go deleted file mode 100644 index b9e7d8e4a8..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_remove.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// PluginRemove removes a plugin -func (cli *Client) PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "plugin", name) -} diff --git a/vendor/github.com/docker/docker/client/plugin_set.go b/vendor/github.com/docker/docker/client/plugin_set.go deleted file mode 100644 index de72cc0d3a..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_set.go +++ /dev/null @@ -1,12 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "golang.org/x/net/context" -) - -// PluginSet modifies settings for an existing plugin -func (cli *Client) PluginSet(ctx context.Context, name string, args []string) error { - resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, args, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_upgrade.go b/vendor/github.com/docker/docker/client/plugin_upgrade.go deleted file mode 100644 index 33b740ca76..0000000000 --- a/vendor/github.com/docker/docker/client/plugin_upgrade.go +++ /dev/null @@ -1,39 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// PluginUpgrade upgrades a plugin -func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { - if err := cli.NewVersionError("1.26", "plugin upgrade"); err != nil { - return nil, err - } - query := url.Values{} - if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil { - return nil, errors.Wrap(err, "invalid remote reference") - } - query.Set("remote", options.RemoteRef) - - privileges, err := cli.checkPluginPermissions(ctx, query, options) - if err != nil { - return nil, err - } - - resp, err := cli.tryPluginUpgrade(ctx, query, privileges, name, options.RegistryAuth) - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, headers) -} diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go deleted file mode 100644 index 986b512dda..0000000000 --- a/vendor/github.com/docker/docker/client/request.go +++ /dev/null @@ -1,262 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "os" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "golang.org/x/net/context" - "golang.org/x/net/context/ctxhttp" -) - -// serverResponse is a wrapper for http API responses. -type serverResponse struct { - body io.ReadCloser - header http.Header - statusCode int - reqURL *url.URL -} - -// head sends an http request to the docker API using the method HEAD. -func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, "HEAD", path, query, nil, headers) -} - -// get sends an http request to the docker API using the method GET with a specific Go context. -func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, "GET", path, query, nil, headers) -} - -// post sends an http request to the docker API using the method POST with a specific Go context. -func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) { - body, headers, err := encodeBody(obj, headers) - if err != nil { - return serverResponse{}, err - } - return cli.sendRequest(ctx, "POST", path, query, body, headers) -} - -func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, "POST", path, query, body, headers) -} - -// put sends an http request to the docker API using the method PUT. -func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) { - body, headers, err := encodeBody(obj, headers) - if err != nil { - return serverResponse{}, err - } - return cli.sendRequest(ctx, "PUT", path, query, body, headers) -} - -// putRaw sends an http request to the docker API using the method PUT. -func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, "PUT", path, query, body, headers) -} - -// delete sends an http request to the docker API using the method DELETE. -func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, "DELETE", path, query, nil, headers) -} - -type headers map[string][]string - -func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) { - if obj == nil { - return nil, headers, nil - } - - body, err := encodeData(obj) - if err != nil { - return nil, headers, err - } - if headers == nil { - headers = make(map[string][]string) - } - headers["Content-Type"] = []string{"application/json"} - return body, headers, nil -} - -func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) { - expectedPayload := (method == "POST" || method == "PUT") - if expectedPayload && body == nil { - body = bytes.NewReader([]byte{}) - } - - req, err := http.NewRequest(method, path, body) - if err != nil { - return nil, err - } - req = cli.addHeaders(req, headers) - - if cli.proto == "unix" || cli.proto == "npipe" { - // For local communications, it doesn't matter what the host is. We just - // need a valid and meaningful host name. (See #189) - req.Host = "docker" - } - - req.URL.Host = cli.addr - req.URL.Scheme = cli.scheme - - if expectedPayload && req.Header.Get("Content-Type") == "" { - req.Header.Set("Content-Type", "text/plain") - } - return req, nil -} - -func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) { - req, err := cli.buildRequest(method, cli.getAPIPath(path, query), body, headers) - if err != nil { - return serverResponse{}, err - } - resp, err := cli.doRequest(ctx, req) - if err != nil { - return resp, err - } - if err := cli.checkResponseErr(resp); err != nil { - return resp, err - } - return resp, nil -} - -func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) { - serverResp := serverResponse{statusCode: -1, reqURL: req.URL} - - resp, err := ctxhttp.Do(ctx, cli.client, req) - if err != nil { - if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { - return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) - } - - if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") { - return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err) - } - - // Don't decorate context sentinel errors; users may be comparing to - // them directly. - switch err { - case context.Canceled, context.DeadlineExceeded: - return serverResp, err - } - - if nErr, ok := err.(*url.Error); ok { - if nErr, ok := nErr.Err.(*net.OpError); ok { - if os.IsPermission(nErr.Err) { - return serverResp, errors.Wrapf(err, "Got permission denied while trying to connect to the Docker daemon socket at %v", cli.host) - } - } - } - - if err, ok := err.(net.Error); ok { - if err.Timeout() { - return serverResp, ErrorConnectionFailed(cli.host) - } - if !err.Temporary() { - if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") { - return serverResp, ErrorConnectionFailed(cli.host) - } - } - } - - // Although there's not a strongly typed error for this in go-winio, - // lots of people are using the default configuration for the docker - // daemon on Windows where the daemon is listening on a named pipe - // `//./pipe/docker_engine, and the client must be running elevated. - // Give users a clue rather than the not-overly useful message - // such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info: - // open //./pipe/docker_engine: The system cannot find the file specified.`. - // Note we can't string compare "The system cannot find the file specified" as - // this is localised - for example in French the error would be - // `open //./pipe/docker_engine: Le fichier spécifié est introuvable.` - if strings.Contains(err.Error(), `open //./pipe/docker_engine`) { - err = errors.New(err.Error() + " In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.") - } - - return serverResp, errors.Wrap(err, "error during connect") - } - - if resp != nil { - serverResp.statusCode = resp.StatusCode - serverResp.body = resp.Body - serverResp.header = resp.Header - } - return serverResp, nil -} - -func (cli *Client) checkResponseErr(serverResp serverResponse) error { - if serverResp.statusCode >= 200 && serverResp.statusCode < 400 { - return nil - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return err - } - if len(body) == 0 { - return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) - } - - var ct string - if serverResp.header != nil { - ct = serverResp.header.Get("Content-Type") - } - - var errorMessage string - if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" { - var errorResponse types.ErrorResponse - if err := json.Unmarshal(body, &errorResponse); err != nil { - return fmt.Errorf("Error reading JSON: %v", err) - } - errorMessage = errorResponse.Message - } else { - errorMessage = string(body) - } - - return fmt.Errorf("Error response from daemon: %s", strings.TrimSpace(errorMessage)) -} - -func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request { - // Add CLI Config's HTTP Headers BEFORE we set the Docker headers - // then the user can't change OUR headers - for k, v := range cli.customHTTPHeaders { - if versions.LessThan(cli.version, "1.25") && k == "User-Agent" { - continue - } - req.Header.Set(k, v) - } - - if headers != nil { - for k, v := range headers { - req.Header[k] = v - } - } - return req -} - -func encodeData(data interface{}) (*bytes.Buffer, error) { - params := bytes.NewBuffer(nil) - if data != nil { - if err := json.NewEncoder(params).Encode(data); err != nil { - return nil, err - } - } - return params, nil -} - -func ensureReaderClosed(response serverResponse) { - if response.body != nil { - // Drain up to 512 bytes and close the body to let the Transport reuse the connection - io.CopyN(ioutil.Discard, response.body, 512) - response.body.Close() - } -} diff --git a/vendor/github.com/docker/docker/client/secret_create.go b/vendor/github.com/docker/docker/client/secret_create.go deleted file mode 100644 index fa639caf5b..0000000000 --- a/vendor/github.com/docker/docker/client/secret_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SecretCreate creates a new Secret. -func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) { - var response types.SecretCreateResponse - if err := cli.NewVersionError("1.25", "secret create"); err != nil { - return response, err - } - resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/secret_inspect.go b/vendor/github.com/docker/docker/client/secret_inspect.go deleted file mode 100644 index 6ff7549e5c..0000000000 --- a/vendor/github.com/docker/docker/client/secret_inspect.go +++ /dev/null @@ -1,33 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SecretInspectWithRaw returns the secret information with raw data -func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) { - if err := cli.NewVersionError("1.25", "secret inspect"); err != nil { - return swarm.Secret{}, nil, err - } - resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) - if err != nil { - return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) - } - defer ensureReaderClosed(resp) - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return swarm.Secret{}, nil, err - } - - var secret swarm.Secret - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&secret) - - return secret, body, err -} diff --git a/vendor/github.com/docker/docker/client/secret_list.go b/vendor/github.com/docker/docker/client/secret_list.go deleted file mode 100644 index adf4d92be2..0000000000 --- a/vendor/github.com/docker/docker/client/secret_list.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SecretList returns the list of secrets. -func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { - if err := cli.NewVersionError("1.25", "secret list"); err != nil { - return nil, err - } - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/secrets", query, nil) - if err != nil { - return nil, err - } - - var secrets []swarm.Secret - err = json.NewDecoder(resp.body).Decode(&secrets) - ensureReaderClosed(resp) - return secrets, err -} diff --git a/vendor/github.com/docker/docker/client/secret_remove.go b/vendor/github.com/docker/docker/client/secret_remove.go deleted file mode 100644 index 89326e0908..0000000000 --- a/vendor/github.com/docker/docker/client/secret_remove.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// SecretRemove removes a Secret. -func (cli *Client) SecretRemove(ctx context.Context, id string) error { - if err := cli.NewVersionError("1.25", "secret remove"); err != nil { - return err - } - resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "secret", id) -} diff --git a/vendor/github.com/docker/docker/client/secret_update.go b/vendor/github.com/docker/docker/client/secret_update.go deleted file mode 100644 index 8efd35c1eb..0000000000 --- a/vendor/github.com/docker/docker/client/secret_update.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SecretUpdate attempts to update a Secret -func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { - if err := cli.NewVersionError("1.25", "secret update"); err != nil { - return err - } - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, secret, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/service_create.go b/vendor/github.com/docker/docker/client/service_create.go deleted file mode 100644 index cf85ca4a18..0000000000 --- a/vendor/github.com/docker/docker/client/service_create.go +++ /dev/null @@ -1,166 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// ServiceCreate creates a new Service. -func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { - var distErr error - - headers := map[string][]string{ - "version": {cli.version}, - } - - if options.EncodedRegistryAuth != "" { - headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} - } - - // Make sure containerSpec is not nil when no runtime is set or the runtime is set to container - if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) { - service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{} - } - - if err := validateServiceSpec(service); err != nil { - return types.ServiceCreateResponse{}, err - } - - // ensure that the image is tagged - var imgPlatforms []swarm.Platform - if service.TaskTemplate.ContainerSpec != nil { - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg - } - if options.QueryRegistry { - var img string - img, imgPlatforms, distErr = imageDigestAndPlatforms(ctx, cli, service.TaskTemplate.ContainerSpec.Image, options.EncodedRegistryAuth) - if img != "" { - service.TaskTemplate.ContainerSpec.Image = img - } - } - } - - // ensure that the image is tagged - if service.TaskTemplate.PluginSpec != nil { - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg - } - if options.QueryRegistry { - var img string - img, imgPlatforms, distErr = imageDigestAndPlatforms(ctx, cli, service.TaskTemplate.PluginSpec.Remote, options.EncodedRegistryAuth) - if img != "" { - service.TaskTemplate.PluginSpec.Remote = img - } - } - } - - if service.TaskTemplate.Placement == nil && len(imgPlatforms) > 0 { - service.TaskTemplate.Placement = &swarm.Placement{} - } - if len(imgPlatforms) > 0 { - service.TaskTemplate.Placement.Platforms = imgPlatforms - } - - var response types.ServiceCreateResponse - resp, err := cli.post(ctx, "/services/create", nil, service, headers) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - - if distErr != nil { - response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) - } - - ensureReaderClosed(resp) - return response, err -} - -func imageDigestAndPlatforms(ctx context.Context, cli DistributionAPIClient, image, encodedAuth string) (string, []swarm.Platform, error) { - distributionInspect, err := cli.DistributionInspect(ctx, image, encodedAuth) - var platforms []swarm.Platform - if err != nil { - return "", nil, err - } - - imageWithDigest := imageWithDigestString(image, distributionInspect.Descriptor.Digest) - - if len(distributionInspect.Platforms) > 0 { - platforms = make([]swarm.Platform, 0, len(distributionInspect.Platforms)) - for _, p := range distributionInspect.Platforms { - // clear architecture field for arm. This is a temporary patch to address - // https://github.com/docker/swarmkit/issues/2294. The issue is that while - // image manifests report "arm" as the architecture, the node reports - // something like "armv7l" (includes the variant), which causes arm images - // to stop working with swarm mode. This patch removes the architecture - // constraint for arm images to ensure tasks get scheduled. - arch := p.Architecture - if strings.ToLower(arch) == "arm" { - arch = "" - } - platforms = append(platforms, swarm.Platform{ - Architecture: arch, - OS: p.OS, - }) - } - } - return imageWithDigest, platforms, err -} - -// imageWithDigestString takes an image string and a digest, and updates -// the image string if it didn't originally contain a digest. It returns -// an empty string if there are no updates. -func imageWithDigestString(image string, dgst digest.Digest) string { - namedRef, err := reference.ParseNormalizedNamed(image) - if err == nil { - if _, isCanonical := namedRef.(reference.Canonical); !isCanonical { - // ensure that image gets a default tag if none is provided - img, err := reference.WithDigest(namedRef, dgst) - if err == nil { - return reference.FamiliarString(img) - } - } - } - return "" -} - -// imageWithTagString takes an image string, and returns a tagged image -// string, adding a 'latest' tag if one was not provided. It returns an -// emptry string if a canonical reference was provided -func imageWithTagString(image string) string { - namedRef, err := reference.ParseNormalizedNamed(image) - if err == nil { - return reference.FamiliarString(reference.TagNameOnly(namedRef)) - } - return "" -} - -// digestWarning constructs a formatted warning string using the -// image name that could not be pinned by digest. The formatting -// is hardcoded, but could me made smarter in the future -func digestWarning(image string) string { - return fmt.Sprintf("image %s could not be accessed on a registry to record\nits digest. Each node will access %s independently,\npossibly leading to different nodes running different\nversions of the image.\n", image, image) -} - -func validateServiceSpec(s swarm.ServiceSpec) error { - if s.TaskTemplate.ContainerSpec != nil && s.TaskTemplate.PluginSpec != nil { - return errors.New("must not specify both a container spec and a plugin spec in the task template") - } - if s.TaskTemplate.PluginSpec != nil && s.TaskTemplate.Runtime != swarm.RuntimePlugin { - return errors.New("mismatched runtime with plugin spec") - } - if s.TaskTemplate.ContainerSpec != nil && (s.TaskTemplate.Runtime != "" && s.TaskTemplate.Runtime != swarm.RuntimeContainer) { - return errors.New("mismatched runtime with container spec") - } - return nil -} diff --git a/vendor/github.com/docker/docker/client/service_inspect.go b/vendor/github.com/docker/docker/client/service_inspect.go deleted file mode 100644 index 67bcc9cfaf..0000000000 --- a/vendor/github.com/docker/docker/client/service_inspect.go +++ /dev/null @@ -1,34 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ServiceInspectWithRaw returns the service information and the raw data. -func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) { - query := url.Values{} - query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) - serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) - if err != nil { - return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID) - } - defer ensureReaderClosed(serverResp) - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Service{}, nil, err - } - - var response swarm.Service - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/service_list.go b/vendor/github.com/docker/docker/client/service_list.go deleted file mode 100644 index fdb33cc221..0000000000 --- a/vendor/github.com/docker/docker/client/service_list.go +++ /dev/null @@ -1,35 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ServiceList returns the list of services. -func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/services", query, nil) - if err != nil { - return nil, err - } - - var services []swarm.Service - err = json.NewDecoder(resp.body).Decode(&services) - ensureReaderClosed(resp) - return services, err -} diff --git a/vendor/github.com/docker/docker/client/service_logs.go b/vendor/github.com/docker/docker/client/service_logs.go deleted file mode 100644 index 4b393bb494..0000000000 --- a/vendor/github.com/docker/docker/client/service_logs.go +++ /dev/null @@ -1,52 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" -) - -// ServiceLogs returns the logs generated by a service in an io.ReadCloser. -// It's up to the caller to close the stream. -func (cli *Client) ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/services/"+serviceID+"/logs", query, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/service_remove.go b/vendor/github.com/docker/docker/client/service_remove.go deleted file mode 100644 index 7ef04e8204..0000000000 --- a/vendor/github.com/docker/docker/client/service_remove.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "golang.org/x/net/context" - -// ServiceRemove kills and removes a service. -func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { - resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "service", serviceID) -} diff --git a/vendor/github.com/docker/docker/client/service_update.go b/vendor/github.com/docker/docker/client/service_update.go deleted file mode 100644 index 57cb45d8d2..0000000000 --- a/vendor/github.com/docker/docker/client/service_update.go +++ /dev/null @@ -1,92 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// ServiceUpdate updates a Service. -func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - var ( - query = url.Values{} - distErr error - ) - - headers := map[string][]string{ - "version": {cli.version}, - } - - if options.EncodedRegistryAuth != "" { - headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} - } - - if options.RegistryAuthFrom != "" { - query.Set("registryAuthFrom", options.RegistryAuthFrom) - } - - if options.Rollback != "" { - query.Set("rollback", options.Rollback) - } - - query.Set("version", strconv.FormatUint(version.Index, 10)) - - if err := validateServiceSpec(service); err != nil { - return types.ServiceUpdateResponse{}, err - } - - var imgPlatforms []swarm.Platform - // ensure that the image is tagged - if service.TaskTemplate.ContainerSpec != nil { - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg - } - if options.QueryRegistry { - var img string - img, imgPlatforms, distErr = imageDigestAndPlatforms(ctx, cli, service.TaskTemplate.ContainerSpec.Image, options.EncodedRegistryAuth) - if img != "" { - service.TaskTemplate.ContainerSpec.Image = img - } - } - } - - // ensure that the image is tagged - if service.TaskTemplate.PluginSpec != nil { - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg - } - if options.QueryRegistry { - var img string - img, imgPlatforms, distErr = imageDigestAndPlatforms(ctx, cli, service.TaskTemplate.PluginSpec.Remote, options.EncodedRegistryAuth) - if img != "" { - service.TaskTemplate.PluginSpec.Remote = img - } - } - } - - if service.TaskTemplate.Placement == nil && len(imgPlatforms) > 0 { - service.TaskTemplate.Placement = &swarm.Placement{} - } - if len(imgPlatforms) > 0 { - service.TaskTemplate.Placement.Platforms = imgPlatforms - } - - var response types.ServiceUpdateResponse - resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - - if distErr != nil { - response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) - } - - ensureReaderClosed(resp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/session.go b/vendor/github.com/docker/docker/client/session.go deleted file mode 100644 index b136538c22..0000000000 --- a/vendor/github.com/docker/docker/client/session.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net" - "net/http" - - "golang.org/x/net/context" -) - -// DialSession returns a connection that can be used communication with daemon -func (cli *Client) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) { - req, err := http.NewRequest("POST", "/session", nil) - if err != nil { - return nil, err - } - req = cli.addHeaders(req, meta) - - return cli.setupHijackConn(req, proto) -} diff --git a/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go b/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go deleted file mode 100644 index c02ae35c6d..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// SwarmGetUnlockKey retrieves the swarm's unlock key. -func (cli *Client) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) { - serverResp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil) - if err != nil { - return types.SwarmUnlockKeyResponse{}, err - } - - var response types.SwarmUnlockKeyResponse - err = json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/swarm_init.go b/vendor/github.com/docker/docker/client/swarm_init.go deleted file mode 100644 index 2997836317..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_init.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SwarmInit initializes the swarm. -func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { - serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil) - if err != nil { - return "", err - } - - var response string - err = json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/swarm_inspect.go b/vendor/github.com/docker/docker/client/swarm_inspect.go deleted file mode 100644 index 02f42aa8a9..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_inspect.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SwarmInspect inspects the swarm. -func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { - serverResp, err := cli.get(ctx, "/swarm", nil, nil) - if err != nil { - return swarm.Swarm{}, err - } - - var response swarm.Swarm - err = json.NewDecoder(serverResp.body).Decode(&response) - ensureReaderClosed(serverResp) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/swarm_join.go b/vendor/github.com/docker/docker/client/swarm_join.go deleted file mode 100644 index 13f8d79d6c..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_join.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SwarmJoin joins the swarm. -func (cli *Client) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error { - resp, err := cli.post(ctx, "/swarm/join", nil, req, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_leave.go b/vendor/github.com/docker/docker/client/swarm_leave.go deleted file mode 100644 index d0d00cbb4a..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_leave.go +++ /dev/null @@ -1,18 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "golang.org/x/net/context" -) - -// SwarmLeave leaves the swarm. -func (cli *Client) SwarmLeave(ctx context.Context, force bool) error { - query := url.Values{} - if force { - query.Set("force", "1") - } - resp, err := cli.post(ctx, "/swarm/leave", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_unlock.go b/vendor/github.com/docker/docker/client/swarm_unlock.go deleted file mode 100644 index 44a26bcc95..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_unlock.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SwarmUnlock unlocks locked swarm. -func (cli *Client) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error { - serverResp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil) - ensureReaderClosed(serverResp) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_update.go b/vendor/github.com/docker/docker/client/swarm_update.go deleted file mode 100644 index df6f1b0dc5..0000000000 --- a/vendor/github.com/docker/docker/client/swarm_update.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "fmt" - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// SwarmUpdate updates the swarm. -func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error { - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - query.Set("rotateWorkerToken", fmt.Sprintf("%v", flags.RotateWorkerToken)) - query.Set("rotateManagerToken", fmt.Sprintf("%v", flags.RotateManagerToken)) - query.Set("rotateManagerUnlockKey", fmt.Sprintf("%v", flags.RotateManagerUnlockKey)) - resp, err := cli.post(ctx, "/swarm/update", query, swarm, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/task_inspect.go b/vendor/github.com/docker/docker/client/task_inspect.go deleted file mode 100644 index a7b31219a6..0000000000 --- a/vendor/github.com/docker/docker/client/task_inspect.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// TaskInspectWithRaw returns the task information and its raw representation.. -func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { - serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) - if err != nil { - return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID) - } - defer ensureReaderClosed(serverResp) - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Task{}, nil, err - } - - var response swarm.Task - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/task_list.go b/vendor/github.com/docker/docker/client/task_list.go deleted file mode 100644 index e56718012c..0000000000 --- a/vendor/github.com/docker/docker/client/task_list.go +++ /dev/null @@ -1,35 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -// TaskList returns the list of tasks. -func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/tasks", query, nil) - if err != nil { - return nil, err - } - - var tasks []swarm.Task - err = json.NewDecoder(resp.body).Decode(&tasks) - ensureReaderClosed(resp) - return tasks, err -} diff --git a/vendor/github.com/docker/docker/client/task_logs.go b/vendor/github.com/docker/docker/client/task_logs.go deleted file mode 100644 index cf0b3f6bba..0000000000 --- a/vendor/github.com/docker/docker/client/task_logs.go +++ /dev/null @@ -1,52 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "io" - "net/url" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" -) - -// TaskLogs returns the logs generated by a task in an io.ReadCloser. -// It's up to the caller to close the stream. -func (cli *Client) TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/tasks/"+taskID+"/logs", query, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/tlsconfig_clone.go b/vendor/github.com/docker/docker/client/tlsconfig_clone.go deleted file mode 100644 index 88200e92c3..0000000000 --- a/vendor/github.com/docker/docker/client/tlsconfig_clone.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build go1.8 - -package client // import "github.com/docker/docker/client" - -import "crypto/tls" - -// tlsConfigClone returns a clone of tls.Config. This function is provided for -// compatibility for go1.7 that doesn't include this method in stdlib. -func tlsConfigClone(c *tls.Config) *tls.Config { - return c.Clone() -} diff --git a/vendor/github.com/docker/docker/client/tlsconfig_clone_go17.go b/vendor/github.com/docker/docker/client/tlsconfig_clone_go17.go deleted file mode 100644 index e298542367..0000000000 --- a/vendor/github.com/docker/docker/client/tlsconfig_clone_go17.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build go1.7,!go1.8 - -package client // import "github.com/docker/docker/client" - -import "crypto/tls" - -// tlsConfigClone returns a clone of tls.Config. This function is provided for -// compatibility for go1.7 that doesn't include this method in stdlib. -func tlsConfigClone(c *tls.Config) *tls.Config { - return &tls.Config{ - Rand: c.Rand, - Time: c.Time, - Certificates: c.Certificates, - NameToCertificate: c.NameToCertificate, - GetCertificate: c.GetCertificate, - RootCAs: c.RootCAs, - NextProtos: c.NextProtos, - ServerName: c.ServerName, - ClientAuth: c.ClientAuth, - ClientCAs: c.ClientCAs, - InsecureSkipVerify: c.InsecureSkipVerify, - CipherSuites: c.CipherSuites, - PreferServerCipherSuites: c.PreferServerCipherSuites, - SessionTicketsDisabled: c.SessionTicketsDisabled, - SessionTicketKey: c.SessionTicketKey, - ClientSessionCache: c.ClientSessionCache, - MinVersion: c.MinVersion, - MaxVersion: c.MaxVersion, - CurvePreferences: c.CurvePreferences, - DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, - Renegotiation: c.Renegotiation, - } -} diff --git a/vendor/github.com/docker/docker/client/transport.go b/vendor/github.com/docker/docker/client/transport.go deleted file mode 100644 index 5541344366..0000000000 --- a/vendor/github.com/docker/docker/client/transport.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "crypto/tls" - "net/http" -) - -// resolveTLSConfig attempts to resolve the TLS configuration from the -// RoundTripper. -func resolveTLSConfig(transport http.RoundTripper) *tls.Config { - switch tr := transport.(type) { - case *http.Transport: - return tr.TLSClientConfig - default: - return nil - } -} diff --git a/vendor/github.com/docker/docker/client/utils.go b/vendor/github.com/docker/docker/client/utils.go deleted file mode 100644 index 7f3ff44eb8..0000000000 --- a/vendor/github.com/docker/docker/client/utils.go +++ /dev/null @@ -1,34 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "regexp" - - "github.com/docker/docker/api/types/filters" -) - -var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`) - -// getDockerOS returns the operating system based on the server header from the daemon. -func getDockerOS(serverHeader string) string { - var osType string - matches := headerRegexp.FindStringSubmatch(serverHeader) - if len(matches) > 0 { - osType = matches[1] - } - return osType -} - -// getFiltersQuery returns a url query with "filters" query term, based on the -// filters provided. -func getFiltersQuery(f filters.Args) (url.Values, error) { - query := url.Values{} - if f.Len() > 0 { - filterJSON, err := filters.ToJSON(f) - if err != nil { - return query, err - } - query.Set("filters", filterJSON) - } - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/version.go b/vendor/github.com/docker/docker/client/version.go deleted file mode 100644 index 4bb60fab58..0000000000 --- a/vendor/github.com/docker/docker/client/version.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// ServerVersion returns information of the docker client and server host. -func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) { - resp, err := cli.get(ctx, "/version", nil, nil) - if err != nil { - return types.Version{}, err - } - - var server types.Version - err = json.NewDecoder(resp.body).Decode(&server) - ensureReaderClosed(resp) - return server, err -} diff --git a/vendor/github.com/docker/docker/client/volume_create.go b/vendor/github.com/docker/docker/client/volume_create.go deleted file mode 100644 index 8108b7b92f..0000000000 --- a/vendor/github.com/docker/docker/client/volume_create.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - - "github.com/docker/docker/api/types" - volumetypes "github.com/docker/docker/api/types/volume" - "golang.org/x/net/context" -) - -// VolumeCreate creates a volume in the docker host. -func (cli *Client) VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error) { - var volume types.Volume - resp, err := cli.post(ctx, "/volumes/create", nil, options, nil) - if err != nil { - return volume, err - } - err = json.NewDecoder(resp.body).Decode(&volume) - ensureReaderClosed(resp) - return volume, err -} diff --git a/vendor/github.com/docker/docker/client/volume_inspect.go b/vendor/github.com/docker/docker/client/volume_inspect.go deleted file mode 100644 index b72e64d793..0000000000 --- a/vendor/github.com/docker/docker/client/volume_inspect.go +++ /dev/null @@ -1,42 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "path" - - "github.com/docker/docker/api/types" - "golang.org/x/net/context" -) - -// VolumeInspect returns the information about a specific volume in the docker host. -func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) { - volume, _, err := cli.VolumeInspectWithRaw(ctx, volumeID) - return volume, err -} - -// VolumeInspectWithRaw returns the information about a specific volume in the docker host and its raw representation -func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) { - // The empty ID needs to be handled here because with an empty ID the - // request url will not contain a trailing / which calls the volume list API - // instead of volume inspect - if volumeID == "" { - return types.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID} - } - - var volume types.Volume - resp, err := cli.get(ctx, path.Join("/volumes", volumeID), nil, nil) - if err != nil { - return volume, nil, wrapResponseError(err, resp, "volume", volumeID) - } - defer ensureReaderClosed(resp) - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return volume, nil, err - } - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&volume) - return volume, body, err -} diff --git a/vendor/github.com/docker/docker/client/volume_list.go b/vendor/github.com/docker/docker/client/volume_list.go deleted file mode 100644 index aeca1cc1a3..0000000000 --- a/vendor/github.com/docker/docker/client/volume_list.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/filters" - volumetypes "github.com/docker/docker/api/types/volume" - "golang.org/x/net/context" -) - -// VolumeList returns the volumes configured in the docker host. -func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error) { - var volumes volumetypes.VolumesListOKBody - query := url.Values{} - - if filter.Len() > 0 { - filterJSON, err := filters.ToParamWithVersion(cli.version, filter) - if err != nil { - return volumes, err - } - query.Set("filters", filterJSON) - } - resp, err := cli.get(ctx, "/volumes", query, nil) - if err != nil { - return volumes, err - } - - err = json.NewDecoder(resp.body).Decode(&volumes) - ensureReaderClosed(resp) - return volumes, err -} diff --git a/vendor/github.com/docker/docker/client/volume_prune.go b/vendor/github.com/docker/docker/client/volume_prune.go deleted file mode 100644 index 090a6a66df..0000000000 --- a/vendor/github.com/docker/docker/client/volume_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -// VolumesPrune requests the daemon to delete unused data -func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) { - var report types.VolumesPruneReport - - if err := cli.NewVersionError("1.25", "volume prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) - if err != nil { - return report, err - } - defer ensureReaderClosed(serverResp) - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving volume prune report: %v", err) - } - - return report, nil -} diff --git a/vendor/github.com/docker/docker/client/volume_remove.go b/vendor/github.com/docker/docker/client/volume_remove.go deleted file mode 100644 index 02ee573a73..0000000000 --- a/vendor/github.com/docker/docker/client/volume_remove.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - - "github.com/docker/docker/api/types/versions" - "golang.org/x/net/context" -) - -// VolumeRemove removes a volume from the docker host. -func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - query := url.Values{} - if versions.GreaterThanOrEqualTo(cli.version, "1.25") { - if force { - query.Set("force", "1") - } - } - resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) - ensureReaderClosed(resp) - return wrapResponseError(err, resp, "volume", volumeID) -} diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go deleted file mode 100644 index ee15ed52b1..0000000000 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go +++ /dev/null @@ -1,21 +0,0 @@ -package homedir // import "github.com/docker/docker/pkg/homedir" - -import ( - "os" - - "github.com/docker/docker/pkg/idtools" -) - -// GetStatic returns the home directory for the current user without calling -// os/user.Current(). This is useful for static-linked binary on glibc-based -// system, because a call to os/user.Current() in a static binary leads to -// segfault due to a glibc issue that won't be fixed in a short term. -// (#29344, golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) -func GetStatic() (string, error) { - uid := os.Getuid() - usr, err := idtools.LookupUID(uid) - if err != nil { - return "", err - } - return usr.Home, nil -} diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go deleted file mode 100644 index 75ada2fe54..0000000000 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !linux - -package homedir // import "github.com/docker/docker/pkg/homedir" - -import ( - "errors" -) - -// GetStatic is not needed for non-linux systems. -// (Precisely, it is needed only for glibc-based linux systems.) -func GetStatic() (string, error) { - return "", errors.New("homedir.GetStatic() is not supported on this system") -} diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go deleted file mode 100644 index d85e124488..0000000000 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build !windows - -package homedir // import "github.com/docker/docker/pkg/homedir" - -import ( - "os" - - "github.com/opencontainers/runc/libcontainer/user" -) - -// Key returns the env var name for the user's home dir based on -// the platform being run on -func Key() string { - return "HOME" -} - -// Get returns the home directory of the current user with the help of -// environment variables depending on the target operating system. -// Returned path should be used with "path/filepath" to form new paths. -func Get() string { - home := os.Getenv(Key()) - if home == "" { - if u, err := user.CurrentUser(); err == nil { - return u.Home - } - } - return home -} - -// GetShortcutString returns the string that is shortcut to user's home directory -// in the native shell of the platform running on. -func GetShortcutString() string { - return "~" -} diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go deleted file mode 100644 index 2f81813b28..0000000000 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go +++ /dev/null @@ -1,24 +0,0 @@ -package homedir // import "github.com/docker/docker/pkg/homedir" - -import ( - "os" -) - -// Key returns the env var name for the user's home dir based on -// the platform being run on -func Key() string { - return "USERPROFILE" -} - -// Get returns the home directory of the current user with the help of -// environment variables depending on the target operating system. -// Returned path should be used with "path/filepath" to form new paths. -func Get() string { - return os.Getenv(Key()) -} - -// GetShortcutString returns the string that is shortcut to user's home directory -// in the native shell of the platform running on. -func GetShortcutString() string { - return "%USERPROFILE%" // be careful while using in format functions -} diff --git a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go deleted file mode 100644 index 99846ffddb..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go +++ /dev/null @@ -1,81 +0,0 @@ -package sockets - -import ( - "errors" - "net" - "sync" -) - -var errClosed = errors.New("use of closed network connection") - -// InmemSocket implements net.Listener using in-memory only connections. -type InmemSocket struct { - chConn chan net.Conn - chClose chan struct{} - addr string - mu sync.Mutex -} - -// dummyAddr is used to satisfy net.Addr for the in-mem socket -// it is just stored as a string and returns the string for all calls -type dummyAddr string - -// NewInmemSocket creates an in-memory only net.Listener -// The addr argument can be any string, but is used to satisfy the `Addr()` part -// of the net.Listener interface -func NewInmemSocket(addr string, bufSize int) *InmemSocket { - return &InmemSocket{ - chConn: make(chan net.Conn, bufSize), - chClose: make(chan struct{}), - addr: addr, - } -} - -// Addr returns the socket's addr string to satisfy net.Listener -func (s *InmemSocket) Addr() net.Addr { - return dummyAddr(s.addr) -} - -// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. -func (s *InmemSocket) Accept() (net.Conn, error) { - select { - case conn := <-s.chConn: - return conn, nil - case <-s.chClose: - return nil, errClosed - } -} - -// Close closes the listener. It will be unavailable for use once closed. -func (s *InmemSocket) Close() error { - s.mu.Lock() - defer s.mu.Unlock() - select { - case <-s.chClose: - default: - close(s.chClose) - } - return nil -} - -// Dial is used to establish a connection with the in-mem server -func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) { - srvConn, clientConn := net.Pipe() - select { - case s.chConn <- srvConn: - case <-s.chClose: - return nil, errClosed - } - - return clientConn, nil -} - -// Network returns the addr string, satisfies net.Addr -func (a dummyAddr) Network() string { - return string(a) -} - -// String returns the string form -func (a dummyAddr) String() string { - return string(a) -} diff --git a/vendor/github.com/docker/go-connections/sockets/proxy.go b/vendor/github.com/docker/go-connections/sockets/proxy.go deleted file mode 100644 index 98e9a1dc61..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/proxy.go +++ /dev/null @@ -1,51 +0,0 @@ -package sockets - -import ( - "net" - "net/url" - "os" - "strings" - - "golang.org/x/net/proxy" -) - -// GetProxyEnv allows access to the uppercase and the lowercase forms of -// proxy-related variables. See the Go specification for details on these -// variables. https://golang.org/pkg/net/http/ -func GetProxyEnv(key string) string { - proxyValue := os.Getenv(strings.ToUpper(key)) - if proxyValue == "" { - return os.Getenv(strings.ToLower(key)) - } - return proxyValue -} - -// DialerFromEnvironment takes in a "direct" *net.Dialer and returns a -// proxy.Dialer which will route the connections through the proxy using the -// given dialer. -func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) { - allProxy := GetProxyEnv("all_proxy") - if len(allProxy) == 0 { - return direct, nil - } - - proxyURL, err := url.Parse(allProxy) - if err != nil { - return direct, err - } - - proxyFromURL, err := proxy.FromURL(proxyURL, direct) - if err != nil { - return direct, err - } - - noProxy := GetProxyEnv("no_proxy") - if len(noProxy) == 0 { - return proxyFromURL, nil - } - - perHost := proxy.NewPerHost(proxyFromURL, direct) - perHost.AddFromString(noProxy) - - return perHost, nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets.go b/vendor/github.com/docker/go-connections/sockets/sockets.go deleted file mode 100644 index a1d7beb4d8..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets.go +++ /dev/null @@ -1,38 +0,0 @@ -// Package sockets provides helper functions to create and configure Unix or TCP sockets. -package sockets - -import ( - "errors" - "net" - "net/http" - "time" -) - -// Why 32? See https://github.com/docker/docker/pull/8035. -const defaultTimeout = 32 * time.Second - -// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system. -var ErrProtocolNotAvailable = errors.New("protocol not available") - -// ConfigureTransport configures the specified Transport according to the -// specified proto and addr. -// If the proto is unix (using a unix socket to communicate) or npipe the -// compression is disabled. -func ConfigureTransport(tr *http.Transport, proto, addr string) error { - switch proto { - case "unix": - return configureUnixTransport(tr, proto, addr) - case "npipe": - return configureNpipeTransport(tr, proto, addr) - default: - tr.Proxy = http.ProxyFromEnvironment - dialer, err := DialerFromEnvironment(&net.Dialer{ - Timeout: defaultTimeout, - }) - if err != nil { - return err - } - tr.Dial = dialer.Dial - } - return nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go deleted file mode 100644 index 386cf0dbbd..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build !windows - -package sockets - -import ( - "fmt" - "net" - "net/http" - "syscall" - "time" -) - -const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path) - -func configureUnixTransport(tr *http.Transport, proto, addr string) error { - if len(addr) > maxUnixSocketPathSize { - return fmt.Errorf("Unix socket path %q is too long", addr) - } - // No need for compression in local communications. - tr.DisableCompression = true - tr.Dial = func(_, _ string) (net.Conn, error) { - return net.DialTimeout(proto, addr, defaultTimeout) - } - return nil -} - -func configureNpipeTransport(tr *http.Transport, proto, addr string) error { - return ErrProtocolNotAvailable -} - -// DialPipe connects to a Windows named pipe. -// This is not supported on other OSes. -func DialPipe(_ string, _ time.Duration) (net.Conn, error) { - return nil, syscall.EAFNOSUPPORT -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go deleted file mode 100644 index 5c21644e1f..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go +++ /dev/null @@ -1,27 +0,0 @@ -package sockets - -import ( - "net" - "net/http" - "time" - - "github.com/Microsoft/go-winio" -) - -func configureUnixTransport(tr *http.Transport, proto, addr string) error { - return ErrProtocolNotAvailable -} - -func configureNpipeTransport(tr *http.Transport, proto, addr string) error { - // No need for compression in local communications. - tr.DisableCompression = true - tr.Dial = func(_, _ string) (net.Conn, error) { - return DialPipe(addr, defaultTimeout) - } - return nil -} - -// DialPipe connects to a Windows named pipe. -func DialPipe(addr string, timeout time.Duration) (net.Conn, error) { - return winio.DialPipe(addr, &timeout) -} diff --git a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go deleted file mode 100644 index 53cbb6c79e..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go +++ /dev/null @@ -1,22 +0,0 @@ -// Package sockets provides helper functions to create and configure Unix or TCP sockets. -package sockets - -import ( - "crypto/tls" - "net" -) - -// NewTCPSocket creates a TCP socket listener with the specified address and -// the specified tls configuration. If TLSConfig is set, will encapsulate the -// TCP listener inside a TLS one. -func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) { - l, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - if tlsConfig != nil { - tlsConfig.NextProtos = []string{"http/1.1"} - l = tls.NewListener(l, tlsConfig) - } - return l, nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go deleted file mode 100644 index a8b5dbb6fd..0000000000 --- a/vendor/github.com/docker/go-connections/sockets/unix_socket.go +++ /dev/null @@ -1,32 +0,0 @@ -// +build !windows - -package sockets - -import ( - "net" - "os" - "syscall" -) - -// NewUnixSocket creates a unix socket with the specified path and group. -func NewUnixSocket(path string, gid int) (net.Listener, error) { - if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) { - return nil, err - } - mask := syscall.Umask(0777) - defer syscall.Umask(mask) - - l, err := net.Listen("unix", path) - if err != nil { - return nil, err - } - if err := os.Chown(path, 0, gid); err != nil { - l.Close() - return nil, err - } - if err := os.Chmod(path, 0660); err != nil { - l.Close() - return nil, err - } - return l, nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go b/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go deleted file mode 100644 index 1ca0965e06..0000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build go1.7 - -package tlsconfig - -import ( - "crypto/x509" - "runtime" -) - -// SystemCertPool returns a copy of the system cert pool, -// returns an error if failed to load or empty pool on windows. -func SystemCertPool() (*x509.CertPool, error) { - certpool, err := x509.SystemCertPool() - if err != nil && runtime.GOOS == "windows" { - return x509.NewCertPool(), nil - } - return certpool, err -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go b/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go deleted file mode 100644 index 9ca974539a..0000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build !go1.7 - -package tlsconfig - -import ( - "crypto/x509" - -) - -// SystemCertPool returns an new empty cert pool, -// accessing system cert pool is supported in go 1.7 -func SystemCertPool() (*x509.CertPool, error) { - return x509.NewCertPool(), nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go deleted file mode 100644 index 1b31bbb8b1..0000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config.go +++ /dev/null @@ -1,244 +0,0 @@ -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -// As a reminder from https://golang.org/pkg/crypto/tls/#Config: -// A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified. -// A Config may be reused; the tls package will also not modify it. -package tlsconfig - -import ( - "crypto/tls" - "crypto/x509" - "encoding/pem" - "fmt" - "io/ioutil" - "os" - - "github.com/pkg/errors" -) - -// Options represents the information needed to create client and server TLS configurations. -type Options struct { - CAFile string - - // If either CertFile or KeyFile is empty, Client() will not load them - // preventing the client from authenticating to the server. - // However, Server() requires them and will error out if they are empty. - CertFile string - KeyFile string - - // client-only option - InsecureSkipVerify bool - // server-only option - ClientAuth tls.ClientAuthType - // If ExclusiveRootPools is set, then if a CA file is provided, the root pool used for TLS - // creds will include exclusively the roots in that CA file. If no CA file is provided, - // the system pool will be used. - ExclusiveRootPools bool - MinVersion uint16 - // If Passphrase is set, it will be used to decrypt a TLS private key - // if the key is encrypted - Passphrase string -} - -// Extra (server-side) accepted CBC cipher suites - will phase out in the future -var acceptedCBCCiphers = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - tls.TLS_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_RSA_WITH_AES_128_CBC_SHA, -} - -// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls -// options struct but wants to use a commonly accepted set of TLS cipher suites, with -// known weak algorithms removed. -var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...) - -// allTLSVersions lists all the TLS versions and is used by the code that validates -// a uint16 value as a TLS version. -var allTLSVersions = map[uint16]struct{}{ - tls.VersionSSL30: {}, - tls.VersionTLS10: {}, - tls.VersionTLS11: {}, - tls.VersionTLS12: {}, -} - -// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration. -func ServerDefault() *tls.Config { - return &tls.Config{ - // Avoid fallback to SSL protocols < TLS1.0 - MinVersion: tls.VersionTLS10, - PreferServerCipherSuites: true, - CipherSuites: DefaultServerAcceptedCiphers, - } -} - -// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration. -func ClientDefault() *tls.Config { - return &tls.Config{ - // Prefer TLS1.2 as the client minimum - MinVersion: tls.VersionTLS12, - CipherSuites: clientCipherSuites, - } -} - -// certPool returns an X.509 certificate pool from `caFile`, the certificate file. -func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) { - // If we should verify the server, we need to load a trusted ca - var ( - certPool *x509.CertPool - err error - ) - if exclusivePool { - certPool = x509.NewCertPool() - } else { - certPool, err = SystemCertPool() - if err != nil { - return nil, fmt.Errorf("failed to read system certificates: %v", err) - } - } - pem, err := ioutil.ReadFile(caFile) - if err != nil { - return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err) - } - if !certPool.AppendCertsFromPEM(pem) { - return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile) - } - return certPool, nil -} - -// isValidMinVersion checks that the input value is a valid tls minimum version -func isValidMinVersion(version uint16) bool { - _, ok := allTLSVersions[version] - return ok -} - -// adjustMinVersion sets the MinVersion on `config`, the input configuration. -// It assumes the current MinVersion on the `config` is the lowest allowed. -func adjustMinVersion(options Options, config *tls.Config) error { - if options.MinVersion > 0 { - if !isValidMinVersion(options.MinVersion) { - return fmt.Errorf("Invalid minimum TLS version: %x", options.MinVersion) - } - if options.MinVersion < config.MinVersion { - return fmt.Errorf("Requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion) - } - config.MinVersion = options.MinVersion - } - - return nil -} - -// IsErrEncryptedKey returns true if the 'err' is an error of incorrect -// password when tryin to decrypt a TLS private key -func IsErrEncryptedKey(err error) bool { - return errors.Cause(err) == x509.IncorrectPasswordError -} - -// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format. -// If the private key is encrypted, 'passphrase' is used to decrypted the -// private key. -func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) { - // this section makes some small changes to code from notary/tuf/utils/x509.go - pemBlock, _ := pem.Decode(keyBytes) - if pemBlock == nil { - return nil, fmt.Errorf("no valid private key found") - } - - var err error - if x509.IsEncryptedPEMBlock(pemBlock) { - keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) - if err != nil { - return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it") - } - keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes}) - } - - return keyBytes, nil -} - -// getCert returns a Certificate from the CertFile and KeyFile in 'options', -// if the key is encrypted, the Passphrase in 'options' will be used to -// decrypt it. -func getCert(options Options) ([]tls.Certificate, error) { - if options.CertFile == "" && options.KeyFile == "" { - return nil, nil - } - - errMessage := "Could not load X509 key pair" - - cert, err := ioutil.ReadFile(options.CertFile) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - prKeyBytes, err := ioutil.ReadFile(options.KeyFile) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - tlsCert, err := tls.X509KeyPair(cert, prKeyBytes) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - return []tls.Certificate{tlsCert}, nil -} - -// Client returns a TLS configuration meant to be used by a client. -func Client(options Options) (*tls.Config, error) { - tlsConfig := ClientDefault() - tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify - if !options.InsecureSkipVerify && options.CAFile != "" { - CAs, err := certPool(options.CAFile, options.ExclusiveRootPools) - if err != nil { - return nil, err - } - tlsConfig.RootCAs = CAs - } - - tlsCerts, err := getCert(options) - if err != nil { - return nil, err - } - tlsConfig.Certificates = tlsCerts - - if err := adjustMinVersion(options, tlsConfig); err != nil { - return nil, err - } - - return tlsConfig, nil -} - -// Server returns a TLS configuration meant to be used by a server. -func Server(options Options) (*tls.Config, error) { - tlsConfig := ServerDefault() - tlsConfig.ClientAuth = options.ClientAuth - tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) - if err != nil { - if os.IsNotExist(err) { - return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err) - } - return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err) - } - tlsConfig.Certificates = []tls.Certificate{tlsCert} - if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" { - CAs, err := certPool(options.CAFile, options.ExclusiveRootPools) - if err != nil { - return nil, err - } - tlsConfig.ClientCAs = CAs - } - - if err := adjustMinVersion(options, tlsConfig); err != nil { - return nil, err - } - - return tlsConfig, nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go deleted file mode 100644 index 6b4c6a7c0d..0000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build go1.5 - -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -package tlsconfig - -import ( - "crypto/tls" -) - -// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) -var clientCipherSuites = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go deleted file mode 100644 index ee22df47cb..0000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !go1.5 - -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -package tlsconfig - -import ( - "crypto/tls" -) - -// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) -var clientCipherSuites = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -} diff --git a/vendor/github.com/docker/go-metrics/LICENSE.code b/vendor/github.com/docker/go-metrics/LICENSE.code deleted file mode 100644 index 8f3fee627a..0000000000 --- a/vendor/github.com/docker/go-metrics/LICENSE.code +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2013-2016 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/docker/go-metrics/LICENSE.docs b/vendor/github.com/docker/go-metrics/LICENSE.docs deleted file mode 100644 index e26cd4fc8e..0000000000 --- a/vendor/github.com/docker/go-metrics/LICENSE.docs +++ /dev/null @@ -1,425 +0,0 @@ -Attribution-ShareAlike 4.0 International - -======================================================================= - -Creative Commons Corporation ("Creative Commons") is not a law firm and -does not provide legal services or legal advice. Distribution of -Creative Commons public licenses does not create a lawyer-client or -other relationship. Creative Commons makes its licenses and related -information available on an "as-is" basis. Creative Commons gives no -warranties regarding its licenses, any material licensed under their -terms and conditions, or any related information. Creative Commons -disclaims all liability for damages resulting from their use to the -fullest extent possible. - -Using Creative Commons Public Licenses - -Creative Commons public licenses provide a standard set of terms and -conditions that creators and other rights holders may use to share -original works of authorship and other material subject to copyright -and certain other rights specified in the public license below. The -following considerations are for informational purposes only, are not -exhaustive, and do not form part of our licenses. - - Considerations for licensors: Our public licenses are - intended for use by those authorized to give the public - permission to use material in ways otherwise restricted by - copyright and certain other rights. Our licenses are - irrevocable. Licensors should read and understand the terms - and conditions of the license they choose before applying it. - Licensors should also secure all rights necessary before - applying our licenses so that the public can reuse the - material as expected. Licensors should clearly mark any - material not subject to the license. This includes other CC- - licensed material, or material used under an exception or - limitation to copyright. More considerations for licensors: - wiki.creativecommons.org/Considerations_for_licensors - - Considerations for the public: By using one of our public - licenses, a licensor grants the public permission to use the - licensed material under specified terms and conditions. If - the licensor's permission is not necessary for any reason--for - example, because of any applicable exception or limitation to - copyright--then that use is not regulated by the license. Our - licenses grant only permissions under copyright and certain - other rights that a licensor has authority to grant. Use of - the licensed material may still be restricted for other - reasons, including because others have copyright or other - rights in the material. A licensor may make special requests, - such as asking that all changes be marked or described. - Although not required by our licenses, you are encouraged to - respect those requests where reasonable. More_considerations - for the public: - wiki.creativecommons.org/Considerations_for_licensees - -======================================================================= - -Creative Commons Attribution-ShareAlike 4.0 International Public -License - -By exercising the Licensed Rights (defined below), You accept and agree -to be bound by the terms and conditions of this Creative Commons -Attribution-ShareAlike 4.0 International Public License ("Public -License"). To the extent this Public License may be interpreted as a -contract, You are granted the Licensed Rights in consideration of Your -acceptance of these terms and conditions, and the Licensor grants You -such rights in consideration of benefits the Licensor receives from -making the Licensed Material available under these terms and -conditions. - - -Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. BY-SA Compatible License means a license listed at - creativecommons.org/compatiblelicenses, approved by Creative - Commons as essentially the equivalent of this Public License. - - d. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - - e. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - f. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - g. License Elements means the license attributes listed in the name - of a Creative Commons Public License. The License Elements of this - Public License are Attribution and ShareAlike. - - h. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - i. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - j. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - k. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - l. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - m. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - -Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part; and - - b. produce, reproduce, and Share Adapted Material. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. Additional offer from the Licensor -- Adapted Material. - Every recipient of Adapted Material from You - automatically receives an offer from the Licensor to - exercise the Licensed Rights in the Adapted Material - under the conditions of the Adapter's License You apply. - - c. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties. - - -Section 3 -- License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the -following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - b. ShareAlike. - - In addition to the conditions in Section 3(a), if You Share - Adapted Material You produce, the following conditions also apply. - - 1. The Adapter's License You apply must be a Creative Commons - license with the same License Elements, this version or - later, or a BY-SA Compatible License. - - 2. You must include the text of, or the URI or hyperlink to, the - Adapter's License You apply. You may satisfy this condition - in any reasonable manner based on the medium, means, and - context in which You Share Adapted Material. - - 3. You may not offer or impose any additional or different terms - or conditions on, or apply any Effective Technological - Measures to, Adapted Material that restrict exercise of the - rights granted under the Adapter's License You apply. - - -Section 4 -- Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that -apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material, - - including for purposes of Section 3(b); and - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not -replace Your obligations under this Public License where the Licensed -Rights include other Copyright and Similar Rights. - - -Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - -Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - -Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - -Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - - -======================================================================= - -Creative Commons is not a party to its public licenses. -Notwithstanding, Creative Commons may elect to apply one of its public -licenses to material it publishes and in those instances will be -considered the "Licensor." Except for the limited purpose of indicating -that material is shared under a Creative Commons public license or as -otherwise permitted by the Creative Commons policies published at -creativecommons.org/policies, Creative Commons does not authorize the -use of the trademark "Creative Commons" or any other trademark or logo -of Creative Commons without its prior written consent including, -without limitation, in connection with any unauthorized modifications -to any of its public licenses or any other arrangements, -understandings, or agreements concerning use of licensed material. For -the avoidance of doubt, this paragraph does not form part of the public -licenses. - -Creative Commons may be contacted at creativecommons.org. diff --git a/vendor/github.com/docker/go-metrics/NOTICE b/vendor/github.com/docker/go-metrics/NOTICE deleted file mode 100644 index 8915f02773..0000000000 --- a/vendor/github.com/docker/go-metrics/NOTICE +++ /dev/null @@ -1,16 +0,0 @@ -Docker -Copyright 2012-2015 Docker, Inc. - -This product includes software developed at Docker, Inc. (https://www.docker.com). - -The following is courtesy of our legal counsel: - - -Use and transfer of Docker may be subject to certain restrictions by the -United States and other governments. -It is your responsibility to ensure that your use and/or transfer does not -violate applicable laws. - -For more information, please see https://www.bis.doc.gov - -See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/vendor/github.com/docker/go-metrics/counter.go b/vendor/github.com/docker/go-metrics/counter.go deleted file mode 100644 index fe36316a45..0000000000 --- a/vendor/github.com/docker/go-metrics/counter.go +++ /dev/null @@ -1,52 +0,0 @@ -package metrics - -import "github.com/prometheus/client_golang/prometheus" - -// Counter is a metrics that can only increment its current count -type Counter interface { - // Inc adds Sum(vs) to the counter. Sum(vs) must be positive. - // - // If len(vs) == 0, increments the counter by 1. - Inc(vs ...float64) -} - -// LabeledCounter is counter that must have labels populated before use. -type LabeledCounter interface { - WithValues(vs ...string) Counter -} - -type labeledCounter struct { - pc *prometheus.CounterVec -} - -func (lc *labeledCounter) WithValues(vs ...string) Counter { - return &counter{pc: lc.pc.WithLabelValues(vs...)} -} - -func (lc *labeledCounter) Describe(ch chan<- *prometheus.Desc) { - lc.pc.Describe(ch) -} - -func (lc *labeledCounter) Collect(ch chan<- prometheus.Metric) { - lc.pc.Collect(ch) -} - -type counter struct { - pc prometheus.Counter -} - -func (c *counter) Inc(vs ...float64) { - if len(vs) == 0 { - c.pc.Inc() - } - - c.pc.Add(sumFloat64(vs...)) -} - -func (c *counter) Describe(ch chan<- *prometheus.Desc) { - c.pc.Describe(ch) -} - -func (c *counter) Collect(ch chan<- prometheus.Metric) { - c.pc.Collect(ch) -} diff --git a/vendor/github.com/docker/go-metrics/docs.go b/vendor/github.com/docker/go-metrics/docs.go deleted file mode 100644 index 8fbdfc697d..0000000000 --- a/vendor/github.com/docker/go-metrics/docs.go +++ /dev/null @@ -1,3 +0,0 @@ -// This package is small wrapper around the prometheus go client to help enforce convention and best practices for metrics collection in Docker projects. - -package metrics diff --git a/vendor/github.com/docker/go-metrics/gauge.go b/vendor/github.com/docker/go-metrics/gauge.go deleted file mode 100644 index 74296e8774..0000000000 --- a/vendor/github.com/docker/go-metrics/gauge.go +++ /dev/null @@ -1,72 +0,0 @@ -package metrics - -import "github.com/prometheus/client_golang/prometheus" - -// Gauge is a metric that allows incrementing and decrementing a value -type Gauge interface { - Inc(...float64) - Dec(...float64) - - // Add adds the provided value to the gauge's current value - Add(float64) - - // Set replaces the gauge's current value with the provided value - Set(float64) -} - -// LabeledGauge describes a gauge the must have values populated before use. -type LabeledGauge interface { - WithValues(labels ...string) Gauge -} - -type labeledGauge struct { - pg *prometheus.GaugeVec -} - -func (lg *labeledGauge) WithValues(labels ...string) Gauge { - return &gauge{pg: lg.pg.WithLabelValues(labels...)} -} - -func (lg *labeledGauge) Describe(c chan<- *prometheus.Desc) { - lg.pg.Describe(c) -} - -func (lg *labeledGauge) Collect(c chan<- prometheus.Metric) { - lg.pg.Collect(c) -} - -type gauge struct { - pg prometheus.Gauge -} - -func (g *gauge) Inc(vs ...float64) { - if len(vs) == 0 { - g.pg.Inc() - } - - g.Add(sumFloat64(vs...)) -} - -func (g *gauge) Dec(vs ...float64) { - if len(vs) == 0 { - g.pg.Dec() - } - - g.Add(-sumFloat64(vs...)) -} - -func (g *gauge) Add(v float64) { - g.pg.Add(v) -} - -func (g *gauge) Set(v float64) { - g.pg.Set(v) -} - -func (g *gauge) Describe(c chan<- *prometheus.Desc) { - g.pg.Describe(c) -} - -func (g *gauge) Collect(c chan<- prometheus.Metric) { - g.pg.Collect(c) -} diff --git a/vendor/github.com/docker/go-metrics/handler.go b/vendor/github.com/docker/go-metrics/handler.go deleted file mode 100644 index 05601e9ecd..0000000000 --- a/vendor/github.com/docker/go-metrics/handler.go +++ /dev/null @@ -1,74 +0,0 @@ -package metrics - -import ( - "net/http" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -// HTTPHandlerOpts describes a set of configurable options of http metrics -type HTTPHandlerOpts struct { - DurationBuckets []float64 - RequestSizeBuckets []float64 - ResponseSizeBuckets []float64 -} - -const ( - InstrumentHandlerResponseSize = iota - InstrumentHandlerRequestSize - InstrumentHandlerDuration - InstrumentHandlerCounter - InstrumentHandlerInFlight -) - -type HTTPMetric struct { - prometheus.Collector - handlerType int -} - -var ( - defaultDurationBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 60} - defaultRequestSizeBuckets = prometheus.ExponentialBuckets(1024, 2, 22) //1K to 4G - defaultResponseSizeBuckets = defaultRequestSizeBuckets -) - -// Handler returns the global http.Handler that provides the prometheus -// metrics format on GET requests. This handler is no longer instrumented. -func Handler() http.Handler { - return promhttp.Handler() -} - -func InstrumentHandler(metrics []*HTTPMetric, handler http.Handler) http.HandlerFunc { - return InstrumentHandlerFunc(metrics, handler.ServeHTTP) -} - -func InstrumentHandlerFunc(metrics []*HTTPMetric, handlerFunc http.HandlerFunc) http.HandlerFunc { - var handler http.Handler - handler = http.HandlerFunc(handlerFunc) - for _, metric := range metrics { - switch metric.handlerType { - case InstrumentHandlerResponseSize: - if collector, ok := metric.Collector.(prometheus.ObserverVec); ok { - handler = promhttp.InstrumentHandlerResponseSize(collector, handler) - } - case InstrumentHandlerRequestSize: - if collector, ok := metric.Collector.(prometheus.ObserverVec); ok { - handler = promhttp.InstrumentHandlerRequestSize(collector, handler) - } - case InstrumentHandlerDuration: - if collector, ok := metric.Collector.(prometheus.ObserverVec); ok { - handler = promhttp.InstrumentHandlerDuration(collector, handler) - } - case InstrumentHandlerCounter: - if collector, ok := metric.Collector.(*prometheus.CounterVec); ok { - handler = promhttp.InstrumentHandlerCounter(collector, handler) - } - case InstrumentHandlerInFlight: - if collector, ok := metric.Collector.(prometheus.Gauge); ok { - handler = promhttp.InstrumentHandlerInFlight(collector, handler) - } - } - } - return handler.ServeHTTP -} diff --git a/vendor/github.com/docker/go-metrics/helpers.go b/vendor/github.com/docker/go-metrics/helpers.go deleted file mode 100644 index 68b7f51b33..0000000000 --- a/vendor/github.com/docker/go-metrics/helpers.go +++ /dev/null @@ -1,10 +0,0 @@ -package metrics - -func sumFloat64(vs ...float64) float64 { - var sum float64 - for _, v := range vs { - sum += v - } - - return sum -} diff --git a/vendor/github.com/docker/go-metrics/namespace.go b/vendor/github.com/docker/go-metrics/namespace.go deleted file mode 100644 index 798315451a..0000000000 --- a/vendor/github.com/docker/go-metrics/namespace.go +++ /dev/null @@ -1,315 +0,0 @@ -package metrics - -import ( - "fmt" - "sync" - - "github.com/prometheus/client_golang/prometheus" -) - -type Labels map[string]string - -// NewNamespace returns a namespaces that is responsible for managing a collection of -// metrics for a particual namespace and subsystem -// -// labels allows const labels to be added to all metrics created in this namespace -// and are commonly used for data like application version and git commit -func NewNamespace(name, subsystem string, labels Labels) *Namespace { - if labels == nil { - labels = make(map[string]string) - } - return &Namespace{ - name: name, - subsystem: subsystem, - labels: labels, - } -} - -// Namespace describes a set of metrics that share a namespace and subsystem. -type Namespace struct { - name string - subsystem string - labels Labels - mu sync.Mutex - metrics []prometheus.Collector -} - -// WithConstLabels returns a namespace with the provided set of labels merged -// with the existing constant labels on the namespace. -// -// Only metrics created with the returned namespace will get the new constant -// labels. The returned namespace must be registered separately. -func (n *Namespace) WithConstLabels(labels Labels) *Namespace { - n.mu.Lock() - ns := &Namespace{ - name: n.name, - subsystem: n.subsystem, - labels: mergeLabels(n.labels, labels), - } - n.mu.Unlock() - return ns -} - -func (n *Namespace) NewCounter(name, help string) Counter { - c := &counter{pc: prometheus.NewCounter(n.newCounterOpts(name, help))} - n.Add(c) - return c -} - -func (n *Namespace) NewLabeledCounter(name, help string, labels ...string) LabeledCounter { - c := &labeledCounter{pc: prometheus.NewCounterVec(n.newCounterOpts(name, help), labels)} - n.Add(c) - return c -} - -func (n *Namespace) newCounterOpts(name, help string) prometheus.CounterOpts { - return prometheus.CounterOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: makeName(name, Total), - Help: help, - ConstLabels: prometheus.Labels(n.labels), - } -} - -func (n *Namespace) NewTimer(name, help string) Timer { - t := &timer{ - m: prometheus.NewHistogram(n.newTimerOpts(name, help)), - } - n.Add(t) - return t -} - -func (n *Namespace) NewLabeledTimer(name, help string, labels ...string) LabeledTimer { - t := &labeledTimer{ - m: prometheus.NewHistogramVec(n.newTimerOpts(name, help), labels), - } - n.Add(t) - return t -} - -func (n *Namespace) newTimerOpts(name, help string) prometheus.HistogramOpts { - return prometheus.HistogramOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: makeName(name, Seconds), - Help: help, - ConstLabels: prometheus.Labels(n.labels), - } -} - -func (n *Namespace) NewGauge(name, help string, unit Unit) Gauge { - g := &gauge{ - pg: prometheus.NewGauge(n.newGaugeOpts(name, help, unit)), - } - n.Add(g) - return g -} - -func (n *Namespace) NewLabeledGauge(name, help string, unit Unit, labels ...string) LabeledGauge { - g := &labeledGauge{ - pg: prometheus.NewGaugeVec(n.newGaugeOpts(name, help, unit), labels), - } - n.Add(g) - return g -} - -func (n *Namespace) newGaugeOpts(name, help string, unit Unit) prometheus.GaugeOpts { - return prometheus.GaugeOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: makeName(name, unit), - Help: help, - ConstLabels: prometheus.Labels(n.labels), - } -} - -func (n *Namespace) Describe(ch chan<- *prometheus.Desc) { - n.mu.Lock() - defer n.mu.Unlock() - - for _, metric := range n.metrics { - metric.Describe(ch) - } -} - -func (n *Namespace) Collect(ch chan<- prometheus.Metric) { - n.mu.Lock() - defer n.mu.Unlock() - - for _, metric := range n.metrics { - metric.Collect(ch) - } -} - -func (n *Namespace) Add(collector prometheus.Collector) { - n.mu.Lock() - n.metrics = append(n.metrics, collector) - n.mu.Unlock() -} - -func (n *Namespace) NewDesc(name, help string, unit Unit, labels ...string) *prometheus.Desc { - name = makeName(name, unit) - namespace := n.name - if n.subsystem != "" { - namespace = fmt.Sprintf("%s_%s", namespace, n.subsystem) - } - name = fmt.Sprintf("%s_%s", namespace, name) - return prometheus.NewDesc(name, help, labels, prometheus.Labels(n.labels)) -} - -// mergeLabels merges two or more labels objects into a single map, favoring -// the later labels. -func mergeLabels(lbs ...Labels) Labels { - merged := make(Labels) - - for _, target := range lbs { - for k, v := range target { - merged[k] = v - } - } - - return merged -} - -func makeName(name string, unit Unit) string { - if unit == "" { - return name - } - - return fmt.Sprintf("%s_%s", name, unit) -} - -func (n *Namespace) NewDefaultHttpMetrics(handlerName string) []*HTTPMetric { - return n.NewHttpMetricsWithOpts(handlerName, HTTPHandlerOpts{ - DurationBuckets: defaultDurationBuckets, - RequestSizeBuckets: defaultResponseSizeBuckets, - ResponseSizeBuckets: defaultResponseSizeBuckets, - }) -} - -func (n *Namespace) NewHttpMetrics(handlerName string, durationBuckets, requestSizeBuckets, responseSizeBuckets []float64) []*HTTPMetric { - return n.NewHttpMetricsWithOpts(handlerName, HTTPHandlerOpts{ - DurationBuckets: durationBuckets, - RequestSizeBuckets: requestSizeBuckets, - ResponseSizeBuckets: responseSizeBuckets, - }) -} - -func (n *Namespace) NewHttpMetricsWithOpts(handlerName string, opts HTTPHandlerOpts) []*HTTPMetric { - var httpMetrics []*HTTPMetric - inFlightMetric := n.NewInFlightGaugeMetric(handlerName) - requestTotalMetric := n.NewRequestTotalMetric(handlerName) - requestDurationMetric := n.NewRequestDurationMetric(handlerName, opts.DurationBuckets) - requestSizeMetric := n.NewRequestSizeMetric(handlerName, opts.RequestSizeBuckets) - responseSizeMetric := n.NewResponseSizeMetric(handlerName, opts.ResponseSizeBuckets) - httpMetrics = append(httpMetrics, inFlightMetric, requestDurationMetric, requestTotalMetric, requestSizeMetric, responseSizeMetric) - return httpMetrics -} - -func (n *Namespace) NewInFlightGaugeMetric(handlerName string) *HTTPMetric { - labels := prometheus.Labels(n.labels) - labels["handler"] = handlerName - metric := prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: "in_flight_requests", - Help: "The in-flight HTTP requests", - ConstLabels: prometheus.Labels(labels), - }) - httpMetric := &HTTPMetric{ - Collector: metric, - handlerType: InstrumentHandlerInFlight, - } - n.Add(httpMetric) - return httpMetric -} - -func (n *Namespace) NewRequestTotalMetric(handlerName string) *HTTPMetric { - labels := prometheus.Labels(n.labels) - labels["handler"] = handlerName - metric := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: prometheus.Labels(labels), - }, - []string{"code", "method"}, - ) - httpMetric := &HTTPMetric{ - Collector: metric, - handlerType: InstrumentHandlerCounter, - } - n.Add(httpMetric) - return httpMetric -} -func (n *Namespace) NewRequestDurationMetric(handlerName string, buckets []float64) *HTTPMetric { - if len(buckets) == 0 { - panic("DurationBuckets must be provided") - } - labels := prometheus.Labels(n.labels) - labels["handler"] = handlerName - opts := prometheus.HistogramOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: "request_duration_seconds", - Help: "The HTTP request latencies in seconds.", - Buckets: buckets, - ConstLabels: prometheus.Labels(labels), - } - metric := prometheus.NewHistogramVec(opts, []string{"method"}) - httpMetric := &HTTPMetric{ - Collector: metric, - handlerType: InstrumentHandlerDuration, - } - n.Add(httpMetric) - return httpMetric -} - -func (n *Namespace) NewRequestSizeMetric(handlerName string, buckets []float64) *HTTPMetric { - if len(buckets) == 0 { - panic("RequestSizeBuckets must be provided") - } - labels := prometheus.Labels(n.labels) - labels["handler"] = handlerName - opts := prometheus.HistogramOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: "request_size_bytes", - Help: "The HTTP request sizes in bytes.", - Buckets: buckets, - ConstLabels: prometheus.Labels(labels), - } - metric := prometheus.NewHistogramVec(opts, []string{}) - httpMetric := &HTTPMetric{ - Collector: metric, - handlerType: InstrumentHandlerRequestSize, - } - n.Add(httpMetric) - return httpMetric -} - -func (n *Namespace) NewResponseSizeMetric(handlerName string, buckets []float64) *HTTPMetric { - if len(buckets) == 0 { - panic("ResponseSizeBuckets must be provided") - } - labels := prometheus.Labels(n.labels) - labels["handler"] = handlerName - opts := prometheus.HistogramOpts{ - Namespace: n.name, - Subsystem: n.subsystem, - Name: "response_size_bytes", - Help: "The HTTP response sizes in bytes.", - Buckets: buckets, - ConstLabels: prometheus.Labels(labels), - } - metrics := prometheus.NewHistogramVec(opts, []string{}) - httpMetric := &HTTPMetric{ - Collector: metrics, - handlerType: InstrumentHandlerResponseSize, - } - n.Add(httpMetric) - return httpMetric -} diff --git a/vendor/github.com/docker/go-metrics/register.go b/vendor/github.com/docker/go-metrics/register.go deleted file mode 100644 index 708358df01..0000000000 --- a/vendor/github.com/docker/go-metrics/register.go +++ /dev/null @@ -1,15 +0,0 @@ -package metrics - -import "github.com/prometheus/client_golang/prometheus" - -// Register adds all the metrics in the provided namespace to the global -// metrics registry -func Register(n *Namespace) { - prometheus.MustRegister(n) -} - -// Deregister removes all the metrics in the provided namespace from the -// global metrics registry -func Deregister(n *Namespace) { - prometheus.Unregister(n) -} diff --git a/vendor/github.com/docker/go-metrics/timer.go b/vendor/github.com/docker/go-metrics/timer.go deleted file mode 100644 index 824c98739c..0000000000 --- a/vendor/github.com/docker/go-metrics/timer.go +++ /dev/null @@ -1,85 +0,0 @@ -package metrics - -import ( - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -// StartTimer begins a timer observation at the callsite. When the target -// operation is completed, the caller should call the return done func(). -func StartTimer(timer Timer) (done func()) { - start := time.Now() - return func() { - timer.Update(time.Since(start)) - } -} - -// Timer is a metric that allows collecting the duration of an action in seconds -type Timer interface { - // Update records an observation, duration, and converts to the target - // units. - Update(duration time.Duration) - - // UpdateSince will add the duration from the provided starting time to the - // timer's summary with the precisions that was used in creation of the timer - UpdateSince(time.Time) -} - -// LabeledTimer is a timer that must have label values populated before use. -type LabeledTimer interface { - WithValues(labels ...string) *labeledTimerObserver -} - -type labeledTimer struct { - m *prometheus.HistogramVec -} - -type labeledTimerObserver struct { - m prometheus.Observer -} - -func (lbo *labeledTimerObserver) Update(duration time.Duration) { - lbo.m.Observe(duration.Seconds()) -} - -func (lbo *labeledTimerObserver) UpdateSince(since time.Time) { - lbo.m.Observe(time.Since(since).Seconds()) -} - -func (lt *labeledTimer) WithValues(labels ...string) *labeledTimerObserver { - return &labeledTimerObserver{m: lt.m.WithLabelValues(labels...)} -} - -func (lt *labeledTimer) Describe(c chan<- *prometheus.Desc) { - lt.m.Describe(c) -} - -func (lt *labeledTimer) Collect(c chan<- prometheus.Metric) { - lt.m.Collect(c) -} - -type timer struct { - m prometheus.Observer -} - -func (t *timer) Update(duration time.Duration) { - t.m.Observe(duration.Seconds()) -} - -func (t *timer) UpdateSince(since time.Time) { - t.m.Observe(time.Since(since).Seconds()) -} - -func (t *timer) Describe(c chan<- *prometheus.Desc) { - c <- t.m.(prometheus.Metric).Desc() -} - -func (t *timer) Collect(c chan<- prometheus.Metric) { - // Are there any observers that don't implement Collector? It is really - // unclear what the point of the upstream change was, but we'll let this - // panic if we get an observer that doesn't implement collector. In this - // case, we should almost always see metricVec objects, so this should - // never panic. - t.m.(prometheus.Collector).Collect(c) -} diff --git a/vendor/github.com/docker/go-metrics/unit.go b/vendor/github.com/docker/go-metrics/unit.go deleted file mode 100644 index c96622f903..0000000000 --- a/vendor/github.com/docker/go-metrics/unit.go +++ /dev/null @@ -1,12 +0,0 @@ -package metrics - -// Unit represents the type or precision of a metric that is appended to -// the metrics fully qualified name -type Unit string - -const ( - Nanoseconds Unit = "nanoseconds" - Seconds Unit = "seconds" - Bytes Unit = "bytes" - Total Unit = "total" -) diff --git a/vendor/github.com/docker/libtrust/LICENSE b/vendor/github.com/docker/libtrust/LICENSE deleted file mode 100644 index 27448585ad..0000000000 --- a/vendor/github.com/docker/libtrust/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/docker/libtrust/certificates.go b/vendor/github.com/docker/libtrust/certificates.go deleted file mode 100644 index 3dcca33cb1..0000000000 --- a/vendor/github.com/docker/libtrust/certificates.go +++ /dev/null @@ -1,175 +0,0 @@ -package libtrust - -import ( - "crypto/rand" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "io/ioutil" - "math/big" - "net" - "time" -) - -type certTemplateInfo struct { - commonName string - domains []string - ipAddresses []net.IP - isCA bool - clientAuth bool - serverAuth bool -} - -func generateCertTemplate(info *certTemplateInfo) *x509.Certificate { - // Generate a certificate template which is valid from the past week to - // 10 years from now. The usage of the certificate depends on the - // specified fields in the given certTempInfo object. - var ( - keyUsage x509.KeyUsage - extKeyUsage []x509.ExtKeyUsage - ) - - if info.isCA { - keyUsage = x509.KeyUsageCertSign - } - - if info.clientAuth { - extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageClientAuth) - } - - if info.serverAuth { - extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageServerAuth) - } - - return &x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{ - CommonName: info.commonName, - }, - NotBefore: time.Now().Add(-time.Hour * 24 * 7), - NotAfter: time.Now().Add(time.Hour * 24 * 365 * 10), - DNSNames: info.domains, - IPAddresses: info.ipAddresses, - IsCA: info.isCA, - KeyUsage: keyUsage, - ExtKeyUsage: extKeyUsage, - BasicConstraintsValid: info.isCA, - } -} - -func generateCert(pub PublicKey, priv PrivateKey, subInfo, issInfo *certTemplateInfo) (cert *x509.Certificate, err error) { - pubCertTemplate := generateCertTemplate(subInfo) - privCertTemplate := generateCertTemplate(issInfo) - - certDER, err := x509.CreateCertificate( - rand.Reader, pubCertTemplate, privCertTemplate, - pub.CryptoPublicKey(), priv.CryptoPrivateKey(), - ) - if err != nil { - return nil, fmt.Errorf("failed to create certificate: %s", err) - } - - cert, err = x509.ParseCertificate(certDER) - if err != nil { - return nil, fmt.Errorf("failed to parse certificate: %s", err) - } - - return -} - -// GenerateSelfSignedServerCert creates a self-signed certificate for the -// given key which is to be used for TLS servers with the given domains and -// IP addresses. -func GenerateSelfSignedServerCert(key PrivateKey, domains []string, ipAddresses []net.IP) (*x509.Certificate, error) { - info := &certTemplateInfo{ - commonName: key.KeyID(), - domains: domains, - ipAddresses: ipAddresses, - serverAuth: true, - } - - return generateCert(key.PublicKey(), key, info, info) -} - -// GenerateSelfSignedClientCert creates a self-signed certificate for the -// given key which is to be used for TLS clients. -func GenerateSelfSignedClientCert(key PrivateKey) (*x509.Certificate, error) { - info := &certTemplateInfo{ - commonName: key.KeyID(), - clientAuth: true, - } - - return generateCert(key.PublicKey(), key, info, info) -} - -// GenerateCACert creates a certificate which can be used as a trusted -// certificate authority. -func GenerateCACert(signer PrivateKey, trustedKey PublicKey) (*x509.Certificate, error) { - subjectInfo := &certTemplateInfo{ - commonName: trustedKey.KeyID(), - isCA: true, - } - issuerInfo := &certTemplateInfo{ - commonName: signer.KeyID(), - } - - return generateCert(trustedKey, signer, subjectInfo, issuerInfo) -} - -// GenerateCACertPool creates a certificate authority pool to be used for a -// TLS configuration. Any self-signed certificates issued by the specified -// trusted keys will be verified during a TLS handshake -func GenerateCACertPool(signer PrivateKey, trustedKeys []PublicKey) (*x509.CertPool, error) { - certPool := x509.NewCertPool() - - for _, trustedKey := range trustedKeys { - cert, err := GenerateCACert(signer, trustedKey) - if err != nil { - return nil, fmt.Errorf("failed to generate CA certificate: %s", err) - } - - certPool.AddCert(cert) - } - - return certPool, nil -} - -// LoadCertificateBundle loads certificates from the given file. The file should be pem encoded -// containing one or more certificates. The expected pem type is "CERTIFICATE". -func LoadCertificateBundle(filename string) ([]*x509.Certificate, error) { - b, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - certificates := []*x509.Certificate{} - var block *pem.Block - block, b = pem.Decode(b) - for ; block != nil; block, b = pem.Decode(b) { - if block.Type == "CERTIFICATE" { - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, err - } - certificates = append(certificates, cert) - } else { - return nil, fmt.Errorf("invalid pem block type: %s", block.Type) - } - } - - return certificates, nil -} - -// LoadCertificatePool loads a CA pool from the given file. The file should be pem encoded -// containing one or more certificates. The expected pem type is "CERTIFICATE". -func LoadCertificatePool(filename string) (*x509.CertPool, error) { - certs, err := LoadCertificateBundle(filename) - if err != nil { - return nil, err - } - pool := x509.NewCertPool() - for _, cert := range certs { - pool.AddCert(cert) - } - return pool, nil -} diff --git a/vendor/github.com/docker/libtrust/doc.go b/vendor/github.com/docker/libtrust/doc.go deleted file mode 100644 index ec5d2159c1..0000000000 --- a/vendor/github.com/docker/libtrust/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -/* -Package libtrust provides an interface for managing authentication and -authorization using public key cryptography. Authentication is handled -using the identity attached to the public key and verified through TLS -x509 certificates, a key challenge, or signature. Authorization and -access control is managed through a trust graph distributed between -both remote trust servers and locally cached and managed data. -*/ -package libtrust diff --git a/vendor/github.com/docker/libtrust/ec_key.go b/vendor/github.com/docker/libtrust/ec_key.go deleted file mode 100644 index 00bbe4b3ca..0000000000 --- a/vendor/github.com/docker/libtrust/ec_key.go +++ /dev/null @@ -1,428 +0,0 @@ -package libtrust - -import ( - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "io" - "math/big" -) - -/* - * EC DSA PUBLIC KEY - */ - -// ecPublicKey implements a libtrust.PublicKey using elliptic curve digital -// signature algorithms. -type ecPublicKey struct { - *ecdsa.PublicKey - curveName string - signatureAlgorithm *signatureAlgorithm - extended map[string]interface{} -} - -func fromECPublicKey(cryptoPublicKey *ecdsa.PublicKey) (*ecPublicKey, error) { - curve := cryptoPublicKey.Curve - - switch { - case curve == elliptic.P256(): - return &ecPublicKey{cryptoPublicKey, "P-256", es256, map[string]interface{}{}}, nil - case curve == elliptic.P384(): - return &ecPublicKey{cryptoPublicKey, "P-384", es384, map[string]interface{}{}}, nil - case curve == elliptic.P521(): - return &ecPublicKey{cryptoPublicKey, "P-521", es512, map[string]interface{}{}}, nil - default: - return nil, errors.New("unsupported elliptic curve") - } -} - -// KeyType returns the key type for elliptic curve keys, i.e., "EC". -func (k *ecPublicKey) KeyType() string { - return "EC" -} - -// CurveName returns the elliptic curve identifier. -// Possible values are "P-256", "P-384", and "P-521". -func (k *ecPublicKey) CurveName() string { - return k.curveName -} - -// KeyID returns a distinct identifier which is unique to this Public Key. -func (k *ecPublicKey) KeyID() string { - return keyIDFromCryptoKey(k) -} - -func (k *ecPublicKey) String() string { - return fmt.Sprintf("EC Public Key <%s>", k.KeyID()) -} - -// Verify verifyies the signature of the data in the io.Reader using this -// PublicKey. The alg parameter should identify the digital signature -// algorithm which was used to produce the signature and should be supported -// by this public key. Returns a nil error if the signature is valid. -func (k *ecPublicKey) Verify(data io.Reader, alg string, signature []byte) error { - // For EC keys there is only one supported signature algorithm depending - // on the curve parameters. - if k.signatureAlgorithm.HeaderParam() != alg { - return fmt.Errorf("unable to verify signature: EC Public Key with curve %q does not support signature algorithm %q", k.curveName, alg) - } - - // signature is the concatenation of (r, s), base64Url encoded. - sigLength := len(signature) - expectedOctetLength := 2 * ((k.Params().BitSize + 7) >> 3) - if sigLength != expectedOctetLength { - return fmt.Errorf("signature length is %d octets long, should be %d", sigLength, expectedOctetLength) - } - - rBytes, sBytes := signature[:sigLength/2], signature[sigLength/2:] - r := new(big.Int).SetBytes(rBytes) - s := new(big.Int).SetBytes(sBytes) - - hasher := k.signatureAlgorithm.HashID().New() - _, err := io.Copy(hasher, data) - if err != nil { - return fmt.Errorf("error reading data to sign: %s", err) - } - hash := hasher.Sum(nil) - - if !ecdsa.Verify(k.PublicKey, hash, r, s) { - return errors.New("invalid signature") - } - - return nil -} - -// CryptoPublicKey returns the internal object which can be used as a -// crypto.PublicKey for use with other standard library operations. The type -// is either *rsa.PublicKey or *ecdsa.PublicKey -func (k *ecPublicKey) CryptoPublicKey() crypto.PublicKey { - return k.PublicKey -} - -func (k *ecPublicKey) toMap() map[string]interface{} { - jwk := make(map[string]interface{}) - for k, v := range k.extended { - jwk[k] = v - } - jwk["kty"] = k.KeyType() - jwk["kid"] = k.KeyID() - jwk["crv"] = k.CurveName() - - xBytes := k.X.Bytes() - yBytes := k.Y.Bytes() - octetLength := (k.Params().BitSize + 7) >> 3 - // MUST include leading zeros in the output so that x, y are each - // *octetLength* bytes long. - xBuf := make([]byte, octetLength-len(xBytes), octetLength) - yBuf := make([]byte, octetLength-len(yBytes), octetLength) - xBuf = append(xBuf, xBytes...) - yBuf = append(yBuf, yBytes...) - - jwk["x"] = joseBase64UrlEncode(xBuf) - jwk["y"] = joseBase64UrlEncode(yBuf) - - return jwk -} - -// MarshalJSON serializes this Public Key using the JWK JSON serialization format for -// elliptic curve keys. -func (k *ecPublicKey) MarshalJSON() (data []byte, err error) { - return json.Marshal(k.toMap()) -} - -// PEMBlock serializes this Public Key to DER-encoded PKIX format. -func (k *ecPublicKey) PEMBlock() (*pem.Block, error) { - derBytes, err := x509.MarshalPKIXPublicKey(k.PublicKey) - if err != nil { - return nil, fmt.Errorf("unable to serialize EC PublicKey to DER-encoded PKIX format: %s", err) - } - k.extended["kid"] = k.KeyID() // For display purposes. - return createPemBlock("PUBLIC KEY", derBytes, k.extended) -} - -func (k *ecPublicKey) AddExtendedField(field string, value interface{}) { - k.extended[field] = value -} - -func (k *ecPublicKey) GetExtendedField(field string) interface{} { - v, ok := k.extended[field] - if !ok { - return nil - } - return v -} - -func ecPublicKeyFromMap(jwk map[string]interface{}) (*ecPublicKey, error) { - // JWK key type (kty) has already been determined to be "EC". - // Need to extract 'crv', 'x', 'y', and 'kid' and check for - // consistency. - - // Get the curve identifier value. - crv, err := stringFromMap(jwk, "crv") - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key curve identifier: %s", err) - } - - var ( - curve elliptic.Curve - sigAlg *signatureAlgorithm - ) - - switch { - case crv == "P-256": - curve = elliptic.P256() - sigAlg = es256 - case crv == "P-384": - curve = elliptic.P384() - sigAlg = es384 - case crv == "P-521": - curve = elliptic.P521() - sigAlg = es512 - default: - return nil, fmt.Errorf("JWK EC Public Key curve identifier not supported: %q\n", crv) - } - - // Get the X and Y coordinates for the public key point. - xB64Url, err := stringFromMap(jwk, "x") - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key x-coordinate: %s", err) - } - x, err := parseECCoordinate(xB64Url, curve) - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key x-coordinate: %s", err) - } - - yB64Url, err := stringFromMap(jwk, "y") - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key y-coordinate: %s", err) - } - y, err := parseECCoordinate(yB64Url, curve) - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key y-coordinate: %s", err) - } - - key := &ecPublicKey{ - PublicKey: &ecdsa.PublicKey{Curve: curve, X: x, Y: y}, - curveName: crv, signatureAlgorithm: sigAlg, - } - - // Key ID is optional too, but if it exists, it should match the key. - _, ok := jwk["kid"] - if ok { - kid, err := stringFromMap(jwk, "kid") - if err != nil { - return nil, fmt.Errorf("JWK EC Public Key ID: %s", err) - } - if kid != key.KeyID() { - return nil, fmt.Errorf("JWK EC Public Key ID does not match: %s", kid) - } - } - - key.extended = jwk - - return key, nil -} - -/* - * EC DSA PRIVATE KEY - */ - -// ecPrivateKey implements a JWK Private Key using elliptic curve digital signature -// algorithms. -type ecPrivateKey struct { - ecPublicKey - *ecdsa.PrivateKey -} - -func fromECPrivateKey(cryptoPrivateKey *ecdsa.PrivateKey) (*ecPrivateKey, error) { - publicKey, err := fromECPublicKey(&cryptoPrivateKey.PublicKey) - if err != nil { - return nil, err - } - - return &ecPrivateKey{*publicKey, cryptoPrivateKey}, nil -} - -// PublicKey returns the Public Key data associated with this Private Key. -func (k *ecPrivateKey) PublicKey() PublicKey { - return &k.ecPublicKey -} - -func (k *ecPrivateKey) String() string { - return fmt.Sprintf("EC Private Key <%s>", k.KeyID()) -} - -// Sign signs the data read from the io.Reader using a signature algorithm supported -// by the elliptic curve private key. If the specified hashing algorithm is -// supported by this key, that hash function is used to generate the signature -// otherwise the the default hashing algorithm for this key is used. Returns -// the signature and the name of the JWK signature algorithm used, e.g., -// "ES256", "ES384", "ES512". -func (k *ecPrivateKey) Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error) { - // Generate a signature of the data using the internal alg. - // The given hashId is only a suggestion, and since EC keys only support - // on signature/hash algorithm given the curve name, we disregard it for - // the elliptic curve JWK signature implementation. - hasher := k.signatureAlgorithm.HashID().New() - _, err = io.Copy(hasher, data) - if err != nil { - return nil, "", fmt.Errorf("error reading data to sign: %s", err) - } - hash := hasher.Sum(nil) - - r, s, err := ecdsa.Sign(rand.Reader, k.PrivateKey, hash) - if err != nil { - return nil, "", fmt.Errorf("error producing signature: %s", err) - } - rBytes, sBytes := r.Bytes(), s.Bytes() - octetLength := (k.ecPublicKey.Params().BitSize + 7) >> 3 - // MUST include leading zeros in the output - rBuf := make([]byte, octetLength-len(rBytes), octetLength) - sBuf := make([]byte, octetLength-len(sBytes), octetLength) - - rBuf = append(rBuf, rBytes...) - sBuf = append(sBuf, sBytes...) - - signature = append(rBuf, sBuf...) - alg = k.signatureAlgorithm.HeaderParam() - - return -} - -// CryptoPrivateKey returns the internal object which can be used as a -// crypto.PublicKey for use with other standard library operations. The type -// is either *rsa.PublicKey or *ecdsa.PublicKey -func (k *ecPrivateKey) CryptoPrivateKey() crypto.PrivateKey { - return k.PrivateKey -} - -func (k *ecPrivateKey) toMap() map[string]interface{} { - jwk := k.ecPublicKey.toMap() - - dBytes := k.D.Bytes() - // The length of this octet string MUST be ceiling(log-base-2(n)/8) - // octets (where n is the order of the curve). This is because the private - // key d must be in the interval [1, n-1] so the bitlength of d should be - // no larger than the bitlength of n-1. The easiest way to find the octet - // length is to take bitlength(n-1), add 7 to force a carry, and shift this - // bit sequence right by 3, which is essentially dividing by 8 and adding - // 1 if there is any remainder. Thus, the private key value d should be - // output to (bitlength(n-1)+7)>>3 octets. - n := k.ecPublicKey.Params().N - octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3 - // Create a buffer with the necessary zero-padding. - dBuf := make([]byte, octetLength-len(dBytes), octetLength) - dBuf = append(dBuf, dBytes...) - - jwk["d"] = joseBase64UrlEncode(dBuf) - - return jwk -} - -// MarshalJSON serializes this Private Key using the JWK JSON serialization format for -// elliptic curve keys. -func (k *ecPrivateKey) MarshalJSON() (data []byte, err error) { - return json.Marshal(k.toMap()) -} - -// PEMBlock serializes this Private Key to DER-encoded PKIX format. -func (k *ecPrivateKey) PEMBlock() (*pem.Block, error) { - derBytes, err := x509.MarshalECPrivateKey(k.PrivateKey) - if err != nil { - return nil, fmt.Errorf("unable to serialize EC PrivateKey to DER-encoded PKIX format: %s", err) - } - k.extended["keyID"] = k.KeyID() // For display purposes. - return createPemBlock("EC PRIVATE KEY", derBytes, k.extended) -} - -func ecPrivateKeyFromMap(jwk map[string]interface{}) (*ecPrivateKey, error) { - dB64Url, err := stringFromMap(jwk, "d") - if err != nil { - return nil, fmt.Errorf("JWK EC Private Key: %s", err) - } - - // JWK key type (kty) has already been determined to be "EC". - // Need to extract the public key information, then extract the private - // key value 'd'. - publicKey, err := ecPublicKeyFromMap(jwk) - if err != nil { - return nil, err - } - - d, err := parseECPrivateParam(dB64Url, publicKey.Curve) - if err != nil { - return nil, fmt.Errorf("JWK EC Private Key d-param: %s", err) - } - - key := &ecPrivateKey{ - ecPublicKey: *publicKey, - PrivateKey: &ecdsa.PrivateKey{ - PublicKey: *publicKey.PublicKey, - D: d, - }, - } - - return key, nil -} - -/* - * Key Generation Functions. - */ - -func generateECPrivateKey(curve elliptic.Curve) (k *ecPrivateKey, err error) { - k = new(ecPrivateKey) - k.PrivateKey, err = ecdsa.GenerateKey(curve, rand.Reader) - if err != nil { - return nil, err - } - - k.ecPublicKey.PublicKey = &k.PrivateKey.PublicKey - k.extended = make(map[string]interface{}) - - return -} - -// GenerateECP256PrivateKey generates a key pair using elliptic curve P-256. -func GenerateECP256PrivateKey() (PrivateKey, error) { - k, err := generateECPrivateKey(elliptic.P256()) - if err != nil { - return nil, fmt.Errorf("error generating EC P-256 key: %s", err) - } - - k.curveName = "P-256" - k.signatureAlgorithm = es256 - - return k, nil -} - -// GenerateECP384PrivateKey generates a key pair using elliptic curve P-384. -func GenerateECP384PrivateKey() (PrivateKey, error) { - k, err := generateECPrivateKey(elliptic.P384()) - if err != nil { - return nil, fmt.Errorf("error generating EC P-384 key: %s", err) - } - - k.curveName = "P-384" - k.signatureAlgorithm = es384 - - return k, nil -} - -// GenerateECP521PrivateKey generates aß key pair using elliptic curve P-521. -func GenerateECP521PrivateKey() (PrivateKey, error) { - k, err := generateECPrivateKey(elliptic.P521()) - if err != nil { - return nil, fmt.Errorf("error generating EC P-521 key: %s", err) - } - - k.curveName = "P-521" - k.signatureAlgorithm = es512 - - return k, nil -} diff --git a/vendor/github.com/docker/libtrust/filter.go b/vendor/github.com/docker/libtrust/filter.go deleted file mode 100644 index 5b2b4fca6f..0000000000 --- a/vendor/github.com/docker/libtrust/filter.go +++ /dev/null @@ -1,50 +0,0 @@ -package libtrust - -import ( - "path/filepath" -) - -// FilterByHosts filters the list of PublicKeys to only those which contain a -// 'hosts' pattern which matches the given host. If *includeEmpty* is true, -// then keys which do not specify any hosts are also returned. -func FilterByHosts(keys []PublicKey, host string, includeEmpty bool) ([]PublicKey, error) { - filtered := make([]PublicKey, 0, len(keys)) - - for _, pubKey := range keys { - var hosts []string - switch v := pubKey.GetExtendedField("hosts").(type) { - case []string: - hosts = v - case []interface{}: - for _, value := range v { - h, ok := value.(string) - if !ok { - continue - } - hosts = append(hosts, h) - } - } - - if len(hosts) == 0 { - if includeEmpty { - filtered = append(filtered, pubKey) - } - continue - } - - // Check if any hosts match pattern - for _, hostPattern := range hosts { - match, err := filepath.Match(hostPattern, host) - if err != nil { - return nil, err - } - - if match { - filtered = append(filtered, pubKey) - continue - } - } - } - - return filtered, nil -} diff --git a/vendor/github.com/docker/libtrust/hash.go b/vendor/github.com/docker/libtrust/hash.go deleted file mode 100644 index a2df787dd9..0000000000 --- a/vendor/github.com/docker/libtrust/hash.go +++ /dev/null @@ -1,56 +0,0 @@ -package libtrust - -import ( - "crypto" - _ "crypto/sha256" // Registrer SHA224 and SHA256 - _ "crypto/sha512" // Registrer SHA384 and SHA512 - "fmt" -) - -type signatureAlgorithm struct { - algHeaderParam string - hashID crypto.Hash -} - -func (h *signatureAlgorithm) HeaderParam() string { - return h.algHeaderParam -} - -func (h *signatureAlgorithm) HashID() crypto.Hash { - return h.hashID -} - -var ( - rs256 = &signatureAlgorithm{"RS256", crypto.SHA256} - rs384 = &signatureAlgorithm{"RS384", crypto.SHA384} - rs512 = &signatureAlgorithm{"RS512", crypto.SHA512} - es256 = &signatureAlgorithm{"ES256", crypto.SHA256} - es384 = &signatureAlgorithm{"ES384", crypto.SHA384} - es512 = &signatureAlgorithm{"ES512", crypto.SHA512} -) - -func rsaSignatureAlgorithmByName(alg string) (*signatureAlgorithm, error) { - switch { - case alg == "RS256": - return rs256, nil - case alg == "RS384": - return rs384, nil - case alg == "RS512": - return rs512, nil - default: - return nil, fmt.Errorf("RSA Digital Signature Algorithm %q not supported", alg) - } -} - -func rsaPKCS1v15SignatureAlgorithmForHashID(hashID crypto.Hash) *signatureAlgorithm { - switch { - case hashID == crypto.SHA512: - return rs512 - case hashID == crypto.SHA384: - return rs384 - case hashID == crypto.SHA256: - fallthrough - default: - return rs256 - } -} diff --git a/vendor/github.com/docker/libtrust/jsonsign.go b/vendor/github.com/docker/libtrust/jsonsign.go deleted file mode 100644 index cb2ca9a769..0000000000 --- a/vendor/github.com/docker/libtrust/jsonsign.go +++ /dev/null @@ -1,657 +0,0 @@ -package libtrust - -import ( - "bytes" - "crypto" - "crypto/x509" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "sort" - "time" - "unicode" -) - -var ( - // ErrInvalidSignContent is used when the content to be signed is invalid. - ErrInvalidSignContent = errors.New("invalid sign content") - - // ErrInvalidJSONContent is used when invalid json is encountered. - ErrInvalidJSONContent = errors.New("invalid json content") - - // ErrMissingSignatureKey is used when the specified signature key - // does not exist in the JSON content. - ErrMissingSignatureKey = errors.New("missing signature key") -) - -type jsHeader struct { - JWK PublicKey `json:"jwk,omitempty"` - Algorithm string `json:"alg"` - Chain []string `json:"x5c,omitempty"` -} - -type jsSignature struct { - Header jsHeader `json:"header"` - Signature string `json:"signature"` - Protected string `json:"protected,omitempty"` -} - -type jsSignaturesSorted []jsSignature - -func (jsbkid jsSignaturesSorted) Swap(i, j int) { jsbkid[i], jsbkid[j] = jsbkid[j], jsbkid[i] } -func (jsbkid jsSignaturesSorted) Len() int { return len(jsbkid) } - -func (jsbkid jsSignaturesSorted) Less(i, j int) bool { - ki, kj := jsbkid[i].Header.JWK.KeyID(), jsbkid[j].Header.JWK.KeyID() - si, sj := jsbkid[i].Signature, jsbkid[j].Signature - - if ki == kj { - return si < sj - } - - return ki < kj -} - -type signKey struct { - PrivateKey - Chain []*x509.Certificate -} - -// JSONSignature represents a signature of a json object. -type JSONSignature struct { - payload string - signatures []jsSignature - indent string - formatLength int - formatTail []byte -} - -func newJSONSignature() *JSONSignature { - return &JSONSignature{ - signatures: make([]jsSignature, 0, 1), - } -} - -// Payload returns the encoded payload of the signature. This -// payload should not be signed directly -func (js *JSONSignature) Payload() ([]byte, error) { - return joseBase64UrlDecode(js.payload) -} - -func (js *JSONSignature) protectedHeader() (string, error) { - protected := map[string]interface{}{ - "formatLength": js.formatLength, - "formatTail": joseBase64UrlEncode(js.formatTail), - "time": time.Now().UTC().Format(time.RFC3339), - } - protectedBytes, err := json.Marshal(protected) - if err != nil { - return "", err - } - - return joseBase64UrlEncode(protectedBytes), nil -} - -func (js *JSONSignature) signBytes(protectedHeader string) ([]byte, error) { - buf := make([]byte, len(js.payload)+len(protectedHeader)+1) - copy(buf, protectedHeader) - buf[len(protectedHeader)] = '.' - copy(buf[len(protectedHeader)+1:], js.payload) - return buf, nil -} - -// Sign adds a signature using the given private key. -func (js *JSONSignature) Sign(key PrivateKey) error { - protected, err := js.protectedHeader() - if err != nil { - return err - } - signBytes, err := js.signBytes(protected) - if err != nil { - return err - } - sigBytes, algorithm, err := key.Sign(bytes.NewReader(signBytes), crypto.SHA256) - if err != nil { - return err - } - - js.signatures = append(js.signatures, jsSignature{ - Header: jsHeader{ - JWK: key.PublicKey(), - Algorithm: algorithm, - }, - Signature: joseBase64UrlEncode(sigBytes), - Protected: protected, - }) - - return nil -} - -// SignWithChain adds a signature using the given private key -// and setting the x509 chain. The public key of the first element -// in the chain must be the public key corresponding with the sign key. -func (js *JSONSignature) SignWithChain(key PrivateKey, chain []*x509.Certificate) error { - // Ensure key.Chain[0] is public key for key - //key.Chain.PublicKey - //key.PublicKey().CryptoPublicKey() - - // Verify chain - protected, err := js.protectedHeader() - if err != nil { - return err - } - signBytes, err := js.signBytes(protected) - if err != nil { - return err - } - sigBytes, algorithm, err := key.Sign(bytes.NewReader(signBytes), crypto.SHA256) - if err != nil { - return err - } - - header := jsHeader{ - Chain: make([]string, len(chain)), - Algorithm: algorithm, - } - - for i, cert := range chain { - header.Chain[i] = base64.StdEncoding.EncodeToString(cert.Raw) - } - - js.signatures = append(js.signatures, jsSignature{ - Header: header, - Signature: joseBase64UrlEncode(sigBytes), - Protected: protected, - }) - - return nil -} - -// Verify verifies all the signatures and returns the list of -// public keys used to sign. Any x509 chains are not checked. -func (js *JSONSignature) Verify() ([]PublicKey, error) { - keys := make([]PublicKey, len(js.signatures)) - for i, signature := range js.signatures { - signBytes, err := js.signBytes(signature.Protected) - if err != nil { - return nil, err - } - var publicKey PublicKey - if len(signature.Header.Chain) > 0 { - certBytes, err := base64.StdEncoding.DecodeString(signature.Header.Chain[0]) - if err != nil { - return nil, err - } - cert, err := x509.ParseCertificate(certBytes) - if err != nil { - return nil, err - } - publicKey, err = FromCryptoPublicKey(cert.PublicKey) - if err != nil { - return nil, err - } - } else if signature.Header.JWK != nil { - publicKey = signature.Header.JWK - } else { - return nil, errors.New("missing public key") - } - - sigBytes, err := joseBase64UrlDecode(signature.Signature) - if err != nil { - return nil, err - } - - err = publicKey.Verify(bytes.NewReader(signBytes), signature.Header.Algorithm, sigBytes) - if err != nil { - return nil, err - } - - keys[i] = publicKey - } - return keys, nil -} - -// VerifyChains verifies all the signatures and the chains associated -// with each signature and returns the list of verified chains. -// Signatures without an x509 chain are not checked. -func (js *JSONSignature) VerifyChains(ca *x509.CertPool) ([][]*x509.Certificate, error) { - chains := make([][]*x509.Certificate, 0, len(js.signatures)) - for _, signature := range js.signatures { - signBytes, err := js.signBytes(signature.Protected) - if err != nil { - return nil, err - } - var publicKey PublicKey - if len(signature.Header.Chain) > 0 { - certBytes, err := base64.StdEncoding.DecodeString(signature.Header.Chain[0]) - if err != nil { - return nil, err - } - cert, err := x509.ParseCertificate(certBytes) - if err != nil { - return nil, err - } - publicKey, err = FromCryptoPublicKey(cert.PublicKey) - if err != nil { - return nil, err - } - intermediates := x509.NewCertPool() - if len(signature.Header.Chain) > 1 { - intermediateChain := signature.Header.Chain[1:] - for i := range intermediateChain { - certBytes, err := base64.StdEncoding.DecodeString(intermediateChain[i]) - if err != nil { - return nil, err - } - intermediate, err := x509.ParseCertificate(certBytes) - if err != nil { - return nil, err - } - intermediates.AddCert(intermediate) - } - } - - verifyOptions := x509.VerifyOptions{ - Intermediates: intermediates, - Roots: ca, - } - - verifiedChains, err := cert.Verify(verifyOptions) - if err != nil { - return nil, err - } - chains = append(chains, verifiedChains...) - - sigBytes, err := joseBase64UrlDecode(signature.Signature) - if err != nil { - return nil, err - } - - err = publicKey.Verify(bytes.NewReader(signBytes), signature.Header.Algorithm, sigBytes) - if err != nil { - return nil, err - } - } - - } - return chains, nil -} - -// JWS returns JSON serialized JWS according to -// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-7.2 -func (js *JSONSignature) JWS() ([]byte, error) { - if len(js.signatures) == 0 { - return nil, errors.New("missing signature") - } - - sort.Sort(jsSignaturesSorted(js.signatures)) - - jsonMap := map[string]interface{}{ - "payload": js.payload, - "signatures": js.signatures, - } - - return json.MarshalIndent(jsonMap, "", " ") -} - -func notSpace(r rune) bool { - return !unicode.IsSpace(r) -} - -func detectJSONIndent(jsonContent []byte) (indent string) { - if len(jsonContent) > 2 && jsonContent[0] == '{' && jsonContent[1] == '\n' { - quoteIndex := bytes.IndexRune(jsonContent[1:], '"') - if quoteIndex > 0 { - indent = string(jsonContent[2 : quoteIndex+1]) - } - } - return -} - -type jsParsedHeader struct { - JWK json.RawMessage `json:"jwk"` - Algorithm string `json:"alg"` - Chain []string `json:"x5c"` -} - -type jsParsedSignature struct { - Header jsParsedHeader `json:"header"` - Signature string `json:"signature"` - Protected string `json:"protected"` -} - -// ParseJWS parses a JWS serialized JSON object into a Json Signature. -func ParseJWS(content []byte) (*JSONSignature, error) { - type jsParsed struct { - Payload string `json:"payload"` - Signatures []jsParsedSignature `json:"signatures"` - } - parsed := &jsParsed{} - err := json.Unmarshal(content, parsed) - if err != nil { - return nil, err - } - if len(parsed.Signatures) == 0 { - return nil, errors.New("missing signatures") - } - payload, err := joseBase64UrlDecode(parsed.Payload) - if err != nil { - return nil, err - } - - js, err := NewJSONSignature(payload) - if err != nil { - return nil, err - } - js.signatures = make([]jsSignature, len(parsed.Signatures)) - for i, signature := range parsed.Signatures { - header := jsHeader{ - Algorithm: signature.Header.Algorithm, - } - if signature.Header.Chain != nil { - header.Chain = signature.Header.Chain - } - if signature.Header.JWK != nil { - publicKey, err := UnmarshalPublicKeyJWK([]byte(signature.Header.JWK)) - if err != nil { - return nil, err - } - header.JWK = publicKey - } - js.signatures[i] = jsSignature{ - Header: header, - Signature: signature.Signature, - Protected: signature.Protected, - } - } - - return js, nil -} - -// NewJSONSignature returns a new unsigned JWS from a json byte array. -// JSONSignature will need to be signed before serializing or storing. -// Optionally, one or more signatures can be provided as byte buffers, -// containing serialized JWS signatures, to assemble a fully signed JWS -// package. It is the callers responsibility to ensure uniqueness of the -// provided signatures. -func NewJSONSignature(content []byte, signatures ...[]byte) (*JSONSignature, error) { - var dataMap map[string]interface{} - err := json.Unmarshal(content, &dataMap) - if err != nil { - return nil, err - } - - js := newJSONSignature() - js.indent = detectJSONIndent(content) - - js.payload = joseBase64UrlEncode(content) - - // Find trailing } and whitespace, put in protected header - closeIndex := bytes.LastIndexFunc(content, notSpace) - if content[closeIndex] != '}' { - return nil, ErrInvalidJSONContent - } - lastRuneIndex := bytes.LastIndexFunc(content[:closeIndex], notSpace) - if content[lastRuneIndex] == ',' { - return nil, ErrInvalidJSONContent - } - js.formatLength = lastRuneIndex + 1 - js.formatTail = content[js.formatLength:] - - if len(signatures) > 0 { - for _, signature := range signatures { - var parsedJSig jsParsedSignature - - if err := json.Unmarshal(signature, &parsedJSig); err != nil { - return nil, err - } - - // TODO(stevvooe): A lot of the code below is repeated in - // ParseJWS. It will require more refactoring to fix that. - jsig := jsSignature{ - Header: jsHeader{ - Algorithm: parsedJSig.Header.Algorithm, - }, - Signature: parsedJSig.Signature, - Protected: parsedJSig.Protected, - } - - if parsedJSig.Header.Chain != nil { - jsig.Header.Chain = parsedJSig.Header.Chain - } - - if parsedJSig.Header.JWK != nil { - publicKey, err := UnmarshalPublicKeyJWK([]byte(parsedJSig.Header.JWK)) - if err != nil { - return nil, err - } - jsig.Header.JWK = publicKey - } - - js.signatures = append(js.signatures, jsig) - } - } - - return js, nil -} - -// NewJSONSignatureFromMap returns a new unsigned JSONSignature from a map or -// struct. JWS will need to be signed before serializing or storing. -func NewJSONSignatureFromMap(content interface{}) (*JSONSignature, error) { - switch content.(type) { - case map[string]interface{}: - case struct{}: - default: - return nil, errors.New("invalid data type") - } - - js := newJSONSignature() - js.indent = " " - - payload, err := json.MarshalIndent(content, "", js.indent) - if err != nil { - return nil, err - } - js.payload = joseBase64UrlEncode(payload) - - // Remove '\n}' from formatted section, put in protected header - js.formatLength = len(payload) - 2 - js.formatTail = payload[js.formatLength:] - - return js, nil -} - -func readIntFromMap(key string, m map[string]interface{}) (int, bool) { - value, ok := m[key] - if !ok { - return 0, false - } - switch v := value.(type) { - case int: - return v, true - case float64: - return int(v), true - default: - return 0, false - } -} - -func readStringFromMap(key string, m map[string]interface{}) (v string, ok bool) { - value, ok := m[key] - if !ok { - return "", false - } - v, ok = value.(string) - return -} - -// ParsePrettySignature parses a formatted signature into a -// JSON signature. If the signatures are missing the format information -// an error is thrown. The formatted signature must be created by -// the same method as format signature. -func ParsePrettySignature(content []byte, signatureKey string) (*JSONSignature, error) { - var contentMap map[string]json.RawMessage - err := json.Unmarshal(content, &contentMap) - if err != nil { - return nil, fmt.Errorf("error unmarshalling content: %s", err) - } - sigMessage, ok := contentMap[signatureKey] - if !ok { - return nil, ErrMissingSignatureKey - } - - var signatureBlocks []jsParsedSignature - err = json.Unmarshal([]byte(sigMessage), &signatureBlocks) - if err != nil { - return nil, fmt.Errorf("error unmarshalling signatures: %s", err) - } - - js := newJSONSignature() - js.signatures = make([]jsSignature, len(signatureBlocks)) - - for i, signatureBlock := range signatureBlocks { - protectedBytes, err := joseBase64UrlDecode(signatureBlock.Protected) - if err != nil { - return nil, fmt.Errorf("base64 decode error: %s", err) - } - var protectedHeader map[string]interface{} - err = json.Unmarshal(protectedBytes, &protectedHeader) - if err != nil { - return nil, fmt.Errorf("error unmarshalling protected header: %s", err) - } - - formatLength, ok := readIntFromMap("formatLength", protectedHeader) - if !ok { - return nil, errors.New("missing formatted length") - } - encodedTail, ok := readStringFromMap("formatTail", protectedHeader) - if !ok { - return nil, errors.New("missing formatted tail") - } - formatTail, err := joseBase64UrlDecode(encodedTail) - if err != nil { - return nil, fmt.Errorf("base64 decode error on tail: %s", err) - } - if js.formatLength == 0 { - js.formatLength = formatLength - } else if js.formatLength != formatLength { - return nil, errors.New("conflicting format length") - } - if len(js.formatTail) == 0 { - js.formatTail = formatTail - } else if bytes.Compare(js.formatTail, formatTail) != 0 { - return nil, errors.New("conflicting format tail") - } - - header := jsHeader{ - Algorithm: signatureBlock.Header.Algorithm, - Chain: signatureBlock.Header.Chain, - } - if signatureBlock.Header.JWK != nil { - publicKey, err := UnmarshalPublicKeyJWK([]byte(signatureBlock.Header.JWK)) - if err != nil { - return nil, fmt.Errorf("error unmarshalling public key: %s", err) - } - header.JWK = publicKey - } - js.signatures[i] = jsSignature{ - Header: header, - Signature: signatureBlock.Signature, - Protected: signatureBlock.Protected, - } - } - if js.formatLength > len(content) { - return nil, errors.New("invalid format length") - } - formatted := make([]byte, js.formatLength+len(js.formatTail)) - copy(formatted, content[:js.formatLength]) - copy(formatted[js.formatLength:], js.formatTail) - js.indent = detectJSONIndent(formatted) - js.payload = joseBase64UrlEncode(formatted) - - return js, nil -} - -// PrettySignature formats a json signature into an easy to read -// single json serialized object. -func (js *JSONSignature) PrettySignature(signatureKey string) ([]byte, error) { - if len(js.signatures) == 0 { - return nil, errors.New("no signatures") - } - payload, err := joseBase64UrlDecode(js.payload) - if err != nil { - return nil, err - } - payload = payload[:js.formatLength] - - sort.Sort(jsSignaturesSorted(js.signatures)) - - var marshalled []byte - var marshallErr error - if js.indent != "" { - marshalled, marshallErr = json.MarshalIndent(js.signatures, js.indent, js.indent) - } else { - marshalled, marshallErr = json.Marshal(js.signatures) - } - if marshallErr != nil { - return nil, marshallErr - } - - buf := bytes.NewBuffer(make([]byte, 0, len(payload)+len(marshalled)+34)) - buf.Write(payload) - buf.WriteByte(',') - if js.indent != "" { - buf.WriteByte('\n') - buf.WriteString(js.indent) - buf.WriteByte('"') - buf.WriteString(signatureKey) - buf.WriteString("\": ") - buf.Write(marshalled) - buf.WriteByte('\n') - } else { - buf.WriteByte('"') - buf.WriteString(signatureKey) - buf.WriteString("\":") - buf.Write(marshalled) - } - buf.WriteByte('}') - - return buf.Bytes(), nil -} - -// Signatures provides the signatures on this JWS as opaque blobs, sorted by -// keyID. These blobs can be stored and reassembled with payloads. Internally, -// they are simply marshaled json web signatures but implementations should -// not rely on this. -func (js *JSONSignature) Signatures() ([][]byte, error) { - sort.Sort(jsSignaturesSorted(js.signatures)) - - var sb [][]byte - for _, jsig := range js.signatures { - p, err := json.Marshal(jsig) - if err != nil { - return nil, err - } - - sb = append(sb, p) - } - - return sb, nil -} - -// Merge combines the signatures from one or more other signatures into the -// method receiver. If the payloads differ for any argument, an error will be -// returned and the receiver will not be modified. -func (js *JSONSignature) Merge(others ...*JSONSignature) error { - merged := js.signatures - for _, other := range others { - if js.payload != other.payload { - return fmt.Errorf("payloads differ from merge target") - } - merged = append(merged, other.signatures...) - } - - js.signatures = merged - return nil -} diff --git a/vendor/github.com/docker/libtrust/key.go b/vendor/github.com/docker/libtrust/key.go deleted file mode 100644 index 73642db2a8..0000000000 --- a/vendor/github.com/docker/libtrust/key.go +++ /dev/null @@ -1,253 +0,0 @@ -package libtrust - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rsa" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "io" -) - -// PublicKey is a generic interface for a Public Key. -type PublicKey interface { - // KeyType returns the key type for this key. For elliptic curve keys, - // this value should be "EC". For RSA keys, this value should be "RSA". - KeyType() string - // KeyID returns a distinct identifier which is unique to this Public Key. - // The format generated by this library is a base32 encoding of a 240 bit - // hash of the public key data divided into 12 groups like so: - // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP - KeyID() string - // Verify verifyies the signature of the data in the io.Reader using this - // Public Key. The alg parameter should identify the digital signature - // algorithm which was used to produce the signature and should be - // supported by this public key. Returns a nil error if the signature - // is valid. - Verify(data io.Reader, alg string, signature []byte) error - // CryptoPublicKey returns the internal object which can be used as a - // crypto.PublicKey for use with other standard library operations. The type - // is either *rsa.PublicKey or *ecdsa.PublicKey - CryptoPublicKey() crypto.PublicKey - // These public keys can be serialized to the standard JSON encoding for - // JSON Web Keys. See section 6 of the IETF draft RFC for JOSE JSON Web - // Algorithms. - MarshalJSON() ([]byte, error) - // These keys can also be serialized to the standard PEM encoding. - PEMBlock() (*pem.Block, error) - // The string representation of a key is its key type and ID. - String() string - AddExtendedField(string, interface{}) - GetExtendedField(string) interface{} -} - -// PrivateKey is a generic interface for a Private Key. -type PrivateKey interface { - // A PrivateKey contains all fields and methods of a PublicKey of the - // same type. The MarshalJSON method also outputs the private key as a - // JSON Web Key, and the PEMBlock method outputs the private key as a - // PEM block. - PublicKey - // PublicKey returns the PublicKey associated with this PrivateKey. - PublicKey() PublicKey - // Sign signs the data read from the io.Reader using a signature algorithm - // supported by the private key. If the specified hashing algorithm is - // supported by this key, that hash function is used to generate the - // signature otherwise the the default hashing algorithm for this key is - // used. Returns the signature and identifier of the algorithm used. - Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error) - // CryptoPrivateKey returns the internal object which can be used as a - // crypto.PublicKey for use with other standard library operations. The - // type is either *rsa.PublicKey or *ecdsa.PublicKey - CryptoPrivateKey() crypto.PrivateKey -} - -// FromCryptoPublicKey returns a libtrust PublicKey representation of the given -// *ecdsa.PublicKey or *rsa.PublicKey. Returns a non-nil error when the given -// key is of an unsupported type. -func FromCryptoPublicKey(cryptoPublicKey crypto.PublicKey) (PublicKey, error) { - switch cryptoPublicKey := cryptoPublicKey.(type) { - case *ecdsa.PublicKey: - return fromECPublicKey(cryptoPublicKey) - case *rsa.PublicKey: - return fromRSAPublicKey(cryptoPublicKey), nil - default: - return nil, fmt.Errorf("public key type %T is not supported", cryptoPublicKey) - } -} - -// FromCryptoPrivateKey returns a libtrust PrivateKey representation of the given -// *ecdsa.PrivateKey or *rsa.PrivateKey. Returns a non-nil error when the given -// key is of an unsupported type. -func FromCryptoPrivateKey(cryptoPrivateKey crypto.PrivateKey) (PrivateKey, error) { - switch cryptoPrivateKey := cryptoPrivateKey.(type) { - case *ecdsa.PrivateKey: - return fromECPrivateKey(cryptoPrivateKey) - case *rsa.PrivateKey: - return fromRSAPrivateKey(cryptoPrivateKey), nil - default: - return nil, fmt.Errorf("private key type %T is not supported", cryptoPrivateKey) - } -} - -// UnmarshalPublicKeyPEM parses the PEM encoded data and returns a libtrust -// PublicKey or an error if there is a problem with the encoding. -func UnmarshalPublicKeyPEM(data []byte) (PublicKey, error) { - pemBlock, _ := pem.Decode(data) - if pemBlock == nil { - return nil, errors.New("unable to find PEM encoded data") - } else if pemBlock.Type != "PUBLIC KEY" { - return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type) - } - - return pubKeyFromPEMBlock(pemBlock) -} - -// UnmarshalPublicKeyPEMBundle parses the PEM encoded data as a bundle of -// PEM blocks appended one after the other and returns a slice of PublicKey -// objects that it finds. -func UnmarshalPublicKeyPEMBundle(data []byte) ([]PublicKey, error) { - pubKeys := []PublicKey{} - - for { - var pemBlock *pem.Block - pemBlock, data = pem.Decode(data) - if pemBlock == nil { - break - } else if pemBlock.Type != "PUBLIC KEY" { - return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type) - } - - pubKey, err := pubKeyFromPEMBlock(pemBlock) - if err != nil { - return nil, err - } - - pubKeys = append(pubKeys, pubKey) - } - - return pubKeys, nil -} - -// UnmarshalPrivateKeyPEM parses the PEM encoded data and returns a libtrust -// PrivateKey or an error if there is a problem with the encoding. -func UnmarshalPrivateKeyPEM(data []byte) (PrivateKey, error) { - pemBlock, _ := pem.Decode(data) - if pemBlock == nil { - return nil, errors.New("unable to find PEM encoded data") - } - - var key PrivateKey - - switch { - case pemBlock.Type == "RSA PRIVATE KEY": - rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) - if err != nil { - return nil, fmt.Errorf("unable to decode RSA Private Key PEM data: %s", err) - } - key = fromRSAPrivateKey(rsaPrivateKey) - case pemBlock.Type == "EC PRIVATE KEY": - ecPrivateKey, err := x509.ParseECPrivateKey(pemBlock.Bytes) - if err != nil { - return nil, fmt.Errorf("unable to decode EC Private Key PEM data: %s", err) - } - key, err = fromECPrivateKey(ecPrivateKey) - if err != nil { - return nil, err - } - default: - return nil, fmt.Errorf("unable to get PrivateKey from PEM type: %s", pemBlock.Type) - } - - addPEMHeadersToKey(pemBlock, key.PublicKey()) - - return key, nil -} - -// UnmarshalPublicKeyJWK unmarshals the given JSON Web Key into a generic -// Public Key to be used with libtrust. -func UnmarshalPublicKeyJWK(data []byte) (PublicKey, error) { - jwk := make(map[string]interface{}) - - err := json.Unmarshal(data, &jwk) - if err != nil { - return nil, fmt.Errorf( - "decoding JWK Public Key JSON data: %s\n", err, - ) - } - - // Get the Key Type value. - kty, err := stringFromMap(jwk, "kty") - if err != nil { - return nil, fmt.Errorf("JWK Public Key type: %s", err) - } - - switch { - case kty == "EC": - // Call out to unmarshal EC public key. - return ecPublicKeyFromMap(jwk) - case kty == "RSA": - // Call out to unmarshal RSA public key. - return rsaPublicKeyFromMap(jwk) - default: - return nil, fmt.Errorf( - "JWK Public Key type not supported: %q\n", kty, - ) - } -} - -// UnmarshalPublicKeyJWKSet parses the JSON encoded data as a JSON Web Key Set -// and returns a slice of Public Key objects. -func UnmarshalPublicKeyJWKSet(data []byte) ([]PublicKey, error) { - rawKeys, err := loadJSONKeySetRaw(data) - if err != nil { - return nil, err - } - - pubKeys := make([]PublicKey, 0, len(rawKeys)) - - for _, rawKey := range rawKeys { - pubKey, err := UnmarshalPublicKeyJWK(rawKey) - if err != nil { - return nil, err - } - pubKeys = append(pubKeys, pubKey) - } - - return pubKeys, nil -} - -// UnmarshalPrivateKeyJWK unmarshals the given JSON Web Key into a generic -// Private Key to be used with libtrust. -func UnmarshalPrivateKeyJWK(data []byte) (PrivateKey, error) { - jwk := make(map[string]interface{}) - - err := json.Unmarshal(data, &jwk) - if err != nil { - return nil, fmt.Errorf( - "decoding JWK Private Key JSON data: %s\n", err, - ) - } - - // Get the Key Type value. - kty, err := stringFromMap(jwk, "kty") - if err != nil { - return nil, fmt.Errorf("JWK Private Key type: %s", err) - } - - switch { - case kty == "EC": - // Call out to unmarshal EC private key. - return ecPrivateKeyFromMap(jwk) - case kty == "RSA": - // Call out to unmarshal RSA private key. - return rsaPrivateKeyFromMap(jwk) - default: - return nil, fmt.Errorf( - "JWK Private Key type not supported: %q\n", kty, - ) - } -} diff --git a/vendor/github.com/docker/libtrust/key_files.go b/vendor/github.com/docker/libtrust/key_files.go deleted file mode 100644 index c526de5455..0000000000 --- a/vendor/github.com/docker/libtrust/key_files.go +++ /dev/null @@ -1,255 +0,0 @@ -package libtrust - -import ( - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "io/ioutil" - "os" - "strings" -) - -var ( - // ErrKeyFileDoesNotExist indicates that the private key file does not exist. - ErrKeyFileDoesNotExist = errors.New("key file does not exist") -) - -func readKeyFileBytes(filename string) ([]byte, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - if os.IsNotExist(err) { - err = ErrKeyFileDoesNotExist - } else { - err = fmt.Errorf("unable to read key file %s: %s", filename, err) - } - - return nil, err - } - - return data, nil -} - -/* - Loading and Saving of Public and Private Keys in either PEM or JWK format. -*/ - -// LoadKeyFile opens the given filename and attempts to read a Private Key -// encoded in either PEM or JWK format (if .json or .jwk file extension). -func LoadKeyFile(filename string) (PrivateKey, error) { - contents, err := readKeyFileBytes(filename) - if err != nil { - return nil, err - } - - var key PrivateKey - - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - key, err = UnmarshalPrivateKeyJWK(contents) - if err != nil { - return nil, fmt.Errorf("unable to decode private key JWK: %s", err) - } - } else { - key, err = UnmarshalPrivateKeyPEM(contents) - if err != nil { - return nil, fmt.Errorf("unable to decode private key PEM: %s", err) - } - } - - return key, nil -} - -// LoadPublicKeyFile opens the given filename and attempts to read a Public Key -// encoded in either PEM or JWK format (if .json or .jwk file extension). -func LoadPublicKeyFile(filename string) (PublicKey, error) { - contents, err := readKeyFileBytes(filename) - if err != nil { - return nil, err - } - - var key PublicKey - - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - key, err = UnmarshalPublicKeyJWK(contents) - if err != nil { - return nil, fmt.Errorf("unable to decode public key JWK: %s", err) - } - } else { - key, err = UnmarshalPublicKeyPEM(contents) - if err != nil { - return nil, fmt.Errorf("unable to decode public key PEM: %s", err) - } - } - - return key, nil -} - -// SaveKey saves the given key to a file using the provided filename. -// This process will overwrite any existing file at the provided location. -func SaveKey(filename string, key PrivateKey) error { - var encodedKey []byte - var err error - - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - // Encode in JSON Web Key format. - encodedKey, err = json.MarshalIndent(key, "", " ") - if err != nil { - return fmt.Errorf("unable to encode private key JWK: %s", err) - } - } else { - // Encode in PEM format. - pemBlock, err := key.PEMBlock() - if err != nil { - return fmt.Errorf("unable to encode private key PEM: %s", err) - } - encodedKey = pem.EncodeToMemory(pemBlock) - } - - err = ioutil.WriteFile(filename, encodedKey, os.FileMode(0600)) - if err != nil { - return fmt.Errorf("unable to write private key file %s: %s", filename, err) - } - - return nil -} - -// SavePublicKey saves the given public key to the file. -func SavePublicKey(filename string, key PublicKey) error { - var encodedKey []byte - var err error - - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - // Encode in JSON Web Key format. - encodedKey, err = json.MarshalIndent(key, "", " ") - if err != nil { - return fmt.Errorf("unable to encode public key JWK: %s", err) - } - } else { - // Encode in PEM format. - pemBlock, err := key.PEMBlock() - if err != nil { - return fmt.Errorf("unable to encode public key PEM: %s", err) - } - encodedKey = pem.EncodeToMemory(pemBlock) - } - - err = ioutil.WriteFile(filename, encodedKey, os.FileMode(0644)) - if err != nil { - return fmt.Errorf("unable to write public key file %s: %s", filename, err) - } - - return nil -} - -// Public Key Set files - -type jwkSet struct { - Keys []json.RawMessage `json:"keys"` -} - -// LoadKeySetFile loads a key set -func LoadKeySetFile(filename string) ([]PublicKey, error) { - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - return loadJSONKeySetFile(filename) - } - - // Must be a PEM format file - return loadPEMKeySetFile(filename) -} - -func loadJSONKeySetRaw(data []byte) ([]json.RawMessage, error) { - if len(data) == 0 { - // This is okay, just return an empty slice. - return []json.RawMessage{}, nil - } - - keySet := jwkSet{} - - err := json.Unmarshal(data, &keySet) - if err != nil { - return nil, fmt.Errorf("unable to decode JSON Web Key Set: %s", err) - } - - return keySet.Keys, nil -} - -func loadJSONKeySetFile(filename string) ([]PublicKey, error) { - contents, err := readKeyFileBytes(filename) - if err != nil && err != ErrKeyFileDoesNotExist { - return nil, err - } - - return UnmarshalPublicKeyJWKSet(contents) -} - -func loadPEMKeySetFile(filename string) ([]PublicKey, error) { - data, err := readKeyFileBytes(filename) - if err != nil && err != ErrKeyFileDoesNotExist { - return nil, err - } - - return UnmarshalPublicKeyPEMBundle(data) -} - -// AddKeySetFile adds a key to a key set -func AddKeySetFile(filename string, key PublicKey) error { - if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".jwk") { - return addKeySetJSONFile(filename, key) - } - - // Must be a PEM format file - return addKeySetPEMFile(filename, key) -} - -func addKeySetJSONFile(filename string, key PublicKey) error { - encodedKey, err := json.Marshal(key) - if err != nil { - return fmt.Errorf("unable to encode trusted client key: %s", err) - } - - contents, err := readKeyFileBytes(filename) - if err != nil && err != ErrKeyFileDoesNotExist { - return err - } - - rawEntries, err := loadJSONKeySetRaw(contents) - if err != nil { - return err - } - - rawEntries = append(rawEntries, json.RawMessage(encodedKey)) - entriesWrapper := jwkSet{Keys: rawEntries} - - encodedEntries, err := json.MarshalIndent(entriesWrapper, "", " ") - if err != nil { - return fmt.Errorf("unable to encode trusted client keys: %s", err) - } - - err = ioutil.WriteFile(filename, encodedEntries, os.FileMode(0644)) - if err != nil { - return fmt.Errorf("unable to write trusted client keys file %s: %s", filename, err) - } - - return nil -} - -func addKeySetPEMFile(filename string, key PublicKey) error { - // Encode to PEM, open file for appending, write PEM. - file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_RDWR, os.FileMode(0644)) - if err != nil { - return fmt.Errorf("unable to open trusted client keys file %s: %s", filename, err) - } - defer file.Close() - - pemBlock, err := key.PEMBlock() - if err != nil { - return fmt.Errorf("unable to encoded trusted key: %s", err) - } - - _, err = file.Write(pem.EncodeToMemory(pemBlock)) - if err != nil { - return fmt.Errorf("unable to write trusted keys file: %s", err) - } - - return nil -} diff --git a/vendor/github.com/docker/libtrust/key_manager.go b/vendor/github.com/docker/libtrust/key_manager.go deleted file mode 100644 index 9a98ae3574..0000000000 --- a/vendor/github.com/docker/libtrust/key_manager.go +++ /dev/null @@ -1,175 +0,0 @@ -package libtrust - -import ( - "crypto/tls" - "crypto/x509" - "fmt" - "io/ioutil" - "net" - "os" - "path" - "sync" -) - -// ClientKeyManager manages client keys on the filesystem -type ClientKeyManager struct { - key PrivateKey - clientFile string - clientDir string - - clientLock sync.RWMutex - clients []PublicKey - - configLock sync.Mutex - configs []*tls.Config -} - -// NewClientKeyManager loads a new manager from a set of key files -// and managed by the given private key. -func NewClientKeyManager(trustKey PrivateKey, clientFile, clientDir string) (*ClientKeyManager, error) { - m := &ClientKeyManager{ - key: trustKey, - clientFile: clientFile, - clientDir: clientDir, - } - if err := m.loadKeys(); err != nil { - return nil, err - } - // TODO Start watching file and directory - - return m, nil -} - -func (c *ClientKeyManager) loadKeys() (err error) { - // Load authorized keys file - var clients []PublicKey - if c.clientFile != "" { - clients, err = LoadKeySetFile(c.clientFile) - if err != nil { - return fmt.Errorf("unable to load authorized keys: %s", err) - } - } - - // Add clients from authorized keys directory - files, err := ioutil.ReadDir(c.clientDir) - if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("unable to open authorized keys directory: %s", err) - } - for _, f := range files { - if !f.IsDir() { - publicKey, err := LoadPublicKeyFile(path.Join(c.clientDir, f.Name())) - if err != nil { - return fmt.Errorf("unable to load authorized key file: %s", err) - } - clients = append(clients, publicKey) - } - } - - c.clientLock.Lock() - c.clients = clients - c.clientLock.Unlock() - - return nil -} - -// RegisterTLSConfig registers a tls configuration to manager -// such that any changes to the keys may be reflected in -// the tls client CA pool -func (c *ClientKeyManager) RegisterTLSConfig(tlsConfig *tls.Config) error { - c.clientLock.RLock() - certPool, err := GenerateCACertPool(c.key, c.clients) - if err != nil { - return fmt.Errorf("CA pool generation error: %s", err) - } - c.clientLock.RUnlock() - - tlsConfig.ClientCAs = certPool - - c.configLock.Lock() - c.configs = append(c.configs, tlsConfig) - c.configLock.Unlock() - - return nil -} - -// NewIdentityAuthTLSConfig creates a tls.Config for the server to use for -// libtrust identity authentication for the domain specified -func NewIdentityAuthTLSConfig(trustKey PrivateKey, clients *ClientKeyManager, addr string, domain string) (*tls.Config, error) { - tlsConfig := newTLSConfig() - - tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert - if err := clients.RegisterTLSConfig(tlsConfig); err != nil { - return nil, err - } - - // Generate cert - ips, domains, err := parseAddr(addr) - if err != nil { - return nil, err - } - // add domain that it expects clients to use - domains = append(domains, domain) - x509Cert, err := GenerateSelfSignedServerCert(trustKey, domains, ips) - if err != nil { - return nil, fmt.Errorf("certificate generation error: %s", err) - } - tlsConfig.Certificates = []tls.Certificate{{ - Certificate: [][]byte{x509Cert.Raw}, - PrivateKey: trustKey.CryptoPrivateKey(), - Leaf: x509Cert, - }} - - return tlsConfig, nil -} - -// NewCertAuthTLSConfig creates a tls.Config for the server to use for -// certificate authentication -func NewCertAuthTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) { - tlsConfig := newTLSConfig() - - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - return nil, fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?", certPath, keyPath, err) - } - tlsConfig.Certificates = []tls.Certificate{cert} - - // Verify client certificates against a CA? - if caPath != "" { - certPool := x509.NewCertPool() - file, err := ioutil.ReadFile(caPath) - if err != nil { - return nil, fmt.Errorf("Couldn't read CA certificate: %s", err) - } - certPool.AppendCertsFromPEM(file) - - tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert - tlsConfig.ClientCAs = certPool - } - - return tlsConfig, nil -} - -func newTLSConfig() *tls.Config { - return &tls.Config{ - NextProtos: []string{"http/1.1"}, - // Avoid fallback on insecure SSL protocols - MinVersion: tls.VersionTLS10, - } -} - -// parseAddr parses an address into an array of IPs and domains -func parseAddr(addr string) ([]net.IP, []string, error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, nil, err - } - var domains []string - var ips []net.IP - ip := net.ParseIP(host) - if ip != nil { - ips = []net.IP{ip} - } else { - domains = []string{host} - } - return ips, domains, nil -} diff --git a/vendor/github.com/docker/libtrust/rsa_key.go b/vendor/github.com/docker/libtrust/rsa_key.go deleted file mode 100644 index dac4cacf20..0000000000 --- a/vendor/github.com/docker/libtrust/rsa_key.go +++ /dev/null @@ -1,427 +0,0 @@ -package libtrust - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "io" - "math/big" -) - -/* - * RSA DSA PUBLIC KEY - */ - -// rsaPublicKey implements a JWK Public Key using RSA digital signature algorithms. -type rsaPublicKey struct { - *rsa.PublicKey - extended map[string]interface{} -} - -func fromRSAPublicKey(cryptoPublicKey *rsa.PublicKey) *rsaPublicKey { - return &rsaPublicKey{cryptoPublicKey, map[string]interface{}{}} -} - -// KeyType returns the JWK key type for RSA keys, i.e., "RSA". -func (k *rsaPublicKey) KeyType() string { - return "RSA" -} - -// KeyID returns a distinct identifier which is unique to this Public Key. -func (k *rsaPublicKey) KeyID() string { - return keyIDFromCryptoKey(k) -} - -func (k *rsaPublicKey) String() string { - return fmt.Sprintf("RSA Public Key <%s>", k.KeyID()) -} - -// Verify verifyies the signature of the data in the io.Reader using this Public Key. -// The alg parameter should be the name of the JWA digital signature algorithm -// which was used to produce the signature and should be supported by this -// public key. Returns a nil error if the signature is valid. -func (k *rsaPublicKey) Verify(data io.Reader, alg string, signature []byte) error { - // Verify the signature of the given date, return non-nil error if valid. - sigAlg, err := rsaSignatureAlgorithmByName(alg) - if err != nil { - return fmt.Errorf("unable to verify Signature: %s", err) - } - - hasher := sigAlg.HashID().New() - _, err = io.Copy(hasher, data) - if err != nil { - return fmt.Errorf("error reading data to sign: %s", err) - } - hash := hasher.Sum(nil) - - err = rsa.VerifyPKCS1v15(k.PublicKey, sigAlg.HashID(), hash, signature) - if err != nil { - return fmt.Errorf("invalid %s signature: %s", sigAlg.HeaderParam(), err) - } - - return nil -} - -// CryptoPublicKey returns the internal object which can be used as a -// crypto.PublicKey for use with other standard library operations. The type -// is either *rsa.PublicKey or *ecdsa.PublicKey -func (k *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { - return k.PublicKey -} - -func (k *rsaPublicKey) toMap() map[string]interface{} { - jwk := make(map[string]interface{}) - for k, v := range k.extended { - jwk[k] = v - } - jwk["kty"] = k.KeyType() - jwk["kid"] = k.KeyID() - jwk["n"] = joseBase64UrlEncode(k.N.Bytes()) - jwk["e"] = joseBase64UrlEncode(serializeRSAPublicExponentParam(k.E)) - - return jwk -} - -// MarshalJSON serializes this Public Key using the JWK JSON serialization format for -// RSA keys. -func (k *rsaPublicKey) MarshalJSON() (data []byte, err error) { - return json.Marshal(k.toMap()) -} - -// PEMBlock serializes this Public Key to DER-encoded PKIX format. -func (k *rsaPublicKey) PEMBlock() (*pem.Block, error) { - derBytes, err := x509.MarshalPKIXPublicKey(k.PublicKey) - if err != nil { - return nil, fmt.Errorf("unable to serialize RSA PublicKey to DER-encoded PKIX format: %s", err) - } - k.extended["kid"] = k.KeyID() // For display purposes. - return createPemBlock("PUBLIC KEY", derBytes, k.extended) -} - -func (k *rsaPublicKey) AddExtendedField(field string, value interface{}) { - k.extended[field] = value -} - -func (k *rsaPublicKey) GetExtendedField(field string) interface{} { - v, ok := k.extended[field] - if !ok { - return nil - } - return v -} - -func rsaPublicKeyFromMap(jwk map[string]interface{}) (*rsaPublicKey, error) { - // JWK key type (kty) has already been determined to be "RSA". - // Need to extract 'n', 'e', and 'kid' and check for - // consistency. - - // Get the modulus parameter N. - nB64Url, err := stringFromMap(jwk, "n") - if err != nil { - return nil, fmt.Errorf("JWK RSA Public Key modulus: %s", err) - } - - n, err := parseRSAModulusParam(nB64Url) - if err != nil { - return nil, fmt.Errorf("JWK RSA Public Key modulus: %s", err) - } - - // Get the public exponent E. - eB64Url, err := stringFromMap(jwk, "e") - if err != nil { - return nil, fmt.Errorf("JWK RSA Public Key exponent: %s", err) - } - - e, err := parseRSAPublicExponentParam(eB64Url) - if err != nil { - return nil, fmt.Errorf("JWK RSA Public Key exponent: %s", err) - } - - key := &rsaPublicKey{ - PublicKey: &rsa.PublicKey{N: n, E: e}, - } - - // Key ID is optional, but if it exists, it should match the key. - _, ok := jwk["kid"] - if ok { - kid, err := stringFromMap(jwk, "kid") - if err != nil { - return nil, fmt.Errorf("JWK RSA Public Key ID: %s", err) - } - if kid != key.KeyID() { - return nil, fmt.Errorf("JWK RSA Public Key ID does not match: %s", kid) - } - } - - if _, ok := jwk["d"]; ok { - return nil, fmt.Errorf("JWK RSA Public Key cannot contain private exponent") - } - - key.extended = jwk - - return key, nil -} - -/* - * RSA DSA PRIVATE KEY - */ - -// rsaPrivateKey implements a JWK Private Key using RSA digital signature algorithms. -type rsaPrivateKey struct { - rsaPublicKey - *rsa.PrivateKey -} - -func fromRSAPrivateKey(cryptoPrivateKey *rsa.PrivateKey) *rsaPrivateKey { - return &rsaPrivateKey{ - *fromRSAPublicKey(&cryptoPrivateKey.PublicKey), - cryptoPrivateKey, - } -} - -// PublicKey returns the Public Key data associated with this Private Key. -func (k *rsaPrivateKey) PublicKey() PublicKey { - return &k.rsaPublicKey -} - -func (k *rsaPrivateKey) String() string { - return fmt.Sprintf("RSA Private Key <%s>", k.KeyID()) -} - -// Sign signs the data read from the io.Reader using a signature algorithm supported -// by the RSA private key. If the specified hashing algorithm is supported by -// this key, that hash function is used to generate the signature otherwise the -// the default hashing algorithm for this key is used. Returns the signature -// and the name of the JWK signature algorithm used, e.g., "RS256", "RS384", -// "RS512". -func (k *rsaPrivateKey) Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error) { - // Generate a signature of the data using the internal alg. - sigAlg := rsaPKCS1v15SignatureAlgorithmForHashID(hashID) - hasher := sigAlg.HashID().New() - - _, err = io.Copy(hasher, data) - if err != nil { - return nil, "", fmt.Errorf("error reading data to sign: %s", err) - } - hash := hasher.Sum(nil) - - signature, err = rsa.SignPKCS1v15(rand.Reader, k.PrivateKey, sigAlg.HashID(), hash) - if err != nil { - return nil, "", fmt.Errorf("error producing signature: %s", err) - } - - alg = sigAlg.HeaderParam() - - return -} - -// CryptoPrivateKey returns the internal object which can be used as a -// crypto.PublicKey for use with other standard library operations. The type -// is either *rsa.PublicKey or *ecdsa.PublicKey -func (k *rsaPrivateKey) CryptoPrivateKey() crypto.PrivateKey { - return k.PrivateKey -} - -func (k *rsaPrivateKey) toMap() map[string]interface{} { - k.Precompute() // Make sure the precomputed values are stored. - jwk := k.rsaPublicKey.toMap() - - jwk["d"] = joseBase64UrlEncode(k.D.Bytes()) - jwk["p"] = joseBase64UrlEncode(k.Primes[0].Bytes()) - jwk["q"] = joseBase64UrlEncode(k.Primes[1].Bytes()) - jwk["dp"] = joseBase64UrlEncode(k.Precomputed.Dp.Bytes()) - jwk["dq"] = joseBase64UrlEncode(k.Precomputed.Dq.Bytes()) - jwk["qi"] = joseBase64UrlEncode(k.Precomputed.Qinv.Bytes()) - - otherPrimes := k.Primes[2:] - - if len(otherPrimes) > 0 { - otherPrimesInfo := make([]interface{}, len(otherPrimes)) - for i, r := range otherPrimes { - otherPrimeInfo := make(map[string]string, 3) - otherPrimeInfo["r"] = joseBase64UrlEncode(r.Bytes()) - crtVal := k.Precomputed.CRTValues[i] - otherPrimeInfo["d"] = joseBase64UrlEncode(crtVal.Exp.Bytes()) - otherPrimeInfo["t"] = joseBase64UrlEncode(crtVal.Coeff.Bytes()) - otherPrimesInfo[i] = otherPrimeInfo - } - jwk["oth"] = otherPrimesInfo - } - - return jwk -} - -// MarshalJSON serializes this Private Key using the JWK JSON serialization format for -// RSA keys. -func (k *rsaPrivateKey) MarshalJSON() (data []byte, err error) { - return json.Marshal(k.toMap()) -} - -// PEMBlock serializes this Private Key to DER-encoded PKIX format. -func (k *rsaPrivateKey) PEMBlock() (*pem.Block, error) { - derBytes := x509.MarshalPKCS1PrivateKey(k.PrivateKey) - k.extended["keyID"] = k.KeyID() // For display purposes. - return createPemBlock("RSA PRIVATE KEY", derBytes, k.extended) -} - -func rsaPrivateKeyFromMap(jwk map[string]interface{}) (*rsaPrivateKey, error) { - // The JWA spec for RSA Private Keys (draft rfc section 5.3.2) states that - // only the private key exponent 'd' is REQUIRED, the others are just for - // signature/decryption optimizations and SHOULD be included when the JWK - // is produced. We MAY choose to accept a JWK which only includes 'd', but - // we're going to go ahead and not choose to accept it without the extra - // fields. Only the 'oth' field will be optional (for multi-prime keys). - privateExponent, err := parseRSAPrivateKeyParamFromMap(jwk, "d") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key exponent: %s", err) - } - firstPrimeFactor, err := parseRSAPrivateKeyParamFromMap(jwk, "p") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err) - } - secondPrimeFactor, err := parseRSAPrivateKeyParamFromMap(jwk, "q") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err) - } - firstFactorCRT, err := parseRSAPrivateKeyParamFromMap(jwk, "dp") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err) - } - secondFactorCRT, err := parseRSAPrivateKeyParamFromMap(jwk, "dq") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err) - } - crtCoeff, err := parseRSAPrivateKeyParamFromMap(jwk, "qi") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key CRT coefficient: %s", err) - } - - var oth interface{} - if _, ok := jwk["oth"]; ok { - oth = jwk["oth"] - delete(jwk, "oth") - } - - // JWK key type (kty) has already been determined to be "RSA". - // Need to extract the public key information, then extract the private - // key values. - publicKey, err := rsaPublicKeyFromMap(jwk) - if err != nil { - return nil, err - } - - privateKey := &rsa.PrivateKey{ - PublicKey: *publicKey.PublicKey, - D: privateExponent, - Primes: []*big.Int{firstPrimeFactor, secondPrimeFactor}, - Precomputed: rsa.PrecomputedValues{ - Dp: firstFactorCRT, - Dq: secondFactorCRT, - Qinv: crtCoeff, - }, - } - - if oth != nil { - // Should be an array of more JSON objects. - otherPrimesInfo, ok := oth.([]interface{}) - if !ok { - return nil, errors.New("JWK RSA Private Key: Invalid other primes info: must be an array") - } - numOtherPrimeFactors := len(otherPrimesInfo) - if numOtherPrimeFactors == 0 { - return nil, errors.New("JWK RSA Privake Key: Invalid other primes info: must be absent or non-empty") - } - otherPrimeFactors := make([]*big.Int, numOtherPrimeFactors) - productOfPrimes := new(big.Int).Mul(firstPrimeFactor, secondPrimeFactor) - crtValues := make([]rsa.CRTValue, numOtherPrimeFactors) - - for i, val := range otherPrimesInfo { - otherPrimeinfo, ok := val.(map[string]interface{}) - if !ok { - return nil, errors.New("JWK RSA Private Key: Invalid other prime info: must be a JSON object") - } - - otherPrimeFactor, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "r") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err) - } - otherFactorCRT, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "d") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err) - } - otherCrtCoeff, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "t") - if err != nil { - return nil, fmt.Errorf("JWK RSA Private Key CRT coefficient: %s", err) - } - - crtValue := crtValues[i] - crtValue.Exp = otherFactorCRT - crtValue.Coeff = otherCrtCoeff - crtValue.R = productOfPrimes - otherPrimeFactors[i] = otherPrimeFactor - productOfPrimes = new(big.Int).Mul(productOfPrimes, otherPrimeFactor) - } - - privateKey.Primes = append(privateKey.Primes, otherPrimeFactors...) - privateKey.Precomputed.CRTValues = crtValues - } - - key := &rsaPrivateKey{ - rsaPublicKey: *publicKey, - PrivateKey: privateKey, - } - - return key, nil -} - -/* - * Key Generation Functions. - */ - -func generateRSAPrivateKey(bits int) (k *rsaPrivateKey, err error) { - k = new(rsaPrivateKey) - k.PrivateKey, err = rsa.GenerateKey(rand.Reader, bits) - if err != nil { - return nil, err - } - - k.rsaPublicKey.PublicKey = &k.PrivateKey.PublicKey - k.extended = make(map[string]interface{}) - - return -} - -// GenerateRSA2048PrivateKey generates a key pair using 2048-bit RSA. -func GenerateRSA2048PrivateKey() (PrivateKey, error) { - k, err := generateRSAPrivateKey(2048) - if err != nil { - return nil, fmt.Errorf("error generating RSA 2048-bit key: %s", err) - } - - return k, nil -} - -// GenerateRSA3072PrivateKey generates a key pair using 3072-bit RSA. -func GenerateRSA3072PrivateKey() (PrivateKey, error) { - k, err := generateRSAPrivateKey(3072) - if err != nil { - return nil, fmt.Errorf("error generating RSA 3072-bit key: %s", err) - } - - return k, nil -} - -// GenerateRSA4096PrivateKey generates a key pair using 4096-bit RSA. -func GenerateRSA4096PrivateKey() (PrivateKey, error) { - k, err := generateRSAPrivateKey(4096) - if err != nil { - return nil, fmt.Errorf("error generating RSA 4096-bit key: %s", err) - } - - return k, nil -} diff --git a/vendor/github.com/docker/libtrust/util.go b/vendor/github.com/docker/libtrust/util.go deleted file mode 100644 index a5a101d3f1..0000000000 --- a/vendor/github.com/docker/libtrust/util.go +++ /dev/null @@ -1,363 +0,0 @@ -package libtrust - -import ( - "bytes" - "crypto" - "crypto/elliptic" - "crypto/tls" - "crypto/x509" - "encoding/base32" - "encoding/base64" - "encoding/binary" - "encoding/pem" - "errors" - "fmt" - "math/big" - "net/url" - "os" - "path/filepath" - "strings" - "time" -) - -// LoadOrCreateTrustKey will load a PrivateKey from the specified path -func LoadOrCreateTrustKey(trustKeyPath string) (PrivateKey, error) { - if err := os.MkdirAll(filepath.Dir(trustKeyPath), 0700); err != nil { - return nil, err - } - - trustKey, err := LoadKeyFile(trustKeyPath) - if err == ErrKeyFileDoesNotExist { - trustKey, err = GenerateECP256PrivateKey() - if err != nil { - return nil, fmt.Errorf("error generating key: %s", err) - } - - if err := SaveKey(trustKeyPath, trustKey); err != nil { - return nil, fmt.Errorf("error saving key file: %s", err) - } - - dir, file := filepath.Split(trustKeyPath) - if err := SavePublicKey(filepath.Join(dir, "public-"+file), trustKey.PublicKey()); err != nil { - return nil, fmt.Errorf("error saving public key file: %s", err) - } - } else if err != nil { - return nil, fmt.Errorf("error loading key file: %s", err) - } - return trustKey, nil -} - -// NewIdentityAuthTLSClientConfig returns a tls.Config configured to use identity -// based authentication from the specified dockerUrl, the rootConfigPath and -// the server name to which it is connecting. -// If trustUnknownHosts is true it will automatically add the host to the -// known-hosts.json in rootConfigPath. -func NewIdentityAuthTLSClientConfig(dockerUrl string, trustUnknownHosts bool, rootConfigPath string, serverName string) (*tls.Config, error) { - tlsConfig := newTLSConfig() - - trustKeyPath := filepath.Join(rootConfigPath, "key.json") - knownHostsPath := filepath.Join(rootConfigPath, "known-hosts.json") - - u, err := url.Parse(dockerUrl) - if err != nil { - return nil, fmt.Errorf("unable to parse machine url") - } - - if u.Scheme == "unix" { - return nil, nil - } - - addr := u.Host - proto := "tcp" - - trustKey, err := LoadOrCreateTrustKey(trustKeyPath) - if err != nil { - return nil, fmt.Errorf("unable to load trust key: %s", err) - } - - knownHosts, err := LoadKeySetFile(knownHostsPath) - if err != nil { - return nil, fmt.Errorf("could not load trusted hosts file: %s", err) - } - - allowedHosts, err := FilterByHosts(knownHosts, addr, false) - if err != nil { - return nil, fmt.Errorf("error filtering hosts: %s", err) - } - - certPool, err := GenerateCACertPool(trustKey, allowedHosts) - if err != nil { - return nil, fmt.Errorf("Could not create CA pool: %s", err) - } - - tlsConfig.ServerName = serverName - tlsConfig.RootCAs = certPool - - x509Cert, err := GenerateSelfSignedClientCert(trustKey) - if err != nil { - return nil, fmt.Errorf("certificate generation error: %s", err) - } - - tlsConfig.Certificates = []tls.Certificate{{ - Certificate: [][]byte{x509Cert.Raw}, - PrivateKey: trustKey.CryptoPrivateKey(), - Leaf: x509Cert, - }} - - tlsConfig.InsecureSkipVerify = true - - testConn, err := tls.Dial(proto, addr, tlsConfig) - if err != nil { - return nil, fmt.Errorf("tls Handshake error: %s", err) - } - - opts := x509.VerifyOptions{ - Roots: tlsConfig.RootCAs, - CurrentTime: time.Now(), - DNSName: tlsConfig.ServerName, - Intermediates: x509.NewCertPool(), - } - - certs := testConn.ConnectionState().PeerCertificates - for i, cert := range certs { - if i == 0 { - continue - } - opts.Intermediates.AddCert(cert) - } - - if _, err := certs[0].Verify(opts); err != nil { - if _, ok := err.(x509.UnknownAuthorityError); ok { - if trustUnknownHosts { - pubKey, err := FromCryptoPublicKey(certs[0].PublicKey) - if err != nil { - return nil, fmt.Errorf("error extracting public key from cert: %s", err) - } - - pubKey.AddExtendedField("hosts", []string{addr}) - - if err := AddKeySetFile(knownHostsPath, pubKey); err != nil { - return nil, fmt.Errorf("error adding machine to known hosts: %s", err) - } - } else { - return nil, fmt.Errorf("unable to connect. unknown host: %s", addr) - } - } - } - - testConn.Close() - tlsConfig.InsecureSkipVerify = false - - return tlsConfig, nil -} - -// joseBase64UrlEncode encodes the given data using the standard base64 url -// encoding format but with all trailing '=' characters omitted in accordance -// with the jose specification. -// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2 -func joseBase64UrlEncode(b []byte) string { - return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=") -} - -// joseBase64UrlDecode decodes the given string using the standard base64 url -// decoder but first adds the appropriate number of trailing '=' characters in -// accordance with the jose specification. -// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2 -func joseBase64UrlDecode(s string) ([]byte, error) { - s = strings.Replace(s, "\n", "", -1) - s = strings.Replace(s, " ", "", -1) - switch len(s) % 4 { - case 0: - case 2: - s += "==" - case 3: - s += "=" - default: - return nil, errors.New("illegal base64url string") - } - return base64.URLEncoding.DecodeString(s) -} - -func keyIDEncode(b []byte) string { - s := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=") - var buf bytes.Buffer - var i int - for i = 0; i < len(s)/4-1; i++ { - start := i * 4 - end := start + 4 - buf.WriteString(s[start:end] + ":") - } - buf.WriteString(s[i*4:]) - return buf.String() -} - -func keyIDFromCryptoKey(pubKey PublicKey) string { - // Generate and return a 'libtrust' fingerprint of the public key. - // For an RSA key this should be: - // SHA256(DER encoded ASN1) - // Then truncated to 240 bits and encoded into 12 base32 groups like so: - // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP - derBytes, err := x509.MarshalPKIXPublicKey(pubKey.CryptoPublicKey()) - if err != nil { - return "" - } - hasher := crypto.SHA256.New() - hasher.Write(derBytes) - return keyIDEncode(hasher.Sum(nil)[:30]) -} - -func stringFromMap(m map[string]interface{}, key string) (string, error) { - val, ok := m[key] - if !ok { - return "", fmt.Errorf("%q value not specified", key) - } - - str, ok := val.(string) - if !ok { - return "", fmt.Errorf("%q value must be a string", key) - } - delete(m, key) - - return str, nil -} - -func parseECCoordinate(cB64Url string, curve elliptic.Curve) (*big.Int, error) { - curveByteLen := (curve.Params().BitSize + 7) >> 3 - - cBytes, err := joseBase64UrlDecode(cB64Url) - if err != nil { - return nil, fmt.Errorf("invalid base64 URL encoding: %s", err) - } - cByteLength := len(cBytes) - if cByteLength != curveByteLen { - return nil, fmt.Errorf("invalid number of octets: got %d, should be %d", cByteLength, curveByteLen) - } - return new(big.Int).SetBytes(cBytes), nil -} - -func parseECPrivateParam(dB64Url string, curve elliptic.Curve) (*big.Int, error) { - dBytes, err := joseBase64UrlDecode(dB64Url) - if err != nil { - return nil, fmt.Errorf("invalid base64 URL encoding: %s", err) - } - - // The length of this octet string MUST be ceiling(log-base-2(n)/8) - // octets (where n is the order of the curve). This is because the private - // key d must be in the interval [1, n-1] so the bitlength of d should be - // no larger than the bitlength of n-1. The easiest way to find the octet - // length is to take bitlength(n-1), add 7 to force a carry, and shift this - // bit sequence right by 3, which is essentially dividing by 8 and adding - // 1 if there is any remainder. Thus, the private key value d should be - // output to (bitlength(n-1)+7)>>3 octets. - n := curve.Params().N - octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3 - dByteLength := len(dBytes) - - if dByteLength != octetLength { - return nil, fmt.Errorf("invalid number of octets: got %d, should be %d", dByteLength, octetLength) - } - - return new(big.Int).SetBytes(dBytes), nil -} - -func parseRSAModulusParam(nB64Url string) (*big.Int, error) { - nBytes, err := joseBase64UrlDecode(nB64Url) - if err != nil { - return nil, fmt.Errorf("invalid base64 URL encoding: %s", err) - } - - return new(big.Int).SetBytes(nBytes), nil -} - -func serializeRSAPublicExponentParam(e int) []byte { - // We MUST use the minimum number of octets to represent E. - // E is supposed to be 65537 for performance and security reasons - // and is what golang's rsa package generates, but it might be - // different if imported from some other generator. - buf := make([]byte, 4) - binary.BigEndian.PutUint32(buf, uint32(e)) - var i int - for i = 0; i < 8; i++ { - if buf[i] != 0 { - break - } - } - return buf[i:] -} - -func parseRSAPublicExponentParam(eB64Url string) (int, error) { - eBytes, err := joseBase64UrlDecode(eB64Url) - if err != nil { - return 0, fmt.Errorf("invalid base64 URL encoding: %s", err) - } - // Only the minimum number of bytes were used to represent E, but - // binary.BigEndian.Uint32 expects at least 4 bytes, so we need - // to add zero padding if necassary. - byteLen := len(eBytes) - buf := make([]byte, 4-byteLen, 4) - eBytes = append(buf, eBytes...) - - return int(binary.BigEndian.Uint32(eBytes)), nil -} - -func parseRSAPrivateKeyParamFromMap(m map[string]interface{}, key string) (*big.Int, error) { - b64Url, err := stringFromMap(m, key) - if err != nil { - return nil, err - } - - paramBytes, err := joseBase64UrlDecode(b64Url) - if err != nil { - return nil, fmt.Errorf("invaled base64 URL encoding: %s", err) - } - - return new(big.Int).SetBytes(paramBytes), nil -} - -func createPemBlock(name string, derBytes []byte, headers map[string]interface{}) (*pem.Block, error) { - pemBlock := &pem.Block{Type: name, Bytes: derBytes, Headers: map[string]string{}} - for k, v := range headers { - switch val := v.(type) { - case string: - pemBlock.Headers[k] = val - case []string: - if k == "hosts" { - pemBlock.Headers[k] = strings.Join(val, ",") - } else { - // Return error, non-encodable type - } - default: - // Return error, non-encodable type - } - } - - return pemBlock, nil -} - -func pubKeyFromPEMBlock(pemBlock *pem.Block) (PublicKey, error) { - cryptoPublicKey, err := x509.ParsePKIXPublicKey(pemBlock.Bytes) - if err != nil { - return nil, fmt.Errorf("unable to decode Public Key PEM data: %s", err) - } - - pubKey, err := FromCryptoPublicKey(cryptoPublicKey) - if err != nil { - return nil, err - } - - addPEMHeadersToKey(pemBlock, pubKey) - - return pubKey, nil -} - -func addPEMHeadersToKey(pemBlock *pem.Block, pubKey PublicKey) { - for key, value := range pemBlock.Headers { - var safeVal interface{} - if key == "hosts" { - safeVal = strings.Split(value, ",") - } else { - safeVal = value - } - pubKey.AddExtendedField(key, safeVal) - } -} diff --git a/vendor/github.com/ghodss/yaml/LICENSE b/vendor/github.com/ghodss/yaml/LICENSE deleted file mode 100644 index 7805d36de7..0000000000 --- a/vendor/github.com/ghodss/yaml/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Sam Ghods - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ghodss/yaml/fields.go b/vendor/github.com/ghodss/yaml/fields.go deleted file mode 100644 index 5860074026..0000000000 --- a/vendor/github.com/ghodss/yaml/fields.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -package yaml - -import ( - "bytes" - "encoding" - "encoding/json" - "reflect" - "sort" - "strings" - "sync" - "unicode" - "unicode/utf8" -) - -// indirect walks down v allocating pointers as needed, -// until it gets to a non-pointer. -// if it encounters an Unmarshaler, indirect stops and returns that. -// if decodingNull is true, indirect stops at the last pointer so it can be set to nil. -func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { - // If v is a named type and is addressable, - // start with its address, so that if the type has pointer methods, - // we find them. - if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { - v = v.Addr() - } - for { - // Load value from interface, but only if the result will be - // usefully addressable. - if v.Kind() == reflect.Interface && !v.IsNil() { - e := v.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { - v = e - continue - } - } - - if v.Kind() != reflect.Ptr { - break - } - - if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { - break - } - if v.IsNil() { - if v.CanSet() { - v.Set(reflect.New(v.Type().Elem())) - } else { - v = reflect.New(v.Type().Elem()) - } - } - if v.Type().NumMethod() > 0 { - if u, ok := v.Interface().(json.Unmarshaler); ok { - return u, nil, reflect.Value{} - } - if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { - return nil, u, reflect.Value{} - } - } - v = v.Elem() - } - return nil, nil, v -} - -// A field represents a single field found in a struct. -type field struct { - name string - nameBytes []byte // []byte(name) - equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent - - tag bool - index []int - typ reflect.Type - omitEmpty bool - quoted bool -} - -func fillField(f field) field { - f.nameBytes = []byte(f.name) - f.equalFold = foldFunc(f.nameBytes) - return f -} - -// byName sorts field by name, breaking ties with depth, -// then breaking ties with "name came from json tag", then -// breaking ties with index sequence. -type byName []field - -func (x byName) Len() int { return len(x) } - -func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - -func (x byName) Less(i, j int) bool { - if x[i].name != x[j].name { - return x[i].name < x[j].name - } - if len(x[i].index) != len(x[j].index) { - return len(x[i].index) < len(x[j].index) - } - if x[i].tag != x[j].tag { - return x[i].tag - } - return byIndex(x).Less(i, j) -} - -// byIndex sorts field by index sequence. -type byIndex []field - -func (x byIndex) Len() int { return len(x) } - -func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - -func (x byIndex) Less(i, j int) bool { - for k, xik := range x[i].index { - if k >= len(x[j].index) { - return false - } - if xik != x[j].index[k] { - return xik < x[j].index[k] - } - } - return len(x[i].index) < len(x[j].index) -} - -// typeFields returns a list of fields that JSON should recognize for the given type. -// The algorithm is breadth-first search over the set of structs to include - the top struct -// and then any reachable anonymous structs. -func typeFields(t reflect.Type) []field { - // Anonymous fields to explore at the current level and the next. - current := []field{} - next := []field{{typ: t}} - - // Count of queued names for current level and the next. - count := map[reflect.Type]int{} - nextCount := map[reflect.Type]int{} - - // Types already visited at an earlier level. - visited := map[reflect.Type]bool{} - - // Fields found. - var fields []field - - for len(next) > 0 { - current, next = next, current[:0] - count, nextCount = nextCount, map[reflect.Type]int{} - - for _, f := range current { - if visited[f.typ] { - continue - } - visited[f.typ] = true - - // Scan f.typ for fields to include. - for i := 0; i < f.typ.NumField(); i++ { - sf := f.typ.Field(i) - if sf.PkgPath != "" { // unexported - continue - } - tag := sf.Tag.Get("json") - if tag == "-" { - continue - } - name, opts := parseTag(tag) - if !isValidTag(name) { - name = "" - } - index := make([]int, len(f.index)+1) - copy(index, f.index) - index[len(f.index)] = i - - ft := sf.Type - if ft.Name() == "" && ft.Kind() == reflect.Ptr { - // Follow pointer. - ft = ft.Elem() - } - - // Record found field and index sequence. - if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { - tagged := name != "" - if name == "" { - name = sf.Name - } - fields = append(fields, fillField(field{ - name: name, - tag: tagged, - index: index, - typ: ft, - omitEmpty: opts.Contains("omitempty"), - quoted: opts.Contains("string"), - })) - if count[f.typ] > 1 { - // If there were multiple instances, add a second, - // so that the annihilation code will see a duplicate. - // It only cares about the distinction between 1 or 2, - // so don't bother generating any more copies. - fields = append(fields, fields[len(fields)-1]) - } - continue - } - - // Record new anonymous struct to explore in next round. - nextCount[ft]++ - if nextCount[ft] == 1 { - next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft})) - } - } - } - } - - sort.Sort(byName(fields)) - - // Delete all fields that are hidden by the Go rules for embedded fields, - // except that fields with JSON tags are promoted. - - // The fields are sorted in primary order of name, secondary order - // of field index length. Loop over names; for each name, delete - // hidden fields by choosing the one dominant field that survives. - out := fields[:0] - for advance, i := 0, 0; i < len(fields); i += advance { - // One iteration per name. - // Find the sequence of fields with the name of this first field. - fi := fields[i] - name := fi.name - for advance = 1; i+advance < len(fields); advance++ { - fj := fields[i+advance] - if fj.name != name { - break - } - } - if advance == 1 { // Only one field with this name - out = append(out, fi) - continue - } - dominant, ok := dominantField(fields[i : i+advance]) - if ok { - out = append(out, dominant) - } - } - - fields = out - sort.Sort(byIndex(fields)) - - return fields -} - -// dominantField looks through the fields, all of which are known to -// have the same name, to find the single field that dominates the -// others using Go's embedding rules, modified by the presence of -// JSON tags. If there are multiple top-level fields, the boolean -// will be false: This condition is an error in Go and we skip all -// the fields. -func dominantField(fields []field) (field, bool) { - // The fields are sorted in increasing index-length order. The winner - // must therefore be one with the shortest index length. Drop all - // longer entries, which is easy: just truncate the slice. - length := len(fields[0].index) - tagged := -1 // Index of first tagged field. - for i, f := range fields { - if len(f.index) > length { - fields = fields[:i] - break - } - if f.tag { - if tagged >= 0 { - // Multiple tagged fields at the same level: conflict. - // Return no field. - return field{}, false - } - tagged = i - } - } - if tagged >= 0 { - return fields[tagged], true - } - // All remaining fields have the same length. If there's more than one, - // we have a conflict (two fields named "X" at the same level) and we - // return no field. - if len(fields) > 1 { - return field{}, false - } - return fields[0], true -} - -var fieldCache struct { - sync.RWMutex - m map[reflect.Type][]field -} - -// cachedTypeFields is like typeFields but uses a cache to avoid repeated work. -func cachedTypeFields(t reflect.Type) []field { - fieldCache.RLock() - f := fieldCache.m[t] - fieldCache.RUnlock() - if f != nil { - return f - } - - // Compute fields without lock. - // Might duplicate effort but won't hold other computations back. - f = typeFields(t) - if f == nil { - f = []field{} - } - - fieldCache.Lock() - if fieldCache.m == nil { - fieldCache.m = map[reflect.Type][]field{} - } - fieldCache.m[t] = f - fieldCache.Unlock() - return f -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - default: - if !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - } - return true -} - -const ( - caseMask = ^byte(0x20) // Mask to ignore case in ASCII. - kelvin = '\u212a' - smallLongEss = '\u017f' -) - -// foldFunc returns one of four different case folding equivalence -// functions, from most general (and slow) to fastest: -// -// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 -// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') -// 3) asciiEqualFold, no special, but includes non-letters (including _) -// 4) simpleLetterEqualFold, no specials, no non-letters. -// -// The letters S and K are special because they map to 3 runes, not just 2: -// * S maps to s and to U+017F 'ſ' Latin small letter long s -// * k maps to K and to U+212A 'K' Kelvin sign -// See http://play.golang.org/p/tTxjOc0OGo -// -// The returned function is specialized for matching against s and -// should only be given s. It's not curried for performance reasons. -func foldFunc(s []byte) func(s, t []byte) bool { - nonLetter := false - special := false // special letter - for _, b := range s { - if b >= utf8.RuneSelf { - return bytes.EqualFold - } - upper := b & caseMask - if upper < 'A' || upper > 'Z' { - nonLetter = true - } else if upper == 'K' || upper == 'S' { - // See above for why these letters are special. - special = true - } - } - if special { - return equalFoldRight - } - if nonLetter { - return asciiEqualFold - } - return simpleLetterEqualFold -} - -// equalFoldRight is a specialization of bytes.EqualFold when s is -// known to be all ASCII (including punctuation), but contains an 's', -// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. -// See comments on foldFunc. -func equalFoldRight(s, t []byte) bool { - for _, sb := range s { - if len(t) == 0 { - return false - } - tb := t[0] - if tb < utf8.RuneSelf { - if sb != tb { - sbUpper := sb & caseMask - if 'A' <= sbUpper && sbUpper <= 'Z' { - if sbUpper != tb&caseMask { - return false - } - } else { - return false - } - } - t = t[1:] - continue - } - // sb is ASCII and t is not. t must be either kelvin - // sign or long s; sb must be s, S, k, or K. - tr, size := utf8.DecodeRune(t) - switch sb { - case 's', 'S': - if tr != smallLongEss { - return false - } - case 'k', 'K': - if tr != kelvin { - return false - } - default: - return false - } - t = t[size:] - - } - if len(t) > 0 { - return false - } - return true -} - -// asciiEqualFold is a specialization of bytes.EqualFold for use when -// s is all ASCII (but may contain non-letters) and contains no -// special-folding letters. -// See comments on foldFunc. -func asciiEqualFold(s, t []byte) bool { - if len(s) != len(t) { - return false - } - for i, sb := range s { - tb := t[i] - if sb == tb { - continue - } - if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { - if sb&caseMask != tb&caseMask { - return false - } - } else { - return false - } - } - return true -} - -// simpleLetterEqualFold is a specialization of bytes.EqualFold for -// use when s is all ASCII letters (no underscores, etc) and also -// doesn't contain 'k', 'K', 's', or 'S'. -// See comments on foldFunc. -func simpleLetterEqualFold(s, t []byte) bool { - if len(s) != len(t) { - return false - } - for i, b := range s { - if b&caseMask != t[i]&caseMask { - return false - } - } - return true -} - -// tagOptions is the string following a comma in a struct field's "json" -// tag, or the empty string. It does not include the leading comma. -type tagOptions string - -// parseTag splits a struct field's json tag into its name and -// comma-separated options. -func parseTag(tag string) (string, tagOptions) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tagOptions(tag[idx+1:]) - } - return tag, tagOptions("") -} - -// Contains reports whether a comma-separated list of options -// contains a particular substr flag. substr must be surrounded by a -// string boundary or commas. -func (o tagOptions) Contains(optionName string) bool { - if len(o) == 0 { - return false - } - s := string(o) - for s != "" { - var next string - i := strings.Index(s, ",") - if i >= 0 { - s, next = s[:i], s[i+1:] - } - if s == optionName { - return true - } - s = next - } - return false -} diff --git a/vendor/github.com/ghodss/yaml/yaml.go b/vendor/github.com/ghodss/yaml/yaml.go deleted file mode 100644 index 4fb4054a8b..0000000000 --- a/vendor/github.com/ghodss/yaml/yaml.go +++ /dev/null @@ -1,277 +0,0 @@ -package yaml - -import ( - "bytes" - "encoding/json" - "fmt" - "reflect" - "strconv" - - "gopkg.in/yaml.v2" -) - -// Marshals the object into JSON then converts JSON to YAML and returns the -// YAML. -func Marshal(o interface{}) ([]byte, error) { - j, err := json.Marshal(o) - if err != nil { - return nil, fmt.Errorf("error marshaling into JSON: %v", err) - } - - y, err := JSONToYAML(j) - if err != nil { - return nil, fmt.Errorf("error converting JSON to YAML: %v", err) - } - - return y, nil -} - -// Converts YAML to JSON then uses JSON to unmarshal into an object. -func Unmarshal(y []byte, o interface{}) error { - vo := reflect.ValueOf(o) - j, err := yamlToJSON(y, &vo) - if err != nil { - return fmt.Errorf("error converting YAML to JSON: %v", err) - } - - err = json.Unmarshal(j, o) - if err != nil { - return fmt.Errorf("error unmarshaling JSON: %v", err) - } - - return nil -} - -// Convert JSON to YAML. -func JSONToYAML(j []byte) ([]byte, error) { - // Convert the JSON to an object. - var jsonObj interface{} - // We are using yaml.Unmarshal here (instead of json.Unmarshal) because the - // Go JSON library doesn't try to pick the right number type (int, float, - // etc.) when unmarshalling to interface{}, it just picks float64 - // universally. go-yaml does go through the effort of picking the right - // number type, so we can preserve number type throughout this process. - err := yaml.Unmarshal(j, &jsonObj) - if err != nil { - return nil, err - } - - // Marshal this object into YAML. - return yaml.Marshal(jsonObj) -} - -// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through -// this method should be a no-op. -// -// Things YAML can do that are not supported by JSON: -// * In YAML you can have binary and null keys in your maps. These are invalid -// in JSON. (int and float keys are converted to strings.) -// * Binary data in YAML with the !!binary tag is not supported. If you want to -// use binary data with this library, encode the data as base64 as usual but do -// not use the !!binary tag in your YAML. This will ensure the original base64 -// encoded data makes it all the way through to the JSON. -func YAMLToJSON(y []byte) ([]byte, error) { - return yamlToJSON(y, nil) -} - -func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) { - // Convert the YAML to an object. - var yamlObj interface{} - err := yaml.Unmarshal(y, &yamlObj) - if err != nil { - return nil, err - } - - // YAML objects are not completely compatible with JSON objects (e.g. you - // can have non-string keys in YAML). So, convert the YAML-compatible object - // to a JSON-compatible object, failing with an error if irrecoverable - // incompatibilties happen along the way. - jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget) - if err != nil { - return nil, err - } - - // Convert this object to JSON and return the data. - return json.Marshal(jsonObj) -} - -func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) { - var err error - - // Resolve jsonTarget to a concrete value (i.e. not a pointer or an - // interface). We pass decodingNull as false because we're not actually - // decoding into the value, we're just checking if the ultimate target is a - // string. - if jsonTarget != nil { - ju, tu, pv := indirect(*jsonTarget, false) - // We have a JSON or Text Umarshaler at this level, so we can't be trying - // to decode into a string. - if ju != nil || tu != nil { - jsonTarget = nil - } else { - jsonTarget = &pv - } - } - - // If yamlObj is a number or a boolean, check if jsonTarget is a string - - // if so, coerce. Else return normal. - // If yamlObj is a map or array, find the field that each key is - // unmarshaling to, and when you recurse pass the reflect.Value for that - // field back into this function. - switch typedYAMLObj := yamlObj.(type) { - case map[interface{}]interface{}: - // JSON does not support arbitrary keys in a map, so we must convert - // these keys to strings. - // - // From my reading of go-yaml v2 (specifically the resolve function), - // keys can only have the types string, int, int64, float64, binary - // (unsupported), or null (unsupported). - strMap := make(map[string]interface{}) - for k, v := range typedYAMLObj { - // Resolve the key to a string first. - var keyString string - switch typedKey := k.(type) { - case string: - keyString = typedKey - case int: - keyString = strconv.Itoa(typedKey) - case int64: - // go-yaml will only return an int64 as a key if the system - // architecture is 32-bit and the key's value is between 32-bit - // and 64-bit. Otherwise the key type will simply be int. - keyString = strconv.FormatInt(typedKey, 10) - case float64: - // Stolen from go-yaml to use the same conversion to string as - // the go-yaml library uses to convert float to string when - // Marshaling. - s := strconv.FormatFloat(typedKey, 'g', -1, 32) - switch s { - case "+Inf": - s = ".inf" - case "-Inf": - s = "-.inf" - case "NaN": - s = ".nan" - } - keyString = s - case bool: - if typedKey { - keyString = "true" - } else { - keyString = "false" - } - default: - return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v", - reflect.TypeOf(k), k, v) - } - - // jsonTarget should be a struct or a map. If it's a struct, find - // the field it's going to map to and pass its reflect.Value. If - // it's a map, find the element type of the map and pass the - // reflect.Value created from that type. If it's neither, just pass - // nil - JSON conversion will error for us if it's a real issue. - if jsonTarget != nil { - t := *jsonTarget - if t.Kind() == reflect.Struct { - keyBytes := []byte(keyString) - // Find the field that the JSON library would use. - var f *field - fields := cachedTypeFields(t.Type()) - for i := range fields { - ff := &fields[i] - if bytes.Equal(ff.nameBytes, keyBytes) { - f = ff - break - } - // Do case-insensitive comparison. - if f == nil && ff.equalFold(ff.nameBytes, keyBytes) { - f = ff - } - } - if f != nil { - // Find the reflect.Value of the most preferential - // struct field. - jtf := t.Field(f.index[0]) - strMap[keyString], err = convertToJSONableObject(v, &jtf) - if err != nil { - return nil, err - } - continue - } - } else if t.Kind() == reflect.Map { - // Create a zero value of the map's element type to use as - // the JSON target. - jtv := reflect.Zero(t.Type().Elem()) - strMap[keyString], err = convertToJSONableObject(v, &jtv) - if err != nil { - return nil, err - } - continue - } - } - strMap[keyString], err = convertToJSONableObject(v, nil) - if err != nil { - return nil, err - } - } - return strMap, nil - case []interface{}: - // We need to recurse into arrays in case there are any - // map[interface{}]interface{}'s inside and to convert any - // numbers to strings. - - // If jsonTarget is a slice (which it really should be), find the - // thing it's going to map to. If it's not a slice, just pass nil - // - JSON conversion will error for us if it's a real issue. - var jsonSliceElemValue *reflect.Value - if jsonTarget != nil { - t := *jsonTarget - if t.Kind() == reflect.Slice { - // By default slices point to nil, but we need a reflect.Value - // pointing to a value of the slice type, so we create one here. - ev := reflect.Indirect(reflect.New(t.Type().Elem())) - jsonSliceElemValue = &ev - } - } - - // Make and use a new array. - arr := make([]interface{}, len(typedYAMLObj)) - for i, v := range typedYAMLObj { - arr[i], err = convertToJSONableObject(v, jsonSliceElemValue) - if err != nil { - return nil, err - } - } - return arr, nil - default: - // If the target type is a string and the YAML type is a number, - // convert the YAML type to a string. - if jsonTarget != nil && (*jsonTarget).Kind() == reflect.String { - // Based on my reading of go-yaml, it may return int, int64, - // float64, or uint64. - var s string - switch typedVal := typedYAMLObj.(type) { - case int: - s = strconv.FormatInt(int64(typedVal), 10) - case int64: - s = strconv.FormatInt(typedVal, 10) - case float64: - s = strconv.FormatFloat(typedVal, 'g', -1, 32) - case uint64: - s = strconv.FormatUint(typedVal, 10) - case bool: - if typedVal { - s = "true" - } else { - s = "false" - } - } - if len(s) > 0 { - yamlObj = interface{}(s) - } - } - return yamlObj, nil - } - - return nil, nil -} diff --git a/vendor/github.com/gogo/protobuf/AUTHORS b/vendor/github.com/gogo/protobuf/AUTHORS deleted file mode 100644 index 3d97fc7a29..0000000000 --- a/vendor/github.com/gogo/protobuf/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -# This is the official list of GoGo authors for copyright purposes. -# This file is distinct from the CONTRIBUTORS file, which -# lists people. For example, employees are listed in CONTRIBUTORS, -# but not in AUTHORS, because the employer holds the copyright. - -# Names should be added to this file as one of -# Organization's name -# Individual's name -# Individual's name - -# Please keep the list sorted. - -Sendgrid, Inc -Vastech SA (PTY) LTD -Walter Schulze diff --git a/vendor/github.com/gogo/protobuf/CONTRIBUTORS b/vendor/github.com/gogo/protobuf/CONTRIBUTORS deleted file mode 100644 index 1b4f6c208a..0000000000 --- a/vendor/github.com/gogo/protobuf/CONTRIBUTORS +++ /dev/null @@ -1,23 +0,0 @@ -Anton Povarov -Brian Goff -Clayton Coleman -Denis Smirnov -DongYun Kang -Dwayne Schultz -Georg Apitz -Gustav Paul -Johan Brandhorst -John Shahid -John Tuley -Laurent -Patrick Lee -Peter Edge -Roger Johansson -Sam Nguyen -Sergio Arbeo -Stephen J Day -Tamir Duberstein -Todd Eisenberger -Tormod Erevik Lea -Vyacheslav Kim -Walter Schulze diff --git a/vendor/github.com/gogo/protobuf/GOLANG_CONTRIBUTORS b/vendor/github.com/gogo/protobuf/GOLANG_CONTRIBUTORS deleted file mode 100644 index b368efb7f2..0000000000 --- a/vendor/github.com/gogo/protobuf/GOLANG_CONTRIBUTORS +++ /dev/null @@ -1,5 +0,0 @@ -The contributors to the Go protobuf repository: - -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at http://tip.golang.org/CONTRIBUTORS. \ No newline at end of file diff --git a/vendor/github.com/gogo/protobuf/LICENSE b/vendor/github.com/gogo/protobuf/LICENSE deleted file mode 100644 index 7be0cc7b62..0000000000 --- a/vendor/github.com/gogo/protobuf/LICENSE +++ /dev/null @@ -1,36 +0,0 @@ -Protocol Buffers for Go with Gadgets - -Copyright (c) 2013, The GoGo Authors. All rights reserved. -http://github.com/gogo/protobuf - -Go support for Protocol Buffers - Google's data interchange format - -Copyright 2010 The Go Authors. All rights reserved. -https://github.com/golang/protobuf - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/vendor/github.com/gogo/protobuf/proto/clone.go b/vendor/github.com/gogo/protobuf/proto/clone.go deleted file mode 100644 index 5d4cba4b51..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/clone.go +++ /dev/null @@ -1,234 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Protocol buffer deep copy and merge. -// TODO: RawMessage. - -package proto - -import ( - "log" - "reflect" - "strings" -) - -// Clone returns a deep copy of a protocol buffer. -func Clone(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - - out := reflect.New(in.Type().Elem()) - // out is empty so a merge is a deep copy. - mergeStruct(out.Elem(), in.Elem()) - return out.Interface().(Message) -} - -// Merge merges src into dst. -// Required and optional fields that are set in src will be set to that value in dst. -// Elements of repeated fields will be appended. -// Merge panics if src and dst are not the same type, or if dst is nil. -func Merge(dst, src Message) { - in := reflect.ValueOf(src) - out := reflect.ValueOf(dst) - if out.IsNil() { - panic("proto: nil destination") - } - if in.Type() != out.Type() { - // Explicit test prior to mergeStruct so that mistyped nils will fail - panic("proto: type mismatch") - } - if in.IsNil() { - // Merging nil into non-nil is a quiet no-op - return - } - mergeStruct(out.Elem(), in.Elem()) -} - -func mergeStruct(out, in reflect.Value) { - sprop := GetProperties(in.Type()) - for i := 0; i < in.NumField(); i++ { - f := in.Type().Field(i) - if strings.HasPrefix(f.Name, "XXX_") { - continue - } - mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) - } - - if emIn, ok := in.Addr().Interface().(extensionsBytes); ok { - emOut := out.Addr().Interface().(extensionsBytes) - bIn := emIn.GetExtensions() - bOut := emOut.GetExtensions() - *bOut = append(*bOut, *bIn...) - } else if emIn, ok := extendable(in.Addr().Interface()); ok { - emOut, _ := extendable(out.Addr().Interface()) - mIn, muIn := emIn.extensionsRead() - if mIn != nil { - mOut := emOut.extensionsWrite() - muIn.Lock() - mergeExtension(mOut, mIn) - muIn.Unlock() - } - } - - uf := in.FieldByName("XXX_unrecognized") - if !uf.IsValid() { - return - } - uin := uf.Bytes() - if len(uin) > 0 { - out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) - } -} - -// mergeAny performs a merge between two values of the same type. -// viaPtr indicates whether the values were indirected through a pointer (implying proto2). -// prop is set if this is a struct field (it may be nil). -func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { - if in.Type() == protoMessageType { - if !in.IsNil() { - if out.IsNil() { - out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) - } else { - Merge(out.Interface().(Message), in.Interface().(Message)) - } - } - return - } - switch in.Kind() { - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, - reflect.String, reflect.Uint32, reflect.Uint64: - if !viaPtr && isProto3Zero(in) { - return - } - out.Set(in) - case reflect.Interface: - // Probably a oneof field; copy non-nil values. - if in.IsNil() { - return - } - // Allocate destination if it is not set, or set to a different type. - // Otherwise we will merge as normal. - if out.IsNil() || out.Elem().Type() != in.Elem().Type() { - out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) - } - mergeAny(out.Elem(), in.Elem(), false, nil) - case reflect.Map: - if in.Len() == 0 { - return - } - if out.IsNil() { - out.Set(reflect.MakeMap(in.Type())) - } - // For maps with value types of *T or []byte we need to deep copy each value. - elemKind := in.Type().Elem().Kind() - for _, key := range in.MapKeys() { - var val reflect.Value - switch elemKind { - case reflect.Ptr: - val = reflect.New(in.Type().Elem().Elem()) - mergeAny(val, in.MapIndex(key), false, nil) - case reflect.Slice: - val = in.MapIndex(key) - val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) - default: - val = in.MapIndex(key) - } - out.SetMapIndex(key, val) - } - case reflect.Ptr: - if in.IsNil() { - return - } - if out.IsNil() { - out.Set(reflect.New(in.Elem().Type())) - } - mergeAny(out.Elem(), in.Elem(), true, nil) - case reflect.Slice: - if in.IsNil() { - return - } - if in.Type().Elem().Kind() == reflect.Uint8 { - // []byte is a scalar bytes field, not a repeated field. - - // Edge case: if this is in a proto3 message, a zero length - // bytes field is considered the zero value, and should not - // be merged. - if prop != nil && prop.proto3 && in.Len() == 0 { - return - } - - // Make a deep copy. - // Append to []byte{} instead of []byte(nil) so that we never end up - // with a nil result. - out.SetBytes(append([]byte{}, in.Bytes()...)) - return - } - n := in.Len() - if out.IsNil() { - out.Set(reflect.MakeSlice(in.Type(), 0, n)) - } - switch in.Type().Elem().Kind() { - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, - reflect.String, reflect.Uint32, reflect.Uint64: - out.Set(reflect.AppendSlice(out, in)) - default: - for i := 0; i < n; i++ { - x := reflect.Indirect(reflect.New(in.Type().Elem())) - mergeAny(x, in.Index(i), false, nil) - out.Set(reflect.Append(out, x)) - } - } - case reflect.Struct: - mergeStruct(out, in) - default: - // unknown type, so not a protocol buffer - log.Printf("proto: don't know how to copy %v", in) - } -} - -func mergeExtension(out, in map[int32]Extension) { - for extNum, eIn := range in { - eOut := Extension{desc: eIn.desc} - if eIn.value != nil { - v := reflect.New(reflect.TypeOf(eIn.value)).Elem() - mergeAny(v, reflect.ValueOf(eIn.value), false, nil) - eOut.value = v.Interface() - } - if eIn.enc != nil { - eOut.enc = make([]byte, len(eIn.enc)) - copy(eOut.enc, eIn.enc) - } - - out[extNum] = eOut - } -} diff --git a/vendor/github.com/gogo/protobuf/proto/decode.go b/vendor/github.com/gogo/protobuf/proto/decode.go deleted file mode 100644 index 737f2731d4..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/decode.go +++ /dev/null @@ -1,978 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -/* - * Routines for decoding protocol buffer data to construct in-memory representations. - */ - -import ( - "errors" - "fmt" - "io" - "os" - "reflect" -) - -// errOverflow is returned when an integer is too large to be represented. -var errOverflow = errors.New("proto: integer overflow") - -// ErrInternalBadWireType is returned by generated code when an incorrect -// wire type is encountered. It does not get returned to user code. -var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") - -// The fundamental decoders that interpret bytes on the wire. -// Those that take integer types all return uint64 and are -// therefore of type valueDecoder. - -// DecodeVarint reads a varint-encoded integer from the slice. -// It returns the integer and the number of bytes consumed, or -// zero if there is not enough. -// This is the format for the -// int32, int64, uint32, uint64, bool, and enum -// protocol buffer types. -func DecodeVarint(buf []byte) (x uint64, n int) { - for shift := uint(0); shift < 64; shift += 7 { - if n >= len(buf) { - return 0, 0 - } - b := uint64(buf[n]) - n++ - x |= (b & 0x7F) << shift - if (b & 0x80) == 0 { - return x, n - } - } - - // The number is too large to represent in a 64-bit value. - return 0, 0 -} - -func (p *Buffer) decodeVarintSlow() (x uint64, err error) { - i := p.index - l := len(p.buf) - - for shift := uint(0); shift < 64; shift += 7 { - if i >= l { - err = io.ErrUnexpectedEOF - return - } - b := p.buf[i] - i++ - x |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - p.index = i - return - } - } - - // The number is too large to represent in a 64-bit value. - err = errOverflow - return -} - -// DecodeVarint reads a varint-encoded integer from the Buffer. -// This is the format for the -// int32, int64, uint32, uint64, bool, and enum -// protocol buffer types. -func (p *Buffer) DecodeVarint() (x uint64, err error) { - i := p.index - buf := p.buf - - if i >= len(buf) { - return 0, io.ErrUnexpectedEOF - } else if buf[i] < 0x80 { - p.index++ - return uint64(buf[i]), nil - } else if len(buf)-i < 10 { - return p.decodeVarintSlow() - } - - var b uint64 - // we already checked the first byte - x = uint64(buf[i]) - 0x80 - i++ - - b = uint64(buf[i]) - i++ - x += b << 7 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 7 - - b = uint64(buf[i]) - i++ - x += b << 14 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 14 - - b = uint64(buf[i]) - i++ - x += b << 21 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 21 - - b = uint64(buf[i]) - i++ - x += b << 28 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 28 - - b = uint64(buf[i]) - i++ - x += b << 35 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 35 - - b = uint64(buf[i]) - i++ - x += b << 42 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 42 - - b = uint64(buf[i]) - i++ - x += b << 49 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 49 - - b = uint64(buf[i]) - i++ - x += b << 56 - if b&0x80 == 0 { - goto done - } - x -= 0x80 << 56 - - b = uint64(buf[i]) - i++ - x += b << 63 - if b&0x80 == 0 { - goto done - } - // x -= 0x80 << 63 // Always zero. - - return 0, errOverflow - -done: - p.index = i - return x, nil -} - -// DecodeFixed64 reads a 64-bit integer from the Buffer. -// This is the format for the -// fixed64, sfixed64, and double protocol buffer types. -func (p *Buffer) DecodeFixed64() (x uint64, err error) { - // x, err already 0 - i := p.index + 8 - if i < 0 || i > len(p.buf) { - err = io.ErrUnexpectedEOF - return - } - p.index = i - - x = uint64(p.buf[i-8]) - x |= uint64(p.buf[i-7]) << 8 - x |= uint64(p.buf[i-6]) << 16 - x |= uint64(p.buf[i-5]) << 24 - x |= uint64(p.buf[i-4]) << 32 - x |= uint64(p.buf[i-3]) << 40 - x |= uint64(p.buf[i-2]) << 48 - x |= uint64(p.buf[i-1]) << 56 - return -} - -// DecodeFixed32 reads a 32-bit integer from the Buffer. -// This is the format for the -// fixed32, sfixed32, and float protocol buffer types. -func (p *Buffer) DecodeFixed32() (x uint64, err error) { - // x, err already 0 - i := p.index + 4 - if i < 0 || i > len(p.buf) { - err = io.ErrUnexpectedEOF - return - } - p.index = i - - x = uint64(p.buf[i-4]) - x |= uint64(p.buf[i-3]) << 8 - x |= uint64(p.buf[i-2]) << 16 - x |= uint64(p.buf[i-1]) << 24 - return -} - -// DecodeZigzag64 reads a zigzag-encoded 64-bit integer -// from the Buffer. -// This is the format used for the sint64 protocol buffer type. -func (p *Buffer) DecodeZigzag64() (x uint64, err error) { - x, err = p.DecodeVarint() - if err != nil { - return - } - x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) - return -} - -// DecodeZigzag32 reads a zigzag-encoded 32-bit integer -// from the Buffer. -// This is the format used for the sint32 protocol buffer type. -func (p *Buffer) DecodeZigzag32() (x uint64, err error) { - x, err = p.DecodeVarint() - if err != nil { - return - } - x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) - return -} - -// These are not ValueDecoders: they produce an array of bytes or a string. -// bytes, embedded messages - -// DecodeRawBytes reads a count-delimited byte buffer from the Buffer. -// This is the format used for the bytes protocol buffer -// type and for embedded messages. -func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { - n, err := p.DecodeVarint() - if err != nil { - return nil, err - } - - nb := int(n) - if nb < 0 { - return nil, fmt.Errorf("proto: bad byte length %d", nb) - } - end := p.index + nb - if end < p.index || end > len(p.buf) { - return nil, io.ErrUnexpectedEOF - } - - if !alloc { - // todo: check if can get more uses of alloc=false - buf = p.buf[p.index:end] - p.index += nb - return - } - - buf = make([]byte, nb) - copy(buf, p.buf[p.index:]) - p.index += nb - return -} - -// DecodeStringBytes reads an encoded string from the Buffer. -// This is the format used for the proto2 string type. -func (p *Buffer) DecodeStringBytes() (s string, err error) { - buf, err := p.DecodeRawBytes(false) - if err != nil { - return - } - return string(buf), nil -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -// If the protocol buffer has extensions, and the field matches, add it as an extension. -// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. -func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { - oi := o.index - - err := o.skip(t, tag, wire) - if err != nil { - return err - } - - if !unrecField.IsValid() { - return nil - } - - ptr := structPointer_Bytes(base, unrecField) - - // Add the skipped field to struct field - obuf := o.buf - - o.buf = *ptr - o.EncodeVarint(uint64(tag<<3 | wire)) - *ptr = append(o.buf, obuf[oi:o.index]...) - - o.buf = obuf - - return nil -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -func (o *Buffer) skip(t reflect.Type, tag, wire int) error { - - var u uint64 - var err error - - switch wire { - case WireVarint: - _, err = o.DecodeVarint() - case WireFixed64: - _, err = o.DecodeFixed64() - case WireBytes: - _, err = o.DecodeRawBytes(false) - case WireFixed32: - _, err = o.DecodeFixed32() - case WireStartGroup: - for { - u, err = o.DecodeVarint() - if err != nil { - break - } - fwire := int(u & 0x7) - if fwire == WireEndGroup { - break - } - ftag := int(u >> 3) - err = o.skip(t, ftag, fwire) - if err != nil { - break - } - } - default: - err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) - } - return err -} - -// Unmarshaler is the interface representing objects that can -// unmarshal themselves. The method should reset the receiver before -// decoding starts. The argument points to data that may be -// overwritten, so implementations should not keep references to the -// buffer. -type Unmarshaler interface { - Unmarshal([]byte) error -} - -// Unmarshal parses the protocol buffer representation in buf and places the -// decoded result in pb. If the struct underlying pb does not match -// the data in buf, the results can be unpredictable. -// -// Unmarshal resets pb before starting to unmarshal, so any -// existing data in pb is always removed. Use UnmarshalMerge -// to preserve and append to existing data. -func Unmarshal(buf []byte, pb Message) error { - pb.Reset() - return UnmarshalMerge(buf, pb) -} - -// UnmarshalMerge parses the protocol buffer representation in buf and -// writes the decoded result to pb. If the struct underlying pb does not match -// the data in buf, the results can be unpredictable. -// -// UnmarshalMerge merges into existing data in pb. -// Most code should use Unmarshal instead. -func UnmarshalMerge(buf []byte, pb Message) error { - // If the object can unmarshal itself, let it. - if u, ok := pb.(Unmarshaler); ok { - return u.Unmarshal(buf) - } - return NewBuffer(buf).Unmarshal(pb) -} - -// DecodeMessage reads a count-delimited message from the Buffer. -func (p *Buffer) DecodeMessage(pb Message) error { - enc, err := p.DecodeRawBytes(false) - if err != nil { - return err - } - return NewBuffer(enc).Unmarshal(pb) -} - -// DecodeGroup reads a tag-delimited group from the Buffer. -func (p *Buffer) DecodeGroup(pb Message) error { - typ, base, err := getbase(pb) - if err != nil { - return err - } - return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) -} - -// Unmarshal parses the protocol buffer representation in the -// Buffer and places the decoded result in pb. If the struct -// underlying pb does not match the data in the buffer, the results can be -// unpredictable. -// -// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. -func (p *Buffer) Unmarshal(pb Message) error { - // If the object can unmarshal itself, let it. - if u, ok := pb.(Unmarshaler); ok { - err := u.Unmarshal(p.buf[p.index:]) - p.index = len(p.buf) - return err - } - - typ, base, err := getbase(pb) - if err != nil { - return err - } - - err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) - - if collectStats { - stats.Decode++ - } - - return err -} - -// unmarshalType does the work of unmarshaling a structure. -func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { - var state errorState - required, reqFields := prop.reqCount, uint64(0) - - var err error - for err == nil && o.index < len(o.buf) { - oi := o.index - var u uint64 - u, err = o.DecodeVarint() - if err != nil { - break - } - wire := int(u & 0x7) - if wire == WireEndGroup { - if is_group { - if required > 0 { - // Not enough information to determine the exact field. - // (See below.) - return &RequiredNotSetError{"{Unknown}"} - } - return nil // input is satisfied - } - return fmt.Errorf("proto: %s: wiretype end group for non-group", st) - } - tag := int(u >> 3) - if tag <= 0 { - return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) - } - fieldnum, ok := prop.decoderTags.get(tag) - if !ok { - // Maybe it's an extension? - if prop.extendable { - if e, eok := structPointer_Interface(base, st).(extensionsBytes); eok { - if isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - ext := e.GetExtensions() - *ext = append(*ext, o.buf[oi:o.index]...) - } - continue - } - } else if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - extmap := e.extensionsWrite() - ext := extmap[int32(tag)] // may be missing - ext.enc = append(ext.enc, o.buf[oi:o.index]...) - extmap[int32(tag)] = ext - } - continue - } - } - // Maybe it's a oneof? - if prop.oneofUnmarshaler != nil { - m := structPointer_Interface(base, st).(Message) - // First return value indicates whether tag is a oneof field. - ok, err = prop.oneofUnmarshaler(m, tag, wire, o) - if err == ErrInternalBadWireType { - // Map the error to something more descriptive. - // Do the formatting here to save generated code space. - err = fmt.Errorf("bad wiretype for oneof field in %T", m) - } - if ok { - continue - } - } - err = o.skipAndSave(st, tag, wire, base, prop.unrecField) - continue - } - p := prop.Prop[fieldnum] - - if p.dec == nil { - fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) - continue - } - dec := p.dec - if wire != WireStartGroup && wire != p.WireType { - if wire == WireBytes && p.packedDec != nil { - // a packable field - dec = p.packedDec - } else { - err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) - continue - } - } - decErr := dec(o, p, base) - if decErr != nil && !state.shouldContinue(decErr, p) { - err = decErr - } - if err == nil && p.Required { - // Successfully decoded a required field. - if tag <= 64 { - // use bitmap for fields 1-64 to catch field reuse. - var mask uint64 = 1 << uint64(tag-1) - if reqFields&mask == 0 { - // new required field - reqFields |= mask - required-- - } - } else { - // This is imprecise. It can be fooled by a required field - // with a tag > 64 that is encoded twice; that's very rare. - // A fully correct implementation would require allocating - // a data structure, which we would like to avoid. - required-- - } - } - } - if err == nil { - if is_group { - return io.ErrUnexpectedEOF - } - if state.err != nil { - return state.err - } - if required > 0 { - // Not enough information to determine the exact field. If we use extra - // CPU, we could determine the field only if the missing required field - // has a tag <= 64 and we check reqFields. - return &RequiredNotSetError{"{Unknown}"} - } - } - return err -} - -// Individual type decoders -// For each, -// u is the decoded value, -// v is a pointer to the field (pointer) in the struct - -// Sizes of the pools to allocate inside the Buffer. -// The goal is modest amortization and allocation -// on at least 16-byte boundaries. -const ( - boolPoolSize = 16 - uint32PoolSize = 8 - uint64PoolSize = 4 -) - -// Decode a bool. -func (o *Buffer) dec_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - if len(o.bools) == 0 { - o.bools = make([]bool, boolPoolSize) - } - o.bools[0] = u != 0 - *structPointer_Bool(base, p.field) = &o.bools[0] - o.bools = o.bools[1:] - return nil -} - -func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - *structPointer_BoolVal(base, p.field) = u != 0 - return nil -} - -// Decode an int32. -func (o *Buffer) dec_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) - return nil -} - -func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) - return nil -} - -// Decode an int64. -func (o *Buffer) dec_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64_Set(structPointer_Word64(base, p.field), o, u) - return nil -} - -func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64Val_Set(structPointer_Word64Val(base, p.field), o, u) - return nil -} - -// Decode a string. -func (o *Buffer) dec_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_String(base, p.field) = &s - return nil -} - -func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_StringVal(base, p.field) = s - return nil -} - -// Decode a slice of bytes ([]byte). -func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - *structPointer_Bytes(base, p.field) = b - return nil -} - -// Decode a slice of bools ([]bool). -func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - v := structPointer_BoolSlice(base, p.field) - *v = append(*v, u != 0) - return nil -} - -// Decode a slice of bools ([]bool) in packed format. -func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { - v := structPointer_BoolSlice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded bools - fin := o.index + nb - if fin < o.index { - return errOverflow - } - - y := *v - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - y = append(y, u != 0) - } - - *v = y - return nil -} - -// Decode a slice of int32s ([]int32). -func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - structPointer_Word32Slice(base, p.field).Append(uint32(u)) - return nil -} - -// Decode a slice of int32s ([]int32) in packed format. -func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int32s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(uint32(u)) - } - return nil -} - -// Decode a slice of int64s ([]int64). -func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - - structPointer_Word64Slice(base, p.field).Append(u) - return nil -} - -// Decode a slice of int64s ([]int64) in packed format. -func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int64s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(u) - } - return nil -} - -// Decode a slice of strings ([]string). -func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - v := structPointer_StringSlice(base, p.field) - *v = append(*v, s) - return nil -} - -// Decode a slice of slice of bytes ([][]byte). -func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - v := structPointer_BytesSlice(base, p.field) - *v = append(*v, b) - return nil -} - -// Decode a map field. -func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - oi := o.index // index at the end of this map entry - o.index -= len(raw) // move buffer back to start of map entry - - mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V - if mptr.Elem().IsNil() { - mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) - } - v := mptr.Elem() // map[K]V - - // Prepare addressable doubly-indirect placeholders for the key and value types. - // See enc_new_map for why. - keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K - keybase := toStructPointer(keyptr.Addr()) // **K - - var valbase structPointer - var valptr reflect.Value - switch p.mtype.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valptr = reflect.ValueOf(&dummy) // *[]byte - valbase = toStructPointer(valptr) // *[]byte - case reflect.Ptr: - // message; valptr is **Msg; need to allocate the intermediate pointer - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valptr.Set(reflect.New(valptr.Type().Elem())) - valbase = toStructPointer(valptr) - default: - // everything else - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valbase = toStructPointer(valptr.Addr()) // **V - } - - // Decode. - // This parses a restricted wire format, namely the encoding of a message - // with two fields. See enc_new_map for the format. - for o.index < oi { - // tagcode for key and value properties are always a single byte - // because they have tags 1 and 2. - tagcode := o.buf[o.index] - o.index++ - switch tagcode { - case p.mkeyprop.tagcode[0]: - if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { - return err - } - case p.mvalprop.tagcode[0]: - if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { - return err - } - default: - // TODO: Should we silently skip this instead? - return fmt.Errorf("proto: bad map data tag %d", raw[0]) - } - } - keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() { - keyelem = reflect.Zero(p.mtype.Key()) - } - if !valelem.IsValid() { - valelem = reflect.Zero(p.mtype.Elem()) - } - - v.SetMapIndex(keyelem, valelem) - return nil -} - -// Decode a group. -func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - return o.unmarshalType(p.stype, p.sprop, true, bas) -} - -// Decode an embedded message. -func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { - raw, e := o.DecodeRawBytes(false) - if e != nil { - return e - } - - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := structPointer_Interface(bas, p.stype) - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, false, bas) - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of embedded messages. -func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, false, base) -} - -// Decode a slice of embedded groups. -func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, true, base) -} - -// Decode a slice of structs ([]*struct). -func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { - v := reflect.New(p.stype) - bas := toStructPointer(v) - structPointer_StructPointerSlice(base, p.field).Append(bas) - - if is_group { - err := o.unmarshalType(p.stype, p.sprop, is_group, bas) - return err - } - - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := v.Interface() - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, is_group, bas) - - o.buf = obuf - o.index = oi - - return err -} diff --git a/vendor/github.com/gogo/protobuf/proto/decode_gogo.go b/vendor/github.com/gogo/protobuf/proto/decode_gogo.go deleted file mode 100644 index 6fb74de4cc..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/decode_gogo.go +++ /dev/null @@ -1,172 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "reflect" -) - -// Decode a reference to a struct pointer. -func (o *Buffer) dec_ref_struct_message(p *Properties, base structPointer) (err error) { - raw, e := o.DecodeRawBytes(false) - if e != nil { - return e - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - panic("not supported, since this is a pointer receiver") - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - bas := structPointer_FieldPointer(base, p.field) - - err = o.unmarshalType(p.stype, p.sprop, false, bas) - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of references to struct pointers ([]struct). -func (o *Buffer) dec_slice_ref_struct(p *Properties, is_group bool, base structPointer) error { - newBas := appendStructPointer(base, p.field, p.sstype) - - if is_group { - panic("not supported, maybe in future, if requested.") - } - - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - panic("not supported, since this is not a pointer receiver.") - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, is_group, newBas) - - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of references to struct pointers. -func (o *Buffer) dec_slice_ref_struct_message(p *Properties, base structPointer) error { - return o.dec_slice_ref_struct(p, false, base) -} - -func setPtrCustomType(base structPointer, f field, v interface{}) { - if v == nil { - return - } - structPointer_SetStructPointer(base, f, toStructPointer(reflect.ValueOf(v))) -} - -func setCustomType(base structPointer, f field, value interface{}) { - if value == nil { - return - } - v := reflect.ValueOf(value).Elem() - t := reflect.TypeOf(value).Elem() - kind := t.Kind() - switch kind { - case reflect.Slice: - slice := reflect.MakeSlice(t, v.Len(), v.Cap()) - reflect.Copy(slice, v) - oldHeader := structPointer_GetSliceHeader(base, f) - oldHeader.Data = slice.Pointer() - oldHeader.Len = v.Len() - oldHeader.Cap = v.Cap() - default: - size := reflect.TypeOf(value).Elem().Size() - structPointer_Copy(toStructPointer(reflect.ValueOf(value)), structPointer_Add(base, f), int(size)) - } -} - -func (o *Buffer) dec_custom_bytes(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - i := reflect.New(p.ctype.Elem()).Interface() - custom := (i).(Unmarshaler) - if err := custom.Unmarshal(b); err != nil { - return err - } - setPtrCustomType(base, p.field, custom) - return nil -} - -func (o *Buffer) dec_custom_ref_bytes(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - i := reflect.New(p.ctype).Interface() - custom := (i).(Unmarshaler) - if err := custom.Unmarshal(b); err != nil { - return err - } - if custom != nil { - setCustomType(base, p.field, custom) - } - return nil -} - -// Decode a slice of bytes ([]byte) into a slice of custom types. -func (o *Buffer) dec_custom_slice_bytes(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - i := reflect.New(p.ctype.Elem()).Interface() - custom := (i).(Unmarshaler) - if err := custom.Unmarshal(b); err != nil { - return err - } - newBas := appendStructPointer(base, p.field, p.ctype) - - var zero field - setCustomType(newBas, zero, custom) - - return nil -} diff --git a/vendor/github.com/gogo/protobuf/proto/discard.go b/vendor/github.com/gogo/protobuf/proto/discard.go deleted file mode 100644 index bd0e3bb4c8..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/discard.go +++ /dev/null @@ -1,151 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2017 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "fmt" - "reflect" - "strings" -) - -// DiscardUnknown recursively discards all unknown fields from this message -// and all embedded messages. -// -// When unmarshaling a message with unrecognized fields, the tags and values -// of such fields are preserved in the Message. This allows a later call to -// marshal to be able to produce a message that continues to have those -// unrecognized fields. To avoid this, DiscardUnknown is used to -// explicitly clear the unknown fields after unmarshaling. -// -// For proto2 messages, the unknown fields of message extensions are only -// discarded from messages that have been accessed via GetExtension. -func DiscardUnknown(m Message) { - discardLegacy(m) -} - -func discardLegacy(m Message) { - v := reflect.ValueOf(m) - if v.Kind() != reflect.Ptr || v.IsNil() { - return - } - v = v.Elem() - if v.Kind() != reflect.Struct { - return - } - t := v.Type() - - for i := 0; i < v.NumField(); i++ { - f := t.Field(i) - if strings.HasPrefix(f.Name, "XXX_") { - continue - } - vf := v.Field(i) - tf := f.Type - - // Unwrap tf to get its most basic type. - var isPointer, isSlice bool - if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { - isSlice = true - tf = tf.Elem() - } - if tf.Kind() == reflect.Ptr { - isPointer = true - tf = tf.Elem() - } - if isPointer && isSlice && tf.Kind() != reflect.Struct { - panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) - } - - switch tf.Kind() { - case reflect.Struct: - switch { - case !isPointer: - panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) - case isSlice: // E.g., []*pb.T - for j := 0; j < vf.Len(); j++ { - discardLegacy(vf.Index(j).Interface().(Message)) - } - default: // E.g., *pb.T - discardLegacy(vf.Interface().(Message)) - } - case reflect.Map: - switch { - case isPointer || isSlice: - panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) - default: // E.g., map[K]V - tv := vf.Type().Elem() - if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) - for _, key := range vf.MapKeys() { - val := vf.MapIndex(key) - discardLegacy(val.Interface().(Message)) - } - } - } - case reflect.Interface: - // Must be oneof field. - switch { - case isPointer || isSlice: - panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) - default: // E.g., test_proto.isCommunique_Union interface - if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { - vf = vf.Elem() // E.g., *test_proto.Communique_Msg - if !vf.IsNil() { - vf = vf.Elem() // E.g., test_proto.Communique_Msg - vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value - if vf.Kind() == reflect.Ptr { - discardLegacy(vf.Interface().(Message)) - } - } - } - } - } - } - - if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { - if vf.Type() != reflect.TypeOf([]byte{}) { - panic("expected XXX_unrecognized to be of type []byte") - } - vf.Set(reflect.ValueOf([]byte(nil))) - } - - // For proto2 messages, only discard unknown fields in message extensions - // that have been accessed via GetExtension. - if em, ok := extendable(m); ok { - // Ignore lock since discardLegacy is not concurrency safe. - emm, _ := em.extensionsRead() - for _, mx := range emm { - if m, ok := mx.value.(Message); ok { - discardLegacy(m) - } - } - } -} diff --git a/vendor/github.com/gogo/protobuf/proto/duration.go b/vendor/github.com/gogo/protobuf/proto/duration.go deleted file mode 100644 index 93464c91cf..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/duration.go +++ /dev/null @@ -1,100 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -// This file implements conversions between google.protobuf.Duration -// and time.Duration. - -import ( - "errors" - "fmt" - "time" -) - -const ( - // Range of a Duration in seconds, as specified in - // google/protobuf/duration.proto. This is about 10,000 years in seconds. - maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) - minSeconds = -maxSeconds -) - -// validateDuration determines whether the Duration is valid according to the -// definition in google/protobuf/duration.proto. A valid Duration -// may still be too large to fit into a time.Duration (the range of Duration -// is about 10,000 years, and the range of time.Duration is about 290). -func validateDuration(d *duration) error { - if d == nil { - return errors.New("duration: nil Duration") - } - if d.Seconds < minSeconds || d.Seconds > maxSeconds { - return fmt.Errorf("duration: %#v: seconds out of range", d) - } - if d.Nanos <= -1e9 || d.Nanos >= 1e9 { - return fmt.Errorf("duration: %#v: nanos out of range", d) - } - // Seconds and Nanos must have the same sign, unless d.Nanos is zero. - if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) { - return fmt.Errorf("duration: %#v: seconds and nanos have different signs", d) - } - return nil -} - -// DurationFromProto converts a Duration to a time.Duration. DurationFromProto -// returns an error if the Duration is invalid or is too large to be -// represented in a time.Duration. -func durationFromProto(p *duration) (time.Duration, error) { - if err := validateDuration(p); err != nil { - return 0, err - } - d := time.Duration(p.Seconds) * time.Second - if int64(d/time.Second) != p.Seconds { - return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p) - } - if p.Nanos != 0 { - d += time.Duration(p.Nanos) - if (d < 0) != (p.Nanos < 0) { - return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p) - } - } - return d, nil -} - -// DurationProto converts a time.Duration to a Duration. -func durationProto(d time.Duration) *duration { - nanos := d.Nanoseconds() - secs := nanos / 1e9 - nanos -= secs * 1e9 - return &duration{ - Seconds: secs, - Nanos: int32(nanos), - } -} diff --git a/vendor/github.com/gogo/protobuf/proto/duration_gogo.go b/vendor/github.com/gogo/protobuf/proto/duration_gogo.go deleted file mode 100644 index 18e2a5f776..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/duration_gogo.go +++ /dev/null @@ -1,203 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2016, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "reflect" - "time" -) - -var durationType = reflect.TypeOf((*time.Duration)(nil)).Elem() - -type duration struct { - Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` - Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` -} - -func (m *duration) Reset() { *m = duration{} } -func (*duration) ProtoMessage() {} -func (*duration) String() string { return "duration" } - -func init() { - RegisterType((*duration)(nil), "gogo.protobuf.proto.duration") -} - -func (o *Buffer) decDuration() (time.Duration, error) { - b, err := o.DecodeRawBytes(true) - if err != nil { - return 0, err - } - dproto := &duration{} - if err := Unmarshal(b, dproto); err != nil { - return 0, err - } - return durationFromProto(dproto) -} - -func (o *Buffer) dec_duration(p *Properties, base structPointer) error { - d, err := o.decDuration() - if err != nil { - return err - } - word64_Set(structPointer_Word64(base, p.field), o, uint64(d)) - return nil -} - -func (o *Buffer) dec_ref_duration(p *Properties, base structPointer) error { - d, err := o.decDuration() - if err != nil { - return err - } - word64Val_Set(structPointer_Word64Val(base, p.field), o, uint64(d)) - return nil -} - -func (o *Buffer) dec_slice_duration(p *Properties, base structPointer) error { - d, err := o.decDuration() - if err != nil { - return err - } - newBas := appendStructPointer(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))) - var zero field - setPtrCustomType(newBas, zero, &d) - return nil -} - -func (o *Buffer) dec_slice_ref_duration(p *Properties, base structPointer) error { - d, err := o.decDuration() - if err != nil { - return err - } - structPointer_Word64Slice(base, p.field).Append(uint64(d)) - return nil -} - -func size_duration(p *Properties, base structPointer) (n int) { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - dur := structPointer_Interface(structp, durationType).(*time.Duration) - d := durationProto(*dur) - size := Size(d) - return size + sizeVarint(uint64(size)) + len(p.tagcode) -} - -func (o *Buffer) enc_duration(p *Properties, base structPointer) error { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - dur := structPointer_Interface(structp, durationType).(*time.Duration) - d := durationProto(*dur) - data, err := Marshal(d) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_ref_duration(p *Properties, base structPointer) (n int) { - dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration) - d := durationProto(*dur) - size := Size(d) - return size + sizeVarint(uint64(size)) + len(p.tagcode) -} - -func (o *Buffer) enc_ref_duration(p *Properties, base structPointer) error { - dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration) - d := durationProto(*dur) - data, err := Marshal(d) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_slice_duration(p *Properties, base structPointer) (n int) { - pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration) - durs := *pdurs - for i := 0; i < len(durs); i++ { - if durs[i] == nil { - return 0 - } - dproto := durationProto(*durs[i]) - size := Size(dproto) - n += len(p.tagcode) + size + sizeVarint(uint64(size)) - } - return n -} - -func (o *Buffer) enc_slice_duration(p *Properties, base structPointer) error { - pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration) - durs := *pdurs - for i := 0; i < len(durs); i++ { - if durs[i] == nil { - return errRepeatedHasNil - } - dproto := durationProto(*durs[i]) - data, err := Marshal(dproto) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - } - return nil -} - -func size_slice_ref_duration(p *Properties, base structPointer) (n int) { - pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration) - durs := *pdurs - for i := 0; i < len(durs); i++ { - dproto := durationProto(durs[i]) - size := Size(dproto) - n += len(p.tagcode) + size + sizeVarint(uint64(size)) - } - return n -} - -func (o *Buffer) enc_slice_ref_duration(p *Properties, base structPointer) error { - pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration) - durs := *pdurs - for i := 0; i < len(durs); i++ { - dproto := durationProto(durs[i]) - data, err := Marshal(dproto) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - } - return nil -} diff --git a/vendor/github.com/gogo/protobuf/proto/encode.go b/vendor/github.com/gogo/protobuf/proto/encode.go deleted file mode 100644 index 8b84d1b22d..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/encode.go +++ /dev/null @@ -1,1362 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -/* - * Routines for encoding data into the wire format for protocol buffers. - */ - -import ( - "errors" - "fmt" - "reflect" - "sort" -) - -// RequiredNotSetError is the error returned if Marshal is called with -// a protocol buffer struct whose required fields have not -// all been initialized. It is also the error returned if Unmarshal is -// called with an encoded protocol buffer that does not include all the -// required fields. -// -// When printed, RequiredNotSetError reports the first unset required field in a -// message. If the field cannot be precisely determined, it is reported as -// "{Unknown}". -type RequiredNotSetError struct { - field string -} - -func (e *RequiredNotSetError) Error() string { - return fmt.Sprintf("proto: required field %q not set", e.field) -} - -var ( - // errRepeatedHasNil is the error returned if Marshal is called with - // a struct with a repeated field containing a nil element. - errRepeatedHasNil = errors.New("proto: repeated field has nil element") - - // errOneofHasNil is the error returned if Marshal is called with - // a struct with a oneof field containing a nil element. - errOneofHasNil = errors.New("proto: oneof field has nil value") - - // ErrNil is the error returned if Marshal is called with nil. - ErrNil = errors.New("proto: Marshal called with nil") - - // ErrTooLarge is the error returned if Marshal is called with a - // message that encodes to >2GB. - ErrTooLarge = errors.New("proto: message encodes to over 2 GB") -) - -// The fundamental encoders that put bytes on the wire. -// Those that take integer types all accept uint64 and are -// therefore of type valueEncoder. - -const maxVarintBytes = 10 // maximum length of a varint - -// maxMarshalSize is the largest allowed size of an encoded protobuf, -// since C++ and Java use signed int32s for the size. -const maxMarshalSize = 1<<31 - 1 - -// EncodeVarint returns the varint encoding of x. -// This is the format for the -// int32, int64, uint32, uint64, bool, and enum -// protocol buffer types. -// Not used by the package itself, but helpful to clients -// wishing to use the same encoding. -func EncodeVarint(x uint64) []byte { - var buf [maxVarintBytes]byte - var n int - for n = 0; x > 127; n++ { - buf[n] = 0x80 | uint8(x&0x7F) - x >>= 7 - } - buf[n] = uint8(x) - n++ - return buf[0:n] -} - -// EncodeVarint writes a varint-encoded integer to the Buffer. -// This is the format for the -// int32, int64, uint32, uint64, bool, and enum -// protocol buffer types. -func (p *Buffer) EncodeVarint(x uint64) error { - for x >= 1<<7 { - p.buf = append(p.buf, uint8(x&0x7f|0x80)) - x >>= 7 - } - p.buf = append(p.buf, uint8(x)) - return nil -} - -// SizeVarint returns the varint encoding size of an integer. -func SizeVarint(x uint64) int { - return sizeVarint(x) -} - -func sizeVarint(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} - -// EncodeFixed64 writes a 64-bit integer to the Buffer. -// This is the format for the -// fixed64, sfixed64, and double protocol buffer types. -func (p *Buffer) EncodeFixed64(x uint64) error { - p.buf = append(p.buf, - uint8(x), - uint8(x>>8), - uint8(x>>16), - uint8(x>>24), - uint8(x>>32), - uint8(x>>40), - uint8(x>>48), - uint8(x>>56)) - return nil -} - -func sizeFixed64(x uint64) int { - return 8 -} - -// EncodeFixed32 writes a 32-bit integer to the Buffer. -// This is the format for the -// fixed32, sfixed32, and float protocol buffer types. -func (p *Buffer) EncodeFixed32(x uint64) error { - p.buf = append(p.buf, - uint8(x), - uint8(x>>8), - uint8(x>>16), - uint8(x>>24)) - return nil -} - -func sizeFixed32(x uint64) int { - return 4 -} - -// EncodeZigzag64 writes a zigzag-encoded 64-bit integer -// to the Buffer. -// This is the format used for the sint64 protocol buffer type. -func (p *Buffer) EncodeZigzag64(x uint64) error { - // use signed number to get arithmetic right shift. - return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63))) -} - -func sizeZigzag64(x uint64) int { - return sizeVarint((x << 1) ^ uint64((int64(x) >> 63))) -} - -// EncodeZigzag32 writes a zigzag-encoded 32-bit integer -// to the Buffer. -// This is the format used for the sint32 protocol buffer type. -func (p *Buffer) EncodeZigzag32(x uint64) error { - // use signed number to get arithmetic right shift. - return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) -} - -func sizeZigzag32(x uint64) int { - return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) -} - -// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. -// This is the format used for the bytes protocol buffer -// type and for embedded messages. -func (p *Buffer) EncodeRawBytes(b []byte) error { - p.EncodeVarint(uint64(len(b))) - p.buf = append(p.buf, b...) - return nil -} - -func sizeRawBytes(b []byte) int { - return sizeVarint(uint64(len(b))) + - len(b) -} - -// EncodeStringBytes writes an encoded string to the Buffer. -// This is the format used for the proto2 string type. -func (p *Buffer) EncodeStringBytes(s string) error { - p.EncodeVarint(uint64(len(s))) - p.buf = append(p.buf, s...) - return nil -} - -func sizeStringBytes(s string) int { - return sizeVarint(uint64(len(s))) + - len(s) -} - -// Marshaler is the interface representing objects that can marshal themselves. -type Marshaler interface { - Marshal() ([]byte, error) -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, returning the data. -func Marshal(pb Message) ([]byte, error) { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - return m.Marshal() - } - p := NewBuffer(nil) - err := p.Marshal(pb) - if p.buf == nil && err == nil { - // Return a non-nil slice on success. - return []byte{}, nil - } - return p.buf, err -} - -// EncodeMessage writes the protocol buffer to the Buffer, -// prefixed by a varint-encoded length. -func (p *Buffer) EncodeMessage(pb Message) error { - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - var state errorState - err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) - } - return err -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, writing the result to the -// Buffer. -func (p *Buffer) Marshal(pb Message) error { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - data, err := m.Marshal() - p.buf = append(p.buf, data...) - return err - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - err = p.enc_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Encode++ // Parens are to work around a goimports bug. - } - - if len(p.buf) > maxMarshalSize { - return ErrTooLarge - } - return err -} - -// Size returns the encoded size of a protocol buffer. -func Size(pb Message) (n int) { - // Can the object marshal itself? If so, Size is slow. - // TODO: add Size to Marshaler, or add a Sizer interface. - if m, ok := pb.(Marshaler); ok { - b, _ := m.Marshal() - return len(b) - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return 0 - } - if err == nil { - n = size_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Size++ // Parens are to work around a goimports bug. - } - - return -} - -// Individual type encoders. - -// Encode a bool. -func (o *Buffer) enc_bool(p *Properties, base structPointer) error { - v := *structPointer_Bool(base, p.field) - if v == nil { - return ErrNil - } - x := 0 - if *v { - x = 1 - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { - v := *structPointer_BoolVal(base, p.field) - if !v { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, 1) - return nil -} - -func size_bool(p *Properties, base structPointer) int { - v := *structPointer_Bool(base, p.field) - if v == nil { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -func size_proto3_bool(p *Properties, base structPointer) int { - v := *structPointer_BoolVal(base, p.field) - if !v && !p.oneof { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -// Encode an int32. -func (o *Buffer) enc_int32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode a uint32. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := word32_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := word32_Get(v) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode an int64. -func (o *Buffer) enc_int64(p *Properties, base structPointer) error { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return ErrNil - } - x := word64_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func size_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return 0 - } - x := word64_Get(v) - n += len(p.tagcode) - n += p.valSize(x) - return -} - -func size_proto3_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(x) - return -} - -// Encode a string. -func (o *Buffer) enc_string(p *Properties, base structPointer) error { - v := *structPointer_String(base, p.field) - if v == nil { - return ErrNil - } - x := *v - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(x) - return nil -} - -func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { - v := *structPointer_StringVal(base, p.field) - if v == "" { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(v) - return nil -} - -func size_string(p *Properties, base structPointer) (n int) { - v := *structPointer_String(base, p.field) - if v == nil { - return 0 - } - x := *v - n += len(p.tagcode) - n += sizeStringBytes(x) - return -} - -func size_proto3_string(p *Properties, base structPointer) (n int) { - v := *structPointer_StringVal(base, p.field) - if v == "" && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeStringBytes(v) - return -} - -// All protocol buffer fields are nillable, but be careful. -func isNil(v reflect.Value) bool { - switch v.Kind() { - case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: - return v.IsNil() - } - return false -} - -// Encode a message struct. -func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { - var state errorState - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return state.err - } - - o.buf = append(o.buf, p.tagcode...) - return o.enc_len_struct(p.sprop, structp, &state) -} - -func size_struct_message(p *Properties, base structPointer) int { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n0 := len(p.tagcode) - n1 := sizeRawBytes(data) - return n0 + n1 - } - - n0 := len(p.tagcode) - n1 := size_struct(p.sprop, structp) - n2 := sizeVarint(uint64(n1)) // size of encoded length - return n0 + n1 + n2 -} - -// Encode a group struct. -func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { - var state errorState - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return ErrNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - err := o.enc_struct(p.sprop, b) - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return state.err -} - -func size_struct_group(p *Properties, base structPointer) (n int) { - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return 0 - } - - n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) - n += size_struct(p.sprop, b) - n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return -} - -// Encode a slice of bools ([]bool). -func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - for _, x := range s { - o.buf = append(o.buf, p.tagcode...) - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_bool(p *Properties, base structPointer) int { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - return l * (len(p.tagcode) + 1) // each bool takes exactly one byte -} - -// Encode a slice of bools ([]bool) in packed format. -func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(l)) // each bool takes exactly one byte - for _, x := range s { - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_packed_bool(p *Properties, base structPointer) (n int) { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - n += len(p.tagcode) - n += sizeVarint(uint64(l)) - n += l // each bool takes exactly one byte - return -} - -// Encode a slice of bytes ([]byte). -func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func size_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if s == nil && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -// Encode a slice of int32s ([]int32). -func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of int32s ([]int32) in packed format. -func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(buf, uint64(x)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - bufSize += p.valSize(uint64(x)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of uint32s ([]uint32). -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := s.Index(i) - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := s.Index(i) - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of uint32s ([]uint32) in packed format. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, uint64(s.Index(i))) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(uint64(s.Index(i))) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of int64s ([]int64). -func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, s.Index(i)) - } - return nil -} - -func size_slice_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - n += p.valSize(s.Index(i)) - } - return -} - -// Encode a slice of int64s ([]int64) in packed format. -func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, s.Index(i)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(s.Index(i)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of slice of bytes ([][]byte). -func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(ss[i]) - } - return nil -} - -func size_slice_slice_byte(p *Properties, base structPointer) (n int) { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return 0 - } - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeRawBytes(ss[i]) - } - return -} - -// Encode a slice of strings ([]string). -func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(ss[i]) - } - return nil -} - -func size_slice_string(p *Properties, base structPointer) (n int) { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeStringBytes(ss[i]) - } - return -} - -// Encode a slice of message structs ([]*struct). -func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return errRepeatedHasNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - continue - } - - o.buf = append(o.buf, p.tagcode...) - err := o.enc_len_struct(p.sprop, structp, &state) - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - } - return state.err -} - -func size_slice_struct_message(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return // return the size up to this point - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n += sizeRawBytes(data) - continue - } - - n0 := size_struct(p.sprop, structp) - n1 := sizeVarint(uint64(n0)) // size of encoded length - n += n0 + n1 - } - return -} - -// Encode a slice of group structs ([]*struct). -func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return errRepeatedHasNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - - err := o.enc_struct(p.sprop, b) - - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - } - return state.err -} - -func size_slice_struct_group(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) - n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return // return size up to this point - } - - n += size_struct(p.sprop, b) - } - return -} - -// Encode an extension map. -func (o *Buffer) enc_map(p *Properties, base structPointer) error { - exts := structPointer_ExtMap(base, p.field) - if err := encodeExtensionsMap(*exts); err != nil { - return err - } - - return o.enc_map_body(*exts) -} - -func (o *Buffer) enc_exts(p *Properties, base structPointer) error { - exts := structPointer_Extensions(base, p.field) - - v, mu := exts.extensionsRead() - if v == nil { - return nil - } - - mu.Lock() - defer mu.Unlock() - if err := encodeExtensionsMap(v); err != nil { - return err - } - - return o.enc_map_body(v) -} - -func (o *Buffer) enc_map_body(v map[int32]Extension) error { - // Fast-path for common cases: zero or one extensions. - if len(v) <= 1 { - for _, e := range v { - o.buf = append(o.buf, e.enc...) - } - return nil - } - - // Sort keys to provide a deterministic encoding. - keys := make([]int, 0, len(v)) - for k := range v { - keys = append(keys, int(k)) - } - sort.Ints(keys) - - for _, k := range keys { - o.buf = append(o.buf, v[int32(k)].enc...) - } - return nil -} - -func size_map(p *Properties, base structPointer) int { - v := structPointer_ExtMap(base, p.field) - return extensionsMapSize(*v) -} - -func size_exts(p *Properties, base structPointer) int { - v := structPointer_Extensions(base, p.field) - return extensionsSize(v) -} - -// Encode a map field. -func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { - var state errorState // XXX: or do we need to plumb this through? - - /* - A map defined as - map map_field = N; - is encoded in the same way as - message MapFieldEntry { - key_type key = 1; - value_type value = 2; - } - repeated MapFieldEntry map_field = N; - */ - - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - if v.Len() == 0 { - return nil - } - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - enc := func() error { - if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { - return err - } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { - return err - } - return nil - } - - // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - - keycopy.Set(key) - valcopy.Set(val) - - o.buf = append(o.buf, p.tagcode...) - if err := o.enc_len_thing(enc, &state); err != nil { - return err - } - } - return nil -} - -func size_new_map(p *Properties, base structPointer) int { - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - n := 0 - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - keycopy.Set(key) - valcopy.Set(val) - - // Tag codes for key and val are the responsibility of the sub-sizer. - keysize := p.mkeyprop.size(p.mkeyprop, keybase) - valsize := p.mvalprop.size(p.mvalprop, valbase) - entry := keysize + valsize - // Add on tag code and length of map entry itself. - n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry - } - return n -} - -// mapEncodeScratch returns a new reflect.Value matching the map's value type, -// and a structPointer suitable for passing to an encoder or sizer. -func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { - // Prepare addressable doubly-indirect placeholders for the key and value types. - // This is needed because the element-type encoders expect **T, but the map iteration produces T. - - keycopy = reflect.New(mapType.Key()).Elem() // addressable K - keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K - keyptr.Set(keycopy.Addr()) // - keybase = toStructPointer(keyptr.Addr()) // **K - - // Value types are more varied and require special handling. - switch mapType.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte - valbase = toStructPointer(valcopy.Addr()) - case reflect.Ptr: - // message; the generated field type is map[K]*Msg (so V is *Msg), - // so we only need one level of indirection. - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valbase = toStructPointer(valcopy.Addr()) - default: - // everything else - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V - valptr.Set(valcopy.Addr()) // - valbase = toStructPointer(valptr.Addr()) // **V - } - return -} - -// Encode a struct. -func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { - var state errorState - // Encode fields in tag order so that decoders may use optimizations - // that depend on the ordering. - // https://developers.google.com/protocol-buffers/docs/encoding#order - for _, i := range prop.order { - p := prop.Prop[i] - if p.enc != nil { - err := p.enc(o, p, base) - if err != nil { - if err == ErrNil { - if p.Required && state.err == nil { - state.err = &RequiredNotSetError{p.Name} - } - } else if err == errRepeatedHasNil { - // Give more context to nil values in repeated fields. - return errors.New("repeated field " + p.OrigName + " has nil element") - } else if !state.shouldContinue(err, p) { - return err - } - } - if len(o.buf) > maxMarshalSize { - return ErrTooLarge - } - } - } - - // Do oneof fields. - if prop.oneofMarshaler != nil { - m := structPointer_Interface(base, prop.stype).(Message) - if err := prop.oneofMarshaler(m, o); err == ErrNil { - return errOneofHasNil - } else if err != nil { - return err - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - if len(o.buf)+len(v) > maxMarshalSize { - return ErrTooLarge - } - if len(v) > 0 { - o.buf = append(o.buf, v...) - } - } - - return state.err -} - -func size_struct(prop *StructProperties, base structPointer) (n int) { - for _, i := range prop.order { - p := prop.Prop[i] - if p.size != nil { - n += p.size(p, base) - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - n += len(v) - } - - // Factor in any oneof fields. - if prop.oneofSizer != nil { - m := structPointer_Interface(base, prop.stype).(Message) - n += prop.oneofSizer(m) - } - - return -} - -var zeroes [20]byte // longer than any conceivable sizeVarint - -// Encode a struct, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { - return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) -} - -// Encode something, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { - iLen := len(o.buf) - o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length - iMsg := len(o.buf) - err := enc() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - lMsg := len(o.buf) - iMsg - lLen := sizeVarint(uint64(lMsg)) - switch x := lLen - (iMsg - iLen); { - case x > 0: // actual length is x bytes larger than the space we reserved - // Move msg x bytes right. - o.buf = append(o.buf, zeroes[:x]...) - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - case x < 0: // actual length is x bytes smaller than the space we reserved - // Move msg x bytes left. - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - o.buf = o.buf[:len(o.buf)+x] // x is negative - } - // Encode the length in the reserved space. - o.buf = o.buf[:iLen] - o.EncodeVarint(uint64(lMsg)) - o.buf = o.buf[:len(o.buf)+lMsg] - return state.err -} - -// errorState maintains the first error that occurs and updates that error -// with additional context. -type errorState struct { - err error -} - -// shouldContinue reports whether encoding should continue upon encountering the -// given error. If the error is RequiredNotSetError, shouldContinue returns true -// and, if this is the first appearance of that error, remembers it for future -// reporting. -// -// If prop is not nil, it may update any error with additional context about the -// field with the error. -func (s *errorState) shouldContinue(err error, prop *Properties) bool { - // Ignore unset required fields. - reqNotSet, ok := err.(*RequiredNotSetError) - if !ok { - return false - } - if s.err == nil { - if prop != nil { - err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} - } - s.err = err - } - return true -} diff --git a/vendor/github.com/gogo/protobuf/proto/encode_gogo.go b/vendor/github.com/gogo/protobuf/proto/encode_gogo.go deleted file mode 100644 index 32111b7f41..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/encode_gogo.go +++ /dev/null @@ -1,350 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// http://github.com/golang/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "reflect" -) - -func NewRequiredNotSetError(field string) *RequiredNotSetError { - return &RequiredNotSetError{field} -} - -type Sizer interface { - Size() int -} - -func (o *Buffer) enc_ext_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return ErrNil - } - o.buf = append(o.buf, s...) - return nil -} - -func size_ext_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return 0 - } - n += len(s) - return -} - -// Encode a reference to bool pointer. -func (o *Buffer) enc_ref_bool(p *Properties, base structPointer) error { - v := *structPointer_BoolVal(base, p.field) - x := 0 - if v { - x = 1 - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_ref_bool(p *Properties, base structPointer) int { - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -// Encode a reference to int32 pointer. -func (o *Buffer) enc_ref_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_ref_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func (o *Buffer) enc_ref_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_ref_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode a reference to an int64 pointer. -func (o *Buffer) enc_ref_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func size_ref_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - n += len(p.tagcode) - n += p.valSize(x) - return -} - -// Encode a reference to a string pointer. -func (o *Buffer) enc_ref_string(p *Properties, base structPointer) error { - v := *structPointer_StringVal(base, p.field) - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(v) - return nil -} - -func size_ref_string(p *Properties, base structPointer) (n int) { - v := *structPointer_StringVal(base, p.field) - n += len(p.tagcode) - n += sizeStringBytes(v) - return -} - -// Encode a reference to a message struct. -func (o *Buffer) enc_ref_struct_message(p *Properties, base structPointer) error { - var state errorState - structp := structPointer_GetRefStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil - } - - o.buf = append(o.buf, p.tagcode...) - return o.enc_len_struct(p.sprop, structp, &state) -} - -//TODO this is only copied, please fix this -func size_ref_struct_message(p *Properties, base structPointer) int { - structp := structPointer_GetRefStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n0 := len(p.tagcode) - n1 := sizeRawBytes(data) - return n0 + n1 - } - - n0 := len(p.tagcode) - n1 := size_struct(p.sprop, structp) - n2 := sizeVarint(uint64(n1)) // size of encoded length - return n0 + n1 + n2 -} - -// Encode a slice of references to message struct pointers ([]struct). -func (o *Buffer) enc_slice_ref_struct_message(p *Properties, base structPointer) error { - var state errorState - ss := structPointer_StructRefSlice(base, p.field, p.stype.Size()) - l := ss.Len() - for i := 0; i < l; i++ { - structp := ss.Index(i) - if structPointer_IsNil(structp) { - return errRepeatedHasNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - continue - } - - o.buf = append(o.buf, p.tagcode...) - err := o.enc_len_struct(p.sprop, structp, &state) - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - - } - return state.err -} - -//TODO this is only copied, please fix this -func size_slice_ref_struct_message(p *Properties, base structPointer) (n int) { - ss := structPointer_StructRefSlice(base, p.field, p.stype.Size()) - l := ss.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - structp := ss.Index(i) - if structPointer_IsNil(structp) { - return // return the size up to this point - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n += len(p.tagcode) - n += sizeRawBytes(data) - continue - } - - n0 := size_struct(p.sprop, structp) - n1 := sizeVarint(uint64(n0)) // size of encoded length - n += n0 + n1 - } - return -} - -func (o *Buffer) enc_custom_bytes(p *Properties, base structPointer) error { - i := structPointer_InterfaceRef(base, p.field, p.ctype) - if i == nil { - return ErrNil - } - custom := i.(Marshaler) - data, err := custom.Marshal() - if err != nil { - return err - } - if data == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_custom_bytes(p *Properties, base structPointer) (n int) { - n += len(p.tagcode) - i := structPointer_InterfaceRef(base, p.field, p.ctype) - if i == nil { - return 0 - } - custom := i.(Marshaler) - data, _ := custom.Marshal() - n += sizeRawBytes(data) - return -} - -func (o *Buffer) enc_custom_ref_bytes(p *Properties, base structPointer) error { - custom := structPointer_InterfaceAt(base, p.field, p.ctype).(Marshaler) - data, err := custom.Marshal() - if err != nil { - return err - } - if data == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_custom_ref_bytes(p *Properties, base structPointer) (n int) { - n += len(p.tagcode) - i := structPointer_InterfaceAt(base, p.field, p.ctype) - if i == nil { - return 0 - } - custom := i.(Marshaler) - data, _ := custom.Marshal() - n += sizeRawBytes(data) - return -} - -func (o *Buffer) enc_custom_slice_bytes(p *Properties, base structPointer) error { - inter := structPointer_InterfaceRef(base, p.field, p.ctype) - if inter == nil { - return ErrNil - } - slice := reflect.ValueOf(inter) - l := slice.Len() - for i := 0; i < l; i++ { - v := slice.Index(i) - custom := v.Interface().(Marshaler) - data, err := custom.Marshal() - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - } - return nil -} - -func size_custom_slice_bytes(p *Properties, base structPointer) (n int) { - inter := structPointer_InterfaceRef(base, p.field, p.ctype) - if inter == nil { - return 0 - } - slice := reflect.ValueOf(inter) - l := slice.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - v := slice.Index(i) - custom := v.Interface().(Marshaler) - data, _ := custom.Marshal() - n += sizeRawBytes(data) - } - return -} diff --git a/vendor/github.com/gogo/protobuf/proto/equal.go b/vendor/github.com/gogo/protobuf/proto/equal.go deleted file mode 100644 index 2ed1cf5966..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/equal.go +++ /dev/null @@ -1,300 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Protocol buffer comparison. - -package proto - -import ( - "bytes" - "log" - "reflect" - "strings" -) - -/* -Equal returns true iff protocol buffers a and b are equal. -The arguments must both be pointers to protocol buffer structs. - -Equality is defined in this way: - - Two messages are equal iff they are the same type, - corresponding fields are equal, unknown field sets - are equal, and extensions sets are equal. - - Two set scalar fields are equal iff their values are equal. - If the fields are of a floating-point type, remember that - NaN != x for all x, including NaN. If the message is defined - in a proto3 .proto file, fields are not "set"; specifically, - zero length proto3 "bytes" fields are equal (nil == {}). - - Two repeated fields are equal iff their lengths are the same, - and their corresponding elements are equal. Note a "bytes" field, - although represented by []byte, is not a repeated field and the - rule for the scalar fields described above applies. - - Two unset fields are equal. - - Two unknown field sets are equal if their current - encoded state is equal. - - Two extension sets are equal iff they have corresponding - elements that are pairwise equal. - - Two map fields are equal iff their lengths are the same, - and they contain the same set of elements. Zero-length map - fields are equal. - - Every other combination of things are not equal. - -The return value is undefined if a and b are not protocol buffers. -*/ -func Equal(a, b Message) bool { - if a == nil || b == nil { - return a == b - } - v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) - if v1.Type() != v2.Type() { - return false - } - if v1.Kind() == reflect.Ptr { - if v1.IsNil() { - return v2.IsNil() - } - if v2.IsNil() { - return false - } - v1, v2 = v1.Elem(), v2.Elem() - } - if v1.Kind() != reflect.Struct { - return false - } - return equalStruct(v1, v2) -} - -// v1 and v2 are known to have the same type. -func equalStruct(v1, v2 reflect.Value) bool { - sprop := GetProperties(v1.Type()) - for i := 0; i < v1.NumField(); i++ { - f := v1.Type().Field(i) - if strings.HasPrefix(f.Name, "XXX_") { - continue - } - f1, f2 := v1.Field(i), v2.Field(i) - if f.Type.Kind() == reflect.Ptr { - if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { - // both unset - continue - } else if n1 != n2 { - // set/unset mismatch - return false - } - b1, ok := f1.Interface().(raw) - if ok { - b2 := f2.Interface().(raw) - // RawMessage - if !bytes.Equal(b1.Bytes(), b2.Bytes()) { - return false - } - continue - } - f1, f2 = f1.Elem(), f2.Elem() - } - if !equalAny(f1, f2, sprop.Prop[i]) { - return false - } - } - - if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { - em2 := v2.FieldByName("XXX_InternalExtensions") - if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { - return false - } - } - - if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { - em2 := v2.FieldByName("XXX_extensions") - if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { - return false - } - } - - uf := v1.FieldByName("XXX_unrecognized") - if !uf.IsValid() { - return true - } - - u1 := uf.Bytes() - u2 := v2.FieldByName("XXX_unrecognized").Bytes() - if !bytes.Equal(u1, u2) { - return false - } - - return true -} - -// v1 and v2 are known to have the same type. -// prop may be nil. -func equalAny(v1, v2 reflect.Value, prop *Properties) bool { - if v1.Type() == protoMessageType { - m1, _ := v1.Interface().(Message) - m2, _ := v2.Interface().(Message) - return Equal(m1, m2) - } - switch v1.Kind() { - case reflect.Bool: - return v1.Bool() == v2.Bool() - case reflect.Float32, reflect.Float64: - return v1.Float() == v2.Float() - case reflect.Int32, reflect.Int64: - return v1.Int() == v2.Int() - case reflect.Interface: - // Probably a oneof field; compare the inner values. - n1, n2 := v1.IsNil(), v2.IsNil() - if n1 || n2 { - return n1 == n2 - } - e1, e2 := v1.Elem(), v2.Elem() - if e1.Type() != e2.Type() { - return false - } - return equalAny(e1, e2, nil) - case reflect.Map: - if v1.Len() != v2.Len() { - return false - } - for _, key := range v1.MapKeys() { - val2 := v2.MapIndex(key) - if !val2.IsValid() { - // This key was not found in the second map. - return false - } - if !equalAny(v1.MapIndex(key), val2, nil) { - return false - } - } - return true - case reflect.Ptr: - // Maps may have nil values in them, so check for nil. - if v1.IsNil() && v2.IsNil() { - return true - } - if v1.IsNil() != v2.IsNil() { - return false - } - return equalAny(v1.Elem(), v2.Elem(), prop) - case reflect.Slice: - if v1.Type().Elem().Kind() == reflect.Uint8 { - // short circuit: []byte - - // Edge case: if this is in a proto3 message, a zero length - // bytes field is considered the zero value. - if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { - return true - } - if v1.IsNil() != v2.IsNil() { - return false - } - return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) - } - - if v1.Len() != v2.Len() { - return false - } - for i := 0; i < v1.Len(); i++ { - if !equalAny(v1.Index(i), v2.Index(i), prop) { - return false - } - } - return true - case reflect.String: - return v1.Interface().(string) == v2.Interface().(string) - case reflect.Struct: - return equalStruct(v1, v2) - case reflect.Uint32, reflect.Uint64: - return v1.Uint() == v2.Uint() - } - - // unknown type, so not a protocol buffer - log.Printf("proto: don't know how to compare %v", v1) - return false -} - -// base is the struct type that the extensions are based on. -// x1 and x2 are InternalExtensions. -func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { - em1, _ := x1.extensionsRead() - em2, _ := x2.extensionsRead() - return equalExtMap(base, em1, em2) -} - -func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { - if len(em1) != len(em2) { - return false - } - - for extNum, e1 := range em1 { - e2, ok := em2[extNum] - if !ok { - return false - } - - m1, m2 := e1.value, e2.value - - if m1 != nil && m2 != nil { - // Both are unencoded. - if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { - return false - } - continue - } - - // At least one is encoded. To do a semantically correct comparison - // we need to unmarshal them first. - var desc *ExtensionDesc - if m := extensionMaps[base]; m != nil { - desc = m[extNum] - } - if desc == nil { - log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) - continue - } - var err error - if m1 == nil { - m1, err = decodeExtension(e1.enc, desc) - } - if m2 == nil && err == nil { - m2, err = decodeExtension(e2.enc, desc) - } - if err != nil { - // The encoded form is invalid. - log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) - return false - } - if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { - return false - } - } - - return true -} diff --git a/vendor/github.com/gogo/protobuf/proto/extensions.go b/vendor/github.com/gogo/protobuf/proto/extensions.go deleted file mode 100644 index 0dfcb538e8..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/extensions.go +++ /dev/null @@ -1,693 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -/* - * Types and routines for supporting protocol buffer extensions. - */ - -import ( - "errors" - "fmt" - "reflect" - "strconv" - "sync" -) - -// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. -var ErrMissingExtension = errors.New("proto: missing extension") - -// ExtensionRange represents a range of message extensions for a protocol buffer. -// Used in code generated by the protocol compiler. -type ExtensionRange struct { - Start, End int32 // both inclusive -} - -// extendableProto is an interface implemented by any protocol buffer generated by the current -// proto compiler that may be extended. -type extendableProto interface { - Message - ExtensionRangeArray() []ExtensionRange - extensionsWrite() map[int32]Extension - extensionsRead() (map[int32]Extension, sync.Locker) -} - -// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous -// version of the proto compiler that may be extended. -type extendableProtoV1 interface { - Message - ExtensionRangeArray() []ExtensionRange - ExtensionMap() map[int32]Extension -} - -type extensionsBytes interface { - Message - ExtensionRangeArray() []ExtensionRange - GetExtensions() *[]byte -} - -// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. -type extensionAdapter struct { - extendableProtoV1 -} - -func (e extensionAdapter) extensionsWrite() map[int32]Extension { - return e.ExtensionMap() -} - -func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { - return e.ExtensionMap(), notLocker{} -} - -// notLocker is a sync.Locker whose Lock and Unlock methods are nops. -type notLocker struct{} - -func (n notLocker) Lock() {} -func (n notLocker) Unlock() {} - -// extendable returns the extendableProto interface for the given generated proto message. -// If the proto message has the old extension format, it returns a wrapper that implements -// the extendableProto interface. -func extendable(p interface{}) (extendableProto, bool) { - if ep, ok := p.(extendableProto); ok { - return ep, ok - } - if ep, ok := p.(extendableProtoV1); ok { - return extensionAdapter{ep}, ok - } - return nil, false -} - -// XXX_InternalExtensions is an internal representation of proto extensions. -// -// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, -// thus gaining the unexported 'extensions' method, which can be called only from the proto package. -// -// The methods of XXX_InternalExtensions are not concurrency safe in general, -// but calls to logically read-only methods such as has and get may be executed concurrently. -type XXX_InternalExtensions struct { - // The struct must be indirect so that if a user inadvertently copies a - // generated message and its embedded XXX_InternalExtensions, they - // avoid the mayhem of a copied mutex. - // - // The mutex serializes all logically read-only operations to p.extensionMap. - // It is up to the client to ensure that write operations to p.extensionMap are - // mutually exclusive with other accesses. - p *struct { - mu sync.Mutex - extensionMap map[int32]Extension - } -} - -// extensionsWrite returns the extension map, creating it on first use. -func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { - if e.p == nil { - e.p = new(struct { - mu sync.Mutex - extensionMap map[int32]Extension - }) - e.p.extensionMap = make(map[int32]Extension) - } - return e.p.extensionMap -} - -// extensionsRead returns the extensions map for read-only use. It may be nil. -// The caller must hold the returned mutex's lock when accessing Elements within the map. -func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { - if e.p == nil { - return nil, nil - } - return e.p.extensionMap, &e.p.mu -} - -type extensionRange interface { - Message - ExtensionRangeArray() []ExtensionRange -} - -var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() -var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() -var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem() -var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem() - -// ExtensionDesc represents an extension specification. -// Used in generated code from the protocol compiler. -type ExtensionDesc struct { - ExtendedType Message // nil pointer to the type that is being extended - ExtensionType interface{} // nil pointer to the extension type - Field int32 // field number - Name string // fully-qualified name of extension, for text formatting - Tag string // protobuf tag style - Filename string // name of the file in which the extension is defined -} - -func (ed *ExtensionDesc) repeated() bool { - t := reflect.TypeOf(ed.ExtensionType) - return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 -} - -// Extension represents an extension in a message. -type Extension struct { - // When an extension is stored in a message using SetExtension - // only desc and value are set. When the message is marshaled - // enc will be set to the encoded form of the message. - // - // When a message is unmarshaled and contains extensions, each - // extension will have only enc set. When such an extension is - // accessed using GetExtension (or GetExtensions) desc and value - // will be set. - desc *ExtensionDesc - value interface{} - enc []byte -} - -// SetRawExtension is for testing only. -func SetRawExtension(base Message, id int32, b []byte) { - if ebase, ok := base.(extensionsBytes); ok { - clearExtension(base, id) - ext := ebase.GetExtensions() - *ext = append(*ext, b...) - return - } - epb, ok := extendable(base) - if !ok { - return - } - extmap := epb.extensionsWrite() - extmap[id] = Extension{enc: b} -} - -// isExtensionField returns true iff the given field number is in an extension range. -func isExtensionField(pb extensionRange, field int32) bool { - for _, er := range pb.ExtensionRangeArray() { - if er.Start <= field && field <= er.End { - return true - } - } - return false -} - -// checkExtensionTypes checks that the given extension is valid for pb. -func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { - var pbi interface{} = pb - // Check the extended type. - if ea, ok := pbi.(extensionAdapter); ok { - pbi = ea.extendableProtoV1 - } - if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { - return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) - } - // Check the range. - if !isExtensionField(pb, extension.Field) { - return errors.New("proto: bad extension number; not in declared ranges") - } - return nil -} - -// extPropKey is sufficient to uniquely identify an extension. -type extPropKey struct { - base reflect.Type - field int32 -} - -var extProp = struct { - sync.RWMutex - m map[extPropKey]*Properties -}{ - m: make(map[extPropKey]*Properties), -} - -func extensionProperties(ed *ExtensionDesc) *Properties { - key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} - - extProp.RLock() - if prop, ok := extProp.m[key]; ok { - extProp.RUnlock() - return prop - } - extProp.RUnlock() - - extProp.Lock() - defer extProp.Unlock() - // Check again. - if prop, ok := extProp.m[key]; ok { - return prop - } - - prop := new(Properties) - prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) - extProp.m[key] = prop - return prop -} - -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensions(e *XXX_InternalExtensions) error { - m, mu := e.extensionsRead() - if m == nil { - return nil // fast path - } - mu.Lock() - defer mu.Unlock() - return encodeExtensionsMap(m) -} - -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensionsMap(m map[int32]Extension) error { - for k, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - m[k] = e - } - return nil -} - -func extensionsSize(e *XXX_InternalExtensions) (n int) { - m, mu := e.extensionsRead() - if m == nil { - return 0 - } - mu.Lock() - defer mu.Unlock() - return extensionsMapSize(m) -} - -func extensionsMapSize(m map[int32]Extension) (n int) { - for _, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - n += len(e.enc) - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - n += props.size(props, toStructPointer(x)) - } - return -} - -// HasExtension returns whether the given extension is present in pb. -func HasExtension(pb Message, extension *ExtensionDesc) bool { - if epb, doki := pb.(extensionsBytes); doki { - ext := epb.GetExtensions() - buf := *ext - o := 0 - for o < len(buf) { - tag, n := DecodeVarint(buf[o:]) - fieldNum := int32(tag >> 3) - if int32(fieldNum) == extension.Field { - return true - } - wireType := int(tag & 0x7) - o += n - l, err := size(buf[o:], wireType) - if err != nil { - return false - } - o += l - } - return false - } - // TODO: Check types, field numbers, etc.? - epb, ok := extendable(pb) - if !ok { - return false - } - extmap, mu := epb.extensionsRead() - if extmap == nil { - return false - } - mu.Lock() - _, ok = extmap[extension.Field] - mu.Unlock() - return ok -} - -func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int { - ext := pb.GetExtensions() - for offset < len(*ext) { - tag, n1 := DecodeVarint((*ext)[offset:]) - fieldNum := int32(tag >> 3) - wireType := int(tag & 0x7) - n2, err := size((*ext)[offset+n1:], wireType) - if err != nil { - panic(err) - } - newOffset := offset + n1 + n2 - if fieldNum == theFieldNum { - *ext = append((*ext)[:offset], (*ext)[newOffset:]...) - return offset - } - offset = newOffset - } - return -1 -} - -// ClearExtension removes the given extension from pb. -func ClearExtension(pb Message, extension *ExtensionDesc) { - clearExtension(pb, extension.Field) -} - -func clearExtension(pb Message, fieldNum int32) { - if epb, doki := pb.(extensionsBytes); doki { - offset := 0 - for offset != -1 { - offset = deleteExtension(epb, fieldNum, offset) - } - return - } - epb, ok := extendable(pb) - if !ok { - return - } - // TODO: Check types, field numbers, etc.? - extmap := epb.extensionsWrite() - delete(extmap, fieldNum) -} - -// GetExtension parses and returns the given extension of pb. -// If the extension is not present and has no default value it returns ErrMissingExtension. -func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { - if epb, doki := pb.(extensionsBytes); doki { - ext := epb.GetExtensions() - o := 0 - for o < len(*ext) { - tag, n := DecodeVarint((*ext)[o:]) - fieldNum := int32(tag >> 3) - wireType := int(tag & 0x7) - l, err := size((*ext)[o+n:], wireType) - if err != nil { - return nil, err - } - if int32(fieldNum) == extension.Field { - v, err := decodeExtension((*ext)[o:o+n+l], extension) - if err != nil { - return nil, err - } - return v, nil - } - o += n + l - } - return defaultExtensionValue(extension) - } - epb, ok := extendable(pb) - if !ok { - return nil, errors.New("proto: not an extendable proto") - } - if err := checkExtensionTypes(epb, extension); err != nil { - return nil, err - } - - emap, mu := epb.extensionsRead() - if emap == nil { - return defaultExtensionValue(extension) - } - mu.Lock() - defer mu.Unlock() - e, ok := emap[extension.Field] - if !ok { - // defaultExtensionValue returns the default value or - // ErrMissingExtension if there is no default. - return defaultExtensionValue(extension) - } - - if e.value != nil { - // Already decoded. Check the descriptor, though. - if e.desc != extension { - // This shouldn't happen. If it does, it means that - // GetExtension was called twice with two different - // descriptors with the same field number. - return nil, errors.New("proto: descriptor conflict") - } - return e.value, nil - } - - v, err := decodeExtension(e.enc, extension) - if err != nil { - return nil, err - } - - // Remember the decoded version and drop the encoded version. - // That way it is safe to mutate what we return. - e.value = v - e.desc = extension - e.enc = nil - emap[extension.Field] = e - return e.value, nil -} - -// defaultExtensionValue returns the default value for extension. -// If no default for an extension is defined ErrMissingExtension is returned. -func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { - t := reflect.TypeOf(extension.ExtensionType) - props := extensionProperties(extension) - - sf, _, err := fieldDefault(t, props) - if err != nil { - return nil, err - } - - if sf == nil || sf.value == nil { - // There is no default value. - return nil, ErrMissingExtension - } - - if t.Kind() != reflect.Ptr { - // We do not need to return a Ptr, we can directly return sf.value. - return sf.value, nil - } - - // We need to return an interface{} that is a pointer to sf.value. - value := reflect.New(t).Elem() - value.Set(reflect.New(value.Type().Elem())) - if sf.kind == reflect.Int32 { - // We may have an int32 or an enum, but the underlying data is int32. - // Since we can't set an int32 into a non int32 reflect.value directly - // set it as a int32. - value.Elem().SetInt(int64(sf.value.(int32))) - } else { - value.Elem().Set(reflect.ValueOf(sf.value)) - } - return value.Interface(), nil -} - -// decodeExtension decodes an extension encoded in b. -func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { - o := NewBuffer(b) - - t := reflect.TypeOf(extension.ExtensionType) - - props := extensionProperties(extension) - - // t is a pointer to a struct, pointer to basic type or a slice. - // Allocate a "field" to store the pointer/slice itself; the - // pointer/slice will be stored here. We pass - // the address of this field to props.dec. - // This passes a zero field and a *t and lets props.dec - // interpret it as a *struct{ x t }. - value := reflect.New(t).Elem() - - for { - // Discard wire type and field number varint. It isn't needed. - if _, err := o.DecodeVarint(); err != nil { - return nil, err - } - - if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { - return nil, err - } - - if o.index >= len(o.buf) { - break - } - } - return value.Interface(), nil -} - -// GetExtensions returns a slice of the extensions present in pb that are also listed in es. -// The returned slice has the same length as es; missing extensions will appear as nil elements. -func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { - extensions = make([]interface{}, len(es)) - for i, e := range es { - extensions[i], err = GetExtension(pb, e) - if err == ErrMissingExtension { - err = nil - } - if err != nil { - return - } - } - return -} - -// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. -// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing -// just the Field field, which defines the extension's field number. -func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { - epb, ok := extendable(pb) - if !ok { - return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) - } - registeredExtensions := RegisteredExtensions(pb) - - emap, mu := epb.extensionsRead() - if emap == nil { - return nil, nil - } - mu.Lock() - defer mu.Unlock() - extensions := make([]*ExtensionDesc, 0, len(emap)) - for extid, e := range emap { - desc := e.desc - if desc == nil { - desc = registeredExtensions[extid] - if desc == nil { - desc = &ExtensionDesc{Field: extid} - } - } - - extensions = append(extensions, desc) - } - return extensions, nil -} - -// SetExtension sets the specified extension of pb to the specified value. -func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { - if epb, doki := pb.(extensionsBytes); doki { - ClearExtension(pb, extension) - ext := epb.GetExtensions() - et := reflect.TypeOf(extension.ExtensionType) - props := extensionProperties(extension) - p := NewBuffer(nil) - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - *ext = append(*ext, p.buf...) - return nil - } - epb, ok := extendable(pb) - if !ok { - return errors.New("proto: not an extendable proto") - } - if err := checkExtensionTypes(epb, extension); err != nil { - return err - } - typ := reflect.TypeOf(extension.ExtensionType) - if typ != reflect.TypeOf(value) { - return errors.New("proto: bad extension value type") - } - // nil extension values need to be caught early, because the - // encoder can't distinguish an ErrNil due to a nil extension - // from an ErrNil due to a missing field. Extensions are - // always optional, so the encoder would just swallow the error - // and drop all the extensions from the encoded message. - if reflect.ValueOf(value).IsNil() { - return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) - } - - extmap := epb.extensionsWrite() - extmap[extension.Field] = Extension{desc: extension, value: value} - return nil -} - -// ClearAllExtensions clears all extensions from pb. -func ClearAllExtensions(pb Message) { - if epb, doki := pb.(extensionsBytes); doki { - ext := epb.GetExtensions() - *ext = []byte{} - return - } - epb, ok := extendable(pb) - if !ok { - return - } - m := epb.extensionsWrite() - for k := range m { - delete(m, k) - } -} - -// A global registry of extensions. -// The generated code will register the generated descriptors by calling RegisterExtension. - -var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) - -// RegisterExtension is called from the generated code. -func RegisterExtension(desc *ExtensionDesc) { - st := reflect.TypeOf(desc.ExtendedType).Elem() - m := extensionMaps[st] - if m == nil { - m = make(map[int32]*ExtensionDesc) - extensionMaps[st] = m - } - if _, ok := m[desc.Field]; ok { - panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) - } - m[desc.Field] = desc -} - -// RegisteredExtensions returns a map of the registered extensions of a -// protocol buffer struct, indexed by the extension number. -// The argument pb should be a nil pointer to the struct type. -func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { - return extensionMaps[reflect.TypeOf(pb).Elem()] -} diff --git a/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go b/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go deleted file mode 100644 index ea6478f009..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go +++ /dev/null @@ -1,294 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "sort" - "strings" - "sync" -) - -func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool { - if reflect.ValueOf(pb).IsNil() { - return ifnotset - } - value, err := GetExtension(pb, extension) - if err != nil { - return ifnotset - } - if value == nil { - return ifnotset - } - if value.(*bool) == nil { - return ifnotset - } - return *(value.(*bool)) -} - -func (this *Extension) Equal(that *Extension) bool { - return bytes.Equal(this.enc, that.enc) -} - -func (this *Extension) Compare(that *Extension) int { - return bytes.Compare(this.enc, that.enc) -} - -func SizeOfInternalExtension(m extendableProto) (n int) { - return SizeOfExtensionMap(m.extensionsWrite()) -} - -func SizeOfExtensionMap(m map[int32]Extension) (n int) { - return extensionsMapSize(m) -} - -type sortableMapElem struct { - field int32 - ext Extension -} - -func newSortableExtensionsFromMap(m map[int32]Extension) sortableExtensions { - s := make(sortableExtensions, 0, len(m)) - for k, v := range m { - s = append(s, &sortableMapElem{field: k, ext: v}) - } - return s -} - -type sortableExtensions []*sortableMapElem - -func (this sortableExtensions) Len() int { return len(this) } - -func (this sortableExtensions) Swap(i, j int) { this[i], this[j] = this[j], this[i] } - -func (this sortableExtensions) Less(i, j int) bool { return this[i].field < this[j].field } - -func (this sortableExtensions) String() string { - sort.Sort(this) - ss := make([]string, len(this)) - for i := range this { - ss[i] = fmt.Sprintf("%d: %v", this[i].field, this[i].ext) - } - return "map[" + strings.Join(ss, ",") + "]" -} - -func StringFromInternalExtension(m extendableProto) string { - return StringFromExtensionsMap(m.extensionsWrite()) -} - -func StringFromExtensionsMap(m map[int32]Extension) string { - return newSortableExtensionsFromMap(m).String() -} - -func StringFromExtensionsBytes(ext []byte) string { - m, err := BytesToExtensionsMap(ext) - if err != nil { - panic(err) - } - return StringFromExtensionsMap(m) -} - -func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) { - return EncodeExtensionMap(m.extensionsWrite(), data) -} - -func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) { - if err := encodeExtensionsMap(m); err != nil { - return 0, err - } - keys := make([]int, 0, len(m)) - for k := range m { - keys = append(keys, int(k)) - } - sort.Ints(keys) - for _, k := range keys { - n += copy(data[n:], m[int32(k)].enc) - } - return n, nil -} - -func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) { - if m[id].value == nil || m[id].desc == nil { - return m[id].enc, nil - } - if err := encodeExtensionsMap(m); err != nil { - return nil, err - } - return m[id].enc, nil -} - -func size(buf []byte, wire int) (int, error) { - switch wire { - case WireVarint: - _, n := DecodeVarint(buf) - return n, nil - case WireFixed64: - return 8, nil - case WireBytes: - v, n := DecodeVarint(buf) - return int(v) + n, nil - case WireFixed32: - return 4, nil - case WireStartGroup: - offset := 0 - for { - u, n := DecodeVarint(buf[offset:]) - fwire := int(u & 0x7) - offset += n - if fwire == WireEndGroup { - return offset, nil - } - s, err := size(buf[offset:], wire) - if err != nil { - return 0, err - } - offset += s - } - } - return 0, fmt.Errorf("proto: can't get size for unknown wire type %d", wire) -} - -func BytesToExtensionsMap(buf []byte) (map[int32]Extension, error) { - m := make(map[int32]Extension) - i := 0 - for i < len(buf) { - tag, n := DecodeVarint(buf[i:]) - if n <= 0 { - return nil, fmt.Errorf("unable to decode varint") - } - fieldNum := int32(tag >> 3) - wireType := int(tag & 0x7) - l, err := size(buf[i+n:], wireType) - if err != nil { - return nil, err - } - end := i + int(l) + n - m[int32(fieldNum)] = Extension{enc: buf[i:end]} - i = end - } - return m, nil -} - -func NewExtension(e []byte) Extension { - ee := Extension{enc: make([]byte, len(e))} - copy(ee.enc, e) - return ee -} - -func AppendExtension(e Message, tag int32, buf []byte) { - if ee, eok := e.(extensionsBytes); eok { - ext := ee.GetExtensions() - *ext = append(*ext, buf...) - return - } - if ee, eok := e.(extendableProto); eok { - m := ee.extensionsWrite() - ext := m[int32(tag)] // may be missing - ext.enc = append(ext.enc, buf...) - m[int32(tag)] = ext - } -} - -func encodeExtension(e *Extension) error { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - return nil - } - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - return nil -} - -func (this Extension) GoString() string { - if this.enc == nil { - if err := encodeExtension(&this); err != nil { - panic(err) - } - } - return fmt.Sprintf("proto.NewExtension(%#v)", this.enc) -} - -func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error { - typ := reflect.TypeOf(pb).Elem() - ext, ok := extensionMaps[typ] - if !ok { - return fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String()) - } - desc, ok := ext[fieldNum] - if !ok { - return errors.New("proto: bad extension number; not in declared ranges") - } - return SetExtension(pb, desc, value) -} - -func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) { - typ := reflect.TypeOf(pb).Elem() - ext, ok := extensionMaps[typ] - if !ok { - return nil, fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String()) - } - desc, ok := ext[fieldNum] - if !ok { - return nil, fmt.Errorf("unregistered field number %d", fieldNum) - } - return GetExtension(pb, desc) -} - -func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions { - x := &XXX_InternalExtensions{ - p: new(struct { - mu sync.Mutex - extensionMap map[int32]Extension - }), - } - x.p.extensionMap = m - return *x -} - -func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension { - pb := extendable.(extendableProto) - return pb.extensionsWrite() -} diff --git a/vendor/github.com/gogo/protobuf/proto/lib.go b/vendor/github.com/gogo/protobuf/proto/lib.go deleted file mode 100644 index c98d73da49..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/lib.go +++ /dev/null @@ -1,897 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* -Package proto converts data structures to and from the wire format of -protocol buffers. It works in concert with the Go source code generated -for .proto files by the protocol compiler. - -A summary of the properties of the protocol buffer interface -for a protocol buffer variable v: - - - Names are turned from camel_case to CamelCase for export. - - There are no methods on v to set fields; just treat - them as structure fields. - - There are getters that return a field's value if set, - and return the field's default value if unset. - The getters work even if the receiver is a nil message. - - The zero value for a struct is its correct initialization state. - All desired fields must be set before marshaling. - - A Reset() method will restore a protobuf struct to its zero state. - - Non-repeated fields are pointers to the values; nil means unset. - That is, optional or required field int32 f becomes F *int32. - - Repeated fields are slices. - - Helper functions are available to aid the setting of fields. - msg.Foo = proto.String("hello") // set field - - Constants are defined to hold the default values of all fields that - have them. They have the form Default_StructName_FieldName. - Because the getter methods handle defaulted values, - direct use of these constants should be rare. - - Enums are given type names and maps from names to values. - Enum values are prefixed by the enclosing message's name, or by the - enum's type name if it is a top-level enum. Enum types have a String - method, and a Enum method to assist in message construction. - - Nested messages, groups and enums have type names prefixed with the name of - the surrounding message type. - - Extensions are given descriptor names that start with E_, - followed by an underscore-delimited list of the nested messages - that contain it (if any) followed by the CamelCased name of the - extension field itself. HasExtension, ClearExtension, GetExtension - and SetExtension are functions for manipulating extensions. - - Oneof field sets are given a single field in their message, - with distinguished wrapper types for each possible field value. - - Marshal and Unmarshal are functions to encode and decode the wire format. - -When the .proto file specifies `syntax="proto3"`, there are some differences: - - - Non-repeated fields of non-message type are values instead of pointers. - - Enum types do not get an Enum method. - -The simplest way to describe this is to see an example. -Given file test.proto, containing - - package example; - - enum FOO { X = 17; } - - message Test { - required string label = 1; - optional int32 type = 2 [default=77]; - repeated int64 reps = 3; - optional group OptionalGroup = 4 { - required string RequiredField = 5; - } - oneof union { - int32 number = 6; - string name = 7; - } - } - -The resulting file, test.pb.go, is: - - package example - - import proto "github.com/gogo/protobuf/proto" - import math "math" - - type FOO int32 - const ( - FOO_X FOO = 17 - ) - var FOO_name = map[int32]string{ - 17: "X", - } - var FOO_value = map[string]int32{ - "X": 17, - } - - func (x FOO) Enum() *FOO { - p := new(FOO) - *p = x - return p - } - func (x FOO) String() string { - return proto.EnumName(FOO_name, int32(x)) - } - func (x *FOO) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(FOO_value, data) - if err != nil { - return err - } - *x = FOO(value) - return nil - } - - type Test struct { - Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` - Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` - Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` - Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` - // Types that are valid to be assigned to Union: - // *Test_Number - // *Test_Name - Union isTest_Union `protobuf_oneof:"union"` - XXX_unrecognized []byte `json:"-"` - } - func (m *Test) Reset() { *m = Test{} } - func (m *Test) String() string { return proto.CompactTextString(m) } - func (*Test) ProtoMessage() {} - - type isTest_Union interface { - isTest_Union() - } - - type Test_Number struct { - Number int32 `protobuf:"varint,6,opt,name=number"` - } - type Test_Name struct { - Name string `protobuf:"bytes,7,opt,name=name"` - } - - func (*Test_Number) isTest_Union() {} - func (*Test_Name) isTest_Union() {} - - func (m *Test) GetUnion() isTest_Union { - if m != nil { - return m.Union - } - return nil - } - const Default_Test_Type int32 = 77 - - func (m *Test) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" - } - - func (m *Test) GetType() int32 { - if m != nil && m.Type != nil { - return *m.Type - } - return Default_Test_Type - } - - func (m *Test) GetOptionalgroup() *Test_OptionalGroup { - if m != nil { - return m.Optionalgroup - } - return nil - } - - type Test_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` - } - func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } - func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } - - func (m *Test_OptionalGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" - } - - func (m *Test) GetNumber() int32 { - if x, ok := m.GetUnion().(*Test_Number); ok { - return x.Number - } - return 0 - } - - func (m *Test) GetName() string { - if x, ok := m.GetUnion().(*Test_Name); ok { - return x.Name - } - return "" - } - - func init() { - proto.RegisterEnum("example.FOO", FOO_name, FOO_value) - } - -To create and play with a Test object: - - package main - - import ( - "log" - - "github.com/gogo/protobuf/proto" - pb "./example.pb" - ) - - func main() { - test := &pb.Test{ - Label: proto.String("hello"), - Type: proto.Int32(17), - Reps: []int64{1, 2, 3}, - Optionalgroup: &pb.Test_OptionalGroup{ - RequiredField: proto.String("good bye"), - }, - Union: &pb.Test_Name{"fred"}, - } - data, err := proto.Marshal(test) - if err != nil { - log.Fatal("marshaling error: ", err) - } - newTest := &pb.Test{} - err = proto.Unmarshal(data, newTest) - if err != nil { - log.Fatal("unmarshaling error: ", err) - } - // Now test and newTest contain the same data. - if test.GetLabel() != newTest.GetLabel() { - log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) - } - // Use a type switch to determine which oneof was set. - switch u := test.Union.(type) { - case *pb.Test_Number: // u.Number contains the number. - case *pb.Test_Name: // u.Name contains the string. - } - // etc. - } -*/ -package proto - -import ( - "encoding/json" - "fmt" - "log" - "reflect" - "sort" - "strconv" - "sync" -) - -// Message is implemented by generated protocol buffer messages. -type Message interface { - Reset() - String() string - ProtoMessage() -} - -// Stats records allocation details about the protocol buffer encoders -// and decoders. Useful for tuning the library itself. -type Stats struct { - Emalloc uint64 // mallocs in encode - Dmalloc uint64 // mallocs in decode - Encode uint64 // number of encodes - Decode uint64 // number of decodes - Chit uint64 // number of cache hits - Cmiss uint64 // number of cache misses - Size uint64 // number of sizes -} - -// Set to true to enable stats collection. -const collectStats = false - -var stats Stats - -// GetStats returns a copy of the global Stats structure. -func GetStats() Stats { return stats } - -// A Buffer is a buffer manager for marshaling and unmarshaling -// protocol buffers. It may be reused between invocations to -// reduce memory usage. It is not necessary to use a Buffer; -// the global functions Marshal and Unmarshal create a -// temporary Buffer and are fine for most applications. -type Buffer struct { - buf []byte // encode/decode byte stream - index int // read point - - // pools of basic types to amortize allocation. - bools []bool - uint32s []uint32 - uint64s []uint64 - - // extra pools, only used with pointer_reflect.go - int32s []int32 - int64s []int64 - float32s []float32 - float64s []float64 -} - -// NewBuffer allocates a new Buffer and initializes its internal data to -// the contents of the argument slice. -func NewBuffer(e []byte) *Buffer { - return &Buffer{buf: e} -} - -// Reset resets the Buffer, ready for marshaling a new protocol buffer. -func (p *Buffer) Reset() { - p.buf = p.buf[0:0] // for reading/writing - p.index = 0 // for reading -} - -// SetBuf replaces the internal buffer with the slice, -// ready for unmarshaling the contents of the slice. -func (p *Buffer) SetBuf(s []byte) { - p.buf = s - p.index = 0 -} - -// Bytes returns the contents of the Buffer. -func (p *Buffer) Bytes() []byte { return p.buf } - -/* - * Helper routines for simplifying the creation of optional fields of basic type. - */ - -// Bool is a helper routine that allocates a new bool value -// to store v and returns a pointer to it. -func Bool(v bool) *bool { - return &v -} - -// Int32 is a helper routine that allocates a new int32 value -// to store v and returns a pointer to it. -func Int32(v int32) *int32 { - return &v -} - -// Int is a helper routine that allocates a new int32 value -// to store v and returns a pointer to it, but unlike Int32 -// its argument value is an int. -func Int(v int) *int32 { - p := new(int32) - *p = int32(v) - return p -} - -// Int64 is a helper routine that allocates a new int64 value -// to store v and returns a pointer to it. -func Int64(v int64) *int64 { - return &v -} - -// Float32 is a helper routine that allocates a new float32 value -// to store v and returns a pointer to it. -func Float32(v float32) *float32 { - return &v -} - -// Float64 is a helper routine that allocates a new float64 value -// to store v and returns a pointer to it. -func Float64(v float64) *float64 { - return &v -} - -// Uint32 is a helper routine that allocates a new uint32 value -// to store v and returns a pointer to it. -func Uint32(v uint32) *uint32 { - return &v -} - -// Uint64 is a helper routine that allocates a new uint64 value -// to store v and returns a pointer to it. -func Uint64(v uint64) *uint64 { - return &v -} - -// String is a helper routine that allocates a new string value -// to store v and returns a pointer to it. -func String(v string) *string { - return &v -} - -// EnumName is a helper function to simplify printing protocol buffer enums -// by name. Given an enum map and a value, it returns a useful string. -func EnumName(m map[int32]string, v int32) string { - s, ok := m[v] - if ok { - return s - } - return strconv.Itoa(int(v)) -} - -// UnmarshalJSONEnum is a helper function to simplify recovering enum int values -// from their JSON-encoded representation. Given a map from the enum's symbolic -// names to its int values, and a byte buffer containing the JSON-encoded -// value, it returns an int32 that can be cast to the enum type by the caller. -// -// The function can deal with both JSON representations, numeric and symbolic. -func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { - if data[0] == '"' { - // New style: enums are strings. - var repr string - if err := json.Unmarshal(data, &repr); err != nil { - return -1, err - } - val, ok := m[repr] - if !ok { - return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) - } - return val, nil - } - // Old style: enums are ints. - var val int32 - if err := json.Unmarshal(data, &val); err != nil { - return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) - } - return val, nil -} - -// DebugPrint dumps the encoded data in b in a debugging format with a header -// including the string s. Used in testing but made available for general debugging. -func (p *Buffer) DebugPrint(s string, b []byte) { - var u uint64 - - obuf := p.buf - sindex := p.index - p.buf = b - p.index = 0 - depth := 0 - - fmt.Printf("\n--- %s ---\n", s) - -out: - for { - for i := 0; i < depth; i++ { - fmt.Print(" ") - } - - index := p.index - if index == len(p.buf) { - break - } - - op, err := p.DecodeVarint() - if err != nil { - fmt.Printf("%3d: fetching op err %v\n", index, err) - break out - } - tag := op >> 3 - wire := op & 7 - - switch wire { - default: - fmt.Printf("%3d: t=%3d unknown wire=%d\n", - index, tag, wire) - break out - - case WireBytes: - var r []byte - - r, err = p.DecodeRawBytes(false) - if err != nil { - break out - } - fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) - if len(r) <= 6 { - for i := 0; i < len(r); i++ { - fmt.Printf(" %.2x", r[i]) - } - } else { - for i := 0; i < 3; i++ { - fmt.Printf(" %.2x", r[i]) - } - fmt.Printf(" ..") - for i := len(r) - 3; i < len(r); i++ { - fmt.Printf(" %.2x", r[i]) - } - } - fmt.Printf("\n") - - case WireFixed32: - u, err = p.DecodeFixed32() - if err != nil { - fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) - break out - } - fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) - - case WireFixed64: - u, err = p.DecodeFixed64() - if err != nil { - fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) - break out - } - fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) - - case WireVarint: - u, err = p.DecodeVarint() - if err != nil { - fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) - break out - } - fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) - - case WireStartGroup: - fmt.Printf("%3d: t=%3d start\n", index, tag) - depth++ - - case WireEndGroup: - depth-- - fmt.Printf("%3d: t=%3d end\n", index, tag) - } - } - - if depth != 0 { - fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) - } - fmt.Printf("\n") - - p.buf = obuf - p.index = sindex -} - -// SetDefaults sets unset protocol buffer fields to their default values. -// It only modifies fields that are both unset and have defined defaults. -// It recursively sets default values in any non-nil sub-messages. -func SetDefaults(pb Message) { - setDefaults(reflect.ValueOf(pb), true, false) -} - -// v is a pointer to a struct. -func setDefaults(v reflect.Value, recur, zeros bool) { - v = v.Elem() - - defaultMu.RLock() - dm, ok := defaults[v.Type()] - defaultMu.RUnlock() - if !ok { - dm = buildDefaultMessage(v.Type()) - defaultMu.Lock() - defaults[v.Type()] = dm - defaultMu.Unlock() - } - - for _, sf := range dm.scalars { - f := v.Field(sf.index) - if !f.IsNil() { - // field already set - continue - } - dv := sf.value - if dv == nil && !zeros { - // no explicit default, and don't want to set zeros - continue - } - fptr := f.Addr().Interface() // **T - // TODO: Consider batching the allocations we do here. - switch sf.kind { - case reflect.Bool: - b := new(bool) - if dv != nil { - *b = dv.(bool) - } - *(fptr.(**bool)) = b - case reflect.Float32: - f := new(float32) - if dv != nil { - *f = dv.(float32) - } - *(fptr.(**float32)) = f - case reflect.Float64: - f := new(float64) - if dv != nil { - *f = dv.(float64) - } - *(fptr.(**float64)) = f - case reflect.Int32: - // might be an enum - if ft := f.Type(); ft != int32PtrType { - // enum - f.Set(reflect.New(ft.Elem())) - if dv != nil { - f.Elem().SetInt(int64(dv.(int32))) - } - } else { - // int32 field - i := new(int32) - if dv != nil { - *i = dv.(int32) - } - *(fptr.(**int32)) = i - } - case reflect.Int64: - i := new(int64) - if dv != nil { - *i = dv.(int64) - } - *(fptr.(**int64)) = i - case reflect.String: - s := new(string) - if dv != nil { - *s = dv.(string) - } - *(fptr.(**string)) = s - case reflect.Uint8: - // exceptional case: []byte - var b []byte - if dv != nil { - db := dv.([]byte) - b = make([]byte, len(db)) - copy(b, db) - } else { - b = []byte{} - } - *(fptr.(*[]byte)) = b - case reflect.Uint32: - u := new(uint32) - if dv != nil { - *u = dv.(uint32) - } - *(fptr.(**uint32)) = u - case reflect.Uint64: - u := new(uint64) - if dv != nil { - *u = dv.(uint64) - } - *(fptr.(**uint64)) = u - default: - log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) - } - } - - for _, ni := range dm.nested { - f := v.Field(ni) - // f is *T or []*T or map[T]*T - switch f.Kind() { - case reflect.Ptr: - if f.IsNil() { - continue - } - setDefaults(f, recur, zeros) - - case reflect.Slice: - for i := 0; i < f.Len(); i++ { - e := f.Index(i) - if e.IsNil() { - continue - } - setDefaults(e, recur, zeros) - } - - case reflect.Map: - for _, k := range f.MapKeys() { - e := f.MapIndex(k) - if e.IsNil() { - continue - } - setDefaults(e, recur, zeros) - } - } - } -} - -var ( - // defaults maps a protocol buffer struct type to a slice of the fields, - // with its scalar fields set to their proto-declared non-zero default values. - defaultMu sync.RWMutex - defaults = make(map[reflect.Type]defaultMessage) - - int32PtrType = reflect.TypeOf((*int32)(nil)) -) - -// defaultMessage represents information about the default values of a message. -type defaultMessage struct { - scalars []scalarField - nested []int // struct field index of nested messages -} - -type scalarField struct { - index int // struct field index - kind reflect.Kind // element type (the T in *T or []T) - value interface{} // the proto-declared default value, or nil -} - -// t is a struct type. -func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { - sprop := GetProperties(t) - for _, prop := range sprop.Prop { - fi, ok := sprop.decoderTags.get(prop.Tag) - if !ok { - // XXX_unrecognized - continue - } - ft := t.Field(fi).Type - - sf, nested, err := fieldDefault(ft, prop) - switch { - case err != nil: - log.Print(err) - case nested: - dm.nested = append(dm.nested, fi) - case sf != nil: - sf.index = fi - dm.scalars = append(dm.scalars, *sf) - } - } - - return dm -} - -// fieldDefault returns the scalarField for field type ft. -// sf will be nil if the field can not have a default. -// nestedMessage will be true if this is a nested message. -// Note that sf.index is not set on return. -func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { - var canHaveDefault bool - switch ft.Kind() { - case reflect.Ptr: - if ft.Elem().Kind() == reflect.Struct { - nestedMessage = true - } else { - canHaveDefault = true // proto2 scalar field - } - - case reflect.Slice: - switch ft.Elem().Kind() { - case reflect.Ptr: - nestedMessage = true // repeated message - case reflect.Uint8: - canHaveDefault = true // bytes field - } - - case reflect.Map: - if ft.Elem().Kind() == reflect.Ptr { - nestedMessage = true // map with message values - } - } - - if !canHaveDefault { - if nestedMessage { - return nil, true, nil - } - return nil, false, nil - } - - // We now know that ft is a pointer or slice. - sf = &scalarField{kind: ft.Elem().Kind()} - - // scalar fields without defaults - if !prop.HasDefault { - return sf, false, nil - } - - // a scalar field: either *T or []byte - switch ft.Elem().Kind() { - case reflect.Bool: - x, err := strconv.ParseBool(prop.Default) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) - } - sf.value = x - case reflect.Float32: - x, err := strconv.ParseFloat(prop.Default, 32) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) - } - sf.value = float32(x) - case reflect.Float64: - x, err := strconv.ParseFloat(prop.Default, 64) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) - } - sf.value = x - case reflect.Int32: - x, err := strconv.ParseInt(prop.Default, 10, 32) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) - } - sf.value = int32(x) - case reflect.Int64: - x, err := strconv.ParseInt(prop.Default, 10, 64) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) - } - sf.value = x - case reflect.String: - sf.value = prop.Default - case reflect.Uint8: - // []byte (not *uint8) - sf.value = []byte(prop.Default) - case reflect.Uint32: - x, err := strconv.ParseUint(prop.Default, 10, 32) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) - } - sf.value = uint32(x) - case reflect.Uint64: - x, err := strconv.ParseUint(prop.Default, 10, 64) - if err != nil { - return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) - } - sf.value = x - default: - return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) - } - - return sf, false, nil -} - -// Map fields may have key types of non-float scalars, strings and enums. -// The easiest way to sort them in some deterministic order is to use fmt. -// If this turns out to be inefficient we can always consider other options, -// such as doing a Schwartzian transform. - -func mapKeys(vs []reflect.Value) sort.Interface { - s := mapKeySorter{ - vs: vs, - // default Less function: textual comparison - less: func(a, b reflect.Value) bool { - return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) - }, - } - - // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; - // numeric keys are sorted numerically. - if len(vs) == 0 { - return s - } - switch vs[0].Kind() { - case reflect.Int32, reflect.Int64: - s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } - case reflect.Uint32, reflect.Uint64: - s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } - } - - return s -} - -type mapKeySorter struct { - vs []reflect.Value - less func(a, b reflect.Value) bool -} - -func (s mapKeySorter) Len() int { return len(s.vs) } -func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } -func (s mapKeySorter) Less(i, j int) bool { - return s.less(s.vs[i], s.vs[j]) -} - -// isProto3Zero reports whether v is a zero proto3 value. -func isProto3Zero(v reflect.Value) bool { - switch v.Kind() { - case reflect.Bool: - return !v.Bool() - case reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint32, reflect.Uint64: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.String: - return v.String() == "" - } - return false -} - -// ProtoPackageIsVersion2 is referenced from generated protocol buffer files -// to assert that that code is compatible with this version of the proto package. -const GoGoProtoPackageIsVersion2 = true - -// ProtoPackageIsVersion1 is referenced from generated protocol buffer files -// to assert that that code is compatible with this version of the proto package. -const GoGoProtoPackageIsVersion1 = true diff --git a/vendor/github.com/gogo/protobuf/proto/lib_gogo.go b/vendor/github.com/gogo/protobuf/proto/lib_gogo.go deleted file mode 100644 index 4b4f7c909e..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/lib_gogo.go +++ /dev/null @@ -1,42 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "encoding/json" - "strconv" -) - -func MarshalJSONEnum(m map[int32]string, value int32) ([]byte, error) { - s, ok := m[value] - if !ok { - s = strconv.Itoa(int(value)) - } - return json.Marshal(s) -} diff --git a/vendor/github.com/gogo/protobuf/proto/message_set.go b/vendor/github.com/gogo/protobuf/proto/message_set.go deleted file mode 100644 index fd982decd6..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/message_set.go +++ /dev/null @@ -1,311 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -/* - * Support for message sets. - */ - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "reflect" - "sort" -) - -// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. -// A message type ID is required for storing a protocol buffer in a message set. -var errNoMessageTypeID = errors.New("proto does not have a message type ID") - -// The first two types (_MessageSet_Item and messageSet) -// model what the protocol compiler produces for the following protocol message: -// message MessageSet { -// repeated group Item = 1 { -// required int32 type_id = 2; -// required string message = 3; -// }; -// } -// That is the MessageSet wire format. We can't use a proto to generate these -// because that would introduce a circular dependency between it and this package. - -type _MessageSet_Item struct { - TypeId *int32 `protobuf:"varint,2,req,name=type_id"` - Message []byte `protobuf:"bytes,3,req,name=message"` -} - -type messageSet struct { - Item []*_MessageSet_Item `protobuf:"group,1,rep"` - XXX_unrecognized []byte - // TODO: caching? -} - -// Make sure messageSet is a Message. -var _ Message = (*messageSet)(nil) - -// messageTypeIder is an interface satisfied by a protocol buffer type -// that may be stored in a MessageSet. -type messageTypeIder interface { - MessageTypeId() int32 -} - -func (ms *messageSet) find(pb Message) *_MessageSet_Item { - mti, ok := pb.(messageTypeIder) - if !ok { - return nil - } - id := mti.MessageTypeId() - for _, item := range ms.Item { - if *item.TypeId == id { - return item - } - } - return nil -} - -func (ms *messageSet) Has(pb Message) bool { - if ms.find(pb) != nil { - return true - } - return false -} - -func (ms *messageSet) Unmarshal(pb Message) error { - if item := ms.find(pb); item != nil { - return Unmarshal(item.Message, pb) - } - if _, ok := pb.(messageTypeIder); !ok { - return errNoMessageTypeID - } - return nil // TODO: return error instead? -} - -func (ms *messageSet) Marshal(pb Message) error { - msg, err := Marshal(pb) - if err != nil { - return err - } - if item := ms.find(pb); item != nil { - // reuse existing item - item.Message = msg - return nil - } - - mti, ok := pb.(messageTypeIder) - if !ok { - return errNoMessageTypeID - } - - mtid := mti.MessageTypeId() - ms.Item = append(ms.Item, &_MessageSet_Item{ - TypeId: &mtid, - Message: msg, - }) - return nil -} - -func (ms *messageSet) Reset() { *ms = messageSet{} } -func (ms *messageSet) String() string { return CompactTextString(ms) } -func (*messageSet) ProtoMessage() {} - -// Support for the message_set_wire_format message option. - -func skipVarint(buf []byte) []byte { - i := 0 - for ; buf[i]&0x80 != 0; i++ { - } - return buf[i+1:] -} - -// MarshalMessageSet encodes the extension map represented by m in the message set wire format. -// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSet(exts interface{}) ([]byte, error) { - var m map[int32]Extension - switch exts := exts.(type) { - case *XXX_InternalExtensions: - if err := encodeExtensions(exts); err != nil { - return nil, err - } - m, _ = exts.extensionsRead() - case map[int32]Extension: - if err := encodeExtensionsMap(exts); err != nil { - return nil, err - } - m = exts - default: - return nil, errors.New("proto: not an extension map") - } - - // Sort extension IDs to provide a deterministic encoding. - // See also enc_map in encode.go. - ids := make([]int, 0, len(m)) - for id := range m { - ids = append(ids, int(id)) - } - sort.Ints(ids) - - ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} - for _, id := range ids { - e := m[int32(id)] - // Remove the wire type and field number varint, as well as the length varint. - msg := skipVarint(skipVarint(e.enc)) - - ms.Item = append(ms.Item, &_MessageSet_Item{ - TypeId: Int32(int32(id)), - Message: msg, - }) - } - return Marshal(ms) -} - -// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. -// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSet(buf []byte, exts interface{}) error { - var m map[int32]Extension - switch exts := exts.(type) { - case *XXX_InternalExtensions: - m = exts.extensionsWrite() - case map[int32]Extension: - m = exts - default: - return errors.New("proto: not an extension map") - } - - ms := new(messageSet) - if err := Unmarshal(buf, ms); err != nil { - return err - } - for _, item := range ms.Item { - id := *item.TypeId - msg := item.Message - - // Restore wire type and field number varint, plus length varint. - // Be careful to preserve duplicate items. - b := EncodeVarint(uint64(id)<<3 | WireBytes) - if ext, ok := m[id]; ok { - // Existing data; rip off the tag and length varint - // so we join the new data correctly. - // We can assume that ext.enc is set because we are unmarshaling. - o := ext.enc[len(b):] // skip wire type and field number - _, n := DecodeVarint(o) // calculate length of length varint - o = o[n:] // skip length varint - msg = append(o, msg...) // join old data and new data - } - b = append(b, EncodeVarint(uint64(len(msg)))...) - b = append(b, msg...) - - m[id] = Extension{enc: b} - } - return nil -} - -// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. -// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { - var m map[int32]Extension - switch exts := exts.(type) { - case *XXX_InternalExtensions: - m, _ = exts.extensionsRead() - case map[int32]Extension: - m = exts - default: - return nil, errors.New("proto: not an extension map") - } - var b bytes.Buffer - b.WriteByte('{') - - // Process the map in key order for deterministic output. - ids := make([]int32, 0, len(m)) - for id := range m { - ids = append(ids, id) - } - sort.Sort(int32Slice(ids)) // int32Slice defined in text.go - - for i, id := range ids { - ext := m[id] - if i > 0 { - b.WriteByte(',') - } - - msd, ok := messageSetMap[id] - if !ok { - // Unknown type; we can't render it, so skip it. - continue - } - fmt.Fprintf(&b, `"[%s]":`, msd.name) - - x := ext.value - if x == nil { - x = reflect.New(msd.t.Elem()).Interface() - if err := Unmarshal(ext.enc, x.(Message)); err != nil { - return nil, err - } - } - d, err := json.Marshal(x) - if err != nil { - return nil, err - } - b.Write(d) - } - b.WriteByte('}') - return b.Bytes(), nil -} - -// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. -// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { - // Common-case fast path. - if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { - return nil - } - - // This is fairly tricky, and it's not clear that it is needed. - return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") -} - -// A global registry of types that can be used in a MessageSet. - -var messageSetMap = make(map[int32]messageSetDesc) - -type messageSetDesc struct { - t reflect.Type // pointer to struct - name string -} - -// RegisterMessageSetType is called from the generated code. -func RegisterMessageSetType(m Message, fieldNum int32, name string) { - messageSetMap[fieldNum] = messageSetDesc{ - t: reflect.TypeOf(m), - name: name, - } -} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go b/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go deleted file mode 100644 index fb512e2e16..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go +++ /dev/null @@ -1,484 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build appengine js - -// This file contains an implementation of proto field accesses using package reflect. -// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can -// be used on App Engine. - -package proto - -import ( - "math" - "reflect" -) - -// A structPointer is a pointer to a struct. -type structPointer struct { - v reflect.Value -} - -// toStructPointer returns a structPointer equivalent to the given reflect value. -// The reflect value must itself be a pointer to a struct. -func toStructPointer(v reflect.Value) structPointer { - return structPointer{v} -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p.v.IsNil() -} - -// Interface returns the struct pointer as an interface value. -func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { - return p.v.Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. -// In this implementation, a field is identified by the sequence of field indices -// passed to reflect's FieldByIndex. -type field []int - -// toField returns a field equivalent to the given reflect field. -func toField(f *reflect.StructField) field { - return f.Index -} - -// invalidField is an invalid field identifier. -var invalidField = field(nil) - -// IsValid reports whether the field identifier is valid. -func (f field) IsValid() bool { return f != nil } - -// field returns the given field in the struct as a reflect value. -func structPointer_field(p structPointer, f field) reflect.Value { - // Special case: an extension map entry with a value of type T - // passes a *T to the struct-handling code with a zero field, - // expecting that it will be treated as equivalent to *struct{ X T }, - // which has the same memory layout. We have to handle that case - // specially, because reflect will panic if we call FieldByIndex on a - // non-struct. - if f == nil { - return p.v.Elem() - } - - return p.v.Elem().FieldByIndex(f) -} - -// ifield returns the given field in the struct as an interface value. -func structPointer_ifield(p structPointer, f field) interface{} { - return structPointer_field(p, f).Addr().Interface() -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return structPointer_ifield(p, f).(*[]byte) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return structPointer_ifield(p, f).(*[][]byte) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return structPointer_ifield(p, f).(**bool) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return structPointer_ifield(p, f).(*bool) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return structPointer_ifield(p, f).(*[]bool) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return structPointer_ifield(p, f).(**string) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return structPointer_ifield(p, f).(*string) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return structPointer_ifield(p, f).(*[]string) -} - -// Extensions returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return structPointer_ifield(p, f).(*XXX_InternalExtensions) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return structPointer_ifield(p, f).(*map[int32]Extension) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return structPointer_field(p, f).Addr() -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - structPointer_field(p, f).Set(q.v) -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return structPointer{structPointer_field(p, f)} -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { - return structPointerSlice{structPointer_field(p, f)} -} - -// A structPointerSlice represents the address of a slice of pointers to structs -// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. -type structPointerSlice struct { - v reflect.Value -} - -func (p structPointerSlice) Len() int { return p.v.Len() } -func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } -func (p structPointerSlice) Append(q structPointer) { - p.v.Set(reflect.Append(p.v, q.v)) -} - -var ( - int32Type = reflect.TypeOf(int32(0)) - uint32Type = reflect.TypeOf(uint32(0)) - float32Type = reflect.TypeOf(float32(0)) - int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) - float64Type = reflect.TypeOf(float64(0)) -) - -// A word32 represents a field of type *int32, *uint32, *float32, or *enum. -// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. -type word32 struct { - v reflect.Value -} - -// IsNil reports whether p is nil. -func word32_IsNil(p word32) bool { - return p.v.IsNil() -} - -// Set sets p to point at a newly allocated word with bits set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - t := p.v.Type().Elem() - switch t { - case int32Type: - if len(o.int32s) == 0 { - o.int32s = make([]int32, uint32PoolSize) - } - o.int32s[0] = int32(x) - p.v.Set(reflect.ValueOf(&o.int32s[0])) - o.int32s = o.int32s[1:] - return - case uint32Type: - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - p.v.Set(reflect.ValueOf(&o.uint32s[0])) - o.uint32s = o.uint32s[1:] - return - case float32Type: - if len(o.float32s) == 0 { - o.float32s = make([]float32, uint32PoolSize) - } - o.float32s[0] = math.Float32frombits(x) - p.v.Set(reflect.ValueOf(&o.float32s[0])) - o.float32s = o.float32s[1:] - return - } - - // must be enum - p.v.Set(reflect.New(t)) - p.v.Elem().SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32_Get(p word32) uint32 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32{structPointer_field(p, f)} -} - -// A word32Val represents a field of type int32, uint32, float32, or enum. -// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. -type word32Val struct { - v reflect.Value -} - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - switch p.v.Type() { - case int32Type: - p.v.SetInt(int64(x)) - return - case uint32Type: - p.v.SetUint(uint64(x)) - return - case float32Type: - p.v.SetFloat(float64(math.Float32frombits(x))) - return - } - - // must be enum - p.v.SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32Val_Get(p word32Val) uint32 { - elem := p.v - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val{structPointer_field(p, f)} -} - -// A word32Slice is a slice of 32-bit values. -// That is, v.Type() is []int32, []uint32, []float32, or []enum. -type word32Slice struct { - v reflect.Value -} - -func (p word32Slice) Append(x uint32) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int32: - elem.SetInt(int64(int32(x))) - case reflect.Uint32: - elem.SetUint(uint64(x)) - case reflect.Float32: - elem.SetFloat(float64(math.Float32frombits(x))) - } -} - -func (p word32Slice) Len() int { - return p.v.Len() -} - -func (p word32Slice) Index(i int) uint32 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) word32Slice { - return word32Slice{structPointer_field(p, f)} -} - -// word64 is like word32 but for 64-bit values. -type word64 struct { - v reflect.Value -} - -func word64_Set(p word64, o *Buffer, x uint64) { - t := p.v.Type().Elem() - switch t { - case int64Type: - if len(o.int64s) == 0 { - o.int64s = make([]int64, uint64PoolSize) - } - o.int64s[0] = int64(x) - p.v.Set(reflect.ValueOf(&o.int64s[0])) - o.int64s = o.int64s[1:] - return - case uint64Type: - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - p.v.Set(reflect.ValueOf(&o.uint64s[0])) - o.uint64s = o.uint64s[1:] - return - case float64Type: - if len(o.float64s) == 0 { - o.float64s = make([]float64, uint64PoolSize) - } - o.float64s[0] = math.Float64frombits(x) - p.v.Set(reflect.ValueOf(&o.float64s[0])) - o.float64s = o.float64s[1:] - return - } - panic("unreachable") -} - -func word64_IsNil(p word64) bool { - return p.v.IsNil() -} - -func word64_Get(p word64) uint64 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) - } - panic("unreachable") -} - -func structPointer_Word64(p structPointer, f field) word64 { - return word64{structPointer_field(p, f)} -} - -// word64Val is like word32Val but for 64-bit values. -type word64Val struct { - v reflect.Value -} - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - switch p.v.Type() { - case int64Type: - p.v.SetInt(int64(x)) - return - case uint64Type: - p.v.SetUint(x) - return - case float64Type: - p.v.SetFloat(math.Float64frombits(x)) - return - } - panic("unreachable") -} - -func word64Val_Get(p word64Val) uint64 { - elem := p.v - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) - } - panic("unreachable") -} - -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val{structPointer_field(p, f)} -} - -type word64Slice struct { - v reflect.Value -} - -func (p word64Slice) Append(x uint64) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int64: - elem.SetInt(int64(int64(x))) - case reflect.Uint64: - elem.SetUint(uint64(x)) - case reflect.Float64: - elem.SetFloat(float64(math.Float64frombits(x))) - } -} - -func (p word64Slice) Len() int { - return p.v.Len() -} - -func (p word64Slice) Index(i int) uint64 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return uint64(elem.Uint()) - case reflect.Float64: - return math.Float64bits(float64(elem.Float())) - } - panic("unreachable") -} - -func structPointer_Word64Slice(p structPointer, f field) word64Slice { - return word64Slice{structPointer_field(p, f)} -} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go b/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go deleted file mode 100644 index 1763a5f227..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go +++ /dev/null @@ -1,85 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2016, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build appengine js - -package proto - -import ( - "reflect" -) - -func structPointer_FieldPointer(p structPointer, f field) structPointer { - panic("not implemented") -} - -func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer { - panic("not implemented") -} - -func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} { - panic("not implemented") -} - -func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} { - panic("not implemented") -} - -func structPointer_GetRefStructPointer(p structPointer, f field) structPointer { - panic("not implemented") -} - -func structPointer_Add(p structPointer, size field) structPointer { - panic("not implemented") -} - -func structPointer_Len(p structPointer, f field) int { - panic("not implemented") -} - -func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader { - panic("not implemented") -} - -func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) { - panic("not implemented") -} - -func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice { - panic("not implemented") -} - -type structRefSlice struct{} - -func (v *structRefSlice) Len() int { - panic("not implemented") -} - -func (v *structRefSlice) Index(i int) structPointer { - panic("not implemented") -} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go deleted file mode 100644 index 6b5567d47c..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go +++ /dev/null @@ -1,270 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !appengine,!js - -// This file contains the implementation of the proto field accesses using package unsafe. - -package proto - -import ( - "reflect" - "unsafe" -) - -// NOTE: These type_Foo functions would more idiomatically be methods, -// but Go does not allow methods on pointer types, and we must preserve -// some pointer type for the garbage collector. We use these -// funcs with clunky names as our poor approximation to methods. -// -// An alternative would be -// type structPointer struct { p unsafe.Pointer } -// but that does not registerize as well. - -// A structPointer is a pointer to a struct. -type structPointer unsafe.Pointer - -// toStructPointer returns a structPointer equivalent to the given reflect value. -func toStructPointer(v reflect.Value) structPointer { - return structPointer(unsafe.Pointer(v.Pointer())) -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p == nil -} - -// Interface returns the struct pointer, assumed to have element type t, -// as an interface value. -func structPointer_Interface(p structPointer, t reflect.Type) interface{} { - return reflect.NewAt(t, unsafe.Pointer(p)).Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. -// In this implementation, a field is identified by its byte offset from the start of the struct. -type field uintptr - -// toField returns a field equivalent to the given reflect field. -func toField(f *reflect.StructField) field { - return field(f.Offset) -} - -// invalidField is an invalid field identifier. -const invalidField = ^field(0) - -// IsValid reports whether the field identifier is valid. -func (f field) IsValid() bool { - return f != ^field(0) -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { - return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). -type structPointerSlice []structPointer - -func (v *structPointerSlice) Len() int { return len(*v) } -func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } -func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } - -// A word32 is the address of a "pointer to 32-bit value" field. -type word32 **uint32 - -// IsNil reports whether *v is nil. -func word32_IsNil(p word32) bool { - return *p == nil -} - -// Set sets *v to point at a newly allocated word set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - *p = &o.uint32s[0] - o.uint32s = o.uint32s[1:] -} - -// Get gets the value pointed at by *v. -func word32_Get(p word32) uint32 { - return **p -} - -// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Val is the address of a 32-bit value field. -type word32Val *uint32 - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - *p = x -} - -// Get gets the value pointed at by p. -func word32Val_Get(p word32Val) uint32 { - return *p -} - -// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Slice is a slice of 32-bit values. -type word32Slice []uint32 - -func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } -func (v *word32Slice) Len() int { return len(*v) } -func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } - -// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) *word32Slice { - return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// word64 is like word32 but for 64-bit values. -type word64 **uint64 - -func word64_Set(p word64, o *Buffer, x uint64) { - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - *p = &o.uint64s[0] - o.uint64s = o.uint64s[1:] -} - -func word64_IsNil(p word64) bool { - return *p == nil -} - -func word64_Get(p word64) uint64 { - return **p -} - -func structPointer_Word64(p structPointer, f field) word64 { - return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// word64Val is like word32Val but for 64-bit values. -type word64Val *uint64 - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - *p = x -} - -func word64Val_Get(p word64Val) uint64 { - return *p -} - -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// word64Slice is like word32Slice but for 64-bit values. -type word64Slice []uint64 - -func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } -func (v *word64Slice) Len() int { return len(*v) } -func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } - -func structPointer_Word64Slice(p structPointer, f field) *word64Slice { - return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go deleted file mode 100644 index f156a29f0e..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go +++ /dev/null @@ -1,128 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !appengine,!js - -// This file contains the implementation of the proto field accesses using package unsafe. - -package proto - -import ( - "reflect" - "unsafe" -) - -func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} { - point := unsafe.Pointer(uintptr(p) + uintptr(f)) - r := reflect.NewAt(t, point) - return r.Interface() -} - -func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} { - point := unsafe.Pointer(uintptr(p) + uintptr(f)) - r := reflect.NewAt(t, point) - if r.Elem().IsNil() { - return nil - } - return r.Elem().Interface() -} - -func copyUintPtr(oldptr, newptr uintptr, size int) { - oldbytes := make([]byte, 0) - oldslice := (*reflect.SliceHeader)(unsafe.Pointer(&oldbytes)) - oldslice.Data = oldptr - oldslice.Len = size - oldslice.Cap = size - newbytes := make([]byte, 0) - newslice := (*reflect.SliceHeader)(unsafe.Pointer(&newbytes)) - newslice.Data = newptr - newslice.Len = size - newslice.Cap = size - copy(newbytes, oldbytes) -} - -func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) { - copyUintPtr(uintptr(oldptr), uintptr(newptr), size) -} - -func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer { - size := typ.Elem().Size() - - oldHeader := structPointer_GetSliceHeader(base, f) - oldSlice := reflect.NewAt(typ, unsafe.Pointer(oldHeader)).Elem() - newLen := oldHeader.Len + 1 - newSlice := reflect.MakeSlice(typ, newLen, newLen) - reflect.Copy(newSlice, oldSlice) - bas := toStructPointer(newSlice) - oldHeader.Data = uintptr(bas) - oldHeader.Len = newLen - oldHeader.Cap = newLen - - return structPointer(unsafe.Pointer(uintptr(unsafe.Pointer(bas)) + uintptr(uintptr(newLen-1)*size))) -} - -func structPointer_FieldPointer(p structPointer, f field) structPointer { - return structPointer(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -func structPointer_GetRefStructPointer(p structPointer, f field) structPointer { - return structPointer((*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader { - return (*reflect.SliceHeader)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -func structPointer_Add(p structPointer, size field) structPointer { - return structPointer(unsafe.Pointer(uintptr(p) + uintptr(size))) -} - -func structPointer_Len(p structPointer, f field) int { - return len(*(*[]interface{})(unsafe.Pointer(structPointer_GetRefStructPointer(p, f)))) -} - -func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice { - return &structRefSlice{p: p, f: f, size: size} -} - -// A structRefSlice represents a slice of structs (themselves submessages or groups). -type structRefSlice struct { - p structPointer - f field - size uintptr -} - -func (v *structRefSlice) Len() int { - return structPointer_Len(v.p, v.f) -} - -func (v *structRefSlice) Index(i int) structPointer { - ss := structPointer_GetStructPointer(v.p, v.f) - ss1 := structPointer_GetRefStructPointer(ss, 0) - return structPointer_Add(ss1, field(uintptr(i)*v.size)) -} diff --git a/vendor/github.com/gogo/protobuf/proto/properties.go b/vendor/github.com/gogo/protobuf/proto/properties.go deleted file mode 100644 index 2a69e8862d..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/properties.go +++ /dev/null @@ -1,971 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -/* - * Routines for encoding data into the wire format for protocol buffers. - */ - -import ( - "fmt" - "log" - "os" - "reflect" - "sort" - "strconv" - "strings" - "sync" -) - -const debug bool = false - -// Constants that identify the encoding of a value on the wire. -const ( - WireVarint = 0 - WireFixed64 = 1 - WireBytes = 2 - WireStartGroup = 3 - WireEndGroup = 4 - WireFixed32 = 5 -) - -const startSize = 10 // initial slice/string sizes - -// Encoders are defined in encode.go -// An encoder outputs the full representation of a field, including its -// tag and encoder type. -type encoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueEncoder encodes a single integer in a particular encoding. -type valueEncoder func(o *Buffer, x uint64) error - -// Sizers are defined in encode.go -// A sizer returns the encoded size of a field, including its tag and encoder -// type. -type sizer func(prop *Properties, base structPointer) int - -// A valueSizer returns the encoded size of a single integer in a particular -// encoding. -type valueSizer func(x uint64) int - -// Decoders are defined in decode.go -// A decoder creates a value from its wire representation. -// Unrecognized subelements are saved in unrec. -type decoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueDecoder decodes a single integer in a particular encoding. -type valueDecoder func(o *Buffer) (x uint64, err error) - -// A oneofMarshaler does the marshaling for all oneof fields in a message. -type oneofMarshaler func(Message, *Buffer) error - -// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. -type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) - -// A oneofSizer does the sizing for all oneof fields in a message. -type oneofSizer func(Message) int - -// tagMap is an optimization over map[int]int for typical protocol buffer -// use-cases. Encoded protocol buffers are often in tag order with small tag -// numbers. -type tagMap struct { - fastTags []int - slowTags map[int]int -} - -// tagMapFastLimit is the upper bound on the tag number that will be stored in -// the tagMap slice rather than its map. -const tagMapFastLimit = 1024 - -func (p *tagMap) get(t int) (int, bool) { - if t > 0 && t < tagMapFastLimit { - if t >= len(p.fastTags) { - return 0, false - } - fi := p.fastTags[t] - return fi, fi >= 0 - } - fi, ok := p.slowTags[t] - return fi, ok -} - -func (p *tagMap) put(t int, fi int) { - if t > 0 && t < tagMapFastLimit { - for len(p.fastTags) < t+1 { - p.fastTags = append(p.fastTags, -1) - } - p.fastTags[t] = fi - return - } - if p.slowTags == nil { - p.slowTags = make(map[int]int) - } - p.slowTags[t] = fi -} - -// StructProperties represents properties for all the fields of a struct. -// decoderTags and decoderOrigNames should only be used by the decoder. -type StructProperties struct { - Prop []*Properties // properties for each field - reqCount int // required count - decoderTags tagMap // map from proto tag to struct field number - decoderOrigNames map[string]int // map from original name to struct field number - order []int // list of struct field numbers in tag order - unrecField field // field id of the XXX_unrecognized []byte field - extendable bool // is this an extendable proto - - oneofMarshaler oneofMarshaler - oneofUnmarshaler oneofUnmarshaler - oneofSizer oneofSizer - stype reflect.Type - - // OneofTypes contains information about the oneof fields in this message. - // It is keyed by the original name of a field. - OneofTypes map[string]*OneofProperties -} - -// OneofProperties represents information about a specific field in a oneof. -type OneofProperties struct { - Type reflect.Type // pointer to generated struct type for this oneof field - Field int // struct field number of the containing oneof in the message - Prop *Properties -} - -// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. -// See encode.go, (*Buffer).enc_struct. - -func (sp *StructProperties) Len() int { return len(sp.order) } -func (sp *StructProperties) Less(i, j int) bool { - return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag -} -func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } - -// Properties represents the protocol-specific behavior of a single struct field. -type Properties struct { - Name string // name of the field, for error messages - OrigName string // original name before protocol compiler (always set) - JSONName string // name to use for JSON; determined by protoc - Wire string - WireType int - Tag int - Required bool - Optional bool - Repeated bool - Packed bool // relevant for repeated primitives only - Enum string // set for enum types only - proto3 bool // whether this is known to be a proto3 field; set for []byte only - oneof bool // whether this is a oneof field - - Default string // default value - HasDefault bool // whether an explicit default was provided - CustomType string - CastType string - StdTime bool - StdDuration bool - - enc encoder - valEnc valueEncoder // set for bool and numeric types only - field field - tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) - tagbuf [8]byte - stype reflect.Type // set for struct types only - sstype reflect.Type // set for slices of structs types only - ctype reflect.Type // set for custom types only - sprop *StructProperties // set for struct types only - isMarshaler bool - isUnmarshaler bool - - mtype reflect.Type // set for map types only - mkeyprop *Properties // set for map types only - mvalprop *Properties // set for map types only - - size sizer - valSize valueSizer // set for bool and numeric types only - - dec decoder - valDec valueDecoder // set for bool and numeric types only - - // If this is a packable field, this will be the decoder for the packed version of the field. - packedDec decoder -} - -// String formats the properties in the protobuf struct field tag style. -func (p *Properties) String() string { - s := p.Wire - s = "," - s += strconv.Itoa(p.Tag) - if p.Required { - s += ",req" - } - if p.Optional { - s += ",opt" - } - if p.Repeated { - s += ",rep" - } - if p.Packed { - s += ",packed" - } - s += ",name=" + p.OrigName - if p.JSONName != p.OrigName { - s += ",json=" + p.JSONName - } - if p.proto3 { - s += ",proto3" - } - if p.oneof { - s += ",oneof" - } - if len(p.Enum) > 0 { - s += ",enum=" + p.Enum - } - if p.HasDefault { - s += ",def=" + p.Default - } - return s -} - -// Parse populates p by parsing a string in the protobuf struct field tag style. -func (p *Properties) Parse(s string) { - // "bytes,49,opt,name=foo,def=hello!" - fields := strings.Split(s, ",") // breaks def=, but handled below. - if len(fields) < 2 { - fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) - return - } - - p.Wire = fields[0] - switch p.Wire { - case "varint": - p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeVarint - p.valDec = (*Buffer).DecodeVarint - p.valSize = sizeVarint - case "fixed32": - p.WireType = WireFixed32 - p.valEnc = (*Buffer).EncodeFixed32 - p.valDec = (*Buffer).DecodeFixed32 - p.valSize = sizeFixed32 - case "fixed64": - p.WireType = WireFixed64 - p.valEnc = (*Buffer).EncodeFixed64 - p.valDec = (*Buffer).DecodeFixed64 - p.valSize = sizeFixed64 - case "zigzag32": - p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag32 - p.valDec = (*Buffer).DecodeZigzag32 - p.valSize = sizeZigzag32 - case "zigzag64": - p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag64 - p.valDec = (*Buffer).DecodeZigzag64 - p.valSize = sizeZigzag64 - case "bytes", "group": - p.WireType = WireBytes - // no numeric converter for non-numeric types - default: - fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) - return - } - - var err error - p.Tag, err = strconv.Atoi(fields[1]) - if err != nil { - return - } - - for i := 2; i < len(fields); i++ { - f := fields[i] - switch { - case f == "req": - p.Required = true - case f == "opt": - p.Optional = true - case f == "rep": - p.Repeated = true - case f == "packed": - p.Packed = true - case strings.HasPrefix(f, "name="): - p.OrigName = f[5:] - case strings.HasPrefix(f, "json="): - p.JSONName = f[5:] - case strings.HasPrefix(f, "enum="): - p.Enum = f[5:] - case f == "proto3": - p.proto3 = true - case f == "oneof": - p.oneof = true - case strings.HasPrefix(f, "def="): - p.HasDefault = true - p.Default = f[4:] // rest of string - if i+1 < len(fields) { - // Commas aren't escaped, and def is always last. - p.Default += "," + strings.Join(fields[i+1:], ",") - break - } - case strings.HasPrefix(f, "embedded="): - p.OrigName = strings.Split(f, "=")[1] - case strings.HasPrefix(f, "customtype="): - p.CustomType = strings.Split(f, "=")[1] - case strings.HasPrefix(f, "casttype="): - p.CastType = strings.Split(f, "=")[1] - case f == "stdtime": - p.StdTime = true - case f == "stdduration": - p.StdDuration = true - } - } -} - -func logNoSliceEnc(t1, t2 reflect.Type) { - fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) -} - -var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() - -// Initialize the fields for encoding and decoding. -func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { - p.enc = nil - p.dec = nil - p.size = nil - isMap := typ.Kind() == reflect.Map - if len(p.CustomType) > 0 && !isMap { - p.setCustomEncAndDec(typ) - p.setTag(lockGetProp) - return - } - if p.StdTime && !isMap { - p.setTimeEncAndDec(typ) - p.setTag(lockGetProp) - return - } - if p.StdDuration && !isMap { - p.setDurationEncAndDec(typ) - p.setTag(lockGetProp) - return - } - switch t1 := typ; t1.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) - - // proto3 scalar types - - case reflect.Bool: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_bool - p.dec = (*Buffer).dec_proto3_bool - p.size = size_proto3_bool - } else { - p.enc = (*Buffer).enc_ref_bool - p.dec = (*Buffer).dec_proto3_bool - p.size = size_ref_bool - } - case reflect.Int32: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_int32 - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_int32 - } else { - p.enc = (*Buffer).enc_ref_int32 - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_ref_int32 - } - case reflect.Uint32: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_uint32 - p.dec = (*Buffer).dec_proto3_int32 // can reuse - p.size = size_proto3_uint32 - } else { - p.enc = (*Buffer).enc_ref_uint32 - p.dec = (*Buffer).dec_proto3_int32 // can reuse - p.size = size_ref_uint32 - } - case reflect.Int64, reflect.Uint64: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_int64 - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - } else { - p.enc = (*Buffer).enc_ref_int64 - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_ref_int64 - } - case reflect.Float32: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_uint32 - } else { - p.enc = (*Buffer).enc_ref_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_ref_uint32 - } - case reflect.Float64: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - } else { - p.enc = (*Buffer).enc_ref_int64 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_ref_int64 - } - case reflect.String: - if p.proto3 { - p.enc = (*Buffer).enc_proto3_string - p.dec = (*Buffer).dec_proto3_string - p.size = size_proto3_string - } else { - p.enc = (*Buffer).enc_ref_string - p.dec = (*Buffer).dec_proto3_string - p.size = size_ref_string - } - case reflect.Struct: - p.stype = typ - p.isMarshaler = isMarshaler(typ) - p.isUnmarshaler = isUnmarshaler(typ) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_ref_struct_message - p.dec = (*Buffer).dec_ref_struct_message - p.size = size_ref_struct_message - } else { - fmt.Fprintf(os.Stderr, "proto: no coders for struct %T\n", typ) - } - - case reflect.Ptr: - switch t2 := t1.Elem(); t2.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) - break - case reflect.Bool: - p.enc = (*Buffer).enc_bool - p.dec = (*Buffer).dec_bool - p.size = size_bool - case reflect.Int32: - p.enc = (*Buffer).enc_int32 - p.dec = (*Buffer).dec_int32 - p.size = size_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_uint32 - p.dec = (*Buffer).dec_int32 // can reuse - p.size = size_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_int64 - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_int32 - p.size = size_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_int64 // can just treat them as bits - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.String: - p.enc = (*Buffer).enc_string - p.dec = (*Buffer).dec_string - p.size = size_string - case reflect.Struct: - p.stype = t1.Elem() - p.isMarshaler = isMarshaler(t1) - p.isUnmarshaler = isUnmarshaler(t1) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_struct_message - p.dec = (*Buffer).dec_struct_message - p.size = size_struct_message - } else { - p.enc = (*Buffer).enc_struct_group - p.dec = (*Buffer).dec_struct_group - p.size = size_struct_group - } - } - - case reflect.Slice: - switch t2 := t1.Elem(); t2.Kind() { - default: - logNoSliceEnc(t1, t2) - break - case reflect.Bool: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_bool - p.size = size_slice_packed_bool - } else { - p.enc = (*Buffer).enc_slice_bool - p.size = size_slice_bool - } - p.dec = (*Buffer).dec_slice_bool - p.packedDec = (*Buffer).dec_slice_packed_bool - case reflect.Int32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int32 - p.size = size_slice_packed_int32 - } else { - p.enc = (*Buffer).enc_slice_int32 - p.size = size_slice_int32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Uint32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Int64, reflect.Uint64: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - case reflect.Uint8: - p.dec = (*Buffer).dec_slice_byte - if p.proto3 { - p.enc = (*Buffer).enc_proto3_slice_byte - p.size = size_proto3_slice_byte - } else { - p.enc = (*Buffer).enc_slice_byte - p.size = size_slice_byte - } - case reflect.Float32, reflect.Float64: - switch t2.Bits() { - case 32: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case 64: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - default: - logNoSliceEnc(t1, t2) - break - } - case reflect.String: - p.enc = (*Buffer).enc_slice_string - p.dec = (*Buffer).dec_slice_string - p.size = size_slice_string - case reflect.Ptr: - switch t3 := t2.Elem(); t3.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) - break - case reflect.Struct: - p.stype = t2.Elem() - p.isMarshaler = isMarshaler(t2) - p.isUnmarshaler = isUnmarshaler(t2) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_slice_struct_message - p.dec = (*Buffer).dec_slice_struct_message - p.size = size_slice_struct_message - } else { - p.enc = (*Buffer).enc_slice_struct_group - p.dec = (*Buffer).dec_slice_struct_group - p.size = size_slice_struct_group - } - } - case reflect.Slice: - switch t2.Elem().Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) - break - case reflect.Uint8: - p.enc = (*Buffer).enc_slice_slice_byte - p.dec = (*Buffer).dec_slice_slice_byte - p.size = size_slice_slice_byte - } - case reflect.Struct: - p.setSliceOfNonPointerStructs(t1) - } - - case reflect.Map: - p.enc = (*Buffer).enc_new_map - p.dec = (*Buffer).dec_new_map - p.size = size_new_map - - p.mtype = t1 - p.mkeyprop = &Properties{} - p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) - p.mvalprop = &Properties{} - vtype := p.mtype.Elem() - if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { - // The value type is not a message (*T) or bytes ([]byte), - // so we need encoders for the pointer to this type. - vtype = reflect.PtrTo(vtype) - } - - p.mvalprop.CustomType = p.CustomType - p.mvalprop.StdDuration = p.StdDuration - p.mvalprop.StdTime = p.StdTime - p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) - } - p.setTag(lockGetProp) -} - -func (p *Properties) setTag(lockGetProp bool) { - // precalculate tag code - wire := p.WireType - if p.Packed { - wire = WireBytes - } - x := uint32(p.Tag)<<3 | uint32(wire) - i := 0 - for i = 0; x > 127; i++ { - p.tagbuf[i] = 0x80 | uint8(x&0x7F) - x >>= 7 - } - p.tagbuf[i] = uint8(x) - p.tagcode = p.tagbuf[0 : i+1] - - if p.stype != nil { - if lockGetProp { - p.sprop = GetProperties(p.stype) - } else { - p.sprop = getPropertiesLocked(p.stype) - } - } -} - -var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() -) - -// isMarshaler reports whether type t implements Marshaler. -func isMarshaler(t reflect.Type) bool { - return t.Implements(marshalerType) -} - -// isUnmarshaler reports whether type t implements Unmarshaler. -func isUnmarshaler(t reflect.Type) bool { - return t.Implements(unmarshalerType) -} - -// Init populates the properties from a protocol buffer struct tag. -func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { - p.init(typ, name, tag, f, true) -} - -func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { - // "bytes,49,opt,def=hello!" - p.Name = name - p.OrigName = name - if f != nil { - p.field = toField(f) - } - if tag == "" { - return - } - p.Parse(tag) - p.setEncAndDec(typ, f, lockGetProp) -} - -var ( - propertiesMu sync.RWMutex - propertiesMap = make(map[reflect.Type]*StructProperties) -) - -// GetProperties returns the list of properties for the type represented by t. -// t must represent a generated struct type of a protocol message. -func GetProperties(t reflect.Type) *StructProperties { - if t.Kind() != reflect.Struct { - panic("proto: type must have kind struct") - } - - // Most calls to GetProperties in a long-running program will be - // retrieving details for types we have seen before. - propertiesMu.RLock() - sprop, ok := propertiesMap[t] - propertiesMu.RUnlock() - if ok { - if collectStats { - stats.Chit++ - } - return sprop - } - - propertiesMu.Lock() - sprop = getPropertiesLocked(t) - propertiesMu.Unlock() - return sprop -} - -// getPropertiesLocked requires that propertiesMu is held. -func getPropertiesLocked(t reflect.Type) *StructProperties { - if prop, ok := propertiesMap[t]; ok { - if collectStats { - stats.Chit++ - } - return prop - } - if collectStats { - stats.Cmiss++ - } - - prop := new(StructProperties) - // in case of recursive protos, fill this in now. - propertiesMap[t] = prop - - // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || - reflect.PtrTo(t).Implements(extendableProtoV1Type) || - reflect.PtrTo(t).Implements(extendableBytesType) - prop.unrecField = invalidField - prop.Prop = make([]*Properties, t.NumField()) - prop.order = make([]int, t.NumField()) - - isOneofMessage := false - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - p := new(Properties) - name := f.Name - p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) - - if f.Name == "XXX_InternalExtensions" { // special case - p.enc = (*Buffer).enc_exts - p.dec = nil // not needed - p.size = size_exts - } else if f.Name == "XXX_extensions" { // special case - if len(f.Tag.Get("protobuf")) > 0 { - p.enc = (*Buffer).enc_ext_slice_byte - p.dec = nil // not needed - p.size = size_ext_slice_byte - } else { - p.enc = (*Buffer).enc_map - p.dec = nil // not needed - p.size = size_map - } - } else if f.Name == "XXX_unrecognized" { // special case - prop.unrecField = toField(&f) - } - oneof := f.Tag.Get("protobuf_oneof") // special case - if oneof != "" { - isOneofMessage = true - // Oneof fields don't use the traditional protobuf tag. - p.OrigName = oneof - } - prop.Prop[i] = p - prop.order[i] = i - if debug { - print(i, " ", f.Name, " ", t.String(), " ") - if p.Tag > 0 { - print(p.String()) - } - print("\n") - } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { - fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") - } - } - - // Re-order prop.order. - sort.Sort(prop) - - type oneofMessage interface { - XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) - } - if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok { - var oots []interface{} - prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() - prop.stype = t - - // Interpret oneof metadata. - prop.OneofTypes = make(map[string]*OneofProperties) - for _, oot := range oots { - oop := &OneofProperties{ - Type: reflect.ValueOf(oot).Type(), // *T - Prop: new(Properties), - } - sft := oop.Type.Elem().Field(0) - oop.Prop.Name = sft.Name - oop.Prop.Parse(sft.Tag.Get("protobuf")) - // There will be exactly one interface field that - // this new value is assignable to. - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if f.Type.Kind() != reflect.Interface { - continue - } - if !oop.Type.AssignableTo(f.Type) { - continue - } - oop.Field = i - break - } - prop.OneofTypes[oop.Prop.OrigName] = oop - } - } - - // build required counts - // build tags - reqCount := 0 - prop.decoderOrigNames = make(map[string]int) - for i, p := range prop.Prop { - if strings.HasPrefix(p.Name, "XXX_") { - // Internal fields should not appear in tags/origNames maps. - // They are handled specially when encoding and decoding. - continue - } - if p.Required { - reqCount++ - } - prop.decoderTags.put(p.Tag, i) - prop.decoderOrigNames[p.OrigName] = i - } - prop.reqCount = reqCount - - return prop -} - -// Return the Properties object for the x[0]'th field of the structure. -func propByIndex(t reflect.Type, x []int) *Properties { - if len(x) != 1 { - fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) - return nil - } - prop := GetProperties(t) - return prop.Prop[x[0]] -} - -// Get the address and type of a pointer to a struct from an interface. -func getbase(pb Message) (t reflect.Type, b structPointer, err error) { - if pb == nil { - err = ErrNil - return - } - // get the reflect type of the pointer to the struct. - t = reflect.TypeOf(pb) - // get the address of the struct. - value := reflect.ValueOf(pb) - b = toStructPointer(value) - return -} - -// A global registry of enum types. -// The generated code will register the generated maps by calling RegisterEnum. - -var enumValueMaps = make(map[string]map[string]int32) -var enumStringMaps = make(map[string]map[int32]string) - -// RegisterEnum is called from the generated code to install the enum descriptor -// maps into the global table to aid parsing text format protocol buffers. -func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { - if _, ok := enumValueMaps[typeName]; ok { - panic("proto: duplicate enum registered: " + typeName) - } - enumValueMaps[typeName] = valueMap - if _, ok := enumStringMaps[typeName]; ok { - panic("proto: duplicate enum registered: " + typeName) - } - enumStringMaps[typeName] = unusedNameMap -} - -// EnumValueMap returns the mapping from names to integers of the -// enum type enumType, or a nil if not found. -func EnumValueMap(enumType string) map[string]int32 { - return enumValueMaps[enumType] -} - -// A registry of all linked message types. -// The string is a fully-qualified proto name ("pkg.Message"). -var ( - protoTypes = make(map[string]reflect.Type) - revProtoTypes = make(map[reflect.Type]string) -) - -// RegisterType is called from generated code and maps from the fully qualified -// proto name to the type (pointer to struct) of the protocol buffer. -func RegisterType(x Message, name string) { - if _, ok := protoTypes[name]; ok { - // TODO: Some day, make this a panic. - log.Printf("proto: duplicate proto type registered: %s", name) - return - } - t := reflect.TypeOf(x) - protoTypes[name] = t - revProtoTypes[t] = name -} - -// MessageName returns the fully-qualified proto name for the given message type. -func MessageName(x Message) string { - type xname interface { - XXX_MessageName() string - } - if m, ok := x.(xname); ok { - return m.XXX_MessageName() - } - return revProtoTypes[reflect.TypeOf(x)] -} - -// MessageType returns the message type (pointer to struct) for a named message. -func MessageType(name string) reflect.Type { return protoTypes[name] } - -// A registry of all linked proto files. -var ( - protoFiles = make(map[string][]byte) // file name => fileDescriptor -) - -// RegisterFile is called from generated code and maps from the -// full file name of a .proto file to its compressed FileDescriptorProto. -func RegisterFile(filename string, fileDescriptor []byte) { - protoFiles[filename] = fileDescriptor -} - -// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. -func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/vendor/github.com/gogo/protobuf/proto/properties_gogo.go b/vendor/github.com/gogo/protobuf/proto/properties_gogo.go deleted file mode 100644 index b6b7176c56..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/properties_gogo.go +++ /dev/null @@ -1,111 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "fmt" - "os" - "reflect" -) - -func (p *Properties) setCustomEncAndDec(typ reflect.Type) { - p.ctype = typ - if p.Repeated { - p.enc = (*Buffer).enc_custom_slice_bytes - p.dec = (*Buffer).dec_custom_slice_bytes - p.size = size_custom_slice_bytes - } else if typ.Kind() == reflect.Ptr { - p.enc = (*Buffer).enc_custom_bytes - p.dec = (*Buffer).dec_custom_bytes - p.size = size_custom_bytes - } else { - p.enc = (*Buffer).enc_custom_ref_bytes - p.dec = (*Buffer).dec_custom_ref_bytes - p.size = size_custom_ref_bytes - } -} - -func (p *Properties) setDurationEncAndDec(typ reflect.Type) { - if p.Repeated { - if typ.Elem().Kind() == reflect.Ptr { - p.enc = (*Buffer).enc_slice_duration - p.dec = (*Buffer).dec_slice_duration - p.size = size_slice_duration - } else { - p.enc = (*Buffer).enc_slice_ref_duration - p.dec = (*Buffer).dec_slice_ref_duration - p.size = size_slice_ref_duration - } - } else if typ.Kind() == reflect.Ptr { - p.enc = (*Buffer).enc_duration - p.dec = (*Buffer).dec_duration - p.size = size_duration - } else { - p.enc = (*Buffer).enc_ref_duration - p.dec = (*Buffer).dec_ref_duration - p.size = size_ref_duration - } -} - -func (p *Properties) setTimeEncAndDec(typ reflect.Type) { - if p.Repeated { - if typ.Elem().Kind() == reflect.Ptr { - p.enc = (*Buffer).enc_slice_time - p.dec = (*Buffer).dec_slice_time - p.size = size_slice_time - } else { - p.enc = (*Buffer).enc_slice_ref_time - p.dec = (*Buffer).dec_slice_ref_time - p.size = size_slice_ref_time - } - } else if typ.Kind() == reflect.Ptr { - p.enc = (*Buffer).enc_time - p.dec = (*Buffer).dec_time - p.size = size_time - } else { - p.enc = (*Buffer).enc_ref_time - p.dec = (*Buffer).dec_ref_time - p.size = size_ref_time - } - -} - -func (p *Properties) setSliceOfNonPointerStructs(typ reflect.Type) { - t2 := typ.Elem() - p.sstype = typ - p.stype = t2 - p.isMarshaler = isMarshaler(t2) - p.isUnmarshaler = isUnmarshaler(t2) - p.enc = (*Buffer).enc_slice_ref_struct_message - p.dec = (*Buffer).dec_slice_ref_struct_message - p.size = size_slice_ref_struct_message - if p.Wire != "bytes" { - fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T \n", typ, t2) - } -} diff --git a/vendor/github.com/gogo/protobuf/proto/skip_gogo.go b/vendor/github.com/gogo/protobuf/proto/skip_gogo.go deleted file mode 100644 index 5a5fd93f7c..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/skip_gogo.go +++ /dev/null @@ -1,119 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "fmt" - "io" -) - -func Skip(data []byte) (n int, err error) { - l := len(data) - index := 0 - for index < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if index >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[index] - index++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for { - if index >= l { - return 0, io.ErrUnexpectedEOF - } - index++ - if data[index-1] < 0x80 { - break - } - } - return index, nil - case 1: - index += 8 - return index, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if index >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[index] - index++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - index += length - return index, nil - case 3: - for { - var innerWire uint64 - var start int = index - for shift := uint(0); ; shift += 7 { - if index >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[index] - index++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := Skip(data[start:]) - if err != nil { - return 0, err - } - index = start + next - } - return index, nil - case 4: - return index, nil - case 5: - index += 4 - return index, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} diff --git a/vendor/github.com/gogo/protobuf/proto/text.go b/vendor/github.com/gogo/protobuf/proto/text.go deleted file mode 100644 index f609d1d453..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/text.go +++ /dev/null @@ -1,939 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -// Functions for writing the text protocol buffer format. - -import ( - "bufio" - "bytes" - "encoding" - "errors" - "fmt" - "io" - "log" - "math" - "reflect" - "sort" - "strings" - "sync" - "time" -) - -var ( - newline = []byte("\n") - spaces = []byte(" ") - gtNewline = []byte(">\n") - endBraceNewline = []byte("}\n") - backslashN = []byte{'\\', 'n'} - backslashR = []byte{'\\', 'r'} - backslashT = []byte{'\\', 't'} - backslashDQ = []byte{'\\', '"'} - backslashBS = []byte{'\\', '\\'} - posInf = []byte("inf") - negInf = []byte("-inf") - nan = []byte("nan") -) - -type writer interface { - io.Writer - WriteByte(byte) error -} - -// textWriter is an io.Writer that tracks its indentation level. -type textWriter struct { - ind int - complete bool // if the current position is a complete line - compact bool // whether to write out as a one-liner - w writer -} - -func (w *textWriter) WriteString(s string) (n int, err error) { - if !strings.Contains(s, "\n") { - if !w.compact && w.complete { - w.writeIndent() - } - w.complete = false - return io.WriteString(w.w, s) - } - // WriteString is typically called without newlines, so this - // codepath and its copy are rare. We copy to avoid - // duplicating all of Write's logic here. - return w.Write([]byte(s)) -} - -func (w *textWriter) Write(p []byte) (n int, err error) { - newlines := bytes.Count(p, newline) - if newlines == 0 { - if !w.compact && w.complete { - w.writeIndent() - } - n, err = w.w.Write(p) - w.complete = false - return n, err - } - - frags := bytes.SplitN(p, newline, newlines+1) - if w.compact { - for i, frag := range frags { - if i > 0 { - if err := w.w.WriteByte(' '); err != nil { - return n, err - } - n++ - } - nn, err := w.w.Write(frag) - n += nn - if err != nil { - return n, err - } - } - return n, nil - } - - for i, frag := range frags { - if w.complete { - w.writeIndent() - } - nn, err := w.w.Write(frag) - n += nn - if err != nil { - return n, err - } - if i+1 < len(frags) { - if err := w.w.WriteByte('\n'); err != nil { - return n, err - } - n++ - } - } - w.complete = len(frags[len(frags)-1]) == 0 - return n, nil -} - -func (w *textWriter) WriteByte(c byte) error { - if w.compact && c == '\n' { - c = ' ' - } - if !w.compact && w.complete { - w.writeIndent() - } - err := w.w.WriteByte(c) - w.complete = c == '\n' - return err -} - -func (w *textWriter) indent() { w.ind++ } - -func (w *textWriter) unindent() { - if w.ind == 0 { - log.Print("proto: textWriter unindented too far") - return - } - w.ind-- -} - -func writeName(w *textWriter, props *Properties) error { - if _, err := w.WriteString(props.OrigName); err != nil { - return err - } - if props.Wire != "group" { - return w.WriteByte(':') - } - return nil -} - -// raw is the interface satisfied by RawMessage. -type raw interface { - Bytes() []byte -} - -func requiresQuotes(u string) bool { - // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. - for _, ch := range u { - switch { - case ch == '.' || ch == '/' || ch == '_': - continue - case '0' <= ch && ch <= '9': - continue - case 'A' <= ch && ch <= 'Z': - continue - case 'a' <= ch && ch <= 'z': - continue - default: - return true - } - } - return false -} - -// isAny reports whether sv is a google.protobuf.Any message -func isAny(sv reflect.Value) bool { - type wkt interface { - XXX_WellKnownType() string - } - t, ok := sv.Addr().Interface().(wkt) - return ok && t.XXX_WellKnownType() == "Any" -} - -// writeProto3Any writes an expanded google.protobuf.Any message. -// -// It returns (false, nil) if sv value can't be unmarshaled (e.g. because -// required messages are not linked in). -// -// It returns (true, error) when sv was written in expanded format or an error -// was encountered. -func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { - turl := sv.FieldByName("TypeUrl") - val := sv.FieldByName("Value") - if !turl.IsValid() || !val.IsValid() { - return true, errors.New("proto: invalid google.protobuf.Any message") - } - - b, ok := val.Interface().([]byte) - if !ok { - return true, errors.New("proto: invalid google.protobuf.Any message") - } - - parts := strings.Split(turl.String(), "/") - mt := MessageType(parts[len(parts)-1]) - if mt == nil { - return false, nil - } - m := reflect.New(mt.Elem()) - if err := Unmarshal(b, m.Interface().(Message)); err != nil { - return false, nil - } - w.Write([]byte("[")) - u := turl.String() - if requiresQuotes(u) { - writeString(w, u) - } else { - w.Write([]byte(u)) - } - if w.compact { - w.Write([]byte("]:<")) - } else { - w.Write([]byte("]: <\n")) - w.ind++ - } - if err := tm.writeStruct(w, m.Elem()); err != nil { - return true, err - } - if w.compact { - w.Write([]byte("> ")) - } else { - w.ind-- - w.Write([]byte(">\n")) - } - return true, nil -} - -func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { - if tm.ExpandAny && isAny(sv) { - if canExpand, err := tm.writeProto3Any(w, sv); canExpand { - return err - } - } - st := sv.Type() - sprops := GetProperties(st) - for i := 0; i < sv.NumField(); i++ { - fv := sv.Field(i) - props := sprops.Prop[i] - name := st.Field(i).Name - - if strings.HasPrefix(name, "XXX_") { - // There are two XXX_ fields: - // XXX_unrecognized []byte - // XXX_extensions map[int32]proto.Extension - // The first is handled here; - // the second is handled at the bottom of this function. - if name == "XXX_unrecognized" && !fv.IsNil() { - if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { - return err - } - } - continue - } - if fv.Kind() == reflect.Ptr && fv.IsNil() { - // Field not filled in. This could be an optional field or - // a required field that wasn't filled in. Either way, there - // isn't anything we can show for it. - continue - } - if fv.Kind() == reflect.Slice && fv.IsNil() { - // Repeated field that is empty, or a bytes field that is unused. - continue - } - - if props.Repeated && fv.Kind() == reflect.Slice { - // Repeated field. - for j := 0; j < fv.Len(); j++ { - if err := writeName(w, props); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - v := fv.Index(j) - if v.Kind() == reflect.Ptr && v.IsNil() { - // A nil message in a repeated field is not valid, - // but we can handle that more gracefully than panicking. - if _, err := w.Write([]byte("\n")); err != nil { - return err - } - continue - } - if len(props.Enum) > 0 { - if err := tm.writeEnum(w, v, props); err != nil { - return err - } - } else if err := tm.writeAny(w, v, props); err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - } - continue - } - if fv.Kind() == reflect.Map { - // Map fields are rendered as a repeated struct with key/value fields. - keys := fv.MapKeys() - sort.Sort(mapKeys(keys)) - for _, key := range keys { - val := fv.MapIndex(key) - if err := writeName(w, props); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - // open struct - if err := w.WriteByte('<'); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - // key - if _, err := w.WriteString("key:"); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - if err := tm.writeAny(w, key, props.mkeyprop); err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - // nil values aren't legal, but we can avoid panicking because of them. - if val.Kind() != reflect.Ptr || !val.IsNil() { - // value - if _, err := w.WriteString("value:"); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - if err := tm.writeAny(w, val, props.mvalprop); err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - } - // close struct - w.unindent() - if err := w.WriteByte('>'); err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - } - continue - } - if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { - // empty bytes field - continue - } - if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { - // proto3 non-repeated scalar field; skip if zero value - if isProto3Zero(fv) { - continue - } - } - - if fv.Kind() == reflect.Interface { - // Check if it is a oneof. - if st.Field(i).Tag.Get("protobuf_oneof") != "" { - // fv is nil, or holds a pointer to generated struct. - // That generated struct has exactly one field, - // which has a protobuf struct tag. - if fv.IsNil() { - continue - } - inner := fv.Elem().Elem() // interface -> *T -> T - tag := inner.Type().Field(0).Tag.Get("protobuf") - props = new(Properties) // Overwrite the outer props var, but not its pointee. - props.Parse(tag) - // Write the value in the oneof, not the oneof itself. - fv = inner.Field(0) - - // Special case to cope with malformed messages gracefully: - // If the value in the oneof is a nil pointer, don't panic - // in writeAny. - if fv.Kind() == reflect.Ptr && fv.IsNil() { - // Use errors.New so writeAny won't render quotes. - msg := errors.New("/* nil */") - fv = reflect.ValueOf(&msg).Elem() - } - } - } - - if err := writeName(w, props); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - if b, ok := fv.Interface().(raw); ok { - if err := writeRaw(w, b.Bytes()); err != nil { - return err - } - continue - } - - if len(props.Enum) > 0 { - if err := tm.writeEnum(w, fv, props); err != nil { - return err - } - } else if err := tm.writeAny(w, fv, props); err != nil { - return err - } - - if err := w.WriteByte('\n'); err != nil { - return err - } - } - - // Extensions (the XXX_extensions field). - pv := sv - if pv.CanAddr() { - pv = sv.Addr() - } else { - pv = reflect.New(sv.Type()) - pv.Elem().Set(sv) - } - if pv.Type().Implements(extensionRangeType) { - if err := tm.writeExtensions(w, pv); err != nil { - return err - } - } - - return nil -} - -// writeRaw writes an uninterpreted raw message. -func writeRaw(w *textWriter, b []byte) error { - if err := w.WriteByte('<'); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - if err := writeUnknownStruct(w, b); err != nil { - return err - } - w.unindent() - if err := w.WriteByte('>'); err != nil { - return err - } - return nil -} - -// writeAny writes an arbitrary field. -func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { - v = reflect.Indirect(v) - - if props != nil { - if len(props.CustomType) > 0 { - custom, ok := v.Interface().(Marshaler) - if ok { - data, err := custom.Marshal() - if err != nil { - return err - } - if err := writeString(w, string(data)); err != nil { - return err - } - return nil - } - } else if len(props.CastType) > 0 { - if _, ok := v.Interface().(interface { - String() string - }); ok { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - _, err := fmt.Fprintf(w, "%d", v.Interface()) - return err - } - } - } else if props.StdTime { - t, ok := v.Interface().(time.Time) - if !ok { - return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface()) - } - tproto, err := timestampProto(t) - if err != nil { - return err - } - propsCopy := *props // Make a copy so that this is goroutine-safe - propsCopy.StdTime = false - err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy) - return err - } else if props.StdDuration { - d, ok := v.Interface().(time.Duration) - if !ok { - return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface()) - } - dproto := durationProto(d) - propsCopy := *props // Make a copy so that this is goroutine-safe - propsCopy.StdDuration = false - err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy) - return err - } - } - - // Floats have special cases. - if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { - x := v.Float() - var b []byte - switch { - case math.IsInf(x, 1): - b = posInf - case math.IsInf(x, -1): - b = negInf - case math.IsNaN(x): - b = nan - } - if b != nil { - _, err := w.Write(b) - return err - } - // Other values are handled below. - } - - // We don't attempt to serialise every possible value type; only those - // that can occur in protocol buffers. - switch v.Kind() { - case reflect.Slice: - // Should only be a []byte; repeated fields are handled in writeStruct. - if err := writeString(w, string(v.Bytes())); err != nil { - return err - } - case reflect.String: - if err := writeString(w, v.String()); err != nil { - return err - } - case reflect.Struct: - // Required/optional group/message. - var bra, ket byte = '<', '>' - if props != nil && props.Wire == "group" { - bra, ket = '{', '}' - } - if err := w.WriteByte(bra); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - if etm, ok := v.Interface().(encoding.TextMarshaler); ok { - text, err := etm.MarshalText() - if err != nil { - return err - } - if _, err = w.Write(text); err != nil { - return err - } - } else if err := tm.writeStruct(w, v); err != nil { - return err - } - w.unindent() - if err := w.WriteByte(ket); err != nil { - return err - } - default: - _, err := fmt.Fprint(w, v.Interface()) - return err - } - return nil -} - -// equivalent to C's isprint. -func isprint(c byte) bool { - return c >= 0x20 && c < 0x7f -} - -// writeString writes a string in the protocol buffer text format. -// It is similar to strconv.Quote except we don't use Go escape sequences, -// we treat the string as a byte sequence, and we use octal escapes. -// These differences are to maintain interoperability with the other -// languages' implementations of the text format. -func writeString(w *textWriter, s string) error { - // use WriteByte here to get any needed indent - if err := w.WriteByte('"'); err != nil { - return err - } - // Loop over the bytes, not the runes. - for i := 0; i < len(s); i++ { - var err error - // Divergence from C++: we don't escape apostrophes. - // There's no need to escape them, and the C++ parser - // copes with a naked apostrophe. - switch c := s[i]; c { - case '\n': - _, err = w.w.Write(backslashN) - case '\r': - _, err = w.w.Write(backslashR) - case '\t': - _, err = w.w.Write(backslashT) - case '"': - _, err = w.w.Write(backslashDQ) - case '\\': - _, err = w.w.Write(backslashBS) - default: - if isprint(c) { - err = w.w.WriteByte(c) - } else { - _, err = fmt.Fprintf(w.w, "\\%03o", c) - } - } - if err != nil { - return err - } - } - return w.WriteByte('"') -} - -func writeUnknownStruct(w *textWriter, data []byte) (err error) { - if !w.compact { - if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { - return err - } - } - b := NewBuffer(data) - for b.index < len(b.buf) { - x, err := b.DecodeVarint() - if err != nil { - _, ferr := fmt.Fprintf(w, "/* %v */\n", err) - return ferr - } - wire, tag := x&7, x>>3 - if wire == WireEndGroup { - w.unindent() - if _, werr := w.Write(endBraceNewline); werr != nil { - return werr - } - continue - } - if _, ferr := fmt.Fprint(w, tag); ferr != nil { - return ferr - } - if wire != WireStartGroup { - if err = w.WriteByte(':'); err != nil { - return err - } - } - if !w.compact || wire == WireStartGroup { - if err = w.WriteByte(' '); err != nil { - return err - } - } - switch wire { - case WireBytes: - buf, e := b.DecodeRawBytes(false) - if e == nil { - _, err = fmt.Fprintf(w, "%q", buf) - } else { - _, err = fmt.Fprintf(w, "/* %v */", e) - } - case WireFixed32: - x, err = b.DecodeFixed32() - err = writeUnknownInt(w, x, err) - case WireFixed64: - x, err = b.DecodeFixed64() - err = writeUnknownInt(w, x, err) - case WireStartGroup: - err = w.WriteByte('{') - w.indent() - case WireVarint: - x, err = b.DecodeVarint() - err = writeUnknownInt(w, x, err) - default: - _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) - } - if err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - } - return nil -} - -func writeUnknownInt(w *textWriter, x uint64, err error) error { - if err == nil { - _, err = fmt.Fprint(w, x) - } else { - _, err = fmt.Fprintf(w, "/* %v */", err) - } - return err -} - -type int32Slice []int32 - -func (s int32Slice) Len() int { return len(s) } -func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } -func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// writeExtensions writes all the extensions in pv. -// pv is assumed to be a pointer to a protocol message struct that is extendable. -func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { - emap := extensionMaps[pv.Type().Elem()] - e := pv.Interface().(Message) - - var m map[int32]Extension - var mu sync.Locker - if em, ok := e.(extensionsBytes); ok { - eb := em.GetExtensions() - var err error - m, err = BytesToExtensionsMap(*eb) - if err != nil { - return err - } - mu = notLocker{} - } else if _, ok := e.(extendableProto); ok { - ep, _ := extendable(e) - m, mu = ep.extensionsRead() - if m == nil { - return nil - } - } - - // Order the extensions by ID. - // This isn't strictly necessary, but it will give us - // canonical output, which will also make testing easier. - - mu.Lock() - ids := make([]int32, 0, len(m)) - for id := range m { - ids = append(ids, id) - } - sort.Sort(int32Slice(ids)) - mu.Unlock() - - for _, extNum := range ids { - ext := m[extNum] - var desc *ExtensionDesc - if emap != nil { - desc = emap[extNum] - } - if desc == nil { - // Unknown extension. - if err := writeUnknownStruct(w, ext.enc); err != nil { - return err - } - continue - } - - pb, err := GetExtension(e, desc) - if err != nil { - return fmt.Errorf("failed getting extension: %v", err) - } - - // Repeated extensions will appear as a slice. - if !desc.repeated() { - if err := tm.writeExtension(w, desc.Name, pb); err != nil { - return err - } - } else { - v := reflect.ValueOf(pb) - for i := 0; i < v.Len(); i++ { - if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { - return err - } - } - } - } - return nil -} - -func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { - if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { - return err - } - if err := w.WriteByte('\n'); err != nil { - return err - } - return nil -} - -func (w *textWriter) writeIndent() { - if !w.complete { - return - } - remain := w.ind * 2 - for remain > 0 { - n := remain - if n > len(spaces) { - n = len(spaces) - } - w.w.Write(spaces[:n]) - remain -= n - } - w.complete = false -} - -// TextMarshaler is a configurable text format marshaler. -type TextMarshaler struct { - Compact bool // use compact text format (one line). - ExpandAny bool // expand google.protobuf.Any messages of known types -} - -// Marshal writes a given protocol buffer in text format. -// The only errors returned are from w. -func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { - val := reflect.ValueOf(pb) - if pb == nil || val.IsNil() { - w.Write([]byte("")) - return nil - } - var bw *bufio.Writer - ww, ok := w.(writer) - if !ok { - bw = bufio.NewWriter(w) - ww = bw - } - aw := &textWriter{ - w: ww, - complete: true, - compact: tm.Compact, - } - - if etm, ok := pb.(encoding.TextMarshaler); ok { - text, err := etm.MarshalText() - if err != nil { - return err - } - if _, err = aw.Write(text); err != nil { - return err - } - if bw != nil { - return bw.Flush() - } - return nil - } - // Dereference the received pointer so we don't have outer < and >. - v := reflect.Indirect(val) - if err := tm.writeStruct(aw, v); err != nil { - return err - } - if bw != nil { - return bw.Flush() - } - return nil -} - -// Text is the same as Marshal, but returns the string directly. -func (tm *TextMarshaler) Text(pb Message) string { - var buf bytes.Buffer - tm.Marshal(&buf, pb) - return buf.String() -} - -var ( - defaultTextMarshaler = TextMarshaler{} - compactTextMarshaler = TextMarshaler{Compact: true} -) - -// TODO: consider removing some of the Marshal functions below. - -// MarshalText writes a given protocol buffer in text format. -// The only errors returned are from w. -func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } - -// MarshalTextString is the same as MarshalText, but returns the string directly. -func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } - -// CompactText writes a given protocol buffer in compact text format (one line). -func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } - -// CompactTextString is the same as CompactText, but returns the string directly. -func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/vendor/github.com/gogo/protobuf/proto/text_gogo.go b/vendor/github.com/gogo/protobuf/proto/text_gogo.go deleted file mode 100644 index 1d6c6aa0e4..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/text_gogo.go +++ /dev/null @@ -1,57 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "fmt" - "reflect" -) - -func (tm *TextMarshaler) writeEnum(w *textWriter, v reflect.Value, props *Properties) error { - m, ok := enumStringMaps[props.Enum] - if !ok { - if err := tm.writeAny(w, v, props); err != nil { - return err - } - } - key := int32(0) - if v.Kind() == reflect.Ptr { - key = int32(v.Elem().Int()) - } else { - key = int32(v.Int()) - } - s, ok := m[key] - if !ok { - if err := tm.writeAny(w, v, props); err != nil { - return err - } - } - _, err := fmt.Fprint(w, s) - return err -} diff --git a/vendor/github.com/gogo/protobuf/proto/text_parser.go b/vendor/github.com/gogo/protobuf/proto/text_parser.go deleted file mode 100644 index f1276729a3..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/text_parser.go +++ /dev/null @@ -1,1013 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -// Functions for parsing the Text protocol buffer format. -// TODO: message sets. - -import ( - "encoding" - "errors" - "fmt" - "reflect" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -// Error string emitted when deserializing Any and fields are already set -const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" - -type ParseError struct { - Message string - Line int // 1-based line number - Offset int // 0-based byte offset from start of input -} - -func (p *ParseError) Error() string { - if p.Line == 1 { - // show offset only for first line - return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) - } - return fmt.Sprintf("line %d: %v", p.Line, p.Message) -} - -type token struct { - value string - err *ParseError - line int // line number - offset int // byte number from start of input, not start of line - unquoted string // the unquoted version of value, if it was a quoted string -} - -func (t *token) String() string { - if t.err == nil { - return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) - } - return fmt.Sprintf("parse error: %v", t.err) -} - -type textParser struct { - s string // remaining input - done bool // whether the parsing is finished (success or error) - backed bool // whether back() was called - offset, line int - cur token -} - -func newTextParser(s string) *textParser { - p := new(textParser) - p.s = s - p.line = 1 - p.cur.line = 1 - return p -} - -func (p *textParser) errorf(format string, a ...interface{}) *ParseError { - pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} - p.cur.err = pe - p.done = true - return pe -} - -// Numbers and identifiers are matched by [-+._A-Za-z0-9] -func isIdentOrNumberChar(c byte) bool { - switch { - case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': - return true - case '0' <= c && c <= '9': - return true - } - switch c { - case '-', '+', '.', '_': - return true - } - return false -} - -func isWhitespace(c byte) bool { - switch c { - case ' ', '\t', '\n', '\r': - return true - } - return false -} - -func isQuote(c byte) bool { - switch c { - case '"', '\'': - return true - } - return false -} - -func (p *textParser) skipWhitespace() { - i := 0 - for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { - if p.s[i] == '#' { - // comment; skip to end of line or input - for i < len(p.s) && p.s[i] != '\n' { - i++ - } - if i == len(p.s) { - break - } - } - if p.s[i] == '\n' { - p.line++ - } - i++ - } - p.offset += i - p.s = p.s[i:len(p.s)] - if len(p.s) == 0 { - p.done = true - } -} - -func (p *textParser) advance() { - // Skip whitespace - p.skipWhitespace() - if p.done { - return - } - - // Start of non-whitespace - p.cur.err = nil - p.cur.offset, p.cur.line = p.offset, p.line - p.cur.unquoted = "" - switch p.s[0] { - case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': - // Single symbol - p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] - case '"', '\'': - // Quoted string - i := 1 - for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { - if p.s[i] == '\\' && i+1 < len(p.s) { - // skip escaped char - i++ - } - i++ - } - if i >= len(p.s) || p.s[i] != p.s[0] { - p.errorf("unmatched quote") - return - } - unq, err := unquoteC(p.s[1:i], rune(p.s[0])) - if err != nil { - p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) - return - } - p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] - p.cur.unquoted = unq - default: - i := 0 - for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { - i++ - } - if i == 0 { - p.errorf("unexpected byte %#x", p.s[0]) - return - } - p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] - } - p.offset += len(p.cur.value) -} - -var ( - errBadUTF8 = errors.New("proto: bad UTF-8") - errBadHex = errors.New("proto: bad hexadecimal") -) - -func unquoteC(s string, quote rune) (string, error) { - // This is based on C++'s tokenizer.cc. - // Despite its name, this is *not* parsing C syntax. - // For instance, "\0" is an invalid quoted string. - - // Avoid allocation in trivial cases. - simple := true - for _, r := range s { - if r == '\\' || r == quote { - simple = false - break - } - } - if simple { - return s, nil - } - - buf := make([]byte, 0, 3*len(s)/2) - for len(s) > 0 { - r, n := utf8.DecodeRuneInString(s) - if r == utf8.RuneError && n == 1 { - return "", errBadUTF8 - } - s = s[n:] - if r != '\\' { - if r < utf8.RuneSelf { - buf = append(buf, byte(r)) - } else { - buf = append(buf, string(r)...) - } - continue - } - - ch, tail, err := unescape(s) - if err != nil { - return "", err - } - buf = append(buf, ch...) - s = tail - } - return string(buf), nil -} - -func unescape(s string) (ch string, tail string, err error) { - r, n := utf8.DecodeRuneInString(s) - if r == utf8.RuneError && n == 1 { - return "", "", errBadUTF8 - } - s = s[n:] - switch r { - case 'a': - return "\a", s, nil - case 'b': - return "\b", s, nil - case 'f': - return "\f", s, nil - case 'n': - return "\n", s, nil - case 'r': - return "\r", s, nil - case 't': - return "\t", s, nil - case 'v': - return "\v", s, nil - case '?': - return "?", s, nil // trigraph workaround - case '\'', '"', '\\': - return string(r), s, nil - case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': - if len(s) < 2 { - return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) - } - base := 8 - ss := s[:2] - s = s[2:] - if r == 'x' || r == 'X' { - base = 16 - } else { - ss = string(r) + ss - } - i, err := strconv.ParseUint(ss, base, 8) - if err != nil { - return "", "", err - } - return string([]byte{byte(i)}), s, nil - case 'u', 'U': - n := 4 - if r == 'U' { - n = 8 - } - if len(s) < n { - return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) - } - - bs := make([]byte, n/2) - for i := 0; i < n; i += 2 { - a, ok1 := unhex(s[i]) - b, ok2 := unhex(s[i+1]) - if !ok1 || !ok2 { - return "", "", errBadHex - } - bs[i/2] = a<<4 | b - } - s = s[n:] - return string(bs), s, nil - } - return "", "", fmt.Errorf(`unknown escape \%c`, r) -} - -// Adapted from src/pkg/strconv/quote.go. -func unhex(b byte) (v byte, ok bool) { - switch { - case '0' <= b && b <= '9': - return b - '0', true - case 'a' <= b && b <= 'f': - return b - 'a' + 10, true - case 'A' <= b && b <= 'F': - return b - 'A' + 10, true - } - return 0, false -} - -// Back off the parser by one token. Can only be done between calls to next(). -// It makes the next advance() a no-op. -func (p *textParser) back() { p.backed = true } - -// Advances the parser and returns the new current token. -func (p *textParser) next() *token { - if p.backed || p.done { - p.backed = false - return &p.cur - } - p.advance() - if p.done { - p.cur.value = "" - } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { - // Look for multiple quoted strings separated by whitespace, - // and concatenate them. - cat := p.cur - for { - p.skipWhitespace() - if p.done || !isQuote(p.s[0]) { - break - } - p.advance() - if p.cur.err != nil { - return &p.cur - } - cat.value += " " + p.cur.value - cat.unquoted += p.cur.unquoted - } - p.done = false // parser may have seen EOF, but we want to return cat - p.cur = cat - } - return &p.cur -} - -func (p *textParser) consumeToken(s string) error { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value != s { - p.back() - return p.errorf("expected %q, found %q", s, tok.value) - } - return nil -} - -// Return a RequiredNotSetError indicating which required field was not set. -func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { - st := sv.Type() - sprops := GetProperties(st) - for i := 0; i < st.NumField(); i++ { - if !isNil(sv.Field(i)) { - continue - } - - props := sprops.Prop[i] - if props.Required { - return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} - } - } - return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen -} - -// Returns the index in the struct for the named field, as well as the parsed tag properties. -func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { - i, ok := sprops.decoderOrigNames[name] - if ok { - return i, sprops.Prop[i], true - } - return -1, nil, false -} - -// Consume a ':' from the input stream (if the next token is a colon), -// returning an error if a colon is needed but not present. -func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value != ":" { - // Colon is optional when the field is a group or message. - needColon := true - switch props.Wire { - case "group": - needColon = false - case "bytes": - // A "bytes" field is either a message, a string, or a repeated field; - // those three become *T, *string and []T respectively, so we can check for - // this field being a pointer to a non-string. - if typ.Kind() == reflect.Ptr { - // *T or *string - if typ.Elem().Kind() == reflect.String { - break - } - } else if typ.Kind() == reflect.Slice { - // []T or []*T - if typ.Elem().Kind() != reflect.Ptr { - break - } - } else if typ.Kind() == reflect.String { - // The proto3 exception is for a string field, - // which requires a colon. - break - } - needColon = false - } - if needColon { - return p.errorf("expected ':', found %q", tok.value) - } - p.back() - } - return nil -} - -func (p *textParser) readStruct(sv reflect.Value, terminator string) error { - st := sv.Type() - sprops := GetProperties(st) - reqCount := sprops.reqCount - var reqFieldErr error - fieldSet := make(map[string]bool) - // A struct is a sequence of "name: value", terminated by one of - // '>' or '}', or the end of the input. A name may also be - // "[extension]" or "[type/url]". - // - // The whole struct can also be an expanded Any message, like: - // [type/url] < ... struct contents ... > - for { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value == terminator { - break - } - if tok.value == "[" { - // Looks like an extension or an Any. - // - // TODO: Check whether we need to handle - // namespace rooted names (e.g. ".something.Foo"). - extName, err := p.consumeExtName() - if err != nil { - return err - } - - if s := strings.LastIndex(extName, "/"); s >= 0 { - // If it contains a slash, it's an Any type URL. - messageName := extName[s+1:] - mt := MessageType(messageName) - if mt == nil { - return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) - } - tok = p.next() - if tok.err != nil { - return tok.err - } - // consume an optional colon - if tok.value == ":" { - tok = p.next() - if tok.err != nil { - return tok.err - } - } - var terminator string - switch tok.value { - case "<": - terminator = ">" - case "{": - terminator = "}" - default: - return p.errorf("expected '{' or '<', found %q", tok.value) - } - v := reflect.New(mt.Elem()) - if pe := p.readStruct(v.Elem(), terminator); pe != nil { - return pe - } - b, err := Marshal(v.Interface().(Message)) - if err != nil { - return p.errorf("failed to marshal message of type %q: %v", messageName, err) - } - if fieldSet["type_url"] { - return p.errorf(anyRepeatedlyUnpacked, "type_url") - } - if fieldSet["value"] { - return p.errorf(anyRepeatedlyUnpacked, "value") - } - sv.FieldByName("TypeUrl").SetString(extName) - sv.FieldByName("Value").SetBytes(b) - fieldSet["type_url"] = true - fieldSet["value"] = true - continue - } - - var desc *ExtensionDesc - // This could be faster, but it's functional. - // TODO: Do something smarter than a linear scan. - for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { - if d.Name == extName { - desc = d - break - } - } - if desc == nil { - return p.errorf("unrecognized extension %q", extName) - } - - props := &Properties{} - props.Parse(desc.Tag) - - typ := reflect.TypeOf(desc.ExtensionType) - if err := p.checkForColon(props, typ); err != nil { - return err - } - - rep := desc.repeated() - - // Read the extension structure, and set it in - // the value we're constructing. - var ext reflect.Value - if !rep { - ext = reflect.New(typ).Elem() - } else { - ext = reflect.New(typ.Elem()).Elem() - } - if err := p.readAny(ext, props); err != nil { - if _, ok := err.(*RequiredNotSetError); !ok { - return err - } - reqFieldErr = err - } - ep := sv.Addr().Interface().(Message) - if !rep { - SetExtension(ep, desc, ext.Interface()) - } else { - old, err := GetExtension(ep, desc) - var sl reflect.Value - if err == nil { - sl = reflect.ValueOf(old) // existing slice - } else { - sl = reflect.MakeSlice(typ, 0, 1) - } - sl = reflect.Append(sl, ext) - SetExtension(ep, desc, sl.Interface()) - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - continue - } - - // This is a normal, non-extension field. - name := tok.value - var dst reflect.Value - fi, props, ok := structFieldByName(sprops, name) - if ok { - dst = sv.Field(fi) - } else if oop, ok := sprops.OneofTypes[name]; ok { - // It is a oneof. - props = oop.Prop - nv := reflect.New(oop.Type.Elem()) - dst = nv.Elem().Field(0) - field := sv.Field(oop.Field) - if !field.IsNil() { - return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) - } - field.Set(nv) - } - if !dst.IsValid() { - return p.errorf("unknown field name %q in %v", name, st) - } - - if dst.Kind() == reflect.Map { - // Consume any colon. - if err := p.checkForColon(props, dst.Type()); err != nil { - return err - } - - // Construct the map if it doesn't already exist. - if dst.IsNil() { - dst.Set(reflect.MakeMap(dst.Type())) - } - key := reflect.New(dst.Type().Key()).Elem() - val := reflect.New(dst.Type().Elem()).Elem() - - // The map entry should be this sequence of tokens: - // < key : KEY value : VALUE > - // However, implementations may omit key or value, and technically - // we should support them in any order. See b/28924776 for a time - // this went wrong. - - tok := p.next() - var terminator string - switch tok.value { - case "<": - terminator = ">" - case "{": - terminator = "}" - default: - return p.errorf("expected '{' or '<', found %q", tok.value) - } - for { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value == terminator { - break - } - switch tok.value { - case "key": - if err := p.consumeToken(":"); err != nil { - return err - } - if err := p.readAny(key, props.mkeyprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - case "value": - if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { - return err - } - if err := p.readAny(val, props.mvalprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - default: - p.back() - return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) - } - } - - dst.SetMapIndex(key, val) - continue - } - - // Check that it's not already set if it's not a repeated field. - if !props.Repeated && fieldSet[name] { - return p.errorf("non-repeated field %q was repeated", name) - } - - if err := p.checkForColon(props, dst.Type()); err != nil { - return err - } - - // Parse into the field. - fieldSet[name] = true - if err := p.readAny(dst, props); err != nil { - if _, ok := err.(*RequiredNotSetError); !ok { - return err - } - reqFieldErr = err - } - if props.Required { - reqCount-- - } - - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - - } - - if reqCount > 0 { - return p.missingRequiredFieldError(sv) - } - return reqFieldErr -} - -// consumeExtName consumes extension name or expanded Any type URL and the -// following ']'. It returns the name or URL consumed. -func (p *textParser) consumeExtName() (string, error) { - tok := p.next() - if tok.err != nil { - return "", tok.err - } - - // If extension name or type url is quoted, it's a single token. - if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { - name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) - if err != nil { - return "", err - } - return name, p.consumeToken("]") - } - - // Consume everything up to "]" - var parts []string - for tok.value != "]" { - parts = append(parts, tok.value) - tok = p.next() - if tok.err != nil { - return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) - } - } - return strings.Join(parts, ""), nil -} - -// consumeOptionalSeparator consumes an optional semicolon or comma. -// It is used in readStruct to provide backward compatibility. -func (p *textParser) consumeOptionalSeparator() error { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value != ";" && tok.value != "," { - p.back() - } - return nil -} - -func (p *textParser) readAny(v reflect.Value, props *Properties) error { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value == "" { - return p.errorf("unexpected EOF") - } - if len(props.CustomType) > 0 { - if props.Repeated { - t := reflect.TypeOf(v.Interface()) - if t.Kind() == reflect.Slice { - tc := reflect.TypeOf(new(Marshaler)) - ok := t.Elem().Implements(tc.Elem()) - if ok { - fv := v - flen := fv.Len() - if flen == fv.Cap() { - nav := reflect.MakeSlice(v.Type(), flen, 2*flen+1) - reflect.Copy(nav, fv) - fv.Set(nav) - } - fv.SetLen(flen + 1) - - // Read one. - p.back() - return p.readAny(fv.Index(flen), props) - } - } - } - if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { - custom := reflect.New(props.ctype.Elem()).Interface().(Unmarshaler) - err := custom.Unmarshal([]byte(tok.unquoted)) - if err != nil { - return p.errorf("%v %v: %v", err, v.Type(), tok.value) - } - v.Set(reflect.ValueOf(custom)) - } else { - custom := reflect.New(reflect.TypeOf(v.Interface())).Interface().(Unmarshaler) - err := custom.Unmarshal([]byte(tok.unquoted)) - if err != nil { - return p.errorf("%v %v: %v", err, v.Type(), tok.value) - } - v.Set(reflect.Indirect(reflect.ValueOf(custom))) - } - return nil - } - if props.StdTime { - fv := v - p.back() - props.StdTime = false - tproto := ×tamp{} - err := p.readAny(reflect.ValueOf(tproto).Elem(), props) - props.StdTime = true - if err != nil { - return err - } - tim, err := timestampFromProto(tproto) - if err != nil { - return err - } - if props.Repeated { - t := reflect.TypeOf(v.Interface()) - if t.Kind() == reflect.Slice { - if t.Elem().Kind() == reflect.Ptr { - ts := fv.Interface().([]*time.Time) - ts = append(ts, &tim) - fv.Set(reflect.ValueOf(ts)) - return nil - } else { - ts := fv.Interface().([]time.Time) - ts = append(ts, tim) - fv.Set(reflect.ValueOf(ts)) - return nil - } - } - } - if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { - v.Set(reflect.ValueOf(&tim)) - } else { - v.Set(reflect.Indirect(reflect.ValueOf(&tim))) - } - return nil - } - if props.StdDuration { - fv := v - p.back() - props.StdDuration = false - dproto := &duration{} - err := p.readAny(reflect.ValueOf(dproto).Elem(), props) - props.StdDuration = true - if err != nil { - return err - } - dur, err := durationFromProto(dproto) - if err != nil { - return err - } - if props.Repeated { - t := reflect.TypeOf(v.Interface()) - if t.Kind() == reflect.Slice { - if t.Elem().Kind() == reflect.Ptr { - ds := fv.Interface().([]*time.Duration) - ds = append(ds, &dur) - fv.Set(reflect.ValueOf(ds)) - return nil - } else { - ds := fv.Interface().([]time.Duration) - ds = append(ds, dur) - fv.Set(reflect.ValueOf(ds)) - return nil - } - } - } - if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { - v.Set(reflect.ValueOf(&dur)) - } else { - v.Set(reflect.Indirect(reflect.ValueOf(&dur))) - } - return nil - } - switch fv := v; fv.Kind() { - case reflect.Slice: - at := v.Type() - if at.Elem().Kind() == reflect.Uint8 { - // Special case for []byte - if tok.value[0] != '"' && tok.value[0] != '\'' { - // Deliberately written out here, as the error after - // this switch statement would write "invalid []byte: ...", - // which is not as user-friendly. - return p.errorf("invalid string: %v", tok.value) - } - bytes := []byte(tok.unquoted) - fv.Set(reflect.ValueOf(bytes)) - return nil - } - // Repeated field. - if tok.value == "[" { - // Repeated field with list notation, like [1,2,3]. - for { - fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) - err := p.readAny(fv.Index(fv.Len()-1), props) - if err != nil { - return err - } - ntok := p.next() - if ntok.err != nil { - return ntok.err - } - if ntok.value == "]" { - break - } - if ntok.value != "," { - return p.errorf("Expected ']' or ',' found %q", ntok.value) - } - } - return nil - } - // One value of the repeated field. - p.back() - fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) - return p.readAny(fv.Index(fv.Len()-1), props) - case reflect.Bool: - // true/1/t/True or false/f/0/False. - switch tok.value { - case "true", "1", "t", "True": - fv.SetBool(true) - return nil - case "false", "0", "f", "False": - fv.SetBool(false) - return nil - } - case reflect.Float32, reflect.Float64: - v := tok.value - // Ignore 'f' for compatibility with output generated by C++, but don't - // remove 'f' when the value is "-inf" or "inf". - if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { - v = v[:len(v)-1] - } - if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { - fv.SetFloat(f) - return nil - } - case reflect.Int32: - if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { - fv.SetInt(x) - return nil - } - - if len(props.Enum) == 0 { - break - } - m, ok := enumValueMaps[props.Enum] - if !ok { - break - } - x, ok := m[tok.value] - if !ok { - break - } - fv.SetInt(int64(x)) - return nil - case reflect.Int64: - if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { - fv.SetInt(x) - return nil - } - - case reflect.Ptr: - // A basic field (indirected through pointer), or a repeated message/group - p.back() - fv.Set(reflect.New(fv.Type().Elem())) - return p.readAny(fv.Elem(), props) - case reflect.String: - if tok.value[0] == '"' || tok.value[0] == '\'' { - fv.SetString(tok.unquoted) - return nil - } - case reflect.Struct: - var terminator string - switch tok.value { - case "{": - terminator = "}" - case "<": - terminator = ">" - default: - return p.errorf("expected '{' or '<', found %q", tok.value) - } - // TODO: Handle nested messages which implement encoding.TextUnmarshaler. - return p.readStruct(fv, terminator) - case reflect.Uint32: - if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { - fv.SetUint(x) - return nil - } - case reflect.Uint64: - if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { - fv.SetUint(x) - return nil - } - } - return p.errorf("invalid %v: %v", v.Type(), tok.value) -} - -// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb -// before starting to unmarshal, so any existing data in pb is always removed. -// If a required field is not set and no other error occurs, -// UnmarshalText returns *RequiredNotSetError. -func UnmarshalText(s string, pb Message) error { - if um, ok := pb.(encoding.TextUnmarshaler); ok { - err := um.UnmarshalText([]byte(s)) - return err - } - pb.Reset() - v := reflect.ValueOf(pb) - if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { - return pe - } - return nil -} diff --git a/vendor/github.com/gogo/protobuf/proto/timestamp.go b/vendor/github.com/gogo/protobuf/proto/timestamp.go deleted file mode 100644 index 9324f6542b..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/timestamp.go +++ /dev/null @@ -1,113 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -// This file implements operations on google.protobuf.Timestamp. - -import ( - "errors" - "fmt" - "time" -) - -const ( - // Seconds field of the earliest valid Timestamp. - // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). - minValidSeconds = -62135596800 - // Seconds field just after the latest valid Timestamp. - // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). - maxValidSeconds = 253402300800 -) - -// validateTimestamp determines whether a Timestamp is valid. -// A valid timestamp represents a time in the range -// [0001-01-01, 10000-01-01) and has a Nanos field -// in the range [0, 1e9). -// -// If the Timestamp is valid, validateTimestamp returns nil. -// Otherwise, it returns an error that describes -// the problem. -// -// Every valid Timestamp can be represented by a time.Time, but the converse is not true. -func validateTimestamp(ts *timestamp) error { - if ts == nil { - return errors.New("timestamp: nil Timestamp") - } - if ts.Seconds < minValidSeconds { - return fmt.Errorf("timestamp: %#v before 0001-01-01", ts) - } - if ts.Seconds >= maxValidSeconds { - return fmt.Errorf("timestamp: %#v after 10000-01-01", ts) - } - if ts.Nanos < 0 || ts.Nanos >= 1e9 { - return fmt.Errorf("timestamp: %#v: nanos not in range [0, 1e9)", ts) - } - return nil -} - -// TimestampFromProto converts a google.protobuf.Timestamp proto to a time.Time. -// It returns an error if the argument is invalid. -// -// Unlike most Go functions, if Timestamp returns an error, the first return value -// is not the zero time.Time. Instead, it is the value obtained from the -// time.Unix function when passed the contents of the Timestamp, in the UTC -// locale. This may or may not be a meaningful time; many invalid Timestamps -// do map to valid time.Times. -// -// A nil Timestamp returns an error. The first return value in that case is -// undefined. -func timestampFromProto(ts *timestamp) (time.Time, error) { - // Don't return the zero value on error, because corresponds to a valid - // timestamp. Instead return whatever time.Unix gives us. - var t time.Time - if ts == nil { - t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp - } else { - t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() - } - return t, validateTimestamp(ts) -} - -// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. -// It returns an error if the resulting Timestamp is invalid. -func timestampProto(t time.Time) (*timestamp, error) { - seconds := t.Unix() - nanos := int32(t.Sub(time.Unix(seconds, 0))) - ts := ×tamp{ - Seconds: seconds, - Nanos: nanos, - } - if err := validateTimestamp(ts); err != nil { - return nil, err - } - return ts, nil -} diff --git a/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go b/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go deleted file mode 100644 index d427647436..0000000000 --- a/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go +++ /dev/null @@ -1,229 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copyright (c) 2016, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "reflect" - "time" -) - -var timeType = reflect.TypeOf((*time.Time)(nil)).Elem() - -type timestamp struct { - Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` - Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` -} - -func (m *timestamp) Reset() { *m = timestamp{} } -func (*timestamp) ProtoMessage() {} -func (*timestamp) String() string { return "timestamp" } - -func init() { - RegisterType((*timestamp)(nil), "gogo.protobuf.proto.timestamp") -} - -func (o *Buffer) decTimestamp() (time.Time, error) { - b, err := o.DecodeRawBytes(true) - if err != nil { - return time.Time{}, err - } - tproto := ×tamp{} - if err := Unmarshal(b, tproto); err != nil { - return time.Time{}, err - } - return timestampFromProto(tproto) -} - -func (o *Buffer) dec_time(p *Properties, base structPointer) error { - t, err := o.decTimestamp() - if err != nil { - return err - } - setPtrCustomType(base, p.field, &t) - return nil -} - -func (o *Buffer) dec_ref_time(p *Properties, base structPointer) error { - t, err := o.decTimestamp() - if err != nil { - return err - } - setCustomType(base, p.field, &t) - return nil -} - -func (o *Buffer) dec_slice_time(p *Properties, base structPointer) error { - t, err := o.decTimestamp() - if err != nil { - return err - } - newBas := appendStructPointer(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType))) - var zero field - setPtrCustomType(newBas, zero, &t) - return nil -} - -func (o *Buffer) dec_slice_ref_time(p *Properties, base structPointer) error { - t, err := o.decTimestamp() - if err != nil { - return err - } - newBas := appendStructPointer(base, p.field, reflect.SliceOf(timeType)) - var zero field - setCustomType(newBas, zero, &t) - return nil -} - -func size_time(p *Properties, base structPointer) (n int) { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - tim := structPointer_Interface(structp, timeType).(*time.Time) - t, err := timestampProto(*tim) - if err != nil { - return 0 - } - size := Size(t) - return size + sizeVarint(uint64(size)) + len(p.tagcode) -} - -func (o *Buffer) enc_time(p *Properties, base structPointer) error { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - tim := structPointer_Interface(structp, timeType).(*time.Time) - t, err := timestampProto(*tim) - if err != nil { - return err - } - data, err := Marshal(t) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_ref_time(p *Properties, base structPointer) (n int) { - tim := structPointer_InterfaceAt(base, p.field, timeType).(*time.Time) - t, err := timestampProto(*tim) - if err != nil { - return 0 - } - size := Size(t) - return size + sizeVarint(uint64(size)) + len(p.tagcode) -} - -func (o *Buffer) enc_ref_time(p *Properties, base structPointer) error { - tim := structPointer_InterfaceAt(base, p.field, timeType).(*time.Time) - t, err := timestampProto(*tim) - if err != nil { - return err - } - data, err := Marshal(t) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return nil -} - -func size_slice_time(p *Properties, base structPointer) (n int) { - ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType))).(*[]*time.Time) - tims := *ptims - for i := 0; i < len(tims); i++ { - if tims[i] == nil { - return 0 - } - tproto, err := timestampProto(*tims[i]) - if err != nil { - return 0 - } - size := Size(tproto) - n += len(p.tagcode) + size + sizeVarint(uint64(size)) - } - return n -} - -func (o *Buffer) enc_slice_time(p *Properties, base structPointer) error { - ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType))).(*[]*time.Time) - tims := *ptims - for i := 0; i < len(tims); i++ { - if tims[i] == nil { - return errRepeatedHasNil - } - tproto, err := timestampProto(*tims[i]) - if err != nil { - return err - } - data, err := Marshal(tproto) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - } - return nil -} - -func size_slice_ref_time(p *Properties, base structPointer) (n int) { - ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(timeType)).(*[]time.Time) - tims := *ptims - for i := 0; i < len(tims); i++ { - tproto, err := timestampProto(tims[i]) - if err != nil { - return 0 - } - size := Size(tproto) - n += len(p.tagcode) + size + sizeVarint(uint64(size)) - } - return n -} - -func (o *Buffer) enc_slice_ref_time(p *Properties, base structPointer) error { - ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(timeType)).(*[]time.Time) - tims := *ptims - for i := 0; i < len(tims); i++ { - tproto, err := timestampProto(tims[i]) - if err != nil { - return err - } - data, err := Marshal(tproto) - if err != nil { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - } - return nil -} diff --git a/vendor/github.com/prometheus/client_golang/LICENSE b/vendor/github.com/google/go-containerregistry/LICENSE similarity index 99% rename from vendor/github.com/prometheus/client_golang/LICENSE rename to vendor/github.com/google/go-containerregistry/LICENSE index 261eeb9e9f..7a4a3ea242 100644 --- a/vendor/github.com/prometheus/client_golang/LICENSE +++ b/vendor/github.com/google/go-containerregistry/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -198,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/google/go-containerregistry/authn/anon.go b/vendor/github.com/google/go-containerregistry/authn/anon.go new file mode 100644 index 0000000000..c9c08ec737 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/anon.go @@ -0,0 +1,26 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +// anonymous implements Authenticator for anonymous authentication. +type anonymous struct{} + +// Authorization implements Authenticator. +func (a *anonymous) Authorization() (string, error) { + return "", nil +} + +// Anonymous is a singleton Authenticator for providing anonymous auth. +var Anonymous Authenticator = &anonymous{} diff --git a/vendor/github.com/google/go-containerregistry/authn/auth.go b/vendor/github.com/google/go-containerregistry/authn/auth.go new file mode 100644 index 0000000000..c39ee5a9f9 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/auth.go @@ -0,0 +1,29 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +import ( + "fmt" +) + +// auth implements Authenticator for an "auth" entry of the docker config. +type auth struct { + token string +} + +// Authorization implements Authenticator. +func (a *auth) Authorization() (string, error) { + return fmt.Sprintf("Basic %s", a.token), nil +} diff --git a/vendor/github.com/google/go-containerregistry/authn/authn.go b/vendor/github.com/google/go-containerregistry/authn/authn.go new file mode 100644 index 0000000000..30e935cbc9 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/authn.go @@ -0,0 +1,21 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +// Authenticator is used to authenticate Docker transports. +type Authenticator interface { + // Authorization returns the value to use in an http transport's Authorization header. + Authorization() (string, error) +} diff --git a/vendor/github.com/google/go-containerregistry/authn/basic.go b/vendor/github.com/google/go-containerregistry/authn/basic.go new file mode 100644 index 0000000000..7cd4984069 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/basic.go @@ -0,0 +1,33 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +import ( + "encoding/base64" + "fmt" +) + +// Basic implements Authenticator for basic authentication. +type Basic struct { + Username string + Password string +} + +// Authorization implements Authenticator. +func (b *Basic) Authorization() (string, error) { + delimited := fmt.Sprintf("%s:%s", b.Username, b.Password) + encoded := base64.StdEncoding.EncodeToString([]byte(delimited)) + return fmt.Sprintf("Basic %s", encoded), nil +} diff --git a/vendor/github.com/google/go-containerregistry/authn/bearer.go b/vendor/github.com/google/go-containerregistry/authn/bearer.go new file mode 100644 index 0000000000..cb1ae5845a --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/bearer.go @@ -0,0 +1,29 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +import ( + "fmt" +) + +// Bearer implements Authenticator for bearer authentication. +type Bearer struct { + Token string `json:"token"` +} + +// Authorization implements Authenticator. +func (b *Bearer) Authorization() (string, error) { + return fmt.Sprintf("Bearer %s", b.Token), nil +} diff --git a/vendor/github.com/google/go-containerregistry/authn/doc.go b/vendor/github.com/google/go-containerregistry/authn/doc.go new file mode 100644 index 0000000000..c2a5fc0267 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/doc.go @@ -0,0 +1,17 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package authn defines different methods of authentication for +// talking to a container registry. +package authn diff --git a/vendor/github.com/google/go-containerregistry/authn/helper.go b/vendor/github.com/google/go-containerregistry/authn/helper.go new file mode 100644 index 0000000000..5b2467ae83 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/helper.go @@ -0,0 +1,94 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +import ( + "bytes" + "encoding/json" + "fmt" + "os/exec" + "strings" + + "github.com/google/go-containerregistry/name" +) + +// magicNotFoundMessage is the string that the CLI special cases to mean +// that a given registry domain wasn't found. +const ( + magicNotFoundMessage = "credentials not found in native keychain" +) + +// runner allows us to swap out how we "Run" os/exec commands. +type runner interface { + Run(*exec.Cmd) error +} + +// defaultRunner implements runner by just calling Run(). +type defaultRunner struct{} + +// Run implements runner. +func (dr *defaultRunner) Run(cmd *exec.Cmd) error { + return cmd.Run() +} + +// helper executes the named credential helper against the given domain. +type helper struct { + name string + domain name.Registry + + // We add this layer of indirection to facilitate unit testing. + r runner +} + +// helperOutput is the expected JSON output form of a credential helper +// (or at least these are the fields that we care about). +type helperOutput struct { + Username string + Secret string +} + +// Authorization implements Authenticator. +func (h *helper) Authorization() (string, error) { + helperName := fmt.Sprintf("docker-credential-%s", h.name) + // We want to execute: + // echo -n {domain} | docker-credential-{name} get + cmd := exec.Command(helperName, "get") + + // Some keychains expect a scheme: + // https://github.com/bazelbuild/rules_docker/issues/111 + cmd.Stdin = strings.NewReader(fmt.Sprintf("https://%v", h.domain)) + + var out bytes.Buffer + cmd.Stdout = &out + if err := h.r.Run(cmd); err != nil { + return "", err + } + output := out.String() + + // If we see this specific message, it means the domain wasn't found + // and we should fall back on anonymous auth. + if output == magicNotFoundMessage { + return Anonymous.Authorization() + } + + // Any other output should be parsed as JSON and the Username / Secret + // fields used for Basic authentication. + ho := helperOutput{} + if err := json.Unmarshal([]byte(output), &ho); err != nil { + return "", err + } + b := Basic{Username: ho.Username, Password: ho.Secret} + return b.Authorization() +} diff --git a/vendor/github.com/google/go-containerregistry/authn/keychain.go b/vendor/github.com/google/go-containerregistry/authn/keychain.go new file mode 100644 index 0000000000..c7c6a15074 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/authn/keychain.go @@ -0,0 +1,140 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authn + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "os/user" + "path" + + "github.com/google/go-containerregistry/name" +) + +// Keychain is an interface for resolving an image reference to a credential. +type Keychain interface { + // Resolve looks up the most appropriate credential for the specified registry. + Resolve(name.Registry) (Authenticator, error) +} + +// defaultKeychain implements Keychain with the semantics of the standard Docker +// credential keychain. +type defaultKeychain struct{} + +// configDir returns the directory containing Docker's config.json +func configDir() (string, error) { + if dc := os.Getenv("DOCKER_CONFIG"); dc != "" { + return dc, nil + } + usr, err := user.Current() + if err != nil { + return "", err + } + return path.Join(usr.HomeDir, ".docker"), nil +} + +// authEntry is a helper for JSON parsing an "auth" entry of config.json +// This is not meant for direct consumption. +type authEntry struct { + Auth string `json:"auth"` + Username string `json:"username"` + Password string `json:"password"` +} + +// cfg is a helper for JSON parsing Docker's config.json +// This is not meant for direct consumption. +type cfg struct { + CredHelper map[string]string `json:"credHelpers,omitempty"` + CredStore string `json:"credsStore,omitempty"` + Auths map[string]authEntry `json:"auths,omitempty"` +} + +// There are a variety of ways a domain may get qualified within the Docker credential file. +// We enumerate them here as format strings. +var ( + domainForms = []string{ + // Allow naked domains + "%s", + // Allow scheme-prefixed. + "https://%s", + "http://%s", + // Allow scheme-prefixes with version in url path. + "https://%s/v1/", + "http://%s/v1/", + "https://%s/v2/", + "http://%s/v2/", + } + + // Export an instance of the default keychain. + DefaultKeychain Keychain = &defaultKeychain{} +) + +// Resolve implements Keychain. +func (dk *defaultKeychain) Resolve(reg name.Registry) (Authenticator, error) { + dir, err := configDir() + if err != nil { + log.Printf("Unable to determine config dir, falling back on anonymous: %v", err) + return Anonymous, nil + } + file := path.Join(dir, "config.json") + content, err := ioutil.ReadFile(file) + if err != nil { + log.Printf("Unable to read %q, falling back on anonymous: %v", file, err) + return Anonymous, nil + } + + var cf cfg + if err := json.Unmarshal(content, &cf); err != nil { + log.Printf("Unable to parse %q, falling back on anonymous: %v", file, err) + return Anonymous, nil + } + + // Per-registry credential helpers take precedence. + if cf.CredHelper != nil { + for _, form := range domainForms { + if entry, ok := cf.CredHelper[fmt.Sprintf(form, reg.Name())]; ok { + return &helper{name: entry, domain: reg, r: &defaultRunner{}}, nil + } + } + } + + // A global credential helper is next in precedence. + if cf.CredStore != "" { + return &helper{name: cf.CredStore, domain: reg, r: &defaultRunner{}}, nil + } + + // Lastly, the 'auths' section directly contains basic auth entries. + if cf.Auths != nil { + for _, form := range domainForms { + if entry, ok := cf.Auths[fmt.Sprintf(form, reg.Name())]; ok { + if entry.Auth != "" { + return &auth{entry.Auth}, nil + } else if entry.Username != "" { + return &Basic{Username: entry.Username, Password: entry.Password}, nil + } else { + // TODO(mattmoor): Support identitytoken + // TODO(mattmoor): Support registrytoken + return nil, fmt.Errorf("Unsupported entry in \"auths\" section of %q", file) + } + } + } + } + + log.Printf("No matching credentials found for %v, falling back on anoynmous", reg) + return Anonymous, nil +} diff --git a/vendor/github.com/google/go-containerregistry/name/check.go b/vendor/github.com/google/go-containerregistry/name/check.go new file mode 100644 index 0000000000..01a25d554a --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/check.go @@ -0,0 +1,52 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import ( + "strings" + "unicode/utf8" +) + +// Strictness defines the level of strictness for name validation. +type Strictness int + +// Enums for CRUD operations. +const ( + StrictValidation Strictness = iota + WeakValidation +) + +// stripRunesFn returns a function which returns -1 (i.e. a value which +// signals deletion in strings.Map) for runes in 'runes', and the rune otherwise. +func stripRunesFn(runes string) func(rune) rune { + return func(r rune) rune { + if strings.ContainsRune(runes, r) { + return -1 + } + return r + } +} + +// checkElement checks a given named element matches character and length restrictions. +// Returns true if the given element adheres to the given restrictions, false otherwise. +func checkElement(name, element, allowedRunes string, minRunes, maxRunes int) error { + numRunes := utf8.RuneCountInString(element) + if (numRunes < minRunes) || (maxRunes < numRunes) { + return NewErrBadName("%s must be between %d and %d runes in length: %s", name, minRunes, maxRunes, element) + } else if len(strings.Map(stripRunesFn(allowedRunes), element)) != 0 { + return NewErrBadName("%s can only contain the runes `%s`: %s", name, allowedRunes, element) + } + return nil +} diff --git a/vendor/github.com/google/go-containerregistry/name/digest.go b/vendor/github.com/google/go-containerregistry/name/digest.go new file mode 100644 index 0000000000..ea6287a847 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/digest.go @@ -0,0 +1,91 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package name defines structured types for representing image references. +package name + +import ( + "strings" +) + +const ( + // These have the form: sha256: + // TODO(dekkagaijin): replace with opencontainers/go-digest or docker/distribution's validation. + digestChars = "sh:0123456789abcdef" + digestDelim = "@" +) + +// Digest stores a digest name in a structured form. +type Digest struct { + Repository + digest string +} + +// Ensure Digest implements Reference +var _ Reference = (*Digest)(nil) + +// Context implements Reference. +func (d Digest) Context() Repository { + return d.Repository +} + +// Identifier implements Reference. +func (d Digest) Identifier() string { + return d.DigestStr() +} + +// DigestStr returns the digest component of the Digest. +func (d Digest) DigestStr() string { + return d.digest +} + +// Name returns the name from which the Digest was derived. +func (d Digest) Name() string { + return d.Repository.Name() + digestDelim + d.DigestStr() +} + +func (d Digest) String() string { + return d.Name() +} + +func checkDigest(name string) error { + return checkElement("digest", name, digestChars, 7+64, 7+64) +} + +// NewDigest returns a new Digest representing the given name, according to the given strictness. +func NewDigest(name string, strict Strictness) (Digest, error) { + // Split on "@" + parts := strings.Split(name, digestDelim) + if len(parts) != 2 { + return Digest{}, NewErrBadName("a digest must contain exactly one '@' separator (e.g. registry/repository@digest) saw: %s", name) + } + base := parts[0] + digest := parts[1] + + // We don't require a digest, but if we get one check it's valid, + // even when not being strict. + // If we are being strict, we want to validate the digest regardless in case + // it's empty. + if digest != "" || strict == StrictValidation { + if err := checkDigest(digest); err != nil { + return Digest{}, err + } + } + + repo, err := NewRepository(base, strict) + if err != nil { + return Digest{}, err + } + return Digest{repo, digest}, nil +} diff --git a/vendor/github.com/google/go-containerregistry/name/errors.go b/vendor/github.com/google/go-containerregistry/name/errors.go new file mode 100644 index 0000000000..7847cc5d1e --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/errors.go @@ -0,0 +1,37 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import "fmt" + +// ErrBadName is an error for when a bad docker name is supplied. +type ErrBadName struct { + info string +} + +func (e *ErrBadName) Error() string { + return e.info +} + +// NewErrBadName returns a ErrBadName which returns the given formatted string from Error(). +func NewErrBadName(fmtStr string, args ...interface{}) *ErrBadName { + return &ErrBadName{fmt.Sprintf(fmtStr, args...)} +} + +// IsErrBadName returns true if the given error is an ErrBadName. +func IsErrBadName(err error) bool { + _, ok := err.(*ErrBadName) + return ok +} diff --git a/vendor/github.com/google/go-containerregistry/name/ref.go b/vendor/github.com/google/go-containerregistry/name/ref.go new file mode 100644 index 0000000000..356d79eb69 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/ref.go @@ -0,0 +1,49 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import ( + "errors" + "fmt" +) + +// Reference defines the interface that consumers use when they can +// take either a tag or a digest. +type Reference interface { + fmt.Stringer + + // Context accesses the Repository context of the reference. + Context() Repository + + // Identifier accesses the type-specific portion of the reference. + Identifier() string + + // Name is the fully-qualified reference name. + Name() string + + // Scope is the scope needed to access this reference. + Scope(string) string +} + +// ParseReference parses the string as a reference, either by tag or digest. +func ParseReference(s string, strict Strictness) (Reference, error) { + if t, err := NewTag(s, strict); err == nil { + return t, nil + } + if d, err := NewDigest(s, strict); err == nil { + return d, nil + } + return nil, errors.New("could not parse reference") +} diff --git a/vendor/github.com/google/go-containerregistry/name/registry.go b/vendor/github.com/google/go-containerregistry/name/registry.go new file mode 100644 index 0000000000..6d06cc5fed --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/registry.go @@ -0,0 +1,79 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import "net/url" + +const ( + DefaultRegistry = "index.docker.io" + defaultRegistryAlias = "docker.io" +) + +// Registry stores a docker registry name in a structured form. +type Registry struct { + registry string +} + +// RegistryStr returns the registry component of the Registry. +func (r Registry) RegistryStr() string { + if r.registry != "" { + return r.registry + } + return DefaultRegistry +} + +// Name returns the name from which the Registry was derived. +func (r Registry) Name() string { + return r.RegistryStr() +} + +func (r Registry) String() string { + return r.Name() +} + +// Scope returns the scope required to access the registry. +func (r Registry) Scope(string) string { + // The only resource under 'registry' is 'catalog'. http://goo.gl/N9cN9Z + return "registry:catalog:*" +} + +func checkRegistry(name string) error { + // Per RFC 3986, registries (authorities) are required to be prefixed with "//" + // url.Host == hostname[:port] == authority + if url, err := url.Parse("//" + name); err != nil || url.Host != name { + return NewErrBadName("registries must be valid RFC 3986 URI authorities: %s", name) + } + return nil +} + +// NewRegistry returns a Registry based on the given name. +// Strict validation requires explicit, valid RFC 3986 URI authorities to be given. +func NewRegistry(name string, strict Strictness) (Registry, error) { + if strict == StrictValidation && len(name) == 0 { + return Registry{}, NewErrBadName("strict validation requires the registry to be explicitly defined") + } + + if err := checkRegistry(name); err != nil { + return Registry{}, err + } + + // Rewrite "docker.io" to "index.docker.io". + // See: https://github.com/google/go-containerregistry/issues/68 + if name == defaultRegistryAlias { + name = DefaultRegistry + } + + return Registry{registry: name}, nil +} diff --git a/vendor/github.com/google/go-containerregistry/name/repository.go b/vendor/github.com/google/go-containerregistry/name/repository.go new file mode 100644 index 0000000000..7c296e394a --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/repository.go @@ -0,0 +1,99 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import ( + "fmt" + "strings" +) + +const ( + defaultNamespace = "library" + repositoryChars = "abcdefghijklmnopqrstuvwxyz0123456789_-./" + regRepoDelimiter = "/" +) + +// Repository stores a docker repository name in a structured form. +type Repository struct { + Registry + repository string +} + +// See https://docs.docker.com/docker-hub/official_repos +func hasImplicitNamespace(repo string, reg Registry) bool { + return !strings.ContainsRune(repo, '/') && reg.RegistryStr() == DefaultRegistry +} + +// RepositoryStr returns the repository component of the Repository. +func (r Repository) RepositoryStr() string { + if hasImplicitNamespace(r.repository, r.Registry) { + return fmt.Sprintf("%s/%s", defaultNamespace, r.repository) + } + return r.repository +} + +// Name returns the name from which the Repository was derived. +func (r Repository) Name() string { + regName := r.Registry.Name() + if regName != "" { + return regName + regRepoDelimiter + r.RepositoryStr() + } + return r.RepositoryStr() +} + +func (r Repository) String() string { + return r.Name() +} + +// Scope returns the scope required to perform the given action on the registry. +// TODO(jonjohnsonjr): consider moving scopes to a separate package. +func (r Repository) Scope(action string) string { + return fmt.Sprintf("repository:%s:%s", r.RepositoryStr(), action) +} + +func checkRepository(repository string) error { + return checkElement("repository", repository, repositoryChars, 2, 255) +} + +// NewRepository returns a new Repository representing the given name, according to the given strictness. +func NewRepository(name string, strict Strictness) (Repository, error) { + if len(name) == 0 { + return Repository{}, NewErrBadName("a repository name must be specified") + } + + var registry string + repo := name + parts := strings.SplitN(name, regRepoDelimiter, 2) + if len(parts) == 2 && (strings.ContainsRune(parts[0], '.') || strings.ContainsRune(parts[0], ':')) { + // The first part of the repository is treated as the registry domain + // iff it contains a '.' or ':' character, otherwise it is all repository + // and the domain defaults to DockerHub. + registry = parts[0] + repo = parts[1] + } + + if err := checkRepository(repo); err != nil { + return Repository{}, err + } + + reg, err := NewRegistry(registry, strict) + if err != nil { + return Repository{}, err + } + if hasImplicitNamespace(repo, reg) && strict == StrictValidation { + return Repository{}, NewErrBadName("strict validation requires the full repository path (missing 'library')") + } + return Repository{reg, repo}, nil +} diff --git a/vendor/github.com/google/go-containerregistry/name/tag.go b/vendor/github.com/google/go-containerregistry/name/tag.go new file mode 100644 index 0000000000..cb0e70b177 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/name/tag.go @@ -0,0 +1,99 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package name + +import ( + "strings" +) + +const ( + defaultTag = "latest" + // TODO(dekkagaijin): use the docker/distribution regexes for validation. + tagChars = "abcdefghijklmnopqrstuvwxyz0123456789_-.ABCDEFGHIJKLMNOPQRSTUVWXYZ" + tagDelim = ":" +) + +// Tag stores a docker tag name in a structured form. +type Tag struct { + Repository + tag string +} + +// Ensure Tag implements Reference +var _ Reference = (*Tag)(nil) + +// Context implements Reference. +func (t Tag) Context() Repository { + return t.Repository +} + +// Identifier implements Reference. +func (t Tag) Identifier() string { + return t.TagStr() +} + +// TagStr returns the tag component of the Tag. +func (t Tag) TagStr() string { + if t.tag != "" { + return t.tag + } + return defaultTag +} + +// Name returns the name from which the Tag was derived. +func (t Tag) Name() string { + return t.Repository.Name() + tagDelim + t.TagStr() +} + +func (t Tag) String() string { + return t.Name() +} + +// Scope returns the scope required to perform the given action on the tag. +func (t Tag) Scope(action string) string { + return t.Repository.Scope(action) +} + +func checkTag(name string) error { + return checkElement("tag", name, tagChars, 1, 127) +} + +// NewTag returns a new Tag representing the given name, according to the given strictness. +func NewTag(name string, strict Strictness) (Tag, error) { + base := name + tag := "" + + // Split on ":" + if parts := strings.Split(name, tagDelim); len(parts) >= 2 { + base = strings.Join(parts[:len(parts)-1], tagDelim) + tag = parts[len(parts)-1] + } + + // We don't require a tag, but if we get one check it's valid, + // even when not being strict. + // If we are being strict, we want to validate the tag regardless in case + // it's empty. + if tag != "" || strict == StrictValidation { + if err := checkTag(tag); err != nil { + return Tag{}, err + } + } + + repo, err := NewRepository(base, strict) + if err != nil { + return Tag{}, err + } + return Tag{repo, tag}, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/config.go b/vendor/github.com/google/go-containerregistry/v1/config.go new file mode 100644 index 0000000000..17fa0d20bf --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/config.go @@ -0,0 +1,108 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "encoding/json" + "io" + "time" +) + +// ConfigFile is the configuration file that holds the metadata describing +// how to launch a container. The names of the fields are chosen to reflect +// the JSON payload of the ConfigFile as defined here: https://git.io/vrAEY +type ConfigFile struct { + Architecture string `json:"architecture"` + Container string `json:"container"` + Created Time `json:"created"` + DockerVersion string `json:"docker_version"` + History []History `json:"history"` + OS string `json:"os"` + RootFS RootFS `json:"rootfs"` + Config Config `json:"config"` + ContainerConfig Config `json:"container_config"` + OSVersion string `json:"osversion"` +} + +// History is one entry of a list recording how this container image was built. +type History struct { + Author string `json:"author"` + Created Time `json:"created"` + CreatedBy string `json:"created_by"` + Comment string `json:"comment"` + EmptyLayer bool `json:"empty_layer,omitempty"` +} + +// Time is a wrapper around time.Time to help with deep copying +type Time struct { + time.Time +} + +// DeepCopyInto creates a deep-copy of the Time value. The underlying time.Time +// type is effectively immutable in the time API, so it is safe to +// copy-by-assign, despite the presence of (unexported) Pointer fields. +func (t *Time) DeepCopyInto(out *Time) { + *out = *t +} + +// RootFS holds the ordered list of file system deltas that comprise the +// container image's root filesystem. +type RootFS struct { + Type string `json:"type"` + DiffIDs []Hash `json:"diff_ids"` +} + +// Config is a submessage of the config file described as: +// The execution parameters which SHOULD be used as a base when running +// a container using the image. +// The names of the fields in this message are chosen to reflect the JSON +// payload of the Config as defined here: +// https://git.io/vrAET +// and +// https://github.com/opencontainers/image-spec/blob/master/config.md +type Config struct { + AttachStderr bool + AttachStdin bool + AttachStdout bool + Cmd []string + Domainname string + Entrypoint []string + Env []string + Hostname string + Image string + Labels map[string]string + OnBuild []string + OpenStdin bool + StdinOnce bool + Tty bool + User string + Volumes map[string]struct{} + WorkingDir string + ExposedPorts map[string]struct{} + ArgsEscaped bool + NetworkDisabled bool + MacAddress string + StopSignal string + Shell []string +} + +// ParseConfigFile parses the io.Reader's contents into a ConfigFile. +func ParseConfigFile(r io.Reader) (*ConfigFile, error) { + cf := ConfigFile{} + if err := json.NewDecoder(r).Decode(&cf); err != nil { + return nil, err + } + return &cf, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/doc.go b/vendor/github.com/google/go-containerregistry/v1/doc.go new file mode 100644 index 0000000000..c9b203173e --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/doc.go @@ -0,0 +1,19 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package v1 defines structured types for OCI v1 images +// +k8s:deepcopy-gen=package + +//go:generate deepcopy-gen -O zz_deepcopy_generated --go-header-file $BOILER_PLATE_FILE -i . +package v1 diff --git a/vendor/github.com/prometheus/common/model/model.go b/vendor/github.com/google/go-containerregistry/v1/empty/doc.go similarity index 70% rename from vendor/github.com/prometheus/common/model/model.go rename to vendor/github.com/google/go-containerregistry/v1/empty/doc.go index a7b9691707..1a521e9a74 100644 --- a/vendor/github.com/prometheus/common/model/model.go +++ b/vendor/github.com/google/go-containerregistry/v1/empty/doc.go @@ -1,9 +1,10 @@ -// Copyright 2013 The Prometheus Authors +// Copyright 2018 Google LLC All Rights Reserved. +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -11,6 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package model contains common data structures that are shared across -// Prometheus components and libraries. -package model +// Package empty provides an implementation of v1.Image equivalent to "FROM scratch". +package empty diff --git a/vendor/github.com/google/go-containerregistry/v1/empty/image.go b/vendor/github.com/google/go-containerregistry/v1/empty/image.go new file mode 100644 index 0000000000..78527b8480 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/empty/image.go @@ -0,0 +1,22 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package empty + +import ( + "github.com/google/go-containerregistry/v1/random" +) + +// Image is a singleton empty image, think: FROM scratch. +var Image, _ = random.Image(0, 0) diff --git a/vendor/github.com/google/go-containerregistry/v1/hash.go b/vendor/github.com/google/go-containerregistry/v1/hash.go new file mode 100644 index 0000000000..f0db0d51cf --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/hash.go @@ -0,0 +1,111 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "hash" + "io" + "strconv" + "strings" +) + +// Hash is an unqualified digest of some content, e.g. sha256:deadbeef +type Hash struct { + // Algorithm holds the algorithm used to compute the hash. + Algorithm string + + // Hex holds the hex portion of the content hash. + Hex string +} + +// String reverses NewHash returning the string-form of the hash. +func (h Hash) String() string { + return fmt.Sprintf("%s:%s", h.Algorithm, h.Hex) +} + +// NewHash validates the input string is a hash and returns a strongly type Hash object. +func NewHash(s string) (Hash, error) { + h := Hash{} + if err := h.parse(s); err != nil { + return Hash{}, err + } + return h, nil +} + +// MarshalJSON implements json.Marshaler +func (h *Hash) MarshalJSON() ([]byte, error) { + return json.Marshal(h.String()) +} + +// UnmarshalJSON implements json.Unmarshaler +func (h *Hash) UnmarshalJSON(data []byte) error { + s, err := strconv.Unquote(string(data)) + if err != nil { + return err + } + return h.parse(s) +} + +// Hasher returns a hash.Hash for the named algorithm (e.g. "sha256") +func Hasher(name string) (hash.Hash, error) { + switch name { + case "sha256": + return sha256.New(), nil + default: + return nil, fmt.Errorf("unsupported hash: %q", name) + } +} + +func (h *Hash) parse(unquoted string) error { + parts := strings.Split(unquoted, ":") + if len(parts) != 2 { + return fmt.Errorf("too many parts in hash: %s", unquoted) + } + + rest := strings.TrimLeft(parts[1], "0123456789abcdef") + if len(rest) != 0 { + return fmt.Errorf("found non-hex character in hash: %c", rest[0]) + } + + hasher, err := Hasher(parts[0]) + if err != nil { + return err + } + // Compare the hex to the expected size (2 hex characters per byte) + if len(parts[1]) != hasher.Size()*2 { + return fmt.Errorf("wrong number of hex digits for %s: %s", parts[0], parts[1]) + } + + h.Algorithm = parts[0] + h.Hex = parts[1] + return nil +} + +// SHA256 computes the Hash of the provided io.Reader's content. +func SHA256(r io.Reader) (Hash, int64, error) { + hasher := sha256.New() + n, err := io.Copy(hasher, r) + if err != nil { + return Hash{}, 0, err + } + return Hash{ + Algorithm: "sha256", + Hex: hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))), + }, n, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/image.go b/vendor/github.com/google/go-containerregistry/v1/image.go new file mode 100644 index 0000000000..89d1439637 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/image.go @@ -0,0 +1,58 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "github.com/google/go-containerregistry/v1/types" +) + +// Image defines the interface for interacting with an OCI v1 image. +type Image interface { + // Layers returns the ordered collection of filesystem layers that comprise this image. + // The order of the list is oldest/base layer first, and most-recent/top layer last. + Layers() ([]Layer, error) + + // BlobSet returns an unordered collection of all the blobs in the image. + BlobSet() (map[Hash]struct{}, error) + + // MediaType of this image's manifest. + MediaType() (types.MediaType, error) + + // ConfigName returns the hash of the image's config file. + ConfigName() (Hash, error) + + // ConfigFile returns this image's config file. + ConfigFile() (*ConfigFile, error) + + // RawConfigFile returns the serialized bytes of ConfigFile() + RawConfigFile() ([]byte, error) + + // Digest returns the sha256 of this image's manifest. + Digest() (Hash, error) + + // Manifest returns this image's Manifest object. + Manifest() (*Manifest, error) + + // RawManifest returns the serialized bytes of Manifest() + RawManifest() ([]byte, error) + + // LayerByDigest returns a Layer for interacting with a particular layer of + // the image, looking it up by "digest" (the compressed hash). + LayerByDigest(Hash) (Layer, error) + + // LayerByDiffID is an analog to LayerByDigest, looking up by "diff id" + // (the uncompressed hash). + LayerByDiffID(Hash) (Layer, error) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/layer.go b/vendor/github.com/google/go-containerregistry/v1/layer.go new file mode 100644 index 0000000000..8b5091e45b --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/layer.go @@ -0,0 +1,37 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "io" +) + +// Layer is an interface for accessing the properties of a particular layer of a v1.Image +type Layer interface { + // Digest returns the Hash of the compressed layer. + Digest() (Hash, error) + + // DiffID returns the Hash of the uncompressed layer. + DiffID() (Hash, error) + + // Compressed returns an io.ReadCloser for the compressed layer contents. + Compressed() (io.ReadCloser, error) + + // Uncompressed returns an io.ReadCloser for the uncompressed layer contents. + Uncompressed() (io.ReadCloser, error) + + // Size returns the compressed size of the Layer. + Size() (int64, error) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/manifest.go b/vendor/github.com/google/go-containerregistry/v1/manifest.go new file mode 100644 index 0000000000..79c9b05291 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/manifest.go @@ -0,0 +1,49 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "encoding/json" + "io" + + "github.com/google/go-containerregistry/v1/types" +) + +// Manifest represents the OCI image manifest in a structured way. +type Manifest struct { + SchemaVersion int64 `json:"schemaVersion"` + MediaType types.MediaType `json:"mediaType"` + Config Descriptor `json:"config"` + Layers []Descriptor `json:"layers"` + Annotations map[string]string `json:"annotations,omitempty"` +} + +// Descriptor holds a reference from the manifest to one of its constituent elements. +type Descriptor struct { + MediaType types.MediaType `json:"mediaType"` + Size int64 `json:"size"` + Digest Hash `json:"digest"` + URLs []string `json:"urls,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ParseManifest parses the io.Reader's contents into a Manifest. +func ParseManifest(r io.Reader) (*Manifest, error) { + m := Manifest{} + if err := json.NewDecoder(r).Decode(&m); err != nil { + return nil, err + } + return &m, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/v1/mutate/mutate.go new file mode 100644 index 0000000000..bd8d4258a9 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/mutate/mutate.go @@ -0,0 +1,233 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mutate + +import ( + "encoding/json" + "errors" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/partial" + "github.com/google/go-containerregistry/v1/types" +) + +// Addendum contains layers and history to be appended +// to a base image +type Addendum struct { + Layer v1.Layer + History v1.History +} + +// AppendLayers applies layers to a base image +func AppendLayers(base v1.Image, layers ...v1.Layer) (v1.Image, error) { + additions := make([]Addendum, 0, len(layers)) + for _, layer := range layers { + additions = append(additions, Addendum{Layer: layer}) + } + + return Append(base, additions...) +} + +// Append will apply the list of addendums to the base image +func Append(base v1.Image, adds ...Addendum) (v1.Image, error) { + if len(adds) == 0 { + return base, nil + } + + if err := validate(adds); err != nil { + return nil, err + } + + m, err := base.Manifest() + if err != nil { + return nil, err + } + + cf, err := base.ConfigFile() + if err != nil { + return nil, err + } + + image := &image{ + Image: base, + manifest: m.DeepCopy(), + configFile: cf.DeepCopy(), + diffIDMap: make(map[v1.Hash]v1.Layer), + digestMap: make(map[v1.Hash]v1.Layer), + } + + diffIDs := image.configFile.RootFS.DiffIDs + history := image.configFile.History + + for _, add := range adds { + diffID, err := add.Layer.DiffID() + if err != nil { + return nil, err + } + diffIDs = append(diffIDs, diffID) + history = append(history, add.History) + image.diffIDMap[diffID] = add.Layer + } + + manifestLayers := image.manifest.Layers + + for _, add := range adds { + d := v1.Descriptor{ + MediaType: types.DockerLayer, + } + + if d.Size, err = add.Layer.Size(); err != nil { + return nil, err + } + + if d.Digest, err = add.Layer.Digest(); err != nil { + return nil, err + } + + manifestLayers = append(manifestLayers, d) + image.digestMap[d.Digest] = add.Layer + } + + image.configFile.RootFS.DiffIDs = diffIDs + image.configFile.History = history + image.manifest.Layers = manifestLayers + image.manifest.Config.Digest, err = image.ConfigName() + if err != nil { + return nil, err + } + + return image, nil +} + +// Config mutates the provided v1.Image to have the provided v1.Config +func Config(base v1.Image, cfg v1.Config) (v1.Image, error) { + m, err := base.Manifest() + if err != nil { + return nil, err + } + + cf, err := base.ConfigFile() + if err != nil { + return nil, err + } + + cf.Config = cfg + + image := &image{ + Image: base, + manifest: m.DeepCopy(), + configFile: cf.DeepCopy(), + diffIDMap: make(map[v1.Hash]v1.Layer), + digestMap: make(map[v1.Hash]v1.Layer), + } + image.manifest.Config.Digest, err = image.ConfigName() + if err != nil { + return nil, err + } + return image, nil +} + +type image struct { + v1.Image + configFile *v1.ConfigFile + manifest *v1.Manifest + diffIDMap map[v1.Hash]v1.Layer + digestMap map[v1.Hash]v1.Layer +} + +// Layers returns the ordered collection of filesystem layers that comprise this image. +// The order of the list is most-recent first, and oldest base layer last. +func (i *image) Layers() ([]v1.Layer, error) { + diffIDs, err := partial.DiffIDs(i) + if err != nil { + return nil, err + } + ls := make([]v1.Layer, 0, len(diffIDs)) + for _, h := range diffIDs { + l, err := i.LayerByDiffID(h) + if err != nil { + return nil, err + } + ls = append(ls, l) + } + return ls, nil +} + +// BlobSet returns an unordered collection of all the blobs in the image. +func (i *image) BlobSet() (map[v1.Hash]struct{}, error) { + return partial.BlobSet(i) +} + +// ConfigName returns the hash of the image's config file. +func (i *image) ConfigName() (v1.Hash, error) { + return partial.ConfigName(i) +} + +// ConfigFile returns this image's config file. +func (i *image) ConfigFile() (*v1.ConfigFile, error) { + return i.configFile, nil +} + +// RawConfigFile returns the serialized bytes of ConfigFile() +func (i *image) RawConfigFile() ([]byte, error) { + return json.Marshal(i.configFile) +} + +// Digest returns the sha256 of this image's manifest. +func (i *image) Digest() (v1.Hash, error) { + return partial.Digest(i) +} + +// Manifest returns this image's Manifest object. +func (i *image) Manifest() (*v1.Manifest, error) { + return i.manifest, nil +} + +// RawManifest returns the serialized bytes of Manifest() +func (i *image) RawManifest() ([]byte, error) { + return json.Marshal(i.manifest) +} + +// LayerByDigest returns a Layer for interacting with a particular layer of +// the image, looking it up by "digest" (the compressed hash). +func (i *image) LayerByDigest(h v1.Hash) (v1.Layer, error) { + if cn, err := i.ConfigName(); err != nil { + return nil, err + } else if h == cn { + return partial.ConfigLayer(i) + } + if layer, ok := i.digestMap[h]; ok { + return layer, nil + } + return i.Image.LayerByDigest(h) +} + +// LayerByDiffID is an analog to LayerByDigest, looking up by "diff id" +// (the uncompressed hash). +func (i *image) LayerByDiffID(h v1.Hash) (v1.Layer, error) { + if layer, ok := i.diffIDMap[h]; ok { + return layer, nil + } + return i.Image.LayerByDiffID(h) +} + +func validate(adds []Addendum) error { + for _, add := range adds { + if add.Layer == nil { + return errors.New("Unable to add a nil layer to the image") + } + } + return nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/partial/compressed.go b/vendor/github.com/google/go-containerregistry/v1/partial/compressed.go new file mode 100644 index 0000000000..1c810ff043 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/partial/compressed.go @@ -0,0 +1,154 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package partial + +import ( + "io" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/v1util" +) + +// CompressedLayer represents the bare minimum interface a natively +// compressed layer must implement for us to produce a v1.Layer +type CompressedLayer interface { + // Digest returns the Hash of the compressed layer. + Digest() (v1.Hash, error) + + // Compressed returns an io.ReadCloser for the compressed layer contents. + Compressed() (io.ReadCloser, error) + + // Size returns the compressed size of the Layer. + Size() (int64, error) +} + +// compressedLayerExtender implements v1.Image using the compressed base properties. +type compressedLayerExtender struct { + CompressedLayer +} + +// Uncompressed implements v1.Layer +func (ule *compressedLayerExtender) Uncompressed() (io.ReadCloser, error) { + u, err := ule.Compressed() + if err != nil { + return nil, err + } + return v1util.GunzipReadCloser(u) +} + +// DiffID implements v1.Layer +func (ule *compressedLayerExtender) DiffID() (v1.Hash, error) { + r, err := ule.Uncompressed() + if err != nil { + return v1.Hash{}, err + } + defer r.Close() + h, _, err := v1.SHA256(r) + return h, err +} + +// CompressedToLayer fills in the missing methods from a CompressedLayer so that it implements v1.Layer +func CompressedToLayer(ul CompressedLayer) (v1.Layer, error) { + return &compressedLayerExtender{ul}, nil +} + +// CompressedImageCore represents the base minimum interface a natively +// compressed image must implement for us to produce a v1.Image. +type CompressedImageCore interface { + imageCore + + // RawManifest returns the serialized bytes of the manifest. + RawManifest() ([]byte, error) + + // LayerByDigest is a variation on the v1.Image method, which returns + // a CompressedLayer instead. + LayerByDigest(v1.Hash) (CompressedLayer, error) +} + +// compressedImageExtender implements v1.Image by extending CompressedImageCore with the +// appropriate methods computed from the minimal core. +type compressedImageExtender struct { + CompressedImageCore +} + +// Assert that our extender type completes the v1.Image interface +var _ v1.Image = (*compressedImageExtender)(nil) + +// BlobSet implements v1.Image +func (i *compressedImageExtender) BlobSet() (map[v1.Hash]struct{}, error) { + return BlobSet(i) +} + +// Digest implements v1.Image +func (i *compressedImageExtender) Digest() (v1.Hash, error) { + return Digest(i) +} + +// ConfigName implements v1.Image +func (i *compressedImageExtender) ConfigName() (v1.Hash, error) { + return ConfigName(i) +} + +// Layers implements v1.Image +func (i *compressedImageExtender) Layers() ([]v1.Layer, error) { + hs, err := FSLayers(i) + if err != nil { + return nil, err + } + ls := make([]v1.Layer, 0, len(hs)) + for _, h := range hs { + l, err := i.LayerByDigest(h) + if err != nil { + return nil, err + } + ls = append(ls, l) + } + return ls, nil +} + +// LayerByDigest implements v1.Image +func (i *compressedImageExtender) LayerByDigest(h v1.Hash) (v1.Layer, error) { + cl, err := i.CompressedImageCore.LayerByDigest(h) + if err != nil { + return nil, err + } + return CompressedToLayer(cl) +} + +// LayerByDiffID implements v1.Image +func (i *compressedImageExtender) LayerByDiffID(h v1.Hash) (v1.Layer, error) { + h, err := DiffIDToBlob(i, h) + if err != nil { + return nil, err + } + return i.LayerByDigest(h) +} + +// ConfigFile implements v1.Image +func (i *compressedImageExtender) ConfigFile() (*v1.ConfigFile, error) { + return ConfigFile(i) +} + +// Manifest implements v1.Image +func (i *compressedImageExtender) Manifest() (*v1.Manifest, error) { + return Manifest(i) +} + +// CompressedToImage fills in the missing methods from a CompressedImageCore so that it implements v1.Image +func CompressedToImage(cic CompressedImageCore) (v1.Image, error) { + return &compressedImageExtender{ + CompressedImageCore: cic, + }, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/partial/doc.go b/vendor/github.com/google/go-containerregistry/v1/partial/doc.go new file mode 100644 index 0000000000..153dfe4d53 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/partial/doc.go @@ -0,0 +1,17 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package partial defines methods for building up a v1.Image from +// minimal subsets that are sufficient for defining a v1.Image. +package partial diff --git a/vendor/github.com/google/go-containerregistry/v1/partial/image.go b/vendor/github.com/google/go-containerregistry/v1/partial/image.go new file mode 100644 index 0000000000..b82ea36b69 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/partial/image.go @@ -0,0 +1,28 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package partial + +import ( + "github.com/google/go-containerregistry/v1/types" +) + +// imageCore is the core set of properties without which we cannot build a v1.Image +type imageCore interface { + // RawConfigFile returns the serialized bytes of this image's config file. + RawConfigFile() ([]byte, error) + + // MediaType of this image's manifest. + MediaType() (types.MediaType, error) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/partial/uncompressed.go b/vendor/github.com/google/go-containerregistry/v1/partial/uncompressed.go new file mode 100644 index 0000000000..fb8c38bd02 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/partial/uncompressed.go @@ -0,0 +1,229 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package partial + +import ( + "bytes" + "io" + "sync" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/types" + "github.com/google/go-containerregistry/v1/v1util" +) + +// UncompressedLayer represents the bare minimum interface a natively +// uncompressed layer must implement for us to produce a v1.Layer +type UncompressedLayer interface { + // DiffID returns the Hash of the uncompressed layer. + DiffID() (v1.Hash, error) + + // Uncompressed returns an io.ReadCloser for the uncompressed layer contents. + Uncompressed() (io.ReadCloser, error) +} + +// uncompressedLayerExtender implements v1.Image using the uncompressed base properties. +type uncompressedLayerExtender struct { + UncompressedLayer + // TODO(mattmoor): Memoize size/hash so that the methods aren't twice as + // expensive as doing this manually. +} + +// Compressed implements v1.Layer +func (ule *uncompressedLayerExtender) Compressed() (io.ReadCloser, error) { + u, err := ule.Uncompressed() + if err != nil { + return nil, err + } + return v1util.GzipReadCloser(u) +} + +// Digest implements v1.Layer +func (ule *uncompressedLayerExtender) Digest() (v1.Hash, error) { + r, err := ule.Compressed() + if err != nil { + return v1.Hash{}, err + } + defer r.Close() + h, _, err := v1.SHA256(r) + return h, err +} + +// Size implements v1.Layer +func (ule *uncompressedLayerExtender) Size() (int64, error) { + r, err := ule.Compressed() + if err != nil { + return -1, err + } + defer r.Close() + _, i, err := v1.SHA256(r) + return i, err +} + +// UncompressedToLayer fills in the missing methods from an UncompressedLayer so that it implements v1.Layer +func UncompressedToLayer(ul UncompressedLayer) (v1.Layer, error) { + return &uncompressedLayerExtender{ul}, nil +} + +// UncompressedImageCore represents the bare minimum interface a natively +// uncompressed image must implement for us to produce a v1.Image +type UncompressedImageCore interface { + imageCore + + // LayerByDiffID is a variation on the v1.Image method, which returns + // an UncompressedLayer instead. + LayerByDiffID(v1.Hash) (UncompressedLayer, error) +} + +// UncompressedToImage fills in the missing methods from an UncompressedImageCore so that it implements v1.Image. +func UncompressedToImage(uic UncompressedImageCore) (v1.Image, error) { + return &uncompressedImageExtender{ + UncompressedImageCore: uic, + }, nil +} + +// uncompressedImageExtender implements v1.Image by extending UncompressedImageCore with the +// appropriate methods computed from the minimal core. +type uncompressedImageExtender struct { + UncompressedImageCore + + lock sync.Mutex + manifest *v1.Manifest +} + +// Assert that our extender type completes the v1.Image interface +var _ v1.Image = (*uncompressedImageExtender)(nil) + +// BlobSet implements v1.Image +func (i *uncompressedImageExtender) BlobSet() (map[v1.Hash]struct{}, error) { + return BlobSet(i) +} + +// Digest implements v1.Image +func (i *uncompressedImageExtender) Digest() (v1.Hash, error) { + return Digest(i) +} + +// Manifest implements v1.Image +func (i *uncompressedImageExtender) Manifest() (*v1.Manifest, error) { + i.lock.Lock() + defer i.lock.Unlock() + if i.manifest != nil { + return i.manifest, nil + } + + b, err := i.RawConfigFile() + if err != nil { + return nil, err + } + + cfgHash, cfgSize, err := v1.SHA256(bytes.NewReader(b)) + if err != nil { + return nil, err + } + + m := &v1.Manifest{ + SchemaVersion: 2, + MediaType: types.DockerManifestSchema2, + Config: v1.Descriptor{ + MediaType: types.DockerConfigJSON, + Size: cfgSize, + Digest: cfgHash, + }, + } + + ls, err := i.Layers() + if err != nil { + return nil, err + } + + m.Layers = make([]v1.Descriptor, len(ls)) + for i, l := range ls { + sz, err := l.Size() + if err != nil { + return nil, err + } + h, err := l.Digest() + if err != nil { + return nil, err + } + + m.Layers[i] = v1.Descriptor{ + MediaType: types.DockerLayer, + Size: sz, + Digest: h, + } + } + + i.manifest = m + return i.manifest, nil +} + +// RawManifest implements v1.Image +func (i *uncompressedImageExtender) RawManifest() ([]byte, error) { + return RawManifest(i) +} + +// ConfigName implements v1.Image +func (i *uncompressedImageExtender) ConfigName() (v1.Hash, error) { + return ConfigName(i) +} + +// ConfigFile implements v1.Image +func (i *uncompressedImageExtender) ConfigFile() (*v1.ConfigFile, error) { + return ConfigFile(i) +} + +// Layers implements v1.Image +func (i *uncompressedImageExtender) Layers() ([]v1.Layer, error) { + diffIDs, err := DiffIDs(i) + if err != nil { + return nil, err + } + ls := make([]v1.Layer, 0, len(diffIDs)) + for _, h := range diffIDs { + l, err := i.LayerByDiffID(h) + if err != nil { + return nil, err + } + ls = append(ls, l) + } + return ls, nil +} + +// LayerByDiffID implements v1.Image +func (i *uncompressedImageExtender) LayerByDiffID(diffID v1.Hash) (v1.Layer, error) { + ul, err := i.UncompressedImageCore.LayerByDiffID(diffID) + if err != nil { + return nil, err + } + return UncompressedToLayer(ul) +} + +// LayerByDigest implements v1.Image +func (i *uncompressedImageExtender) LayerByDigest(h v1.Hash) (v1.Layer, error) { + // Support returning the ConfigFile when asked for its hash. + if cfgName, err := i.ConfigName(); err != nil { + return nil, err + } else if cfgName == h { + return ConfigLayer(i) + } + + diffID, err := BlobToDiffID(i, h) + if err != nil { + return nil, err + } + return i.LayerByDiffID(diffID) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/partial/with.go b/vendor/github.com/google/go-containerregistry/v1/partial/with.go new file mode 100644 index 0000000000..0557449afd --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/partial/with.go @@ -0,0 +1,291 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package partial + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/v1util" +) + +// WithRawConfigFile defines the subset of v1.Image used by these helper methods +type WithRawConfigFile interface { + // RawConfigFile returns the serialized bytes of this image's config file. + RawConfigFile() ([]byte, error) +} + +// ConfigFile is a helper for implementing v1.Image +func ConfigFile(i WithRawConfigFile) (*v1.ConfigFile, error) { + b, err := i.RawConfigFile() + if err != nil { + return nil, err + } + return v1.ParseConfigFile(bytes.NewReader(b)) +} + +// ConfigName is a helper for implementing v1.Image +func ConfigName(i WithRawConfigFile) (v1.Hash, error) { + b, err := i.RawConfigFile() + if err != nil { + return v1.Hash{}, err + } + h, _, err := v1.SHA256(bytes.NewReader(b)) + return h, err +} + +// configLayer implements v1.Layer from the raw config bytes. +// This is so that clients (e.g. remote) can access the config as a blob. +type configLayer struct { + hash v1.Hash + content []byte +} + +// Digest implements v1.Layer +func (cl *configLayer) Digest() (v1.Hash, error) { + return cl.hash, nil +} + +// DiffID implements v1.Layer +func (cl *configLayer) DiffID() (v1.Hash, error) { + return cl.hash, nil +} + +// Uncompressed implements v1.Layer +func (cl *configLayer) Uncompressed() (io.ReadCloser, error) { + return v1util.NopReadCloser(bytes.NewBuffer(cl.content)), nil +} + +// Compressed implements v1.Layer +func (cl *configLayer) Compressed() (io.ReadCloser, error) { + return v1util.NopReadCloser(bytes.NewBuffer(cl.content)), nil +} + +// Size implements v1.Layer +func (cl *configLayer) Size() (int64, error) { + return int64(len(cl.content)), nil +} + +var _ v1.Layer = (*configLayer)(nil) + +func ConfigLayer(i WithRawConfigFile) (v1.Layer, error) { + h, err := ConfigName(i) + if err != nil { + return nil, err + } + rcfg, err := i.RawConfigFile() + if err != nil { + return nil, err + } + return &configLayer{ + hash: h, + content: rcfg, + }, nil +} + +// WithConfigFile defines the subset of v1.Image used by these helper methods +type WithConfigFile interface { + // ConfigFile returns this image's config file. + ConfigFile() (*v1.ConfigFile, error) +} + +// DiffIDs is a helper for implementing v1.Image +func DiffIDs(i WithConfigFile) ([]v1.Hash, error) { + cfg, err := i.ConfigFile() + if err != nil { + return nil, err + } + dids := make([]v1.Hash, len(cfg.RootFS.DiffIDs)) + for i, did := range cfg.RootFS.DiffIDs { + dids[len(dids)-i-1] = did + } + return dids, nil +} + +// RawConfigFile is a helper for implementing v1.Image +func RawConfigFile(i WithConfigFile) ([]byte, error) { + cfg, err := i.ConfigFile() + if err != nil { + return nil, err + } + return json.Marshal(cfg) +} + +// WithUncompressedLayer defines the subset of v1.Image used by these helper methods +type WithUncompressedLayer interface { + // UncompressedLayer is like UncompressedBlob, but takes the "diff id". + UncompressedLayer(v1.Hash) (io.ReadCloser, error) +} + +// Layer is the same as Blob, but takes the "diff id". +func Layer(wul WithUncompressedLayer, h v1.Hash) (io.ReadCloser, error) { + rc, err := wul.UncompressedLayer(h) + if err != nil { + return nil, err + } + return v1util.GzipReadCloser(rc) +} + +// WithRawManifest defines the subset of v1.Image used by these helper methods +type WithRawManifest interface { + // RawManifest returns the serialized bytes of this image's config file. + RawManifest() ([]byte, error) +} + +// Digest is a helper for implementing v1.Image +func Digest(i WithRawManifest) (v1.Hash, error) { + mb, err := i.RawManifest() + if err != nil { + return v1.Hash{}, err + } + digest, _, err := v1.SHA256(bytes.NewReader(mb)) + return digest, err +} + +// Manifest is a helper for implementing v1.Image +func Manifest(i WithRawManifest) (*v1.Manifest, error) { + b, err := i.RawManifest() + if err != nil { + return nil, err + } + return v1.ParseManifest(bytes.NewReader(b)) +} + +// WithManifest defines the subset of v1.Image used by these helper methods +type WithManifest interface { + // Manifest returns this image's Manifest object. + Manifest() (*v1.Manifest, error) +} + +// RawManifest is a helper for implementing v1.Image +func RawManifest(i WithManifest) ([]byte, error) { + m, err := i.Manifest() + if err != nil { + return nil, err + } + return json.Marshal(m) +} + +// FSLayers is a helper for implementing v1.Image +func FSLayers(i WithManifest) ([]v1.Hash, error) { + m, err := i.Manifest() + if err != nil { + return nil, err + } + fsl := make([]v1.Hash, len(m.Layers)) + for i, l := range m.Layers { + fsl[i] = l.Digest + } + return fsl, nil +} + +// BlobSet is a helper for implementing v1.Image +func BlobSet(i WithManifest) (map[v1.Hash]struct{}, error) { + m, err := i.Manifest() + if err != nil { + return nil, err + } + bs := make(map[v1.Hash]struct{}) + for _, l := range m.Layers { + bs[l.Digest] = struct{}{} + } + bs[m.Config.Digest] = struct{}{} + return bs, nil +} + +// BlobSize is a helper for implementing v1.Image +func BlobSize(i WithManifest, h v1.Hash) (int64, error) { + m, err := i.Manifest() + if err != nil { + return -1, err + } + for _, l := range m.Layers { + if l.Digest == h { + return l.Size, nil + } + } + return -1, fmt.Errorf("blob %v not found", h) +} + +// WithManifestAndConfigFile defines the subset of v1.Image used by these helper methods +type WithManifestAndConfigFile interface { + WithConfigFile + + // Manifest returns this image's Manifest object. + Manifest() (*v1.Manifest, error) +} + +// BlobToDiffID is a helper for mapping between compressed +// and uncompressed blob hashes. +func BlobToDiffID(i WithManifestAndConfigFile, h v1.Hash) (v1.Hash, error) { + blobs, err := FSLayers(i) + if err != nil { + return v1.Hash{}, err + } + diffIDs, err := DiffIDs(i) + if err != nil { + return v1.Hash{}, err + } + if len(blobs) != len(diffIDs) { + return v1.Hash{}, fmt.Errorf("mismatched fs layers (%d) and diff ids (%d)", len(blobs), len(diffIDs)) + } + for i, blob := range blobs { + if blob == h { + return diffIDs[i], nil + } + } + return v1.Hash{}, fmt.Errorf("unknown blob %v", h) +} + +// DiffIDToBlob is a helper for mapping between uncompressed +// and compressed blob hashes. +func DiffIDToBlob(wm WithManifestAndConfigFile, h v1.Hash) (v1.Hash, error) { + blobs, err := FSLayers(wm) + if err != nil { + return v1.Hash{}, err + } + diffIDs, err := DiffIDs(wm) + if err != nil { + return v1.Hash{}, err + } + if len(blobs) != len(diffIDs) { + return v1.Hash{}, fmt.Errorf("mismatched fs layers (%d) and diff ids (%d)", len(blobs), len(diffIDs)) + } + for i, diffID := range diffIDs { + if diffID == h { + return blobs[i], nil + } + } + return v1.Hash{}, fmt.Errorf("unknown diffID %v", h) + +} + +// WithBlob defines the subset of v1.Image used by these helper methods +type WithBlob interface { + // Blob returns a ReadCloser for streaming the blob's content. + Blob(v1.Hash) (io.ReadCloser, error) +} + +// UncompressedBlob returns a ReadCloser for streaming the blob's content uncompressed. +func UncompressedBlob(b WithBlob, h v1.Hash) (io.ReadCloser, error) { + rc, err := b.Blob(h) + if err != nil { + return nil, err + } + return v1util.GunzipReadCloser(rc) +} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go b/vendor/github.com/google/go-containerregistry/v1/random/doc.go similarity index 72% rename from vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go rename to vendor/github.com/google/go-containerregistry/v1/random/doc.go index c318385cbe..d3712767d2 100644 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go +++ b/vendor/github.com/google/go-containerregistry/v1/random/doc.go @@ -1,10 +1,10 @@ -// Copyright 2013 Matt T. Proud +// Copyright 2018 Google LLC All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,5 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package pbutil provides record length-delimited Protocol Buffer streaming. -package pbutil +// Package random provides a facility for synthesizing pseudo-random images. +package random diff --git a/vendor/github.com/google/go-containerregistry/v1/random/image.go b/vendor/github.com/google/go-containerregistry/v1/random/image.go new file mode 100644 index 0000000000..03b3c4384b --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/random/image.go @@ -0,0 +1,110 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package random + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/partial" + "github.com/google/go-containerregistry/v1/types" + "github.com/google/go-containerregistry/v1/v1util" +) + +// uncompressedLayer implements partial.UncompressedLayer from raw bytes. +// TODO(mattmoor): Consider moving this into a library. +type uncompressedLayer struct { + diffID v1.Hash + content []byte +} + +// DiffID implements partial.UncompressedLayer +func (ul *uncompressedLayer) DiffID() (v1.Hash, error) { + return ul.diffID, nil +} + +// Uncompressed implements partial.UncompressedLayer +func (ul *uncompressedLayer) Uncompressed() (io.ReadCloser, error) { + return v1util.NopReadCloser(bytes.NewBuffer(ul.content)), nil +} + +var _ partial.UncompressedLayer = (*uncompressedLayer)(nil) + +// Image returns a pseudo-randomly generated Image. +func Image(byteSize, layers int64) (v1.Image, error) { + layerz := make(map[v1.Hash]partial.UncompressedLayer) + for i := int64(0); i < layers; i++ { + b := bytes.NewBuffer(nil) + if _, err := io.CopyN(b, rand.Reader, byteSize); err != nil { + return nil, err + } + bts := b.Bytes() + h, _, err := v1.SHA256(bytes.NewReader(bts)) + if err != nil { + return nil, err + } + layerz[h] = &uncompressedLayer{ + diffID: h, + content: bts, + } + } + + cfg := &v1.ConfigFile{} + + // It is ok that iteration order is random in Go, because this is the random image anyways. + for k := range layerz { + cfg.RootFS.DiffIDs = append(cfg.RootFS.DiffIDs, k) + } + + return partial.UncompressedToImage(&image{ + config: cfg, + layers: layerz, + }) +} + +// image is pseudo-randomly generated. +type image struct { + config *v1.ConfigFile + layers map[v1.Hash]partial.UncompressedLayer +} + +var _ partial.UncompressedImageCore = (*image)(nil) + +// RawConfigFile implements partial.UncompressedImageCore +func (i *image) RawConfigFile() ([]byte, error) { + return partial.RawConfigFile(i) +} + +// ConfigFile implements v1.Image +func (i *image) ConfigFile() (*v1.ConfigFile, error) { + return i.config, nil +} + +// MediaType implements partial.UncompressedImageCore +func (i *image) MediaType() (types.MediaType, error) { + return types.DockerManifestSchema2, nil +} + +// LayerByDiffID implements partial.UncompressedImageCore +func (i *image) LayerByDiffID(diffID v1.Hash) (partial.UncompressedLayer, error) { + l, ok := i.layers[diffID] + if !ok { + return nil, fmt.Errorf("unknown diff_id: %v", diffID) + } + return l, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/delete.go b/vendor/github.com/google/go-containerregistry/v1/remote/delete.go new file mode 100644 index 0000000000..48f2c44a8f --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/delete.go @@ -0,0 +1,70 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package remote + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/url" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1/remote/transport" +) + +// DeleteOptions are used to expose optional information to guide or +// control the image deletion. +type DeleteOptions struct { + // TODO(mattmoor): Fail on not found? + // TODO(mattmoor): Delete tag and manifest? +} + +// Delete removes the specified image reference from the remote registry. +func Delete(ref name.Reference, auth authn.Authenticator, t http.RoundTripper, do DeleteOptions) error { + tr, err := transport.New(ref, auth, t, transport.DeleteScope) + if err != nil { + return err + } + c := &http.Client{Transport: tr} + + u := url.URL{ + Scheme: transport.Scheme(ref.Context().Registry), + Host: ref.Context().RegistryStr(), + Path: fmt.Sprintf("/v2/%s/manifests/%s", ref.Context().RepositoryStr(), ref.Identifier()), + } + + req, err := http.NewRequest(http.MethodDelete, u.String(), nil) + if err != nil { + return err + } + + resp, err := c.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + switch resp.StatusCode { + case http.StatusOK, http.StatusAccepted: + return nil + default: + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + return fmt.Errorf("unrecognized status code during DELETE: %v; %v", resp.Status, string(b)) + } +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/doc.go b/vendor/github.com/google/go-containerregistry/v1/remote/doc.go new file mode 100644 index 0000000000..846ba07cda --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/doc.go @@ -0,0 +1,17 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package remote provides facilities for reading/writing v1.Images from/to +// a remote image registry. +package remote diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/error.go b/vendor/github.com/google/go-containerregistry/v1/remote/error.go new file mode 100644 index 0000000000..8c4b814e24 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/error.go @@ -0,0 +1,106 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package remote + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" +) + +// Error implements error to support the following error specification: +// https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors +type Error struct { + Errors []Diagnostic `json:"errors,omitempty"` +} + +// Check that Error implements error +var _ error = (*Error)(nil) + +// Error implements error +func (e *Error) Error() string { + switch len(e.Errors) { + case 0: + return "" + case 1: + return e.Errors[0].String() + default: + var errors []string + for _, d := range e.Errors { + errors = append(errors, d.String()) + } + return fmt.Sprintf("multiple errors returned: %s", + strings.Join(errors, ";")) + } +} + +// Diagnostic represents a single error returned by a Docker registry interaction. +type Diagnostic struct { + Code ErrorCode `json:"code"` + Message string `json:"message,omitempty"` + Detail interface{} `json:"detail,omitempty"` +} + +// String stringifies the Diagnostic +func (d Diagnostic) String() string { + return fmt.Sprintf("%s: %q", d.Code, d.Message) +} + +// ErrorCode is an enumeration of supported error codes. +type ErrorCode string + +// The set of error conditions a registry may return: +// https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors-2 +const ( + BlobUnknownErrorCode ErrorCode = "BLOB_UNKNOWN" + BlobUploadInvalidErrorCode ErrorCode = "BLOB_UPLOAD_INVALID" + BlobUploadUnknownErrorCode ErrorCode = "BLOB_UPLOAD_UNKNOWN" + DigestInvalidErrorCode ErrorCode = "DIGEST_INVALID" + ManifestBlobUnknownErrorCode ErrorCode = "MANIFEST_BLOB_UNKNOWN" + ManifestInvalidErrorCode ErrorCode = "MANIFEST_INVALID" + ManifestUnknownErrorCode ErrorCode = "MANIFEST_UNKNOWN" + ManifestUnverifiedErrorCode ErrorCode = "MANIFEST_UNVERIFIED" + NameInvalidErrorCode ErrorCode = "NAME_INVALID" + NameUnknownErrorCode ErrorCode = "NAME_UNKNOWN" + SizeInvalidErrorCode ErrorCode = "SIZE_INVALID" + TagInvalidErrorCode ErrorCode = "TAG_INVALID" + UnauthorizedErrorCode ErrorCode = "UNAUTHORIZED" + DeniedErrorCode ErrorCode = "DENIED" + UnsupportedErrorCode ErrorCode = "UNSUPPORTED" +) + +func checkError(resp *http.Response, codes ...int) error { + for _, code := range codes { + if resp.StatusCode == code { + // This is one of the supported status codes. + return nil + } + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + // https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors + var structuredError Error + if err := json.Unmarshal(b, &structuredError); err != nil { + // If the response isn't an unstructured error, then return some + // reasonable error response containing the response body. + return fmt.Errorf("unsupported status code %d; body: %s", resp.StatusCode, string(b)) + } + return &structuredError +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/image.go b/vendor/github.com/google/go-containerregistry/v1/remote/image.go new file mode 100644 index 0000000000..52e9a7e763 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/image.go @@ -0,0 +1,201 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package remote + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" + "sync" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/partial" + "github.com/google/go-containerregistry/v1/remote/transport" + "github.com/google/go-containerregistry/v1/types" + "github.com/google/go-containerregistry/v1/v1util" +) + +// remoteImage accesses an image from a remote registry +type remoteImage struct { + ref name.Reference + client *http.Client + manifestLock sync.Mutex // Protects manifest + manifest []byte + configLock sync.Mutex // Protects config + config []byte +} + +var _ partial.CompressedImageCore = (*remoteImage)(nil) + +// Image accesses a given image reference over the provided transport, with the provided authentication. +func Image(ref name.Reference, auth authn.Authenticator, t http.RoundTripper) (v1.Image, error) { + tr, err := transport.New(ref, auth, t, transport.PullScope) + if err != nil { + return nil, err + } + return partial.CompressedToImage(&remoteImage{ + ref: ref, + client: &http.Client{Transport: tr}, + }) +} + +func (r *remoteImage) url(resource, identifier string) url.URL { + return url.URL{ + Scheme: transport.Scheme(r.ref.Context().Registry), + Host: r.ref.Context().RegistryStr(), + Path: fmt.Sprintf("/v2/%s/%s/%s", r.ref.Context().RepositoryStr(), resource, identifier), + } +} + +func (r *remoteImage) MediaType() (types.MediaType, error) { + // TODO(jonjohnsonjr): Determine this based on response. + return types.DockerManifestSchema2, nil +} + +// TODO(jonjohnsonjr): Handle manifest lists. +func (r *remoteImage) RawManifest() ([]byte, error) { + r.manifestLock.Lock() + defer r.manifestLock.Unlock() + if r.manifest != nil { + return r.manifest, nil + } + + u := r.url("manifests", r.ref.Identifier()) + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + // TODO(jonjohnsonjr): Accept OCI manifest, manifest list, and image index. + req.Header.Set("Accept", string(types.DockerManifestSchema2)) + resp, err := r.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if err := checkError(resp, http.StatusOK); err != nil { + return nil, err + } + + manifest, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + digest, _, err := v1.SHA256(bytes.NewReader(manifest)) + if err != nil { + return nil, err + } + + // Validate the digest matches what we asked for, if pulling by digest. + if dgst, ok := r.ref.(name.Digest); ok { + if digest.String() != dgst.DigestStr() { + return nil, fmt.Errorf("manifest digest: %q does not match requested digest: %q for %q", digest, dgst.DigestStr(), r.ref) + } + } else if checksum := resp.Header.Get("Docker-Content-Digest"); checksum != "" && checksum != digest.String() { + err := fmt.Errorf("manifest digest: %q does not match Docker-Content-Digest: %q for %q", digest, checksum, r.ref) + if r.ref.Context().RegistryStr() == name.DefaultRegistry { + // TODO(docker/distribution#2395): Remove this check. + log.Println(err) + } else { + // When pulling by tag, we can only validate that the digest matches what the registry told us it should be. + return nil, err + } + } + + r.manifest = manifest + return r.manifest, nil +} + +func (r *remoteImage) RawConfigFile() ([]byte, error) { + r.configLock.Lock() + defer r.configLock.Unlock() + if r.config != nil { + return r.config, nil + } + + m, err := partial.Manifest(r) + if err != nil { + return nil, err + } + + cl, err := r.LayerByDigest(m.Config.Digest) + if err != nil { + return nil, err + } + body, err := cl.Compressed() + if err != nil { + return nil, err + } + defer body.Close() + + r.config, err = ioutil.ReadAll(body) + if err != nil { + return nil, err + } + return r.config, nil +} + +// remoteLayer implements partial.CompressedLayer +type remoteLayer struct { + ri *remoteImage + digest v1.Hash +} + +// Digest implements partial.CompressedLayer +func (rl *remoteLayer) Digest() (v1.Hash, error) { + return rl.digest, nil +} + +// Compressed implements partial.CompressedLayer +func (rl *remoteLayer) Compressed() (io.ReadCloser, error) { + u := rl.ri.url("blobs", rl.digest.String()) + resp, err := rl.ri.client.Get(u.String()) + if err != nil { + return nil, err + } + + if err := checkError(resp, http.StatusOK); err != nil { + resp.Body.Close() + return nil, err + } + + return v1util.VerifyReadCloser(resp.Body, rl.digest) +} + +// Manifest implements partial.WithManifest so that we can use partial.BlobSize below. +func (rl *remoteLayer) Manifest() (*v1.Manifest, error) { + return partial.Manifest(rl.ri) +} + +// Size implements partial.CompressedLayer +func (rl *remoteLayer) Size() (int64, error) { + // Look up the size of this digest in the manifest to avoid a request. + return partial.BlobSize(rl, rl.digest) +} + +// LayerByDigest implements partial.CompressedLayer +func (r *remoteImage) LayerByDigest(h v1.Hash) (partial.CompressedLayer, error) { + return &remoteLayer{ + ri: r, + digest: h, + }, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/basic.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/basic.go new file mode 100644 index 0000000000..a9ab46beb3 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/basic.go @@ -0,0 +1,47 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "net/http" + + "github.com/google/go-containerregistry/authn" +) + +type basicTransport struct { + inner http.RoundTripper + auth authn.Authenticator + target string +} + +var _ http.RoundTripper = (*basicTransport)(nil) + +// RoundTrip implements http.RoundTripper +func (bt *basicTransport) RoundTrip(in *http.Request) (*http.Response, error) { + hdr, err := bt.auth.Authorization() + if err != nil { + return nil, err + } + + // http.Client handles redirects at a layer above the http.RoundTripper + // abstraction, so to avoid forwarding Authorization headers to places + // we are redirected, only set it when the authorization header matches + // the host with which we are interacting. + if in.Host == bt.target { + in.Header.Set("Authorization", hdr) + } + in.Header.Set("User-Agent", transportName) + return bt.inner.RoundTrip(in) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/bearer.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/bearer.go new file mode 100644 index 0000000000..82a96c507f --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/bearer.go @@ -0,0 +1,119 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "fmt" + + "encoding/json" + "io/ioutil" + "net/http" + "net/url" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" +) + +type bearerTransport struct { + // Wrapped by bearerTransport. + inner http.RoundTripper + // Basic credentials that we exchange for bearer tokens. + basic authn.Authenticator + // Holds the bearer response from the token service. + bearer *authn.Bearer + // Registry to which we send bearer tokens. + registry name.Registry + // See https://tools.ietf.org/html/rfc6750#section-3 + realm string + // See https://docs.docker.com/registry/spec/auth/token/ + service string + scope string +} + +var _ http.RoundTripper = (*bearerTransport)(nil) + +// RoundTrip implements http.RoundTripper +func (bt *bearerTransport) RoundTrip(in *http.Request) (*http.Response, error) { + hdr, err := bt.bearer.Authorization() + if err != nil { + return nil, err + } + + // http.Client handles redirects at a layer above the http.RoundTripper + // abstraction, so to avoid forwarding Authorization headers to places + // we are redirected, only set it when the authorization header matches + // the registry with which we are interacting. + if in.Host == bt.registry.RegistryStr() { + in.Header.Set("Authorization", hdr) + } + in.Header.Set("User-Agent", transportName) + + // TODO(mattmoor): On 401s perform a single refresh() and retry. + return bt.inner.RoundTrip(in) +} + +func (bt *bearerTransport) refresh() error { + u, err := url.Parse(bt.realm) + if err != nil { + return err + } + b := &basicTransport{ + inner: bt.inner, + auth: bt.basic, + target: u.Host, + } + client := http.Client{Transport: b} + + u.RawQuery = url.Values{ + "scope": []string{bt.scope}, + "service": []string{bt.service}, + }.Encode() + + resp, err := client.Get(u.String()) + if err != nil { + return err + } + defer resp.Body.Close() + + content, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + // Some registries don't have "token" in the response. See #54. + type tokenResponse struct { + Token string `json:"token"` + AccessToken string `json:"access_token"` + } + + var response tokenResponse + if err := json.Unmarshal(content, &response); err != nil { + return err + } + + // Find a token to turn into a Bearer authenticator + var bearer authn.Bearer + if response.Token != "" { + bearer = authn.Bearer{Token: response.Token} + } else if response.AccessToken != "" { + bearer = authn.Bearer{Token: response.AccessToken} + } else { + return fmt.Errorf("no token in bearer response:\n%s", content) + } + + // Replace our old bearer authenticator (if we had one) with our newly refreshed authenticator. + bt.bearer = &bearer + return nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/doc.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/doc.go new file mode 100644 index 0000000000..ff7025b5c0 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/doc.go @@ -0,0 +1,18 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package transport provides facilities for setting up an authenticated +// http.RoundTripper given an Authenticator and base RoundTripper. See +// transport.New for more information. +package transport diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/ping.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/ping.go new file mode 100644 index 0000000000..82d7546490 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/ping.go @@ -0,0 +1,89 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "fmt" + "net/http" + "strings" + + "github.com/google/go-containerregistry/name" +) + +type challenge string + +const ( + anonymous challenge = "Anonymous" + basic challenge = "Basic" + bearer challenge = "Bearer" +) + +type pingResp struct { + challenge challenge + + // Following the challenge there are often key/value pairs + // e.g. Bearer service="gcr.io",realm="https://auth.gcr.io/v36/tokenz" + parameters map[string]string +} + +func parseChallenge(suffix string) map[string]string { + kv := make(map[string]string) + for _, token := range strings.Split(suffix, ",") { + // Trim any whitespace around each token. + token = strings.Trim(token, " ") + + // Break the token into a key/value pair + if parts := strings.SplitN(token, "=", 2); len(parts) == 2 { + // Unquote the value, if it is quoted. + kv[parts[0]] = strings.Trim(parts[1], `"`) + } else { + // If there was only one part, treat is as a key with an empty value + kv[token] = "" + } + } + return kv +} + +func ping(reg name.Registry, t http.RoundTripper) (*pingResp, error) { + client := http.Client{Transport: t} + + url := fmt.Sprintf("%s://%s/v2/", Scheme(reg), reg.Name()) + resp, err := client.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + switch resp.StatusCode { + case http.StatusOK: + // If we get a 200, then no authentication is needed. + return &pingResp{challenge: anonymous}, nil + case http.StatusUnauthorized: + wac := resp.Header.Get(http.CanonicalHeaderKey("WWW-Authenticate")) + if parts := strings.SplitN(wac, " ", 2); len(parts) == 2 { + // If there are two parts, then parse the challenge parameters. + return &pingResp{ + challenge: challenge(strings.Title(parts[0])), + parameters: parseChallenge(parts[1]), + }, nil + } + // Otherwise, just return the challenge without parameters. + return &pingResp{ + challenge: challenge(strings.Title(wac)), + }, nil + default: + return nil, fmt.Errorf("unrecognized HTTP status: %v", resp.Status) + } +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/scheme.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/scheme.go new file mode 100644 index 0000000000..b9d1dd3bf0 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/scheme.go @@ -0,0 +1,42 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "regexp" + "strings" + + "github.com/google/go-containerregistry/name" +) + +// Detect more complex forms of local references. +var reLocal = regexp.MustCompile(`.*\.local(?:host)?(?::\d{1,5})?$`) + +// Detect the loopback IP (127.0.0.1) +var reLoopback = regexp.MustCompile(regexp.QuoteMeta("127.0.0.1")) + +// Scheme returns https scheme for all the endpoints except localhost. +func Scheme(reg name.Registry) string { + if strings.HasPrefix(reg.Name(), "localhost:") { + return "http" + } + if reLocal.MatchString(reg.Name()) { + return "http" + } + if reLoopback.MatchString(reg.Name()) { + return "http" + } + return "https" +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/scope.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/scope.go new file mode 100644 index 0000000000..7f5a8bf0a5 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/scope.go @@ -0,0 +1,27 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +// Scope is an enumeration of the supported scopes to pass a transport. +type Scope string + +// Scopes suitable to pass to New() +const ( + PullScope Scope = "pull" + PushScope Scope = "push,pull" + // For now DELETE is PUSH, which is the read/write ACL. + DeleteScope Scope = PushScope + CatalogScope Scope = "catalog" +) diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/transport/transport.go b/vendor/github.com/google/go-containerregistry/v1/remote/transport/transport.go new file mode 100644 index 0000000000..9ef17ac1c2 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/transport/transport.go @@ -0,0 +1,84 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "fmt" + "net/http" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" +) + +const ( + transportName = "go-containerregistry" +) + +// New returns a new RoundTripper based on the provided RoundTripper that has been +// setup to authenticate with the remote registry hosting "ref", in the capacity +// laid out by the specified Scope. +func New(ref name.Reference, auth authn.Authenticator, t http.RoundTripper, a Scope) (http.RoundTripper, error) { + // The handshake: + // 1. Use "t" to ping() the registry for the authentication challenge. + // + // 2a. If we get back a 200, then simply use "t". + // + // 2b. If we get back a 401 with a Basic challenge, then use a transport + // that just attachs auth each roundtrip. + // + // 2c. If we get back a 401 with a Bearer challenge, then use a transport + // that attaches a bearer token to each request, and refreshes is on 401s. + // Perform an initial refresh to seed the bearer token. + + // First we ping the registry to determine the parameters of the authentication handshake + // (if one is even necessary). + pr, err := ping(ref.Context().Registry, t) + if err != nil { + return nil, err + } + + switch pr.challenge { + case anonymous: + return t, nil + case basic: + return &basicTransport{inner: t, auth: auth, target: ref.Context().RegistryStr()}, nil + case bearer: + // We require the realm, which tells us where to send our Basic auth to turn it into Bearer auth. + realm, ok := pr.parameters["realm"] + if !ok { + return nil, fmt.Errorf("malformed www-authenticate, missing realm: %v", pr.parameters) + } + service, ok := pr.parameters["service"] + if !ok { + // If the service parameter is not specified, then default it to the registry + // with which we are talking. + service = ref.Context().Registry.String() + } + bt := &bearerTransport{ + inner: t, + basic: auth, + realm: realm, + registry: ref.Context().Registry, + service: service, + scope: ref.Scope(string(a)), + } + if err := bt.refresh(); err != nil { + return nil, err + } + return bt, nil + default: + return nil, fmt.Errorf("Unrecognized challenge: %s", pr.challenge) + } +} diff --git a/vendor/github.com/google/go-containerregistry/v1/remote/write.go b/vendor/github.com/google/go-containerregistry/v1/remote/write.go new file mode 100644 index 0000000000..fe8eb69c6f --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/remote/write.go @@ -0,0 +1,281 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package remote + +import ( + "bytes" + "errors" + "fmt" + "log" + "net/http" + "net/url" + + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/remote/transport" +) + +// WriteOptions are used to expose optional information to guide or +// control the image write. +type WriteOptions struct { + // The set of paths from which to attempt to mount blobs. + MountPaths []name.Repository + // TODO(mattmoor): Expose "threads" to limit parallelism? +} + +// Write pushes the provided img to the specified image reference. +func Write(ref name.Reference, img v1.Image, auth authn.Authenticator, t http.RoundTripper, + wo WriteOptions) error { + tr, err := transport.New(ref, auth, t, transport.PushScope) + if err != nil { + return err + } + w := writer{ + ref: ref, + client: &http.Client{Transport: tr}, + img: img, + options: wo, + } + + bs, err := img.BlobSet() + if err != nil { + return err + } + + // Spin up go routines to publish each of the members of BlobSet(), + // and use an error channel to collect their results. + errCh := make(chan error) + defer close(errCh) + for h := range bs { + go func(h v1.Hash) { + errCh <- w.uploadOne(h) + }(h) + } + + // Now wait for all of the blob uploads to complete. + var errors []error + for _ = range bs { + if err := <-errCh; err != nil { + errors = append(errors, err) + } + } + if len(errors) > 0 { + // Return the first error we encountered. + return errors[0] + } + + // With all of the constituent elements uploaded, upload the manifest + // to commit the image. + return w.commitImage() +} + +// writer writes the elements of an image to a remote image reference. +type writer struct { + ref name.Reference + client *http.Client + img v1.Image + options WriteOptions +} + +// url returns a url.Url for the specified path in the context of this remote image reference. +func (w *writer) url(path string) url.URL { + return url.URL{ + Scheme: transport.Scheme(w.ref.Context().Registry), + Host: w.ref.Context().RegistryStr(), + Path: path, + } +} + +// nextLocation extracts the fully-qualified URL to which we should send the next request in an upload sequence. +func (w *writer) nextLocation(resp *http.Response) (string, error) { + loc := resp.Header.Get("Location") + if len(loc) == 0 { + return "", errors.New("missing Location header") + } + u, err := url.Parse(loc) + if err != nil { + return "", err + } + + // If the location header returned is just a url path, then fully qualify it. + // We cannot simply call w.url, since there might be an embedded query string. + return resp.Request.URL.ResolveReference(u).String(), nil +} + +// initiateUpload initiates the blob upload, which starts with a POST that can +// optionally include the hash of the layer and a list of repositories from +// which that layer might be read. On failure, an error is returned. +// On success, the layer was either mounted (nothing more to do) or a blob +// upload was initiated and the body of that blob should be sent to the returned +// location. +func (w *writer) initiateUpload(h v1.Hash) (location string, mounted bool, err error) { + u := w.url(fmt.Sprintf("/v2/%s/blobs/uploads/", w.ref.Context().RepositoryStr())) + uv := url.Values{ + "mount": []string{h.String()}, + } + var from []string + for _, m := range w.options.MountPaths { + from = append(from, m.RepositoryStr()) + } + // We currently avoid HEAD because it's semi-redundant with the mount that is part + // of initiating the blob upload. GCR will perform an existence check on the initiation + // if "mount" is specified, even if no "from" sources are specified. If this turns out + // to not be broadly applicable then we should replace mounts without "from"s with a HEAD. + if len(from) > 0 { + uv["from"] = from + } + u.RawQuery = uv.Encode() + + // Make the request to initiate the blob upload. + resp, err := w.client.Post(u.String(), "application/json", nil) + if err != nil { + return "", false, err + } + defer resp.Body.Close() + + if err := checkError(resp, http.StatusCreated, http.StatusAccepted); err != nil { + return "", false, err + } + + // Check the response code to determine the result. + switch resp.StatusCode { + case http.StatusCreated: + // We're done, we were able to fast-path. + return "", true, nil + case http.StatusAccepted: + // Proceed to PATCH, upload has begun. + loc, err := w.nextLocation(resp) + return loc, false, err + default: + panic("Unreachable: initiateUpload") + } +} + +// streamBlob streams the contents of the blob to the specified location. +// On failure, this will return an error. On success, this will return the location +// header indicating how to commit the streamed blob. +func (w *writer) streamBlob(h v1.Hash, streamLocation string) (commitLocation string, err error) { + l, err := w.img.LayerByDigest(h) + if err != nil { + return "", err + } + blob, err := l.Compressed() + if err != nil { + return "", err + } + defer blob.Close() + + req, err := http.NewRequest(http.MethodPatch, streamLocation, blob) + if err != nil { + return "", err + } + + resp, err := w.client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if err := checkError(resp, http.StatusNoContent, http.StatusAccepted, http.StatusCreated); err != nil { + return "", err + } + + // The blob has been uploaded, return the location header indicating + // how to commit this layer. + return w.nextLocation(resp) +} + +// commitBlob commits this blob by sending a PUT to the location returned from streaming the blob. +func (w *writer) commitBlob(h v1.Hash, location string) (err error) { + u, err := url.Parse(location) + if err != nil { + return err + } + v := u.Query() + v.Set("digest", h.String()) + u.RawQuery = v.Encode() + + req, err := http.NewRequest(http.MethodPut, u.String(), nil) + if err != nil { + return err + } + + resp, err := w.client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + return checkError(resp, http.StatusCreated) +} + +// uploadOne performs a complete upload of a single layer. +func (w *writer) uploadOne(h v1.Hash) error { + location, mounted, err := w.initiateUpload(h) + if err != nil { + return err + } else if mounted { + log.Printf("mounted %v", h) + return nil + } + + location, err = w.streamBlob(h, location) + if err != nil { + return err + } + + if err := w.commitBlob(h, location); err != nil { + return err + } + log.Printf("pushed %v", h) + return nil +} + +// commitImage does a PUT of the image's manifest. +func (w *writer) commitImage() error { + raw, err := w.img.RawManifest() + if err != nil { + return err + } + mt, err := w.img.MediaType() + if err != nil { + return err + } + + u := w.url(fmt.Sprintf("/v2/%s/manifests/%s", w.ref.Context().RepositoryStr(), w.ref.Identifier())) + + // Make the request to PUT the serialized manifest + req, err := http.NewRequest(http.MethodPut, u.String(), bytes.NewBuffer(raw)) + if err != nil { + return err + } + req.Header.Set("Content-Type", string(mt)) + + resp, err := w.client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if err := checkError(resp, http.StatusOK, http.StatusCreated, http.StatusAccepted); err != nil { + return err + } + // The image was successfully pushed! + log.Printf("pushed %v", w.ref) + return nil +} + +// TODO(mattmoor): WriteIndex diff --git a/vendor/github.com/google/go-containerregistry/v1/tarball/doc.go b/vendor/github.com/google/go-containerregistry/v1/tarball/doc.go new file mode 100644 index 0000000000..4eb79bb4e5 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/tarball/doc.go @@ -0,0 +1,17 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tarball provides facilities for reading/writing v1.Images from/to +// a tarball on-disk. +package tarball diff --git a/vendor/github.com/google/go-containerregistry/v1/tarball/image.go b/vendor/github.com/google/go-containerregistry/v1/tarball/image.go new file mode 100644 index 0000000000..7346dbcef2 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/tarball/image.go @@ -0,0 +1,338 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tarball + +import ( + "archive/tar" + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "sync" + + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/partial" + "github.com/google/go-containerregistry/v1/types" + "github.com/google/go-containerregistry/v1/v1util" +) + +type image struct { + opener Opener + td *tarDescriptor + config []byte + imgDescriptor *singleImageTarDescriptor + + tag *name.Tag +} + +type uncompressedImage struct { + *image +} + +type compressedImage struct { + *image + manifestLock sync.Mutex // Protects manifest + manifest *v1.Manifest +} + +var _ partial.UncompressedImageCore = (*uncompressedImage)(nil) +var _ partial.CompressedImageCore = (*compressedImage)(nil) + +type Opener func() (io.ReadCloser, error) + +func pathOpener(path string) Opener { + return func() (io.ReadCloser, error) { + return os.Open(path) + } +} + +func ImageFromPath(path string, tag *name.Tag) (v1.Image, error) { + return Image(pathOpener(path), tag) +} + +// Image exposes an image from the tarball at the provided path. +func Image(opener Opener, tag *name.Tag) (v1.Image, error) { + img := &image{ + opener: opener, + tag: tag, + } + if err := img.loadTarDescriptorAndConfig(); err != nil { + return nil, err + } + + // Peek at the first layer and see if it's compressed. + compressed, err := img.areLayersCompressed() + if err != nil { + return nil, err + } + if compressed { + c := compressedImage{ + image: img, + } + return partial.CompressedToImage(&c) + } + + uc := uncompressedImage{ + image: img, + } + return partial.UncompressedToImage(&uc) +} + +func (i *image) MediaType() (types.MediaType, error) { + return types.DockerManifestSchema2, nil +} + +// singleImageTarDescriptor is the struct used to represent a single image inside a `docker save` tarball. +type singleImageTarDescriptor struct { + Config string + RepoTags []string + Layers []string +} + +// tarDescriptor is the struct used inside the `manifest.json` file of a `docker save` tarball. +type tarDescriptor []singleImageTarDescriptor + +func (td tarDescriptor) findSpecifiedImageDescriptor(tag *name.Tag) (*singleImageTarDescriptor, error) { + if tag == nil { + if len(td) != 1 { + return nil, errors.New("tarball must contain only a single image to be used with tarball.Image") + } + return &(td)[0], nil + } + for _, img := range td { + for _, tagStr := range img.RepoTags { + repoTag, err := name.NewTag(tagStr, name.WeakValidation) + if err != nil { + return nil, err + } + + // Compare the resolved names, since there are several ways to specify the same tag. + if repoTag.Name() == tag.Name() { + return &img, nil + } + } + } + return nil, fmt.Errorf("tag %s not found in tarball", tag) +} + +func (i *image) areLayersCompressed() (bool, error) { + if len(i.imgDescriptor.Layers) == 0 { + return false, errors.New("0 layers found in image") + } + layer := i.imgDescriptor.Layers[0] + blob, err := extractFileFromTar(i.opener, layer) + if err != nil { + return false, err + } + defer blob.Close() + return v1util.IsGzipped(blob) +} + +func (i *image) loadTarDescriptorAndConfig() error { + td, err := extractFileFromTar(i.opener, "manifest.json") + if err != nil { + return err + } + defer td.Close() + + if err := json.NewDecoder(td).Decode(&i.td); err != nil { + return err + } + + i.imgDescriptor, err = i.td.findSpecifiedImageDescriptor(i.tag) + if err != nil { + return err + } + + cfg, err := extractFileFromTar(i.opener, i.imgDescriptor.Config) + if err != nil { + return err + } + defer cfg.Close() + + i.config, err = ioutil.ReadAll(cfg) + if err != nil { + return err + } + return nil +} + +func (i *image) RawConfigFile() ([]byte, error) { + return i.config, nil +} + +// tarFile represents a single file inside a tar. Closing it closes the tar itself. +type tarFile struct { + io.Reader + io.Closer +} + +func extractFileFromTar(opener Opener, filePath string) (io.ReadCloser, error) { + f, err := opener() + if err != nil { + return nil, err + } + tf := tar.NewReader(f) + for { + hdr, err := tf.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if hdr.Name == filePath { + return tarFile{ + Reader: tf, + Closer: f, + }, nil + } + } + return nil, fmt.Errorf("file %s not found in tar", filePath) +} + +// uncompressedLayerFromTarball implements partial.UncompressedLayer +type uncompressedLayerFromTarball struct { + diffID v1.Hash + opener Opener + filePath string +} + +// DiffID implements partial.UncompressedLayer +func (ulft *uncompressedLayerFromTarball) DiffID() (v1.Hash, error) { + return ulft.diffID, nil +} + +// Uncompressed implements partial.UncompressedLayer +func (ulft *uncompressedLayerFromTarball) Uncompressed() (io.ReadCloser, error) { + return extractFileFromTar(ulft.opener, ulft.filePath) +} + +func (i *uncompressedImage) LayerByDiffID(h v1.Hash) (partial.UncompressedLayer, error) { + cfg, err := partial.ConfigFile(i) + if err != nil { + return nil, err + } + for idx, diffID := range cfg.RootFS.DiffIDs { + if diffID == h { + return &uncompressedLayerFromTarball{ + diffID: diffID, + opener: i.opener, + filePath: i.imgDescriptor.Layers[idx], + }, nil + } + } + return nil, fmt.Errorf("diff id %q not found", h) +} + +func (c *compressedImage) Manifest() (*v1.Manifest, error) { + c.manifestLock.Lock() + defer c.manifestLock.Unlock() + if c.manifest != nil { + return c.manifest, nil + } + + b, err := c.RawConfigFile() + if err != nil { + return nil, err + } + + cfgHash, cfgSize, err := v1.SHA256(bytes.NewReader(b)) + if err != nil { + return nil, err + } + + c.manifest = &v1.Manifest{ + SchemaVersion: 2, + MediaType: types.DockerManifestSchema2, + Config: v1.Descriptor{ + MediaType: types.DockerConfigJSON, + Size: cfgSize, + Digest: cfgHash, + }, + } + + for _, p := range c.imgDescriptor.Layers { + l, err := extractFileFromTar(c.opener, p) + if err != nil { + return nil, err + } + defer l.Close() + sha, size, err := v1.SHA256(l) + if err != nil { + return nil, err + } + c.manifest.Layers = append(c.manifest.Layers, v1.Descriptor{ + MediaType: types.DockerLayer, + Size: size, + Digest: sha, + }) + } + return c.manifest, nil +} + +func (c *compressedImage) RawManifest() ([]byte, error) { + return partial.RawManifest(c) +} + +// compressedLayerFromTarball implements partial.CompressedLayer +type compressedLayerFromTarball struct { + digest v1.Hash + opener Opener + filePath string +} + +// DiffID implements partial.CompressedLayer +func (clft *compressedLayerFromTarball) Digest() (v1.Hash, error) { + return clft.digest, nil +} + +// Compressed implements partial.CompressedLayer +func (clft *compressedLayerFromTarball) Compressed() (io.ReadCloser, error) { + return extractFileFromTar(clft.opener, clft.filePath) +} + +// Size implements partial.CompressedLayer +func (clft *compressedLayerFromTarball) Size() (int64, error) { + r, err := clft.Compressed() + if err != nil { + return -1, err + } + defer r.Close() + _, i, err := v1.SHA256(r) + return i, err +} + +func (c *compressedImage) LayerByDigest(h v1.Hash) (partial.CompressedLayer, error) { + m, err := c.Manifest() + if err != nil { + return nil, err + } + for i, l := range m.Layers { + if l.Digest == h { + fp := c.imgDescriptor.Layers[i] + return &compressedLayerFromTarball{ + digest: h, + opener: c.opener, + filePath: fp, + }, nil + } + } + return nil, fmt.Errorf("blob %v not found", h) +} diff --git a/vendor/github.com/google/go-containerregistry/v1/tarball/layer.go b/vendor/github.com/google/go-containerregistry/v1/tarball/layer.go new file mode 100644 index 0000000000..ba8d8b339c --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/tarball/layer.go @@ -0,0 +1,144 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tarball + +import ( + "compress/gzip" + "io" + "io/ioutil" + "os" + + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/v1util" +) + +type layer struct { + digest v1.Hash + diffID v1.Hash + size int64 + opener Opener + compressed bool +} + +func (l *layer) Digest() (v1.Hash, error) { + return l.digest, nil +} + +func (l *layer) DiffID() (v1.Hash, error) { + return l.diffID, nil +} + +func (l *layer) Compressed() (io.ReadCloser, error) { + rc, err := l.opener() + if err == nil && !l.compressed { + return v1util.GzipReadCloser(rc) + } + + return rc, err +} + +func (l *layer) Uncompressed() (io.ReadCloser, error) { + rc, err := l.opener() + if err == nil && l.compressed { + return v1util.GunzipReadCloser(rc) + } + + return rc, err +} + +func (l *layer) Size() (int64, error) { + return l.size, nil +} + +// LayerFromFile returns a v1.Layer given a tarball +func LayerFromFile(path string) (v1.Layer, error) { + opener := func() (io.ReadCloser, error) { + return os.Open(path) + } + return LayerFromOpener(opener) +} + +// LayerFromOpener returns a v1.Layer given an Opener function +func LayerFromOpener(opener Opener) (v1.Layer, error) { + rc, err := opener() + if err != nil { + return nil, err + } + defer rc.Close() + + compressed, err := v1util.IsGzipped(rc) + if err != nil { + return nil, err + } + + var digest v1.Hash + var size int64 + if digest, size, err = computeDigest(opener, compressed); err != nil { + return nil, err + } + + diffID, err := computeDiffID(opener, compressed) + if err != nil { + return nil, err + } + + return &layer{ + digest: digest, + diffID: diffID, + size: size, + compressed: compressed, + opener: opener, + }, nil +} + +func computeDigest(opener Opener, compressed bool) (v1.Hash, int64, error) { + rc, err := opener() + if err != nil { + return v1.Hash{}, 0, err + } + defer rc.Close() + + if compressed { + return v1.SHA256(rc) + } + + reader, err := v1util.GzipReadCloser(ioutil.NopCloser(rc)) + if err != nil { + return v1.Hash{}, 0, err + } + + return v1.SHA256(reader) +} + +func computeDiffID(opener Opener, compressed bool) (v1.Hash, error) { + rc, err := opener() + if err != nil { + return v1.Hash{}, err + } + defer rc.Close() + + if !compressed { + digest, _, err := v1.SHA256(rc) + return digest, err + } + + reader, err := gzip.NewReader(rc) + if err != nil { + return v1.Hash{}, err + } + + diffID, _, err := v1.SHA256(reader) + return diffID, err +} diff --git a/vendor/github.com/google/go-containerregistry/v1/tarball/write.go b/vendor/github.com/google/go-containerregistry/v1/tarball/write.go new file mode 100644 index 0000000000..cd37ed70dd --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/tarball/write.go @@ -0,0 +1,122 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tarball + +import ( + "archive/tar" + "bytes" + "encoding/json" + "io" + "os" + + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" +) + +// WriteOptions are used to expose optional information to guide or +// control the image write. +type WriteOptions struct { + // TODO(mattmoor): Whether to store things compressed? +} + +// Write saves the image as the given tag in a tarball at the given path. +func Write(p string, tag name.Tag, img v1.Image, wo *WriteOptions) error { + // Write in the compressed format. + // This is a tarball, on-disk, with: + // One manifest.json file at the top level containing information about several images. + // One file for each layer, named after the layer's SHA. + // One file for the config blob, named after its SHA. + + w, err := os.Create(p) + if err != nil { + return err + } + defer w.Close() + + tf := tar.NewWriter(w) + defer tf.Close() + + // Write the config. + cfgName, err := img.ConfigName() + if err != nil { + return err + } + cfg, err := img.ConfigFile() + if err != nil { + return err + } + cfgBlob, err := json.Marshal(cfg) + if err != nil { + return err + } + if err := writeFile(tf, cfgName.String(), bytes.NewReader(cfgBlob), int64(len(cfgBlob))); err != nil { + return err + } + + // Write the layers. + layers, err := img.Layers() + if err != nil { + return err + } + digests := make([]string, len(layers)) + for i, l := range layers { + d, err := l.Digest() + if err != nil { + return err + } + + digests[i] = d.String() + r, err := l.Compressed() + if err != nil { + return err + } + blobSize, err := l.Size() + if err != nil { + return err + } + + if err := writeFile(tf, d.String(), r, blobSize); err != nil { + return err + } + } + + // Generate the tar descriptor and write it. + td := tarDescriptor{ + singleImageTarDescriptor{ + Config: cfgName.String(), + RepoTags: []string{tag.String()}, + Layers: digests, + }, + } + tdBytes, err := json.Marshal(td) + if err != nil { + return err + } + return writeFile(tf, "manifest.json", bytes.NewReader(tdBytes), int64(len(tdBytes))) +} + +func writeFile(tf *tar.Writer, path string, r io.Reader, size int64) error { + hdr := &tar.Header{ + Mode: 0644, + Typeflag: tar.TypeReg, + Size: size, + Name: path, + } + if err := tf.WriteHeader(hdr); err != nil { + return err + } + _, err := io.Copy(tf, r) + return err +} diff --git a/vendor/github.com/google/go-containerregistry/v1/types/types.go b/vendor/github.com/google/go-containerregistry/v1/types/types.go new file mode 100644 index 0000000000..ddaf71962e --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/types/types.go @@ -0,0 +1,40 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +// MediaType is an enumeration of the supported mime types that an element of an image might have. +type MediaType string + +// The collection of known MediaType values. +const ( + OCIContentDescriptor MediaType = "application/vnd.oci.descriptor.v1+json" + OCIImageIndex MediaType = "application/vnd.oci.image.index.v1+json" + OCIManifestSchema1 MediaType = "application/vnd.oci.image.manifest.v1+json" + OCIConfigJSON MediaType = "application/vnd.oci.image.config.v1+json" + OCILayer MediaType = "application/vnd.oci.image.layer.v1.tar+gzip" + OCIRestrictedLayer MediaType = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" + OCIUncompressedLayer MediaType = "application/vnd.oci.image.layer.v1.tar" + OCIUncompressedRestrictedLayer MediaType = "application/vnd.oci.image.layer.nondistributable.v1.tar" + + DockerManifestSchema1 MediaType = "application/vnd.docker.distribution.manifest.v1+json" + DockerManifestSchema1Signed MediaType = "application/vnd.docker.distribution.manifest.v1+prettyjws" + DockerManifestSchema2 MediaType = "application/vnd.docker.distribution.manifest.v2+json" + DockerManifestList MediaType = "application/vnd.docker.distribution.manifest.list.v2+json" + DockerLayer MediaType = "application/vnd.docker.image.rootfs.diff.tar.gzip" + DockerConfigJSON MediaType = "application/vnd.docker.container.image.v1+json" + DockerPluginConfig MediaType = "application/vnd.docker.plugin.v1+json" + DockerForeignLayer MediaType = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" + DockerUncompressedLayer MediaType = "application/vnd.docker.image.rootfs.diff.tar" +) diff --git a/vendor/github.com/google/go-containerregistry/v1/v1util/and_closer.go b/vendor/github.com/google/go-containerregistry/v1/v1util/and_closer.go new file mode 100644 index 0000000000..0925f13d54 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/v1util/and_closer.go @@ -0,0 +1,47 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1util + +import ( + "io" +) + +// readAndCloser implements io.ReadCloser by reading from a particular io.Reader +// and then calling the provided "Close()" method. +type readAndCloser struct { + io.Reader + CloseFunc func() error +} + +var _ io.ReadCloser = (*readAndCloser)(nil) + +// Close implements io.ReadCloser +func (rac *readAndCloser) Close() error { + return rac.CloseFunc() +} + +// writeAndCloser implements io.WriteCloser by reading from a particular io.Writer +// and then calling the provided "Close()" method. +type writeAndCloser struct { + io.Writer + CloseFunc func() error +} + +var _ io.WriteCloser = (*writeAndCloser)(nil) + +// Close implements io.WriteCloser +func (wac *writeAndCloser) Close() error { + return wac.CloseFunc() +} diff --git a/vendor/github.com/google/go-containerregistry/v1/v1util/nop.go b/vendor/github.com/google/go-containerregistry/v1/v1util/nop.go new file mode 100644 index 0000000000..8ff288d978 --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/v1util/nop.go @@ -0,0 +1,40 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1util + +import ( + "io" +) + +func nop() error { + return nil +} + +// NopWriteCloser wraps the io.Writer as an io.WriteCloser with a Close() method that does nothing. +func NopWriteCloser(w io.Writer) io.WriteCloser { + return &writeAndCloser{ + Writer: w, + CloseFunc: nop, + } +} + +// NopReadCloser wraps the io.Reader as an io.ReadCloser with a Close() method that does nothing. +// This is technically redundant with ioutil.NopCloser, but provided for symmetry and clarity. +func NopReadCloser(r io.Reader) io.ReadCloser { + return &readAndCloser{ + Reader: r, + CloseFunc: nop, + } +} diff --git a/vendor/github.com/google/go-containerregistry/v1/v1util/verify.go b/vendor/github.com/google/go-containerregistry/v1/v1util/verify.go new file mode 100644 index 0000000000..610ca5c01b --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/v1util/verify.go @@ -0,0 +1,61 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1util + +import ( + "encoding/hex" + "fmt" + "hash" + "io" + + "github.com/google/go-containerregistry/v1" +) + +type verifyReader struct { + inner io.Reader + hasher hash.Hash + expected v1.Hash +} + +// Read implements io.Reader +func (vc *verifyReader) Read(b []byte) (int, error) { + n, err := vc.inner.Read(b) + if err == io.EOF { + got := hex.EncodeToString(vc.hasher.Sum(make([]byte, 0, vc.hasher.Size()))) + if want := vc.expected.Hex; got != want { + return n, fmt.Errorf("error verifying %s checksum; got %q, want %q", + vc.expected.Algorithm, got, want) + } + } + return n, err +} + +// VerifyReadCloser wraps the given io.ReadCloser to verify that its contents match +// the provided v1.Hash before io.EOF is returned. +func VerifyReadCloser(r io.ReadCloser, h v1.Hash) (io.ReadCloser, error) { + w, err := v1.Hasher(h.Algorithm) + if err != nil { + return nil, err + } + r2 := io.TeeReader(r, w) + return &readAndCloser{ + Reader: &verifyReader{ + inner: r2, + hasher: w, + expected: h, + }, + CloseFunc: r.Close, + }, nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/v1util/zip.go b/vendor/github.com/google/go-containerregistry/v1/v1util/zip.go new file mode 100644 index 0000000000..469d29146f --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/v1util/zip.go @@ -0,0 +1,117 @@ +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1util + +import ( + "bytes" + "compress/gzip" + "io" +) + +var gzipMagicHeader = []byte{'\x1f', '\x8b'} + +// GzipReadCloser reads uncompressed input data from the io.ReadCloser and +// returns an io.ReadCloser from which compressed data may be read. +func GzipReadCloser(r io.ReadCloser) (io.ReadCloser, error) { + pr, pw := io.Pipe() + + go func() { + defer pw.Close() + defer r.Close() + + gw, _ := gzip.NewWriterLevel(pw, gzip.BestCompression) + defer gw.Close() + + _, err := io.Copy(gw, r) + if err != nil { + pr.CloseWithError(err) + } + }() + + return pr, nil +} + +// GunzipReadCloser reads compressed input data from the io.ReadCloser and +// returns an io.ReadCloser from which uncompessed data may be read. +func GunzipReadCloser(r io.ReadCloser) (io.ReadCloser, error) { + gr, err := gzip.NewReader(r) + if err != nil { + return nil, err + } + return &readAndCloser{ + Reader: gr, + CloseFunc: func() error { + if err := gr.Close(); err != nil { + return err + } + return r.Close() + }, + }, nil +} + +// GzipWriteCloser returns an io.WriteCloser to which uncompressed data may be +// written, and the compressed data is then written to the provided +// io.WriteCloser. +func GzipWriteCloser(w io.WriteCloser) io.WriteCloser { + gw := gzip.NewWriter(w) + return &writeAndCloser{ + Writer: gw, + CloseFunc: func() error { + if err := gw.Close(); err != nil { + return err + } + return w.Close() + }, + } +} + +// gunzipWriteCloser implements io.WriteCloser +// It is used to implement GunzipWriteClose. +type gunzipWriteCloser struct { + *bytes.Buffer + writer io.WriteCloser +} + +// Close implements io.WriteCloser +func (gwc *gunzipWriteCloser) Close() error { + // TODO(mattmoor): How to avoid buffering this whole thing into memory? + gr, err := gzip.NewReader(gwc.Buffer) + if err != nil { + return err + } + if _, err := io.Copy(gwc.writer, gr); err != nil { + return err + } + return gwc.writer.Close() +} + +// GunzipWriteCloser returns an io.WriteCloser to which compressed data may be +// written, and the uncompressed data is then written to the provided +// io.WriteCloser. +func GunzipWriteCloser(w io.WriteCloser) (io.WriteCloser, error) { + return &gunzipWriteCloser{ + Buffer: bytes.NewBuffer(nil), + writer: w, + }, nil +} + +// IsGzipped detects whether the input stream is compressed. +func IsGzipped(r io.Reader) (bool, error) { + magicHeader := make([]byte, 2) + if _, err := r.Read(magicHeader); err != nil { + return false, err + } + return bytes.Equal(magicHeader, gzipMagicHeader), nil +} diff --git a/vendor/github.com/google/go-containerregistry/v1/zz_deepcopy_generated.go b/vendor/github.com/google/go-containerregistry/v1/zz_deepcopy_generated.go new file mode 100644 index 0000000000..530e048fbd --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/v1/zz_deepcopy_generated.go @@ -0,0 +1,232 @@ +// +build !ignore_autogenerated + +// Copyright 2018 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Config) DeepCopyInto(out *Config) { + *out = *in + if in.Cmd != nil { + in, out := &in.Cmd, &out.Cmd + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Entrypoint != nil { + in, out := &in.Entrypoint, &out.Entrypoint + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.OnBuild != nil { + in, out := &in.OnBuild, &out.OnBuild + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make(map[string]struct{}, len(*in)) + for key := range *in { + (*out)[key] = struct{}{} + } + } + if in.ExposedPorts != nil { + in, out := &in.ExposedPorts, &out.ExposedPorts + *out = make(map[string]struct{}, len(*in)) + for key := range *in { + (*out)[key] = struct{}{} + } + } + if in.Shell != nil { + in, out := &in.Shell, &out.Shell + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. +func (in *Config) DeepCopy() *Config { + if in == nil { + return nil + } + out := new(Config) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigFile) DeepCopyInto(out *ConfigFile) { + *out = *in + in.Created.DeepCopyInto(&out.Created) + if in.History != nil { + in, out := &in.History, &out.History + *out = make([]History, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.RootFS.DeepCopyInto(&out.RootFS) + in.Config.DeepCopyInto(&out.Config) + in.ContainerConfig.DeepCopyInto(&out.ContainerConfig) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigFile. +func (in *ConfigFile) DeepCopy() *ConfigFile { + if in == nil { + return nil + } + out := new(ConfigFile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Descriptor) DeepCopyInto(out *Descriptor) { + *out = *in + out.Digest = in.Digest + if in.URLs != nil { + in, out := &in.URLs, &out.URLs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Descriptor. +func (in *Descriptor) DeepCopy() *Descriptor { + if in == nil { + return nil + } + out := new(Descriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Hash) DeepCopyInto(out *Hash) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Hash. +func (in *Hash) DeepCopy() *Hash { + if in == nil { + return nil + } + out := new(Hash) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *History) DeepCopyInto(out *History) { + *out = *in + in.Created.DeepCopyInto(&out.Created) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new History. +func (in *History) DeepCopy() *History { + if in == nil { + return nil + } + out := new(History) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Manifest) DeepCopyInto(out *Manifest) { + *out = *in + in.Config.DeepCopyInto(&out.Config) + if in.Layers != nil { + in, out := &in.Layers, &out.Layers + *out = make([]Descriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Manifest. +func (in *Manifest) DeepCopy() *Manifest { + if in == nil { + return nil + } + out := new(Manifest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RootFS) DeepCopyInto(out *RootFS) { + *out = *in + if in.DiffIDs != nil { + in, out := &in.DiffIDs, &out.DiffIDs + *out = make([]Hash, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RootFS. +func (in *RootFS) DeepCopy() *RootFS { + if in == nil { + return nil + } + out := new(RootFS) + in.DeepCopyInto(out) + return out +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Time. +func (in *Time) DeepCopy() *Time { + if in == nil { + return nil + } + out := new(Time) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/gorilla/context/LICENSE b/vendor/github.com/gorilla/context/LICENSE deleted file mode 100644 index 0e5fb87280..0000000000 --- a/vendor/github.com/gorilla/context/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/context/context.go b/vendor/github.com/gorilla/context/context.go deleted file mode 100644 index 81cb128b19..0000000000 --- a/vendor/github.com/gorilla/context/context.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context - -import ( - "net/http" - "sync" - "time" -) - -var ( - mutex sync.RWMutex - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) -) - -// Set stores a value for a given key in a given request. -func Set(r *http.Request, key, val interface{}) { - mutex.Lock() - if data[r] == nil { - data[r] = make(map[interface{}]interface{}) - datat[r] = time.Now().Unix() - } - data[r][key] = val - mutex.Unlock() -} - -// Get returns a value stored for a given key in a given request. -func Get(r *http.Request, key interface{}) interface{} { - mutex.RLock() - if ctx := data[r]; ctx != nil { - value := ctx[key] - mutex.RUnlock() - return value - } - mutex.RUnlock() - return nil -} - -// GetOk returns stored value and presence state like multi-value return of map access. -func GetOk(r *http.Request, key interface{}) (interface{}, bool) { - mutex.RLock() - if _, ok := data[r]; ok { - value, ok := data[r][key] - mutex.RUnlock() - return value, ok - } - mutex.RUnlock() - return nil, false -} - -// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. -func GetAll(r *http.Request) map[interface{}]interface{} { - mutex.RLock() - if context, ok := data[r]; ok { - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result - } - mutex.RUnlock() - return nil -} - -// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if -// the request was registered. -func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { - mutex.RLock() - context, ok := data[r] - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result, ok -} - -// Delete removes a value stored for a given key in a given request. -func Delete(r *http.Request, key interface{}) { - mutex.Lock() - if data[r] != nil { - delete(data[r], key) - } - mutex.Unlock() -} - -// Clear removes all values stored for a given request. -// -// This is usually called by a handler wrapper to clean up request -// variables at the end of a request lifetime. See ClearHandler(). -func Clear(r *http.Request) { - mutex.Lock() - clear(r) - mutex.Unlock() -} - -// clear is Clear without the lock. -func clear(r *http.Request) { - delete(data, r) - delete(datat, r) -} - -// Purge removes request data stored for longer than maxAge, in seconds. -// It returns the amount of requests removed. -// -// If maxAge <= 0, all request data is removed. -// -// This is only used for sanity check: in case context cleaning was not -// properly set some request data can be kept forever, consuming an increasing -// amount of memory. In case this is detected, Purge() must be called -// periodically until the problem is fixed. -func Purge(maxAge int) int { - mutex.Lock() - count := 0 - if maxAge <= 0 { - count = len(data) - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) - } else { - min := time.Now().Unix() - int64(maxAge) - for r := range data { - if datat[r] < min { - clear(r) - count++ - } - } - } - mutex.Unlock() - return count -} - -// ClearHandler wraps an http.Handler and clears request values at the end -// of a request lifetime. -func ClearHandler(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer Clear(r) - h.ServeHTTP(w, r) - }) -} diff --git a/vendor/github.com/gorilla/context/doc.go b/vendor/github.com/gorilla/context/doc.go deleted file mode 100644 index 73c7400311..0000000000 --- a/vendor/github.com/gorilla/context/doc.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package context stores values shared during a request lifetime. - -For example, a router can set variables extracted from the URL and later -application handlers can access those values, or it can be used to store -sessions values to be saved at the end of a request. There are several -others common uses. - -The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: - - http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 - -Here's the basic usage: first define the keys that you will need. The key -type is interface{} so a key can be of any type that supports equality. -Here we define a key using a custom int type to avoid name collisions: - - package foo - - import ( - "github.com/gorilla/context" - ) - - type key int - - const MyKey key = 0 - -Then set a variable. Variables are bound to an http.Request object, so you -need a request instance to set a value: - - context.Set(r, MyKey, "bar") - -The application can later access the variable using the same key you provided: - - func MyHandler(w http.ResponseWriter, r *http.Request) { - // val is "bar". - val := context.Get(r, foo.MyKey) - - // returns ("bar", true) - val, ok := context.GetOk(r, foo.MyKey) - // ... - } - -And that's all about the basic usage. We discuss some other ideas below. - -Any type can be stored in the context. To enforce a given type, make the key -private and wrap Get() and Set() to accept and return values of a specific -type: - - type key int - - const mykey key = 0 - - // GetMyKey returns a value for this package from the request values. - func GetMyKey(r *http.Request) SomeType { - if rv := context.Get(r, mykey); rv != nil { - return rv.(SomeType) - } - return nil - } - - // SetMyKey sets a value for this package in the request values. - func SetMyKey(r *http.Request, val SomeType) { - context.Set(r, mykey, val) - } - -Variables must be cleared at the end of a request, to remove all values -that were stored. This can be done in an http.Handler, after a request was -served. Just call Clear() passing the request: - - context.Clear(r) - -...or use ClearHandler(), which conveniently wraps an http.Handler to clear -variables at the end of a request lifetime. - -The Routers from the packages gorilla/mux and gorilla/pat call Clear() -so if you are using either of them you don't need to clear the context manually. -*/ -package context diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE deleted file mode 100644 index 0e5fb87280..0000000000 --- a/vendor/github.com/gorilla/mux/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/mux/context_gorilla.go b/vendor/github.com/gorilla/mux/context_gorilla.go deleted file mode 100644 index d7adaa8fad..0000000000 --- a/vendor/github.com/gorilla/mux/context_gorilla.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -package mux - -import ( - "net/http" - - "github.com/gorilla/context" -) - -func contextGet(r *http.Request, key interface{}) interface{} { - return context.Get(r, key) -} - -func contextSet(r *http.Request, key, val interface{}) *http.Request { - if val == nil { - return r - } - - context.Set(r, key, val) - return r -} - -func contextClear(r *http.Request) { - context.Clear(r) -} diff --git a/vendor/github.com/gorilla/mux/context_native.go b/vendor/github.com/gorilla/mux/context_native.go deleted file mode 100644 index 209cbea7d6..0000000000 --- a/vendor/github.com/gorilla/mux/context_native.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build go1.7 - -package mux - -import ( - "context" - "net/http" -) - -func contextGet(r *http.Request, key interface{}) interface{} { - return r.Context().Value(key) -} - -func contextSet(r *http.Request, key, val interface{}) *http.Request { - if val == nil { - return r - } - - return r.WithContext(context.WithValue(r.Context(), key, val)) -} - -func contextClear(r *http.Request) { - return -} diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go deleted file mode 100644 index 013f088985..0000000000 --- a/vendor/github.com/gorilla/mux/doc.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package mux implements a request router and dispatcher. - -The name mux stands for "HTTP request multiplexer". Like the standard -http.ServeMux, mux.Router matches incoming requests against a list of -registered routes and calls a handler for the route that matches the URL -or other conditions. The main features are: - - * Requests can be matched based on URL host, path, path prefix, schemes, - header and query values, HTTP methods or using custom matchers. - * URL hosts, paths and query values can have variables with an optional - regular expression. - * Registered URLs can be built, or "reversed", which helps maintaining - references to resources. - * Routes can be used as subrouters: nested routes are only tested if the - parent route matches. This is useful to define groups of routes that - share common conditions like a host, a path prefix or other repeated - attributes. As a bonus, this optimizes request matching. - * It implements the http.Handler interface so it is compatible with the - standard http.ServeMux. - -Let's start registering a couple of URL paths and handlers: - - func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) - } - -Here we register three routes mapping URL paths to handlers. This is -equivalent to how http.HandleFunc() works: if an incoming request URL matches -one of the paths, the corresponding handler is called passing -(http.ResponseWriter, *http.Request) as parameters. - -Paths can have variables. They are defined using the format {name} or -{name:pattern}. If a regular expression pattern is not defined, the matched -variable will be anything until the next slash. For example: - - r := mux.NewRouter() - r.HandleFunc("/products/{key}", ProductHandler) - r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) - -Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: - - r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) - -The names are used to create a map of route variables which can be retrieved -calling mux.Vars(): - - vars := mux.Vars(request) - category := vars["category"] - -Note that if any capturing groups are present, mux will panic() during parsing. To prevent -this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to -"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably -when capturing groups were present. - -And this is all you need to know about the basic usage. More advanced options -are explained below. - -Routes can also be restricted to a domain or subdomain. Just define a host -pattern to be matched. They can also have variables: - - r := mux.NewRouter() - // Only matches if domain is "www.example.com". - r.Host("www.example.com") - // Matches a dynamic subdomain. - r.Host("{subdomain:[a-z]+}.domain.com") - -There are several other matchers that can be added. To match path prefixes: - - r.PathPrefix("/products/") - -...or HTTP methods: - - r.Methods("GET", "POST") - -...or URL schemes: - - r.Schemes("https") - -...or header values: - - r.Headers("X-Requested-With", "XMLHttpRequest") - -...or query values: - - r.Queries("key", "value") - -...or to use a custom matcher function: - - r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 - }) - -...and finally, it is possible to combine several matchers in a single route: - - r.HandleFunc("/products", ProductsHandler). - Host("www.example.com"). - Methods("GET"). - Schemes("http") - -Setting the same matching conditions again and again can be boring, so we have -a way to group several routes that share the same requirements. -We call it "subrouting". - -For example, let's say we have several URLs that should only match when the -host is "www.example.com". Create a route for that host and get a "subrouter" -from it: - - r := mux.NewRouter() - s := r.Host("www.example.com").Subrouter() - -Then register routes in the subrouter: - - s.HandleFunc("/products/", ProductsHandler) - s.HandleFunc("/products/{key}", ProductHandler) - s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) - -The three URL paths we registered above will only be tested if the domain is -"www.example.com", because the subrouter is tested first. This is not -only convenient, but also optimizes request matching. You can create -subrouters combining any attribute matchers accepted by a route. - -Subrouters can be used to create domain or path "namespaces": you define -subrouters in a central place and then parts of the app can register its -paths relatively to a given subrouter. - -There's one more thing about subroutes. When a subrouter has a path prefix, -the inner routes use it as base for their paths: - - r := mux.NewRouter() - s := r.PathPrefix("/products").Subrouter() - // "/products/" - s.HandleFunc("/", ProductsHandler) - // "/products/{key}/" - s.HandleFunc("/{key}/", ProductHandler) - // "/products/{key}/details" - s.HandleFunc("/{key}/details", ProductDetailsHandler) - -Note that the path provided to PathPrefix() represents a "wildcard": calling -PathPrefix("/static/").Handler(...) means that the handler will be passed any -request that matches "/static/*". This makes it easy to serve static files with mux: - - func main() { - var dir string - - flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") - flag.Parse() - r := mux.NewRouter() - - // This will serve files under http://localhost:8000/static/ - r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) - - srv := &http.Server{ - Handler: r, - Addr: "127.0.0.1:8000", - // Good practice: enforce timeouts for servers you create! - WriteTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - } - - log.Fatal(srv.ListenAndServe()) - } - -Now let's see how to build registered URLs. - -Routes can be named. All routes that define a name can have their URLs built, -or "reversed". We define a name calling Name() on a route. For example: - - r := mux.NewRouter() - r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). - Name("article") - -To build a URL, get the route and call the URL() method, passing a sequence of -key/value pairs for the route variables. For the previous route, we would do: - - url, err := r.Get("article").URL("category", "technology", "id", "42") - -...and the result will be a url.URL with the following path: - - "/articles/technology/42" - -This also works for host and query value variables: - - r := mux.NewRouter() - r.Host("{subdomain}.domain.com"). - Path("/articles/{category}/{id:[0-9]+}"). - Queries("filter", "{filter}"). - HandlerFunc(ArticleHandler). - Name("article") - - // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42", - "filter", "gorilla") - -All variables defined in the route are required, and their values must -conform to the corresponding patterns. These requirements guarantee that a -generated URL will always match a registered route -- the only exception is -for explicitly defined "build-only" routes which never match. - -Regex support also exists for matching Headers within a route. For example, we could do: - - r.HeadersRegexp("Content-Type", "application/(text|json)") - -...and the route will match both requests with a Content-Type of `application/json` as well as -`application/text` - -There's also a way to build only the URL host or path for a route: -use the methods URLHost() or URLPath() instead. For the previous route, -we would do: - - // "http://news.domain.com/" - host, err := r.Get("article").URLHost("subdomain", "news") - - // "/articles/technology/42" - path, err := r.Get("article").URLPath("category", "technology", "id", "42") - -And if you use subrouters, host and path defined separately can be built -as well: - - r := mux.NewRouter() - s := r.Host("{subdomain}.domain.com").Subrouter() - s.Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - - // "http://news.domain.com/articles/technology/42" - url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") - -Since **vX.Y.Z**, mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed if a -match is found (including subrouters). Middlewares are defined using the de facto standard type: - - type MiddlewareFunc func(http.Handler) http.Handler - -Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). - -A very basic middleware which logs the URI of the request being handled could be written as: - - func simpleMw(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Do stuff here - log.Println(r.RequestURI) - // Call the next handler, which can be another middleware in the chain, or the final handler. - next.ServeHTTP(w, r) - }) - } - -Middlewares can be added to a router using `Router.Use()`: - - r := mux.NewRouter() - r.HandleFunc("/", handler) - r.AddMiddleware(simpleMw) - -A more complex authentication middleware, which maps session token to users, could be written as: - - // Define our struct - type authenticationMiddleware struct { - tokenUsers map[string]string - } - - // Initialize it somewhere - func (amw *authenticationMiddleware) Populate() { - amw.tokenUsers["00000000"] = "user0" - amw.tokenUsers["aaaaaaaa"] = "userA" - amw.tokenUsers["05f717e5"] = "randomUser" - amw.tokenUsers["deadbeef"] = "user0" - } - - // Middleware function, which will be called for each request - func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - token := r.Header.Get("X-Session-Token") - - if user, found := amw.tokenUsers[token]; found { - // We found the token in our map - log.Printf("Authenticated user %s\n", user) - next.ServeHTTP(w, r) - } else { - http.Error(w, "Forbidden", 403) - } - }) - } - - r := mux.NewRouter() - r.HandleFunc("/", handler) - - amw := authenticationMiddleware{} - amw.Populate() - - r.Use(amw.Middleware) - -Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. - -*/ -package mux diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go deleted file mode 100644 index 8f898675ea..0000000000 --- a/vendor/github.com/gorilla/mux/middleware.go +++ /dev/null @@ -1,28 +0,0 @@ -package mux - -import "net/http" - -// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. -// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed -// to it, and then calls the handler passed as parameter to the MiddlewareFunc. -type MiddlewareFunc func(http.Handler) http.Handler - -// middleware interface is anything which implements a MiddlewareFunc named Middleware. -type middleware interface { - Middleware(handler http.Handler) http.Handler -} - -// MiddlewareFunc also implements the middleware interface. -func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { - return mw(handler) -} - -// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. -func (r *Router) Use(mwf MiddlewareFunc) { - r.middlewares = append(r.middlewares, mwf) -} - -// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. -func (r *Router) useInterface(mw middleware) { - r.middlewares = append(r.middlewares, mw) -} diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go deleted file mode 100644 index efabd24175..0000000000 --- a/vendor/github.com/gorilla/mux/mux.go +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mux - -import ( - "errors" - "fmt" - "net/http" - "path" - "regexp" -) - -var ( - ErrMethodMismatch = errors.New("method is not allowed") - ErrNotFound = errors.New("no matching route was found") -) - -// NewRouter returns a new router instance. -func NewRouter() *Router { - return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} -} - -// Router registers routes to be matched and dispatches a handler. -// -// It implements the http.Handler interface, so it can be registered to serve -// requests: -// -// var router = mux.NewRouter() -// -// func main() { -// http.Handle("/", router) -// } -// -// Or, for Google App Engine, register it in a init() function: -// -// func init() { -// http.Handle("/", router) -// } -// -// This will send all incoming requests to the router. -type Router struct { - // Configurable Handler to be used when no route matches. - NotFoundHandler http.Handler - - // Configurable Handler to be used when the request method does not match the route. - MethodNotAllowedHandler http.Handler - - // Parent route, if this is a subrouter. - parent parentRoute - // Routes to be matched, in order. - routes []*Route - // Routes by name for URL building. - namedRoutes map[string]*Route - // See Router.StrictSlash(). This defines the flag for new routes. - strictSlash bool - // See Router.SkipClean(). This defines the flag for new routes. - skipClean bool - // If true, do not clear the request context after handling the request. - // This has no effect when go1.7+ is used, since the context is stored - // on the request itself. - KeepContext bool - // see Router.UseEncodedPath(). This defines a flag for all routes. - useEncodedPath bool - // Slice of middlewares to be called after a match is found - middlewares []middleware -} - -// Match attempts to match the given request against the router's registered routes. -// -// If the request matches a route of this router or one of its subrouters the Route, -// Handler, and Vars fields of the the match argument are filled and this function -// returns true. -// -// If the request does not match any of this router's or its subrouters' routes -// then this function returns false. If available, a reason for the match failure -// will be filled in the match argument's MatchErr field. If the match failure type -// (eg: not found) has a registered handler, the handler is assigned to the Handler -// field of the match argument. -func (r *Router) Match(req *http.Request, match *RouteMatch) bool { - for _, route := range r.routes { - if route.Match(req, match) { - // Build middleware chain if no error was found - if match.MatchErr == nil { - for i := len(r.middlewares) - 1; i >= 0; i-- { - match.Handler = r.middlewares[i].Middleware(match.Handler) - } - } - return true - } - } - - if match.MatchErr == ErrMethodMismatch { - if r.MethodNotAllowedHandler != nil { - match.Handler = r.MethodNotAllowedHandler - return true - } else { - return false - } - } - - // Closest match for a router (includes sub-routers) - if r.NotFoundHandler != nil { - match.Handler = r.NotFoundHandler - match.MatchErr = ErrNotFound - return true - } - - match.MatchErr = ErrNotFound - return false -} - -// ServeHTTP dispatches the handler registered in the matched route. -// -// When there is a match, the route variables can be retrieved calling -// mux.Vars(request). -func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if !r.skipClean { - path := req.URL.Path - if r.useEncodedPath { - path = req.URL.EscapedPath() - } - // Clean path to canonical form and redirect. - if p := cleanPath(path); p != path { - - // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. - // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: - // http://code.google.com/p/go/issues/detail?id=5252 - url := *req.URL - url.Path = p - p = url.String() - - w.Header().Set("Location", p) - w.WriteHeader(http.StatusMovedPermanently) - return - } - } - var match RouteMatch - var handler http.Handler - if r.Match(req, &match) { - handler = match.Handler - req = setVars(req, match.Vars) - req = setCurrentRoute(req, match.Route) - } - - if handler == nil && match.MatchErr == ErrMethodMismatch { - handler = methodNotAllowedHandler() - } - - if handler == nil { - handler = http.NotFoundHandler() - } - - if !r.KeepContext { - defer contextClear(req) - } - - handler.ServeHTTP(w, req) -} - -// Get returns a route registered with the given name. -func (r *Router) Get(name string) *Route { - return r.getNamedRoutes()[name] -} - -// GetRoute returns a route registered with the given name. This method -// was renamed to Get() and remains here for backwards compatibility. -func (r *Router) GetRoute(name string) *Route { - return r.getNamedRoutes()[name] -} - -// StrictSlash defines the trailing slash behavior for new routes. The initial -// value is false. -// -// When true, if the route path is "/path/", accessing "/path" will perform a redirect -// to the former and vice versa. In other words, your application will always -// see the path as specified in the route. -// -// When false, if the route path is "/path", accessing "/path/" will not match -// this route and vice versa. -// -// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for -// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed -// request will be made as a GET by most clients. Use middleware or client settings -// to modify this behaviour as needed. -// -// Special case: when a route sets a path prefix using the PathPrefix() method, -// strict slash is ignored for that route because the redirect behavior can't -// be determined from a prefix alone. However, any subrouters created from that -// route inherit the original StrictSlash setting. -func (r *Router) StrictSlash(value bool) *Router { - r.strictSlash = value - return r -} - -// SkipClean defines the path cleaning behaviour for new routes. The initial -// value is false. Users should be careful about which routes are not cleaned -// -// When true, if the route path is "/path//to", it will remain with the double -// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/ -// -// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will -// become /fetch/http/xkcd.com/534 -func (r *Router) SkipClean(value bool) *Router { - r.skipClean = value - return r -} - -// UseEncodedPath tells the router to match the encoded original path -// to the routes. -// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". -// -// If not called, the router will match the unencoded path to the routes. -// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" -func (r *Router) UseEncodedPath() *Router { - r.useEncodedPath = true - return r -} - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -func (r *Router) getBuildScheme() string { - if r.parent != nil { - return r.parent.getBuildScheme() - } - return "" -} - -// getNamedRoutes returns the map where named routes are registered. -func (r *Router) getNamedRoutes() map[string]*Route { - if r.namedRoutes == nil { - if r.parent != nil { - r.namedRoutes = r.parent.getNamedRoutes() - } else { - r.namedRoutes = make(map[string]*Route) - } - } - return r.namedRoutes -} - -// getRegexpGroup returns regexp definitions from the parent route, if any. -func (r *Router) getRegexpGroup() *routeRegexpGroup { - if r.parent != nil { - return r.parent.getRegexpGroup() - } - return nil -} - -func (r *Router) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - return m -} - -// ---------------------------------------------------------------------------- -// Route factories -// ---------------------------------------------------------------------------- - -// NewRoute registers an empty route. -func (r *Router) NewRoute() *Route { - route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean, useEncodedPath: r.useEncodedPath} - r.routes = append(r.routes, route) - return route -} - -// Handle registers a new route with a matcher for the URL path. -// See Route.Path() and Route.Handler(). -func (r *Router) Handle(path string, handler http.Handler) *Route { - return r.NewRoute().Path(path).Handler(handler) -} - -// HandleFunc registers a new route with a matcher for the URL path. -// See Route.Path() and Route.HandlerFunc(). -func (r *Router) HandleFunc(path string, f func(http.ResponseWriter, - *http.Request)) *Route { - return r.NewRoute().Path(path).HandlerFunc(f) -} - -// Headers registers a new route with a matcher for request header values. -// See Route.Headers(). -func (r *Router) Headers(pairs ...string) *Route { - return r.NewRoute().Headers(pairs...) -} - -// Host registers a new route with a matcher for the URL host. -// See Route.Host(). -func (r *Router) Host(tpl string) *Route { - return r.NewRoute().Host(tpl) -} - -// MatcherFunc registers a new route with a custom matcher function. -// See Route.MatcherFunc(). -func (r *Router) MatcherFunc(f MatcherFunc) *Route { - return r.NewRoute().MatcherFunc(f) -} - -// Methods registers a new route with a matcher for HTTP methods. -// See Route.Methods(). -func (r *Router) Methods(methods ...string) *Route { - return r.NewRoute().Methods(methods...) -} - -// Path registers a new route with a matcher for the URL path. -// See Route.Path(). -func (r *Router) Path(tpl string) *Route { - return r.NewRoute().Path(tpl) -} - -// PathPrefix registers a new route with a matcher for the URL path prefix. -// See Route.PathPrefix(). -func (r *Router) PathPrefix(tpl string) *Route { - return r.NewRoute().PathPrefix(tpl) -} - -// Queries registers a new route with a matcher for URL query values. -// See Route.Queries(). -func (r *Router) Queries(pairs ...string) *Route { - return r.NewRoute().Queries(pairs...) -} - -// Schemes registers a new route with a matcher for URL schemes. -// See Route.Schemes(). -func (r *Router) Schemes(schemes ...string) *Route { - return r.NewRoute().Schemes(schemes...) -} - -// BuildVarsFunc registers a new route with a custom function for modifying -// route variables before building a URL. -func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route { - return r.NewRoute().BuildVarsFunc(f) -} - -// Walk walks the router and all its sub-routers, calling walkFn for each route -// in the tree. The routes are walked in the order they were added. Sub-routers -// are explored depth-first. -func (r *Router) Walk(walkFn WalkFunc) error { - return r.walk(walkFn, []*Route{}) -} - -// SkipRouter is used as a return value from WalkFuncs to indicate that the -// router that walk is about to descend down to should be skipped. -var SkipRouter = errors.New("skip this router") - -// WalkFunc is the type of the function called for each route visited by Walk. -// At every invocation, it is given the current route, and the current router, -// and a list of ancestor routes that lead to the current route. -type WalkFunc func(route *Route, router *Router, ancestors []*Route) error - -func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { - for _, t := range r.routes { - err := walkFn(t, r, ancestors) - if err == SkipRouter { - continue - } - if err != nil { - return err - } - for _, sr := range t.matchers { - if h, ok := sr.(*Router); ok { - ancestors = append(ancestors, t) - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - ancestors = ancestors[:len(ancestors)-1] - } - } - if h, ok := t.handler.(*Router); ok { - ancestors = append(ancestors, t) - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - ancestors = ancestors[:len(ancestors)-1] - } - } - return nil -} - -// ---------------------------------------------------------------------------- -// Context -// ---------------------------------------------------------------------------- - -// RouteMatch stores information about a matched route. -type RouteMatch struct { - Route *Route - Handler http.Handler - Vars map[string]string - - // MatchErr is set to appropriate matching error - // It is set to ErrMethodMismatch if there is a mismatch in - // the request method and route method - MatchErr error -} - -type contextKey int - -const ( - varsKey contextKey = iota - routeKey -) - -// Vars returns the route variables for the current request, if any. -func Vars(r *http.Request) map[string]string { - if rv := contextGet(r, varsKey); rv != nil { - return rv.(map[string]string) - } - return nil -} - -// CurrentRoute returns the matched route for the current request, if any. -// This only works when called inside the handler of the matched route -// because the matched route is stored in the request context which is cleared -// after the handler returns, unless the KeepContext option is set on the -// Router. -func CurrentRoute(r *http.Request) *Route { - if rv := contextGet(r, routeKey); rv != nil { - return rv.(*Route) - } - return nil -} - -func setVars(r *http.Request, val interface{}) *http.Request { - return contextSet(r, varsKey, val) -} - -func setCurrentRoute(r *http.Request, val interface{}) *http.Request { - return contextSet(r, routeKey, val) -} - -// ---------------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------------- - -// cleanPath returns the canonical path for p, eliminating . and .. elements. -// Borrowed from the net/http package. -func cleanPath(p string) string { - if p == "" { - return "/" - } - if p[0] != '/' { - p = "/" + p - } - np := path.Clean(p) - // path.Clean removes trailing slash except for root; - // put the trailing slash back if necessary. - if p[len(p)-1] == '/' && np != "/" { - np += "/" - } - - return np -} - -// uniqueVars returns an error if two slices contain duplicated strings. -func uniqueVars(s1, s2 []string) error { - for _, v1 := range s1 { - for _, v2 := range s2 { - if v1 == v2 { - return fmt.Errorf("mux: duplicated route variable %q", v2) - } - } - } - return nil -} - -// checkPairs returns the count of strings passed in, and an error if -// the count is not an even number. -func checkPairs(pairs ...string) (int, error) { - length := len(pairs) - if length%2 != 0 { - return length, fmt.Errorf( - "mux: number of parameters must be multiple of 2, got %v", pairs) - } - return length, nil -} - -// mapFromPairsToString converts variadic string parameters to a -// string to string map. -func mapFromPairsToString(pairs ...string) (map[string]string, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } - m := make(map[string]string, length/2) - for i := 0; i < length; i += 2 { - m[pairs[i]] = pairs[i+1] - } - return m, nil -} - -// mapFromPairsToRegex converts variadic string parameters to a -// string to regex map. -func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } - m := make(map[string]*regexp.Regexp, length/2) - for i := 0; i < length; i += 2 { - regex, err := regexp.Compile(pairs[i+1]) - if err != nil { - return nil, err - } - m[pairs[i]] = regex - } - return m, nil -} - -// matchInArray returns true if the given string value is in the array. -func matchInArray(arr []string, value string) bool { - for _, v := range arr { - if v == value { - return true - } - } - return false -} - -// matchMapWithString returns true if the given key/value pairs exist in a given map. -func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool { - for k, v := range toCheck { - // Check if key exists. - if canonicalKey { - k = http.CanonicalHeaderKey(k) - } - if values := toMatch[k]; values == nil { - return false - } else if v != "" { - // If value was defined as an empty string we only check that the - // key exists. Otherwise we also check for equality. - valueExists := false - for _, value := range values { - if v == value { - valueExists = true - break - } - } - if !valueExists { - return false - } - } - } - return true -} - -// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against -// the given regex -func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool { - for k, v := range toCheck { - // Check if key exists. - if canonicalKey { - k = http.CanonicalHeaderKey(k) - } - if values := toMatch[k]; values == nil { - return false - } else if v != nil { - // If value was defined as an empty string we only check that the - // key exists. Otherwise we also check for equality. - valueExists := false - for _, value := range values { - if v.MatchString(value) { - valueExists = true - break - } - } - if !valueExists { - return false - } - } - } - return true -} - -// methodNotAllowed replies to the request with an HTTP status code 405. -func methodNotAllowed(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusMethodNotAllowed) -} - -// methodNotAllowedHandler returns a simple request handler -// that replies to each request with a status code 405. -func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go deleted file mode 100644 index 2b57e5627d..0000000000 --- a/vendor/github.com/gorilla/mux/regexp.go +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mux - -import ( - "bytes" - "fmt" - "net/http" - "net/url" - "regexp" - "strconv" - "strings" -) - -type routeRegexpOptions struct { - strictSlash bool - useEncodedPath bool -} - -type regexpType int - -const ( - regexpTypePath regexpType = 0 - regexpTypeHost regexpType = 1 - regexpTypePrefix regexpType = 2 - regexpTypeQuery regexpType = 3 -) - -// newRouteRegexp parses a route template and returns a routeRegexp, -// used to match a host, a path or a query string. -// -// It will extract named variables, assemble a regexp to be matched, create -// a "reverse" template to build URLs and compile regexps to validate variable -// values used in URL building. -// -// Previously we accepted only Python-like identifiers for variable -// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that -// name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { - // Check if it is well-formed. - idxs, errBraces := braceIndices(tpl) - if errBraces != nil { - return nil, errBraces - } - // Backup the original. - template := tpl - // Now let's parse it. - defaultPattern := "[^/]+" - if typ == regexpTypeQuery { - defaultPattern = ".*" - } else if typ == regexpTypeHost { - defaultPattern = "[^.]+" - } - // Only match strict slash if not matching - if typ != regexpTypePath { - options.strictSlash = false - } - // Set a flag for strictSlash. - endSlash := false - if options.strictSlash && strings.HasSuffix(tpl, "/") { - tpl = tpl[:len(tpl)-1] - endSlash = true - } - varsN := make([]string, len(idxs)/2) - varsR := make([]*regexp.Regexp, len(idxs)/2) - pattern := bytes.NewBufferString("") - pattern.WriteByte('^') - reverse := bytes.NewBufferString("") - var end int - var err error - for i := 0; i < len(idxs); i += 2 { - // Set all values we are interested in. - raw := tpl[end:idxs[i]] - end = idxs[i+1] - parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) - name := parts[0] - patt := defaultPattern - if len(parts) == 2 { - patt = parts[1] - } - // Name or pattern can't be empty. - if name == "" || patt == "" { - return nil, fmt.Errorf("mux: missing name or pattern in %q", - tpl[idxs[i]:end]) - } - // Build the regexp pattern. - fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt) - - // Build the reverse template. - fmt.Fprintf(reverse, "%s%%s", raw) - - // Append variable name and compiled pattern. - varsN[i/2] = name - varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) - if err != nil { - return nil, err - } - } - // Add the remaining. - raw := tpl[end:] - pattern.WriteString(regexp.QuoteMeta(raw)) - if options.strictSlash { - pattern.WriteString("[/]?") - } - if typ == regexpTypeQuery { - // Add the default pattern if the query value is empty - if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { - pattern.WriteString(defaultPattern) - } - } - if typ != regexpTypePrefix { - pattern.WriteByte('$') - } - reverse.WriteString(raw) - if endSlash { - reverse.WriteByte('/') - } - // Compile full regexp. - reg, errCompile := regexp.Compile(pattern.String()) - if errCompile != nil { - return nil, errCompile - } - - // Check for capturing groups which used to work in older versions - if reg.NumSubexp() != len(idxs)/2 { - panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + - "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") - } - - // Done! - return &routeRegexp{ - template: template, - regexpType: typ, - options: options, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, - }, nil -} - -// routeRegexp stores a regexp to match a host or path and information to -// collect and validate route variables. -type routeRegexp struct { - // The unmodified template. - template string - // The type of match - regexpType regexpType - // Options for matching - options routeRegexpOptions - // Expanded regexp. - regexp *regexp.Regexp - // Reverse template. - reverse string - // Variable names. - varsN []string - // Variable regexps (validators). - varsR []*regexp.Regexp -} - -// Match matches the regexp against the URL host or path. -func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if r.regexpType != regexpTypeHost { - if r.regexpType == regexpTypeQuery { - return r.matchQueryString(req) - } - path := req.URL.Path - if r.options.useEncodedPath { - path = req.URL.EscapedPath() - } - return r.regexp.MatchString(path) - } - - return r.regexp.MatchString(getHost(req)) -} - -// url builds a URL part using the given values. -func (r *routeRegexp) url(values map[string]string) (string, error) { - urlValues := make([]interface{}, len(r.varsN)) - for k, v := range r.varsN { - value, ok := values[v] - if !ok { - return "", fmt.Errorf("mux: missing route variable %q", v) - } - if r.regexpType == regexpTypeQuery { - value = url.QueryEscape(value) - } - urlValues[k] = value - } - rv := fmt.Sprintf(r.reverse, urlValues...) - if !r.regexp.MatchString(rv) { - // The URL is checked against the full regexp, instead of checking - // individual variables. This is faster but to provide a good error - // message, we check individual regexps if the URL doesn't match. - for k, v := range r.varsN { - if !r.varsR[k].MatchString(values[v]) { - return "", fmt.Errorf( - "mux: variable %q doesn't match, expected %q", values[v], - r.varsR[k].String()) - } - } - } - return rv, nil -} - -// getURLQuery returns a single query parameter from a request URL. -// For a URL with foo=bar&baz=ding, we return only the relevant key -// value pair for the routeRegexp. -func (r *routeRegexp) getURLQuery(req *http.Request) string { - if r.regexpType != regexpTypeQuery { - return "" - } - templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } - } - return "" -} - -func (r *routeRegexp) matchQueryString(req *http.Request) bool { - return r.regexp.MatchString(r.getURLQuery(req)) -} - -// braceIndices returns the first level curly brace indices from a string. -// It returns an error in case of unbalanced braces. -func braceIndices(s string) ([]int, error) { - var level, idx int - var idxs []int - for i := 0; i < len(s); i++ { - switch s[i] { - case '{': - if level++; level == 1 { - idx = i - } - case '}': - if level--; level == 0 { - idxs = append(idxs, idx, i+1) - } else if level < 0 { - return nil, fmt.Errorf("mux: unbalanced braces in %q", s) - } - } - } - if level != 0 { - return nil, fmt.Errorf("mux: unbalanced braces in %q", s) - } - return idxs, nil -} - -// varGroupName builds a capturing group name for the indexed variable. -func varGroupName(idx int) string { - return "v" + strconv.Itoa(idx) -} - -// ---------------------------------------------------------------------------- -// routeRegexpGroup -// ---------------------------------------------------------------------------- - -// routeRegexpGroup groups the route matchers that carry variables. -type routeRegexpGroup struct { - host *routeRegexp - path *routeRegexp - queries []*routeRegexp -} - -// setMatch extracts the variables from the URL once a route matches. -func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { - // Store host variables. - if v.host != nil { - host := getHost(req) - matches := v.host.regexp.FindStringSubmatchIndex(host) - if len(matches) > 0 { - extractVars(host, matches, v.host.varsN, m.Vars) - } - } - path := req.URL.Path - if r.useEncodedPath { - path = req.URL.EscapedPath() - } - // Store path variables. - if v.path != nil { - matches := v.path.regexp.FindStringSubmatchIndex(path) - if len(matches) > 0 { - extractVars(path, matches, v.path.varsN, m.Vars) - // Check if we should redirect. - if v.path.options.strictSlash { - p1 := strings.HasSuffix(path, "/") - p2 := strings.HasSuffix(v.path.template, "/") - if p1 != p2 { - u, _ := url.Parse(req.URL.String()) - if p1 { - u.Path = u.Path[:len(u.Path)-1] - } else { - u.Path += "/" - } - m.Handler = http.RedirectHandler(u.String(), 301) - } - } - } - } - // Store query string variables. - for _, q := range v.queries { - queryURL := q.getURLQuery(req) - matches := q.regexp.FindStringSubmatchIndex(queryURL) - if len(matches) > 0 { - extractVars(queryURL, matches, q.varsN, m.Vars) - } - } -} - -// getHost tries its best to return the request host. -func getHost(r *http.Request) string { - if r.URL.IsAbs() { - return r.URL.Host - } - host := r.Host - // Slice off any port information. - if i := strings.Index(host, ":"); i != -1 { - host = host[:i] - } - return host - -} - -func extractVars(input string, matches []int, names []string, output map[string]string) { - for i, name := range names { - output[name] = input[matches[2*i+2]:matches[2*i+3]] - } -} diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go deleted file mode 100644 index 4ce098d4fb..0000000000 --- a/vendor/github.com/gorilla/mux/route.go +++ /dev/null @@ -1,761 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mux - -import ( - "errors" - "fmt" - "net/http" - "net/url" - "regexp" - "strings" -) - -// Route stores information to match a request and build URLs. -type Route struct { - // Parent where the route was registered (a Router). - parent parentRoute - // Request handler for the route. - handler http.Handler - // List of matchers. - matchers []matcher - // Manager for the variables from host and path. - regexp *routeRegexpGroup - // If true, when the path pattern is "/path/", accessing "/path" will - // redirect to the former and vice versa. - strictSlash bool - // If true, when the path pattern is "/path//to", accessing "/path//to" - // will not redirect - skipClean bool - // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" - useEncodedPath bool - // The scheme used when building URLs. - buildScheme string - // If true, this route never matches: it is only used to build URLs. - buildOnly bool - // The name used to build URLs. - name string - // Error resulted from building a route. - err error - - buildVarsFunc BuildVarsFunc -} - -func (r *Route) SkipClean() bool { - return r.skipClean -} - -// Match matches the route against the request. -func (r *Route) Match(req *http.Request, match *RouteMatch) bool { - if r.buildOnly || r.err != nil { - return false - } - - var matchErr error - - // Match everything. - for _, m := range r.matchers { - if matched := m.Match(req, match); !matched { - if _, ok := m.(methodMatcher); ok { - matchErr = ErrMethodMismatch - continue - } - matchErr = nil - return false - } - } - - if matchErr != nil { - match.MatchErr = matchErr - return false - } - - if match.MatchErr == ErrMethodMismatch { - // We found a route which matches request method, clear MatchErr - match.MatchErr = nil - // Then override the mis-matched handler - match.Handler = r.handler - } - - // Yay, we have a match. Let's collect some info about it. - if match.Route == nil { - match.Route = r - } - if match.Handler == nil { - match.Handler = r.handler - } - if match.Vars == nil { - match.Vars = make(map[string]string) - } - - // Set variables. - if r.regexp != nil { - r.regexp.setMatch(req, match, r) - } - return true -} - -// ---------------------------------------------------------------------------- -// Route attributes -// ---------------------------------------------------------------------------- - -// GetError returns an error resulted from building the route, if any. -func (r *Route) GetError() error { - return r.err -} - -// BuildOnly sets the route to never match: it is only used to build URLs. -func (r *Route) BuildOnly() *Route { - r.buildOnly = true - return r -} - -// Handler -------------------------------------------------------------------- - -// Handler sets a handler for the route. -func (r *Route) Handler(handler http.Handler) *Route { - if r.err == nil { - r.handler = handler - } - return r -} - -// HandlerFunc sets a handler function for the route. -func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route { - return r.Handler(http.HandlerFunc(f)) -} - -// GetHandler returns the handler for the route, if any. -func (r *Route) GetHandler() http.Handler { - return r.handler -} - -// Name ----------------------------------------------------------------------- - -// Name sets the name for the route, used to build URLs. -// If the name was registered already it will be overwritten. -func (r *Route) Name(name string) *Route { - if r.name != "" { - r.err = fmt.Errorf("mux: route already has name %q, can't set %q", - r.name, name) - } - if r.err == nil { - r.name = name - r.getNamedRoutes()[name] = r - } - return r -} - -// GetName returns the name for the route, if any. -func (r *Route) GetName() string { - return r.name -} - -// ---------------------------------------------------------------------------- -// Matchers -// ---------------------------------------------------------------------------- - -// matcher types try to match a request. -type matcher interface { - Match(*http.Request, *RouteMatch) bool -} - -// addMatcher adds a matcher to the route. -func (r *Route) addMatcher(m matcher) *Route { - if r.err == nil { - r.matchers = append(r.matchers, m) - } - return r -} - -// addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { - if r.err != nil { - return r.err - } - r.regexp = r.getRegexpGroup() - if typ == regexpTypePath || typ == regexpTypePrefix { - if len(tpl) > 0 && tpl[0] != '/' { - return fmt.Errorf("mux: path must start with a slash, got %q", tpl) - } - if r.regexp.path != nil { - tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl - } - } - rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ - strictSlash: r.strictSlash, - useEncodedPath: r.useEncodedPath, - }) - if err != nil { - return err - } - for _, q := range r.regexp.queries { - if err = uniqueVars(rr.varsN, q.varsN); err != nil { - return err - } - } - if typ == regexpTypeHost { - if r.regexp.path != nil { - if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { - return err - } - } - r.regexp.host = rr - } else { - if r.regexp.host != nil { - if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil { - return err - } - } - if typ == regexpTypeQuery { - r.regexp.queries = append(r.regexp.queries, rr) - } else { - r.regexp.path = rr - } - } - r.addMatcher(rr) - return nil -} - -// Headers -------------------------------------------------------------------- - -// headerMatcher matches the request against header values. -type headerMatcher map[string]string - -func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithString(m, r.Header, true) -} - -// Headers adds a matcher for request header values. -// It accepts a sequence of key/value pairs to be matched. For example: -// -// r := mux.NewRouter() -// r.Headers("Content-Type", "application/json", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will only match if both request header values match. -// If the value is an empty string, it will match any value if the key is set. -func (r *Route) Headers(pairs ...string) *Route { - if r.err == nil { - var headers map[string]string - headers, r.err = mapFromPairsToString(pairs...) - return r.addMatcher(headerMatcher(headers)) - } - return r -} - -// headerRegexMatcher matches the request against the route given a regex for the header -type headerRegexMatcher map[string]*regexp.Regexp - -func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithRegex(m, r.Header, true) -} - -// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex -// support. For example: -// -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will only match if both the request header matches both regular expressions. -// If the value is an empty string, it will match any value if the key is set. -// Use the start and end of string anchors (^ and $) to match an exact value. -func (r *Route) HeadersRegexp(pairs ...string) *Route { - if r.err == nil { - var headers map[string]*regexp.Regexp - headers, r.err = mapFromPairsToRegex(pairs...) - return r.addMatcher(headerRegexMatcher(headers)) - } - return r -} - -// Host ----------------------------------------------------------------------- - -// Host adds a matcher for the URL host. -// It accepts a template with zero or more URL variables enclosed by {}. -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next dot. -// -// - {name:pattern} matches the given regexp pattern. -// -// For example: -// -// r := mux.NewRouter() -// r.Host("www.example.com") -// r.Host("{subdomain}.domain.com") -// r.Host("{subdomain:[a-z]+}.domain.com") -// -// Variable names must be unique in a given route. They can be retrieved -// calling mux.Vars(request). -func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypeHost) - return r -} - -// MatcherFunc ---------------------------------------------------------------- - -// MatcherFunc is the function signature used by custom matchers. -type MatcherFunc func(*http.Request, *RouteMatch) bool - -// Match returns the match for a given request. -func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { - return m(r, match) -} - -// MatcherFunc adds a custom function to be used as request matcher. -func (r *Route) MatcherFunc(f MatcherFunc) *Route { - return r.addMatcher(f) -} - -// Methods -------------------------------------------------------------------- - -// methodMatcher matches the request against HTTP methods. -type methodMatcher []string - -func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.Method) -} - -// Methods adds a matcher for HTTP methods. -// It accepts a sequence of one or more methods to be matched, e.g.: -// "GET", "POST", "PUT". -func (r *Route) Methods(methods ...string) *Route { - for k, v := range methods { - methods[k] = strings.ToUpper(v) - } - return r.addMatcher(methodMatcher(methods)) -} - -// Path ----------------------------------------------------------------------- - -// Path adds a matcher for the URL path. -// It accepts a template with zero or more URL variables enclosed by {}. The -// template must start with a "/". -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next slash. -// -// - {name:pattern} matches the given regexp pattern. -// -// For example: -// -// r := mux.NewRouter() -// r.Path("/products/").Handler(ProductsHandler) -// r.Path("/products/{key}").Handler(ProductsHandler) -// r.Path("/articles/{category}/{id:[0-9]+}"). -// Handler(ArticleHandler) -// -// Variable names must be unique in a given route. They can be retrieved -// calling mux.Vars(request). -func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypePath) - return r -} - -// PathPrefix ----------------------------------------------------------------- - -// PathPrefix adds a matcher for the URL path prefix. This matches if the given -// template is a prefix of the full URL path. See Route.Path() for details on -// the tpl argument. -// -// Note that it does not treat slashes specially ("/foobar/" will be matched by -// the prefix "/foo") so you may want to use a trailing slash here. -// -// Also note that the setting of Router.StrictSlash() has no effect on routes -// with a PathPrefix matcher. -func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) - return r -} - -// Query ---------------------------------------------------------------------- - -// Queries adds a matcher for URL query values. -// It accepts a sequence of key/value pairs. Values may define variables. -// For example: -// -// r := mux.NewRouter() -// r.Queries("foo", "bar", "id", "{id:[0-9]+}") -// -// The above route will only match if the URL contains the defined queries -// values, e.g.: ?foo=bar&id=42. -// -// It the value is an empty string, it will match any value if the key is set. -// -// Variables can define an optional regexp pattern to be matched: -// -// - {name} matches anything until the next slash. -// -// - {name:pattern} matches the given regexp pattern. -func (r *Route) Queries(pairs ...string) *Route { - length := len(pairs) - if length%2 != 0 { - r.err = fmt.Errorf( - "mux: number of parameters must be multiple of 2, got %v", pairs) - return nil - } - for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { - return r - } - } - - return r -} - -// Schemes -------------------------------------------------------------------- - -// schemeMatcher matches the request against URL schemes. -type schemeMatcher []string - -func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.URL.Scheme) -} - -// Schemes adds a matcher for URL schemes. -// It accepts a sequence of schemes to be matched, e.g.: "http", "https". -func (r *Route) Schemes(schemes ...string) *Route { - for k, v := range schemes { - schemes[k] = strings.ToLower(v) - } - if r.buildScheme == "" && len(schemes) > 0 { - r.buildScheme = schemes[0] - } - return r.addMatcher(schemeMatcher(schemes)) -} - -// BuildVarsFunc -------------------------------------------------------------- - -// BuildVarsFunc is the function signature used by custom build variable -// functions (which can modify route variables before a route's URL is built). -type BuildVarsFunc func(map[string]string) map[string]string - -// BuildVarsFunc adds a custom function to be used to modify build variables -// before a route's URL is built. -func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { - r.buildVarsFunc = f - return r -} - -// Subrouter ------------------------------------------------------------------ - -// Subrouter creates a subrouter for the route. -// -// It will test the inner routes only if the parent route matched. For example: -// -// r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() -// s.HandleFunc("/products/", ProductsHandler) -// s.HandleFunc("/products/{key}", ProductHandler) -// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) -// -// Here, the routes registered in the subrouter won't be tested if the host -// doesn't match. -func (r *Route) Subrouter() *Router { - router := &Router{parent: r, strictSlash: r.strictSlash} - r.addMatcher(router) - return router -} - -// ---------------------------------------------------------------------------- -// URL building -// ---------------------------------------------------------------------------- - -// URL builds a URL for the route. -// -// It accepts a sequence of key/value pairs for the route variables. For -// example, given this route: -// -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") -// -// ...a URL for it can be built using: -// -// url, err := r.Get("article").URL("category", "technology", "id", "42") -// -// ...which will return an url.URL with the following path: -// -// "/articles/technology/42" -// -// This also works for host variables: -// -// r := mux.NewRouter() -// r.Host("{subdomain}.domain.com"). -// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") -// -// // url.String() will be "http://news.domain.com/articles/technology/42" -// url, err := r.Get("article").URL("subdomain", "news", -// "category", "technology", -// "id", "42") -// -// All variables defined in the route are required, and their values must -// conform to the corresponding patterns. -func (r *Route) URL(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil { - return nil, errors.New("mux: route doesn't have a host or path") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - var scheme, host, path string - queries := make([]string, 0, len(r.regexp.queries)) - if r.regexp.host != nil { - if host, err = r.regexp.host.url(values); err != nil { - return nil, err - } - scheme = "http" - if s := r.getBuildScheme(); s != "" { - scheme = s - } - } - if r.regexp.path != nil { - if path, err = r.regexp.path.url(values); err != nil { - return nil, err - } - } - for _, q := range r.regexp.queries { - var query string - if query, err = q.url(values); err != nil { - return nil, err - } - queries = append(queries, query) - } - return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, - RawQuery: strings.Join(queries, "&"), - }, nil -} - -// URLHost builds the host part of the URL for a route. See Route.URL(). -// -// The route must have a host defined. -func (r *Route) URLHost(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.host == nil { - return nil, errors.New("mux: route doesn't have a host") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - host, err := r.regexp.host.url(values) - if err != nil { - return nil, err - } - u := &url.URL{ - Scheme: "http", - Host: host, - } - if s := r.getBuildScheme(); s != "" { - u.Scheme = s - } - return u, nil -} - -// URLPath builds the path part of the URL for a route. See Route.URL(). -// -// The route must have a path defined. -func (r *Route) URLPath(pairs ...string) (*url.URL, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.path == nil { - return nil, errors.New("mux: route doesn't have a path") - } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - path, err := r.regexp.path.url(values) - if err != nil { - return nil, err - } - return &url.URL{ - Path: path, - }, nil -} - -// GetPathTemplate returns the template used to build the -// route match. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a path. -func (r *Route) GetPathTemplate() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.path == nil { - return "", errors.New("mux: route doesn't have a path") - } - return r.regexp.path.template, nil -} - -// GetPathRegexp returns the expanded regular expression used to match route path. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a path. -func (r *Route) GetPathRegexp() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.path == nil { - return "", errors.New("mux: route does not have a path") - } - return r.regexp.path.regexp.String(), nil -} - -// GetQueriesRegexp returns the expanded regular expressions used to match the -// route queries. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An empty list will be returned if the route does not have queries. -func (r *Route) GetQueriesRegexp() ([]string, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.queries == nil { - return nil, errors.New("mux: route doesn't have queries") - } - var queries []string - for _, query := range r.regexp.queries { - queries = append(queries, query.regexp.String()) - } - return queries, nil -} - -// GetQueriesTemplates returns the templates used to build the -// query matching. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An empty list will be returned if the route does not define queries. -func (r *Route) GetQueriesTemplates() ([]string, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.queries == nil { - return nil, errors.New("mux: route doesn't have queries") - } - var queries []string - for _, query := range r.regexp.queries { - queries = append(queries, query.template) - } - return queries, nil -} - -// GetMethods returns the methods the route matches against -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An empty list will be returned if route does not have methods. -func (r *Route) GetMethods() ([]string, error) { - if r.err != nil { - return nil, r.err - } - for _, m := range r.matchers { - if methods, ok := m.(methodMatcher); ok { - return []string(methods), nil - } - } - return nil, nil -} - -// GetHostTemplate returns the template used to build the -// route match. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a host. -func (r *Route) GetHostTemplate() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.host == nil { - return "", errors.New("mux: route doesn't have a host") - } - return r.regexp.host.template, nil -} - -// prepareVars converts the route variable pairs into a map. If the route has a -// BuildVarsFunc, it is invoked. -func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { - m, err := mapFromPairsToString(pairs...) - if err != nil { - return nil, err - } - return r.buildVars(m), nil -} - -func (r *Route) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - if r.buildVarsFunc != nil { - m = r.buildVarsFunc(m) - } - return m -} - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// parentRoute allows routes to know about parent host and path definitions. -type parentRoute interface { - getBuildScheme() string - getNamedRoutes() map[string]*Route - getRegexpGroup() *routeRegexpGroup - buildVars(map[string]string) map[string]string -} - -func (r *Route) getBuildScheme() string { - if r.buildScheme != "" { - return r.buildScheme - } - if r.parent != nil { - return r.parent.getBuildScheme() - } - return "" -} - -// getNamedRoutes returns the map where named routes are registered. -func (r *Route) getNamedRoutes() map[string]*Route { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - return r.parent.getNamedRoutes() -} - -// getRegexpGroup returns regexp definitions from this route. -func (r *Route) getRegexpGroup() *routeRegexpGroup { - if r.regexp == nil { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - regexp := r.parent.getRegexpGroup() - if regexp == nil { - r.regexp = new(routeRegexpGroup) - } else { - // Copy. - r.regexp = &routeRegexpGroup{ - host: regexp.host, - path: regexp.path, - queries: regexp.queries, - } - } - } - return r.regexp -} diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go deleted file mode 100644 index 8b2c4a4c58..0000000000 --- a/vendor/github.com/gorilla/mux/test_helpers.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mux - -import "net/http" - -// SetURLVars sets the URL variables for the given request, to be accessed via -// mux.Vars for testing route behaviour. -// -// This API should only be used for testing purposes; it provides a way to -// inject variables into the request context. Alternatively, URL variables -// can be set by making a route that captures the required variables, -// starting a server and sending the request to that server. -func SetURLVars(r *http.Request, val map[string]string) *http.Request { - return setVars(r, val) -} diff --git a/vendor/github.com/imdario/mergo/LICENSE b/vendor/github.com/imdario/mergo/LICENSE deleted file mode 100644 index 686680298d..0000000000 --- a/vendor/github.com/imdario/mergo/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2013 Dario Castañé. All rights reserved. -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/imdario/mergo/doc.go b/vendor/github.com/imdario/mergo/doc.go deleted file mode 100644 index 6e9aa7baf3..0000000000 --- a/vendor/github.com/imdario/mergo/doc.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 Dario Castañé. All rights reserved. -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package mergo merges same-type structs and maps by setting default values in zero-value fields. - -Mergo won't merge unexported (private) fields but will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection). - -Usage - -From my own work-in-progress project: - - type networkConfig struct { - Protocol string - Address string - ServerType string `json: "server_type"` - Port uint16 - } - - type FssnConfig struct { - Network networkConfig - } - - var fssnDefault = FssnConfig { - networkConfig { - "tcp", - "127.0.0.1", - "http", - 31560, - }, - } - - // Inside a function [...] - - if err := mergo.Merge(&config, fssnDefault); err != nil { - log.Fatal(err) - } - - // More code [...] - -*/ -package mergo diff --git a/vendor/github.com/imdario/mergo/map.go b/vendor/github.com/imdario/mergo/map.go deleted file mode 100644 index 6ea38e636b..0000000000 --- a/vendor/github.com/imdario/mergo/map.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2014 Dario Castañé. All rights reserved. -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Based on src/pkg/reflect/deepequal.go from official -// golang's stdlib. - -package mergo - -import ( - "fmt" - "reflect" - "unicode" - "unicode/utf8" -) - -func changeInitialCase(s string, mapper func(rune) rune) string { - if s == "" { - return s - } - r, n := utf8.DecodeRuneInString(s) - return string(mapper(r)) + s[n:] -} - -func isExported(field reflect.StructField) bool { - r, _ := utf8.DecodeRuneInString(field.Name) - return r >= 'A' && r <= 'Z' -} - -// Traverses recursively both values, assigning src's fields values to dst. -// The map argument tracks comparisons that have already been seen, which allows -// short circuiting on recursive types. -func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { - overwrite := config.Overwrite - if dst.CanAddr() { - addr := dst.UnsafeAddr() - h := 17 * addr - seen := visited[h] - typ := dst.Type() - for p := seen; p != nil; p = p.next { - if p.ptr == addr && p.typ == typ { - return nil - } - } - // Remember, remember... - visited[h] = &visit{addr, typ, seen} - } - zeroValue := reflect.Value{} - switch dst.Kind() { - case reflect.Map: - dstMap := dst.Interface().(map[string]interface{}) - for i, n := 0, src.NumField(); i < n; i++ { - srcType := src.Type() - field := srcType.Field(i) - if !isExported(field) { - continue - } - fieldName := field.Name - fieldName = changeInitialCase(fieldName, unicode.ToLower) - if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) { - dstMap[fieldName] = src.Field(i).Interface() - } - } - case reflect.Ptr: - if dst.IsNil() { - v := reflect.New(dst.Type().Elem()) - dst.Set(v) - } - dst = dst.Elem() - fallthrough - case reflect.Struct: - srcMap := src.Interface().(map[string]interface{}) - for key := range srcMap { - srcValue := srcMap[key] - fieldName := changeInitialCase(key, unicode.ToUpper) - dstElement := dst.FieldByName(fieldName) - if dstElement == zeroValue { - // We discard it because the field doesn't exist. - continue - } - srcElement := reflect.ValueOf(srcValue) - dstKind := dstElement.Kind() - srcKind := srcElement.Kind() - if srcKind == reflect.Ptr && dstKind != reflect.Ptr { - srcElement = srcElement.Elem() - srcKind = reflect.TypeOf(srcElement.Interface()).Kind() - } else if dstKind == reflect.Ptr { - // Can this work? I guess it can't. - if srcKind != reflect.Ptr && srcElement.CanAddr() { - srcPtr := srcElement.Addr() - srcElement = reflect.ValueOf(srcPtr) - srcKind = reflect.Ptr - } - } - - if !srcElement.IsValid() { - continue - } - if srcKind == dstKind { - if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { - return - } - } else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface { - if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { - return - } - } else if srcKind == reflect.Map { - if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil { - return - } - } else { - return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind) - } - } - } - return -} - -// Map sets fields' values in dst from src. -// src can be a map with string keys or a struct. dst must be the opposite: -// if src is a map, dst must be a valid pointer to struct. If src is a struct, -// dst must be map[string]interface{}. -// It won't merge unexported (private) fields and will do recursively -// any exported field. -// If dst is a map, keys will be src fields' names in lower camel case. -// Missing key in src that doesn't match a field in dst will be skipped. This -// doesn't apply if dst is a map. -// This is separated method from Merge because it is cleaner and it keeps sane -// semantics: merging equal types, mapping different (restricted) types. -func Map(dst, src interface{}, opts ...func(*Config)) error { - return _map(dst, src, opts...) -} - -// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overridden by -// non-empty src attribute values. -// Deprecated: Use Map(…) with WithOverride -func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { - return _map(dst, src, append(opts, WithOverride)...) -} - -func _map(dst, src interface{}, opts ...func(*Config)) error { - var ( - vDst, vSrc reflect.Value - err error - ) - config := &Config{} - - for _, opt := range opts { - opt(config) - } - - if vDst, vSrc, err = resolveValues(dst, src); err != nil { - return err - } - // To be friction-less, we redirect equal-type arguments - // to deepMerge. Only because arguments can be anything. - if vSrc.Kind() == vDst.Kind() { - return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) - } - switch vSrc.Kind() { - case reflect.Struct: - if vDst.Kind() != reflect.Map { - return ErrExpectedMapAsDestination - } - case reflect.Map: - if vDst.Kind() != reflect.Struct { - return ErrExpectedStructAsDestination - } - default: - return ErrNotSupported - } - return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config) -} diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/github.com/imdario/mergo/merge.go deleted file mode 100644 index f0e17924ac..0000000000 --- a/vendor/github.com/imdario/mergo/merge.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2013 Dario Castañé. All rights reserved. -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Based on src/pkg/reflect/deepequal.go from official -// golang's stdlib. - -package mergo - -import ( - "reflect" -) - -func hasExportedField(dst reflect.Value) (exported bool) { - for i, n := 0, dst.NumField(); i < n; i++ { - field := dst.Type().Field(i) - if field.Anonymous && dst.Field(i).Kind() == reflect.Struct { - exported = exported || hasExportedField(dst.Field(i)) - } else { - exported = exported || len(field.PkgPath) == 0 - } - } - return -} - -type Config struct { - Overwrite bool - AppendSlice bool - Transformers Transformers -} - -type Transformers interface { - Transformer(reflect.Type) func(dst, src reflect.Value) error -} - -// Traverses recursively both values, assigning src's fields values to dst. -// The map argument tracks comparisons that have already been seen, which allows -// short circuiting on recursive types. -func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { - overwrite := config.Overwrite - - if !src.IsValid() { - return - } - if dst.CanAddr() { - addr := dst.UnsafeAddr() - h := 17 * addr - seen := visited[h] - typ := dst.Type() - for p := seen; p != nil; p = p.next { - if p.ptr == addr && p.typ == typ { - return nil - } - } - // Remember, remember... - visited[h] = &visit{addr, typ, seen} - } - - if config.Transformers != nil && !isEmptyValue(dst) { - if fn := config.Transformers.Transformer(dst.Type()); fn != nil { - err = fn(dst, src) - return - } - } - - switch dst.Kind() { - case reflect.Struct: - if hasExportedField(dst) { - for i, n := 0, dst.NumField(); i < n; i++ { - if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil { - return - } - } - } else { - if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { - dst.Set(src) - } - } - case reflect.Map: - if dst.IsNil() && !src.IsNil() { - dst.Set(reflect.MakeMap(dst.Type())) - } - for _, key := range src.MapKeys() { - srcElement := src.MapIndex(key) - if !srcElement.IsValid() { - continue - } - dstElement := dst.MapIndex(key) - switch srcElement.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice: - if srcElement.IsNil() { - continue - } - fallthrough - default: - if !srcElement.CanInterface() { - continue - } - switch reflect.TypeOf(srcElement.Interface()).Kind() { - case reflect.Struct: - fallthrough - case reflect.Ptr: - fallthrough - case reflect.Map: - if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { - return - } - case reflect.Slice: - srcSlice := reflect.ValueOf(srcElement.Interface()) - - var dstSlice reflect.Value - if !dstElement.IsValid() || dstElement.IsNil() { - dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len()) - } else { - dstSlice = reflect.ValueOf(dstElement.Interface()) - } - - dstSlice = reflect.AppendSlice(dstSlice, srcSlice) - dst.SetMapIndex(key, dstSlice) - } - } - if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map { - continue - } - - if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) { - if dst.IsNil() { - dst.Set(reflect.MakeMap(dst.Type())) - } - dst.SetMapIndex(key, srcElement) - } - } - case reflect.Slice: - if !dst.CanSet() { - break - } - if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { - dst.Set(src) - } else { - dst.Set(reflect.AppendSlice(dst, src)) - } - case reflect.Ptr: - fallthrough - case reflect.Interface: - if src.IsNil() { - break - } - if src.Kind() != reflect.Interface { - if dst.IsNil() || overwrite { - if dst.CanSet() && (overwrite || isEmptyValue(dst)) { - dst.Set(src) - } - } else if src.Kind() == reflect.Ptr { - if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { - return - } - } else if dst.Elem().Type() == src.Type() { - if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil { - return - } - } else { - return ErrDifferentArgumentsTypes - } - break - } - if dst.IsNil() || overwrite { - if dst.CanSet() && (overwrite || isEmptyValue(dst)) { - dst.Set(src) - } - } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { - return - } - default: - if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { - dst.Set(src) - } - } - return -} - -// Merge will fill any empty for value type attributes on the dst struct using corresponding -// src attributes if they themselves are not empty. dst and src must be valid same-type structs -// and dst must be a pointer to struct. -// It won't merge unexported (private) fields and will do recursively any exported field. -func Merge(dst, src interface{}, opts ...func(*Config)) error { - return merge(dst, src, opts...) -} - -// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by -// non-empty src attribute values. -// Deprecated: use Merge(…) with WithOverride -func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { - return merge(dst, src, append(opts, WithOverride)...) -} - -// WithTransformers adds transformers to merge, allowing to customize the merging of some types. -func WithTransformers(transformers Transformers) func(*Config) { - return func(config *Config) { - config.Transformers = transformers - } -} - -// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values. -func WithOverride(config *Config) { - config.Overwrite = true -} - -// WithAppendSlice will make merge append slices instead of overwriting it -func WithAppendSlice(config *Config) { - config.AppendSlice = true -} - -func merge(dst, src interface{}, opts ...func(*Config)) error { - var ( - vDst, vSrc reflect.Value - err error - ) - - config := &Config{} - - for _, opt := range opts { - opt(config) - } - - if vDst, vSrc, err = resolveValues(dst, src); err != nil { - return err - } - if vDst.Type() != vSrc.Type() { - return ErrDifferentArgumentsTypes - } - return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) -} diff --git a/vendor/github.com/imdario/mergo/mergo.go b/vendor/github.com/imdario/mergo/mergo.go deleted file mode 100644 index 785618cd07..0000000000 --- a/vendor/github.com/imdario/mergo/mergo.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2013 Dario Castañé. All rights reserved. -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Based on src/pkg/reflect/deepequal.go from official -// golang's stdlib. - -package mergo - -import ( - "errors" - "reflect" -) - -// Errors reported by Mergo when it finds invalid arguments. -var ( - ErrNilArguments = errors.New("src and dst must not be nil") - ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type") - ErrNotSupported = errors.New("only structs and maps are supported") - ErrExpectedMapAsDestination = errors.New("dst was expected to be a map") - ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct") -) - -// During deepMerge, must keep track of checks that are -// in progress. The comparison algorithm assumes that all -// checks in progress are true when it reencounters them. -// Visited are stored in a map indexed by 17 * a1 + a2; -type visit struct { - ptr uintptr - typ reflect.Type - next *visit -} - -// From src/pkg/encoding/json/encode.go. -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr, reflect.Func: - return v.IsNil() - case reflect.Invalid: - return true - } - return false -} - -func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) { - if dst == nil || src == nil { - err = ErrNilArguments - return - } - vDst = reflect.ValueOf(dst).Elem() - if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map { - err = ErrNotSupported - return - } - vSrc = reflect.ValueOf(src) - // We check if vSrc is a pointer to dereference it. - if vSrc.Kind() == reflect.Ptr { - vSrc = vSrc.Elem() - } - return -} - -// Traverses recursively both values, assigning src's fields values to dst. -// The map argument tracks comparisons that have already been seen, which allows -// short circuiting on recursive types. -func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) { - if dst.CanAddr() { - addr := dst.UnsafeAddr() - h := 17 * addr - seen := visited[h] - typ := dst.Type() - for p := seen; p != nil; p = p.next { - if p.ptr == addr && p.typ == typ { - return nil - } - } - // Remember, remember... - visited[h] = &visit{addr, typ, seen} - } - return // TODO refactor -} diff --git a/vendor/github.com/imdario/mergo/testdata/license.yml b/vendor/github.com/imdario/mergo/testdata/license.yml deleted file mode 100644 index 2f1ad0082b..0000000000 --- a/vendor/github.com/imdario/mergo/testdata/license.yml +++ /dev/null @@ -1,4 +0,0 @@ -import: ../../../../fossene/db/schema/thing.yml -fields: - site: string - author: root diff --git a/vendor/github.com/mattn/go-runewidth/LICENSE b/vendor/github.com/mattn/go-runewidth/LICENSE deleted file mode 100644 index 91b5cef30e..0000000000 --- a/vendor/github.com/mattn/go-runewidth/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go deleted file mode 100644 index 2164497ad9..0000000000 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ /dev/null @@ -1,1223 +0,0 @@ -package runewidth - -var ( - // EastAsianWidth will be set true if the current locale is CJK - EastAsianWidth = IsEastAsian() - - // DefaultCondition is a condition in current locale - DefaultCondition = &Condition{EastAsianWidth} -) - -type interval struct { - first rune - last rune -} - -type table []interval - -func inTables(r rune, ts ...table) bool { - for _, t := range ts { - if inTable(r, t) { - return true - } - } - return false -} - -func inTable(r rune, t table) bool { - // func (t table) IncludesRune(r rune) bool { - if r < t[0].first { - return false - } - - bot := 0 - top := len(t) - 1 - for top >= bot { - mid := (bot + top) / 2 - - switch { - case t[mid].last < r: - bot = mid + 1 - case t[mid].first > r: - top = mid - 1 - default: - return true - } - } - - return false -} - -var private = table{ - {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, -} - -var nonprint = table{ - {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, - {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, - {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, - {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, -} - -var combining = table{ - {0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD}, - {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, - {0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F}, - {0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4}, - {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711}, - {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, - {0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827}, - {0x0829, 0x082D}, {0x0859, 0x085B}, {0x08D4, 0x08E1}, - {0x08E3, 0x0903}, {0x093A, 0x093C}, {0x093E, 0x094F}, - {0x0951, 0x0957}, {0x0962, 0x0963}, {0x0981, 0x0983}, - {0x09BC, 0x09BC}, {0x09BE, 0x09C4}, {0x09C7, 0x09C8}, - {0x09CB, 0x09CD}, {0x09D7, 0x09D7}, {0x09E2, 0x09E3}, - {0x0A01, 0x0A03}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, - {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, - {0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A83}, - {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, - {0x0ACB, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B03}, - {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48}, - {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B62, 0x0B63}, - {0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, - {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C03}, - {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, - {0x0C55, 0x0C56}, {0x0C62, 0x0C63}, {0x0C81, 0x0C83}, - {0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8}, - {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, {0x0CE2, 0x0CE3}, - {0x0D01, 0x0D03}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48}, - {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63}, - {0x0D82, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, - {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3}, - {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F}, - {0x0F71, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102B, 0x103E}, - {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064}, - {0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D}, - {0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F}, - {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, - {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, - {0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9}, - {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B}, - {0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F}, - {0x1AB0, 0x1ABE}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44}, - {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD}, - {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2}, - {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF2, 0x1CF4}, - {0x1CF8, 0x1CF9}, {0x1DC0, 0x1DF5}, {0x1DFB, 0x1DFF}, - {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, - {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A}, - {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, - {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806}, - {0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA880, 0xA881}, - {0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA926, 0xA92D}, - {0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0}, - {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43}, - {0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0}, - {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF}, - {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6}, - {0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E}, - {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, - {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, - {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, - {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x11000, 0x11002}, - {0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA}, - {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11173, 0x11173}, - {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111CA, 0x111CC}, - {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA}, - {0x11300, 0x11303}, {0x1133C, 0x1133C}, {0x1133E, 0x11344}, - {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, - {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, - {0x11435, 0x11446}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, - {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, - {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x11C2F, 0x11C36}, - {0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, - {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F51, 0x16F7E}, - {0x16F8F, 0x16F92}, {0x1BC9D, 0x1BC9E}, {0x1D165, 0x1D169}, - {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, - {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, - {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, - {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, - {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, - {0xE0100, 0xE01EF}, -} - -var doublewidth = table{ - {0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A}, - {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3}, - {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653}, - {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, - {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, - {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, - {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, - {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B}, - {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E}, - {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, - {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, - {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, - {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, - {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, - {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, - {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, - {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, - {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, - {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, - {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, - {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE0}, {0x17000, 0x187EC}, - {0x18800, 0x18AF2}, {0x1B000, 0x1B001}, {0x1F004, 0x1F004}, - {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, - {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, - {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, - {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, - {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, - {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, - {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, - {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, - {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, - {0x1F6D0, 0x1F6D2}, {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, - {0x1F910, 0x1F91E}, {0x1F920, 0x1F927}, {0x1F930, 0x1F930}, - {0x1F933, 0x1F93E}, {0x1F940, 0x1F94B}, {0x1F950, 0x1F95E}, - {0x1F980, 0x1F991}, {0x1F9C0, 0x1F9C0}, {0x20000, 0x2FFFD}, - {0x30000, 0x3FFFD}, -} - -var ambiguous = table{ - {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, - {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, - {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, - {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, - {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, - {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, - {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, - {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, - {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, - {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, - {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, - {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, - {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, - {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, - {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, - {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, - {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, - {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, - {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, - {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, - {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, - {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, - {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, - {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, - {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, - {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, - {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, - {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, - {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, - {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, - {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, - {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, - {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, - {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, - {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, - {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, - {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, - {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, - {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, - {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, - {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, - {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, - {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, - {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, - {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, - {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, - {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, - {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, - {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, - {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, - {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, - {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, - {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, - {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, - {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, - {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, - {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, - {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, - {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, - {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, -} - -var emoji = table{ - {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F321}, {0x1F324, 0x1F32C}, - {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F396, 0x1F397}, - {0x1F399, 0x1F39B}, {0x1F39E, 0x1F39F}, {0x1F3CB, 0x1F3CE}, - {0x1F3D4, 0x1F3DF}, {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3F7}, - {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FD}, - {0x1F549, 0x1F54A}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F579}, - {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, - {0x1F5A5, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2}, - {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3}, - {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3}, - {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3}, - {0x1F5FA, 0x1F5FA}, {0x1F6CB, 0x1F6CF}, {0x1F6E0, 0x1F6E5}, - {0x1F6E9, 0x1F6E9}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F3}, -} - -var notassigned = table{ - {0x0378, 0x0379}, {0x0380, 0x0383}, {0x038B, 0x038B}, - {0x038D, 0x038D}, {0x03A2, 0x03A2}, {0x0530, 0x0530}, - {0x0557, 0x0558}, {0x0560, 0x0560}, {0x0588, 0x0588}, - {0x058B, 0x058C}, {0x0590, 0x0590}, {0x05C8, 0x05CF}, - {0x05EB, 0x05EF}, {0x05F5, 0x05FF}, {0x061D, 0x061D}, - {0x070E, 0x070E}, {0x074B, 0x074C}, {0x07B2, 0x07BF}, - {0x07FB, 0x07FF}, {0x082E, 0x082F}, {0x083F, 0x083F}, - {0x085C, 0x085D}, {0x085F, 0x089F}, {0x08B5, 0x08B5}, - {0x08BE, 0x08D3}, {0x0984, 0x0984}, {0x098D, 0x098E}, - {0x0991, 0x0992}, {0x09A9, 0x09A9}, {0x09B1, 0x09B1}, - {0x09B3, 0x09B5}, {0x09BA, 0x09BB}, {0x09C5, 0x09C6}, - {0x09C9, 0x09CA}, {0x09CF, 0x09D6}, {0x09D8, 0x09DB}, - {0x09DE, 0x09DE}, {0x09E4, 0x09E5}, {0x09FC, 0x0A00}, - {0x0A04, 0x0A04}, {0x0A0B, 0x0A0E}, {0x0A11, 0x0A12}, - {0x0A29, 0x0A29}, {0x0A31, 0x0A31}, {0x0A34, 0x0A34}, - {0x0A37, 0x0A37}, {0x0A3A, 0x0A3B}, {0x0A3D, 0x0A3D}, - {0x0A43, 0x0A46}, {0x0A49, 0x0A4A}, {0x0A4E, 0x0A50}, - {0x0A52, 0x0A58}, {0x0A5D, 0x0A5D}, {0x0A5F, 0x0A65}, - {0x0A76, 0x0A80}, {0x0A84, 0x0A84}, {0x0A8E, 0x0A8E}, - {0x0A92, 0x0A92}, {0x0AA9, 0x0AA9}, {0x0AB1, 0x0AB1}, - {0x0AB4, 0x0AB4}, {0x0ABA, 0x0ABB}, {0x0AC6, 0x0AC6}, - {0x0ACA, 0x0ACA}, {0x0ACE, 0x0ACF}, {0x0AD1, 0x0ADF}, - {0x0AE4, 0x0AE5}, {0x0AF2, 0x0AF8}, {0x0AFA, 0x0B00}, - {0x0B04, 0x0B04}, {0x0B0D, 0x0B0E}, {0x0B11, 0x0B12}, - {0x0B29, 0x0B29}, {0x0B31, 0x0B31}, {0x0B34, 0x0B34}, - {0x0B3A, 0x0B3B}, {0x0B45, 0x0B46}, {0x0B49, 0x0B4A}, - {0x0B4E, 0x0B55}, {0x0B58, 0x0B5B}, {0x0B5E, 0x0B5E}, - {0x0B64, 0x0B65}, {0x0B78, 0x0B81}, {0x0B84, 0x0B84}, - {0x0B8B, 0x0B8D}, {0x0B91, 0x0B91}, {0x0B96, 0x0B98}, - {0x0B9B, 0x0B9B}, {0x0B9D, 0x0B9D}, {0x0BA0, 0x0BA2}, - {0x0BA5, 0x0BA7}, {0x0BAB, 0x0BAD}, {0x0BBA, 0x0BBD}, - {0x0BC3, 0x0BC5}, {0x0BC9, 0x0BC9}, {0x0BCE, 0x0BCF}, - {0x0BD1, 0x0BD6}, {0x0BD8, 0x0BE5}, {0x0BFB, 0x0BFF}, - {0x0C04, 0x0C04}, {0x0C0D, 0x0C0D}, {0x0C11, 0x0C11}, - {0x0C29, 0x0C29}, {0x0C3A, 0x0C3C}, {0x0C45, 0x0C45}, - {0x0C49, 0x0C49}, {0x0C4E, 0x0C54}, {0x0C57, 0x0C57}, - {0x0C5B, 0x0C5F}, {0x0C64, 0x0C65}, {0x0C70, 0x0C77}, - {0x0C84, 0x0C84}, {0x0C8D, 0x0C8D}, {0x0C91, 0x0C91}, - {0x0CA9, 0x0CA9}, {0x0CB4, 0x0CB4}, {0x0CBA, 0x0CBB}, - {0x0CC5, 0x0CC5}, {0x0CC9, 0x0CC9}, {0x0CCE, 0x0CD4}, - {0x0CD7, 0x0CDD}, {0x0CDF, 0x0CDF}, {0x0CE4, 0x0CE5}, - {0x0CF0, 0x0CF0}, {0x0CF3, 0x0D00}, {0x0D04, 0x0D04}, - {0x0D0D, 0x0D0D}, {0x0D11, 0x0D11}, {0x0D3B, 0x0D3C}, - {0x0D45, 0x0D45}, {0x0D49, 0x0D49}, {0x0D50, 0x0D53}, - {0x0D64, 0x0D65}, {0x0D80, 0x0D81}, {0x0D84, 0x0D84}, - {0x0D97, 0x0D99}, {0x0DB2, 0x0DB2}, {0x0DBC, 0x0DBC}, - {0x0DBE, 0x0DBF}, {0x0DC7, 0x0DC9}, {0x0DCB, 0x0DCE}, - {0x0DD5, 0x0DD5}, {0x0DD7, 0x0DD7}, {0x0DE0, 0x0DE5}, - {0x0DF0, 0x0DF1}, {0x0DF5, 0x0E00}, {0x0E3B, 0x0E3E}, - {0x0E5C, 0x0E80}, {0x0E83, 0x0E83}, {0x0E85, 0x0E86}, - {0x0E89, 0x0E89}, {0x0E8B, 0x0E8C}, {0x0E8E, 0x0E93}, - {0x0E98, 0x0E98}, {0x0EA0, 0x0EA0}, {0x0EA4, 0x0EA4}, - {0x0EA6, 0x0EA6}, {0x0EA8, 0x0EA9}, {0x0EAC, 0x0EAC}, - {0x0EBA, 0x0EBA}, {0x0EBE, 0x0EBF}, {0x0EC5, 0x0EC5}, - {0x0EC7, 0x0EC7}, {0x0ECE, 0x0ECF}, {0x0EDA, 0x0EDB}, - {0x0EE0, 0x0EFF}, {0x0F48, 0x0F48}, {0x0F6D, 0x0F70}, - {0x0F98, 0x0F98}, {0x0FBD, 0x0FBD}, {0x0FCD, 0x0FCD}, - {0x0FDB, 0x0FFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC}, - {0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F}, - {0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F}, - {0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1}, - {0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1}, - {0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311}, - {0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F}, - {0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF}, - {0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D}, - {0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F}, - {0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F}, - {0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF}, - {0x180F, 0x180F}, {0x181A, 0x181F}, {0x1878, 0x187F}, - {0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F}, - {0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943}, - {0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF}, - {0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D}, - {0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F}, - {0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1ABF, 0x1AFF}, - {0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB}, - {0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1CBF}, - {0x1CC8, 0x1CCF}, {0x1CF7, 0x1CF7}, {0x1CFA, 0x1CFF}, - {0x1DF6, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F}, - {0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58}, - {0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E}, - {0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5}, - {0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF1}, - {0x1FF5, 0x1FF5}, {0x1FFF, 0x1FFF}, {0x2065, 0x2065}, - {0x2072, 0x2073}, {0x208F, 0x208F}, {0x209D, 0x209F}, - {0x20BF, 0x20CF}, {0x20F1, 0x20FF}, {0x218C, 0x218F}, - {0x23FF, 0x23FF}, {0x2427, 0x243F}, {0x244B, 0x245F}, - {0x2B74, 0x2B75}, {0x2B96, 0x2B97}, {0x2BBA, 0x2BBC}, - {0x2BC9, 0x2BC9}, {0x2BD2, 0x2BEB}, {0x2BF0, 0x2BFF}, - {0x2C2F, 0x2C2F}, {0x2C5F, 0x2C5F}, {0x2CF4, 0x2CF8}, - {0x2D26, 0x2D26}, {0x2D28, 0x2D2C}, {0x2D2E, 0x2D2F}, - {0x2D68, 0x2D6E}, {0x2D71, 0x2D7E}, {0x2D97, 0x2D9F}, - {0x2DA7, 0x2DA7}, {0x2DAF, 0x2DAF}, {0x2DB7, 0x2DB7}, - {0x2DBF, 0x2DBF}, {0x2DC7, 0x2DC7}, {0x2DCF, 0x2DCF}, - {0x2DD7, 0x2DD7}, {0x2DDF, 0x2DDF}, {0x2E45, 0x2E7F}, - {0x2E9A, 0x2E9A}, {0x2EF4, 0x2EFF}, {0x2FD6, 0x2FEF}, - {0x2FFC, 0x2FFF}, {0x3040, 0x3040}, {0x3097, 0x3098}, - {0x3100, 0x3104}, {0x312E, 0x3130}, {0x318F, 0x318F}, - {0x31BB, 0x31BF}, {0x31E4, 0x31EF}, {0x321F, 0x321F}, - {0x32FF, 0x32FF}, {0x4DB6, 0x4DBF}, {0x9FD6, 0x9FFF}, - {0xA48D, 0xA48F}, {0xA4C7, 0xA4CF}, {0xA62C, 0xA63F}, - {0xA6F8, 0xA6FF}, {0xA7AF, 0xA7AF}, {0xA7B8, 0xA7F6}, - {0xA82C, 0xA82F}, {0xA83A, 0xA83F}, {0xA878, 0xA87F}, - {0xA8C6, 0xA8CD}, {0xA8DA, 0xA8DF}, {0xA8FE, 0xA8FF}, - {0xA954, 0xA95E}, {0xA97D, 0xA97F}, {0xA9CE, 0xA9CE}, - {0xA9DA, 0xA9DD}, {0xA9FF, 0xA9FF}, {0xAA37, 0xAA3F}, - {0xAA4E, 0xAA4F}, {0xAA5A, 0xAA5B}, {0xAAC3, 0xAADA}, - {0xAAF7, 0xAB00}, {0xAB07, 0xAB08}, {0xAB0F, 0xAB10}, - {0xAB17, 0xAB1F}, {0xAB27, 0xAB27}, {0xAB2F, 0xAB2F}, - {0xAB66, 0xAB6F}, {0xABEE, 0xABEF}, {0xABFA, 0xABFF}, - {0xD7A4, 0xD7AF}, {0xD7C7, 0xD7CA}, {0xD7FC, 0xD7FF}, - {0xFA6E, 0xFA6F}, {0xFADA, 0xFAFF}, {0xFB07, 0xFB12}, - {0xFB18, 0xFB1C}, {0xFB37, 0xFB37}, {0xFB3D, 0xFB3D}, - {0xFB3F, 0xFB3F}, {0xFB42, 0xFB42}, {0xFB45, 0xFB45}, - {0xFBC2, 0xFBD2}, {0xFD40, 0xFD4F}, {0xFD90, 0xFD91}, - {0xFDC8, 0xFDEF}, {0xFDFE, 0xFDFF}, {0xFE1A, 0xFE1F}, - {0xFE53, 0xFE53}, {0xFE67, 0xFE67}, {0xFE6C, 0xFE6F}, - {0xFE75, 0xFE75}, {0xFEFD, 0xFEFE}, {0xFF00, 0xFF00}, - {0xFFBF, 0xFFC1}, {0xFFC8, 0xFFC9}, {0xFFD0, 0xFFD1}, - {0xFFD8, 0xFFD9}, {0xFFDD, 0xFFDF}, {0xFFE7, 0xFFE7}, - {0xFFEF, 0xFFF8}, {0xFFFE, 0xFFFF}, {0x1000C, 0x1000C}, - {0x10027, 0x10027}, {0x1003B, 0x1003B}, {0x1003E, 0x1003E}, - {0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF}, - {0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F}, - {0x1019C, 0x1019F}, {0x101A1, 0x101CF}, {0x101FE, 0x1027F}, - {0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF}, - {0x10324, 0x1032F}, {0x1034B, 0x1034F}, {0x1037B, 0x1037F}, - {0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF}, - {0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7}, - {0x104FC, 0x104FF}, {0x10528, 0x1052F}, {0x10564, 0x1056E}, - {0x10570, 0x105FF}, {0x10737, 0x1073F}, {0x10756, 0x1075F}, - {0x10768, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809}, - {0x10836, 0x10836}, {0x10839, 0x1083B}, {0x1083D, 0x1083E}, - {0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF}, - {0x108F3, 0x108F3}, {0x108F6, 0x108FA}, {0x1091C, 0x1091E}, - {0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB}, - {0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B}, - {0x10A14, 0x10A14}, {0x10A18, 0x10A18}, {0x10A34, 0x10A37}, - {0x10A3B, 0x10A3E}, {0x10A48, 0x10A4F}, {0x10A59, 0x10A5F}, - {0x10AA0, 0x10ABF}, {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF}, - {0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77}, - {0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF}, - {0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, {0x10CF3, 0x10CF9}, - {0x10D00, 0x10E5F}, {0x10E7F, 0x10FFF}, {0x1104E, 0x11051}, - {0x11070, 0x1107E}, {0x110C2, 0x110CF}, {0x110E9, 0x110EF}, - {0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11144, 0x1114F}, - {0x11177, 0x1117F}, {0x111CE, 0x111CF}, {0x111E0, 0x111E0}, - {0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x1123F, 0x1127F}, - {0x11287, 0x11287}, {0x11289, 0x11289}, {0x1128E, 0x1128E}, - {0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF}, - {0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E}, - {0x11311, 0x11312}, {0x11329, 0x11329}, {0x11331, 0x11331}, - {0x11334, 0x11334}, {0x1133A, 0x1133B}, {0x11345, 0x11346}, - {0x11349, 0x1134A}, {0x1134E, 0x1134F}, {0x11351, 0x11356}, - {0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F}, - {0x11375, 0x113FF}, {0x1145A, 0x1145A}, {0x1145C, 0x1145C}, - {0x1145E, 0x1147F}, {0x114C8, 0x114CF}, {0x114DA, 0x1157F}, - {0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F}, - {0x1165A, 0x1165F}, {0x1166D, 0x1167F}, {0x116B8, 0x116BF}, - {0x116CA, 0x116FF}, {0x1171A, 0x1171C}, {0x1172C, 0x1172F}, - {0x11740, 0x1189F}, {0x118F3, 0x118FE}, {0x11900, 0x11ABF}, - {0x11AF9, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37}, - {0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, {0x11C90, 0x11C91}, - {0x11CA8, 0x11CA8}, {0x11CB7, 0x11FFF}, {0x1239A, 0x123FF}, - {0x1246F, 0x1246F}, {0x12475, 0x1247F}, {0x12544, 0x12FFF}, - {0x1342F, 0x143FF}, {0x14647, 0x167FF}, {0x16A39, 0x16A3F}, - {0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16A70, 0x16ACF}, - {0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F}, - {0x16B5A, 0x16B5A}, {0x16B62, 0x16B62}, {0x16B78, 0x16B7C}, - {0x16B90, 0x16EFF}, {0x16F45, 0x16F4F}, {0x16F7F, 0x16F8E}, - {0x16FA0, 0x16FDF}, {0x16FE1, 0x16FFF}, {0x187ED, 0x187FF}, - {0x18AF3, 0x1AFFF}, {0x1B002, 0x1BBFF}, {0x1BC6B, 0x1BC6F}, - {0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B}, - {0x1BCA4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, {0x1D127, 0x1D128}, - {0x1D1E9, 0x1D1FF}, {0x1D246, 0x1D2FF}, {0x1D357, 0x1D35F}, - {0x1D372, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D}, - {0x1D4A0, 0x1D4A1}, {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8}, - {0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC}, - {0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C}, - {0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, {0x1D53A, 0x1D53A}, - {0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549}, - {0x1D551, 0x1D551}, {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD}, - {0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DFFF}, - {0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022}, - {0x1E025, 0x1E025}, {0x1E02B, 0x1E7FF}, {0x1E8C5, 0x1E8C6}, - {0x1E8D7, 0x1E8FF}, {0x1E94B, 0x1E94F}, {0x1E95A, 0x1E95D}, - {0x1E960, 0x1EDFF}, {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20}, - {0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28}, - {0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A}, - {0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, {0x1EE48, 0x1EE48}, - {0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50}, - {0x1EE53, 0x1EE53}, {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58}, - {0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E}, - {0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66}, - {0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, {0x1EE78, 0x1EE78}, - {0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A}, - {0x1EE9C, 0x1EEA0}, {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA}, - {0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F}, - {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0}, - {0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F10D, 0x1F10F}, - {0x1F12F, 0x1F12F}, {0x1F16C, 0x1F16F}, {0x1F1AD, 0x1F1E5}, - {0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F}, - {0x1F252, 0x1F2FF}, {0x1F6D3, 0x1F6DF}, {0x1F6ED, 0x1F6EF}, - {0x1F6F7, 0x1F6FF}, {0x1F774, 0x1F77F}, {0x1F7D5, 0x1F7FF}, - {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, - {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F90F}, {0x1F91F, 0x1F91F}, - {0x1F928, 0x1F92F}, {0x1F931, 0x1F932}, {0x1F93F, 0x1F93F}, - {0x1F94C, 0x1F94F}, {0x1F95F, 0x1F97F}, {0x1F992, 0x1F9BF}, - {0x1F9C1, 0x1FFFF}, {0x2A6D7, 0x2A6FF}, {0x2B735, 0x2B73F}, - {0x2B81E, 0x2B81F}, {0x2CEA2, 0x2F7FF}, {0x2FA1E, 0xE0000}, - {0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, {0xE01F0, 0xEFFFF}, - {0xFFFFE, 0xFFFFF}, -} - -var neutral = table{ - {0x0000, 0x001F}, {0x007F, 0x007F}, {0x0080, 0x009F}, - {0x00A0, 0x00A0}, {0x00A9, 0x00A9}, {0x00AB, 0x00AB}, - {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, {0x00C0, 0x00C5}, - {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, {0x00D9, 0x00DD}, - {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, {0x00EB, 0x00EB}, - {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, {0x00F4, 0x00F6}, - {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, {0x00FF, 0x00FF}, - {0x0100, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, - {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, - {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, - {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, - {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, - {0x016C, 0x017F}, {0x0180, 0x01BA}, {0x01BB, 0x01BB}, - {0x01BC, 0x01BF}, {0x01C0, 0x01C3}, {0x01C4, 0x01CD}, - {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, {0x01D3, 0x01D3}, - {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, {0x01D9, 0x01D9}, - {0x01DB, 0x01DB}, {0x01DD, 0x024F}, {0x0250, 0x0250}, - {0x0252, 0x0260}, {0x0262, 0x0293}, {0x0294, 0x0294}, - {0x0295, 0x02AF}, {0x02B0, 0x02C1}, {0x02C2, 0x02C3}, - {0x02C5, 0x02C5}, {0x02C6, 0x02C6}, {0x02C8, 0x02C8}, - {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, {0x02D1, 0x02D1}, - {0x02D2, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, - {0x02E0, 0x02E4}, {0x02E5, 0x02EB}, {0x02EC, 0x02EC}, - {0x02ED, 0x02ED}, {0x02EE, 0x02EE}, {0x02EF, 0x02FF}, - {0x0370, 0x0373}, {0x0374, 0x0374}, {0x0375, 0x0375}, - {0x0376, 0x0377}, {0x037A, 0x037A}, {0x037B, 0x037D}, - {0x037E, 0x037E}, {0x037F, 0x037F}, {0x0384, 0x0385}, - {0x0386, 0x0386}, {0x0387, 0x0387}, {0x0388, 0x038A}, - {0x038C, 0x038C}, {0x038E, 0x0390}, {0x03AA, 0x03B0}, - {0x03C2, 0x03C2}, {0x03CA, 0x03F5}, {0x03F6, 0x03F6}, - {0x03F7, 0x03FF}, {0x0400, 0x0400}, {0x0402, 0x040F}, - {0x0450, 0x0450}, {0x0452, 0x0481}, {0x0482, 0x0482}, - {0x0483, 0x0487}, {0x0488, 0x0489}, {0x048A, 0x04FF}, - {0x0500, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x0559}, - {0x055A, 0x055F}, {0x0561, 0x0587}, {0x0589, 0x0589}, - {0x058A, 0x058A}, {0x058D, 0x058E}, {0x058F, 0x058F}, - {0x0591, 0x05BD}, {0x05BE, 0x05BE}, {0x05BF, 0x05BF}, - {0x05C0, 0x05C0}, {0x05C1, 0x05C2}, {0x05C3, 0x05C3}, - {0x05C4, 0x05C5}, {0x05C6, 0x05C6}, {0x05C7, 0x05C7}, - {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x05F3, 0x05F4}, - {0x0600, 0x0605}, {0x0606, 0x0608}, {0x0609, 0x060A}, - {0x060B, 0x060B}, {0x060C, 0x060D}, {0x060E, 0x060F}, - {0x0610, 0x061A}, {0x061B, 0x061B}, {0x061C, 0x061C}, - {0x061E, 0x061F}, {0x0620, 0x063F}, {0x0640, 0x0640}, - {0x0641, 0x064A}, {0x064B, 0x065F}, {0x0660, 0x0669}, - {0x066A, 0x066D}, {0x066E, 0x066F}, {0x0670, 0x0670}, - {0x0671, 0x06D3}, {0x06D4, 0x06D4}, {0x06D5, 0x06D5}, - {0x06D6, 0x06DC}, {0x06DD, 0x06DD}, {0x06DE, 0x06DE}, - {0x06DF, 0x06E4}, {0x06E5, 0x06E6}, {0x06E7, 0x06E8}, - {0x06E9, 0x06E9}, {0x06EA, 0x06ED}, {0x06EE, 0x06EF}, - {0x06F0, 0x06F9}, {0x06FA, 0x06FC}, {0x06FD, 0x06FE}, - {0x06FF, 0x06FF}, {0x0700, 0x070D}, {0x070F, 0x070F}, - {0x0710, 0x0710}, {0x0711, 0x0711}, {0x0712, 0x072F}, - {0x0730, 0x074A}, {0x074D, 0x074F}, {0x0750, 0x077F}, - {0x0780, 0x07A5}, {0x07A6, 0x07B0}, {0x07B1, 0x07B1}, - {0x07C0, 0x07C9}, {0x07CA, 0x07EA}, {0x07EB, 0x07F3}, - {0x07F4, 0x07F5}, {0x07F6, 0x07F6}, {0x07F7, 0x07F9}, - {0x07FA, 0x07FA}, {0x0800, 0x0815}, {0x0816, 0x0819}, - {0x081A, 0x081A}, {0x081B, 0x0823}, {0x0824, 0x0824}, - {0x0825, 0x0827}, {0x0828, 0x0828}, {0x0829, 0x082D}, - {0x0830, 0x083E}, {0x0840, 0x0858}, {0x0859, 0x085B}, - {0x085E, 0x085E}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD}, - {0x08D4, 0x08E1}, {0x08E2, 0x08E2}, {0x08E3, 0x08FF}, - {0x0900, 0x0902}, {0x0903, 0x0903}, {0x0904, 0x0939}, - {0x093A, 0x093A}, {0x093B, 0x093B}, {0x093C, 0x093C}, - {0x093D, 0x093D}, {0x093E, 0x0940}, {0x0941, 0x0948}, - {0x0949, 0x094C}, {0x094D, 0x094D}, {0x094E, 0x094F}, - {0x0950, 0x0950}, {0x0951, 0x0957}, {0x0958, 0x0961}, - {0x0962, 0x0963}, {0x0964, 0x0965}, {0x0966, 0x096F}, - {0x0970, 0x0970}, {0x0971, 0x0971}, {0x0972, 0x097F}, - {0x0980, 0x0980}, {0x0981, 0x0981}, {0x0982, 0x0983}, - {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, - {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, - {0x09BC, 0x09BC}, {0x09BD, 0x09BD}, {0x09BE, 0x09C0}, - {0x09C1, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CC}, - {0x09CD, 0x09CD}, {0x09CE, 0x09CE}, {0x09D7, 0x09D7}, - {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09E2, 0x09E3}, - {0x09E6, 0x09EF}, {0x09F0, 0x09F1}, {0x09F2, 0x09F3}, - {0x09F4, 0x09F9}, {0x09FA, 0x09FA}, {0x09FB, 0x09FB}, - {0x0A01, 0x0A02}, {0x0A03, 0x0A03}, {0x0A05, 0x0A0A}, - {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, - {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, - {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A40}, {0x0A41, 0x0A42}, - {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, - {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A6F}, - {0x0A70, 0x0A71}, {0x0A72, 0x0A74}, {0x0A75, 0x0A75}, - {0x0A81, 0x0A82}, {0x0A83, 0x0A83}, {0x0A85, 0x0A8D}, - {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, - {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0ABC}, - {0x0ABD, 0x0ABD}, {0x0ABE, 0x0AC0}, {0x0AC1, 0x0AC5}, - {0x0AC7, 0x0AC8}, {0x0AC9, 0x0AC9}, {0x0ACB, 0x0ACC}, - {0x0ACD, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE1}, - {0x0AE2, 0x0AE3}, {0x0AE6, 0x0AEF}, {0x0AF0, 0x0AF0}, - {0x0AF1, 0x0AF1}, {0x0AF9, 0x0AF9}, {0x0B01, 0x0B01}, - {0x0B02, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, - {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, - {0x0B35, 0x0B39}, {0x0B3C, 0x0B3C}, {0x0B3D, 0x0B3D}, - {0x0B3E, 0x0B3E}, {0x0B3F, 0x0B3F}, {0x0B40, 0x0B40}, - {0x0B41, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4C}, - {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B57, 0x0B57}, - {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B62, 0x0B63}, - {0x0B66, 0x0B6F}, {0x0B70, 0x0B70}, {0x0B71, 0x0B71}, - {0x0B72, 0x0B77}, {0x0B82, 0x0B82}, {0x0B83, 0x0B83}, - {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, - {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, - {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, - {0x0BBE, 0x0BBF}, {0x0BC0, 0x0BC0}, {0x0BC1, 0x0BC2}, - {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCC}, {0x0BCD, 0x0BCD}, - {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BEF}, - {0x0BF0, 0x0BF2}, {0x0BF3, 0x0BF8}, {0x0BF9, 0x0BF9}, - {0x0BFA, 0x0BFA}, {0x0C00, 0x0C00}, {0x0C01, 0x0C03}, - {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, - {0x0C2A, 0x0C39}, {0x0C3D, 0x0C3D}, {0x0C3E, 0x0C40}, - {0x0C41, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, - {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C61}, - {0x0C62, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C78, 0x0C7E}, - {0x0C7F, 0x0C7F}, {0x0C80, 0x0C80}, {0x0C81, 0x0C81}, - {0x0C82, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, - {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, - {0x0CBC, 0x0CBC}, {0x0CBD, 0x0CBD}, {0x0CBE, 0x0CBE}, - {0x0CBF, 0x0CBF}, {0x0CC0, 0x0CC4}, {0x0CC6, 0x0CC6}, - {0x0CC7, 0x0CC8}, {0x0CCA, 0x0CCB}, {0x0CCC, 0x0CCD}, - {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, - {0x0CE2, 0x0CE3}, {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, - {0x0D01, 0x0D01}, {0x0D02, 0x0D03}, {0x0D05, 0x0D0C}, - {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, {0x0D3D, 0x0D3D}, - {0x0D3E, 0x0D40}, {0x0D41, 0x0D44}, {0x0D46, 0x0D48}, - {0x0D4A, 0x0D4C}, {0x0D4D, 0x0D4D}, {0x0D4E, 0x0D4E}, - {0x0D4F, 0x0D4F}, {0x0D54, 0x0D56}, {0x0D57, 0x0D57}, - {0x0D58, 0x0D5E}, {0x0D5F, 0x0D61}, {0x0D62, 0x0D63}, - {0x0D66, 0x0D6F}, {0x0D70, 0x0D78}, {0x0D79, 0x0D79}, - {0x0D7A, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96}, - {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, - {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD1}, - {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, - {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF3}, {0x0DF4, 0x0DF4}, - {0x0E01, 0x0E30}, {0x0E31, 0x0E31}, {0x0E32, 0x0E33}, - {0x0E34, 0x0E3A}, {0x0E3F, 0x0E3F}, {0x0E40, 0x0E45}, - {0x0E46, 0x0E46}, {0x0E47, 0x0E4E}, {0x0E4F, 0x0E4F}, - {0x0E50, 0x0E59}, {0x0E5A, 0x0E5B}, {0x0E81, 0x0E82}, - {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, - {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, - {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, - {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EB0}, {0x0EB1, 0x0EB1}, - {0x0EB2, 0x0EB3}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, - {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, - {0x0F00, 0x0F00}, {0x0F01, 0x0F03}, {0x0F04, 0x0F12}, - {0x0F13, 0x0F13}, {0x0F14, 0x0F14}, {0x0F15, 0x0F17}, - {0x0F18, 0x0F19}, {0x0F1A, 0x0F1F}, {0x0F20, 0x0F29}, - {0x0F2A, 0x0F33}, {0x0F34, 0x0F34}, {0x0F35, 0x0F35}, - {0x0F36, 0x0F36}, {0x0F37, 0x0F37}, {0x0F38, 0x0F38}, - {0x0F39, 0x0F39}, {0x0F3A, 0x0F3A}, {0x0F3B, 0x0F3B}, - {0x0F3C, 0x0F3C}, {0x0F3D, 0x0F3D}, {0x0F3E, 0x0F3F}, - {0x0F40, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F7E}, - {0x0F7F, 0x0F7F}, {0x0F80, 0x0F84}, {0x0F85, 0x0F85}, - {0x0F86, 0x0F87}, {0x0F88, 0x0F8C}, {0x0F8D, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FBE, 0x0FC5}, {0x0FC6, 0x0FC6}, - {0x0FC7, 0x0FCC}, {0x0FCE, 0x0FCF}, {0x0FD0, 0x0FD4}, - {0x0FD5, 0x0FD8}, {0x0FD9, 0x0FDA}, {0x1000, 0x102A}, - {0x102B, 0x102C}, {0x102D, 0x1030}, {0x1031, 0x1031}, - {0x1032, 0x1037}, {0x1038, 0x1038}, {0x1039, 0x103A}, - {0x103B, 0x103C}, {0x103D, 0x103E}, {0x103F, 0x103F}, - {0x1040, 0x1049}, {0x104A, 0x104F}, {0x1050, 0x1055}, - {0x1056, 0x1057}, {0x1058, 0x1059}, {0x105A, 0x105D}, - {0x105E, 0x1060}, {0x1061, 0x1061}, {0x1062, 0x1064}, - {0x1065, 0x1066}, {0x1067, 0x106D}, {0x106E, 0x1070}, - {0x1071, 0x1074}, {0x1075, 0x1081}, {0x1082, 0x1082}, - {0x1083, 0x1084}, {0x1085, 0x1086}, {0x1087, 0x108C}, - {0x108D, 0x108D}, {0x108E, 0x108E}, {0x108F, 0x108F}, - {0x1090, 0x1099}, {0x109A, 0x109C}, {0x109D, 0x109D}, - {0x109E, 0x109F}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, - {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FB, 0x10FB}, - {0x10FC, 0x10FC}, {0x10FD, 0x10FF}, {0x1160, 0x11FF}, - {0x1200, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, - {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, - {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, - {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, - {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, - {0x1318, 0x135A}, {0x135D, 0x135F}, {0x1360, 0x1368}, - {0x1369, 0x137C}, {0x1380, 0x138F}, {0x1390, 0x1399}, - {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x1400}, - {0x1401, 0x166C}, {0x166D, 0x166E}, {0x166F, 0x167F}, - {0x1680, 0x1680}, {0x1681, 0x169A}, {0x169B, 0x169B}, - {0x169C, 0x169C}, {0x16A0, 0x16EA}, {0x16EB, 0x16ED}, - {0x16EE, 0x16F0}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, - {0x170E, 0x1711}, {0x1712, 0x1714}, {0x1720, 0x1731}, - {0x1732, 0x1734}, {0x1735, 0x1736}, {0x1740, 0x1751}, - {0x1752, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, - {0x1772, 0x1773}, {0x1780, 0x17B3}, {0x17B4, 0x17B5}, - {0x17B6, 0x17B6}, {0x17B7, 0x17BD}, {0x17BE, 0x17C5}, - {0x17C6, 0x17C6}, {0x17C7, 0x17C8}, {0x17C9, 0x17D3}, - {0x17D4, 0x17D6}, {0x17D7, 0x17D7}, {0x17D8, 0x17DA}, - {0x17DB, 0x17DB}, {0x17DC, 0x17DC}, {0x17DD, 0x17DD}, - {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x1805}, - {0x1806, 0x1806}, {0x1807, 0x180A}, {0x180B, 0x180D}, - {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1842}, - {0x1843, 0x1843}, {0x1844, 0x1877}, {0x1880, 0x1884}, - {0x1885, 0x1886}, {0x1887, 0x18A8}, {0x18A9, 0x18A9}, - {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, - {0x1920, 0x1922}, {0x1923, 0x1926}, {0x1927, 0x1928}, - {0x1929, 0x192B}, {0x1930, 0x1931}, {0x1932, 0x1932}, - {0x1933, 0x1938}, {0x1939, 0x193B}, {0x1940, 0x1940}, - {0x1944, 0x1945}, {0x1946, 0x194F}, {0x1950, 0x196D}, - {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, - {0x19D0, 0x19D9}, {0x19DA, 0x19DA}, {0x19DE, 0x19DF}, - {0x19E0, 0x19FF}, {0x1A00, 0x1A16}, {0x1A17, 0x1A18}, - {0x1A19, 0x1A1A}, {0x1A1B, 0x1A1B}, {0x1A1E, 0x1A1F}, - {0x1A20, 0x1A54}, {0x1A55, 0x1A55}, {0x1A56, 0x1A56}, - {0x1A57, 0x1A57}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60}, - {0x1A61, 0x1A61}, {0x1A62, 0x1A62}, {0x1A63, 0x1A64}, - {0x1A65, 0x1A6C}, {0x1A6D, 0x1A72}, {0x1A73, 0x1A7C}, - {0x1A7F, 0x1A7F}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, - {0x1AA0, 0x1AA6}, {0x1AA7, 0x1AA7}, {0x1AA8, 0x1AAD}, - {0x1AB0, 0x1ABD}, {0x1ABE, 0x1ABE}, {0x1B00, 0x1B03}, - {0x1B04, 0x1B04}, {0x1B05, 0x1B33}, {0x1B34, 0x1B34}, - {0x1B35, 0x1B35}, {0x1B36, 0x1B3A}, {0x1B3B, 0x1B3B}, - {0x1B3C, 0x1B3C}, {0x1B3D, 0x1B41}, {0x1B42, 0x1B42}, - {0x1B43, 0x1B44}, {0x1B45, 0x1B4B}, {0x1B50, 0x1B59}, - {0x1B5A, 0x1B60}, {0x1B61, 0x1B6A}, {0x1B6B, 0x1B73}, - {0x1B74, 0x1B7C}, {0x1B80, 0x1B81}, {0x1B82, 0x1B82}, - {0x1B83, 0x1BA0}, {0x1BA1, 0x1BA1}, {0x1BA2, 0x1BA5}, - {0x1BA6, 0x1BA7}, {0x1BA8, 0x1BA9}, {0x1BAA, 0x1BAA}, - {0x1BAB, 0x1BAD}, {0x1BAE, 0x1BAF}, {0x1BB0, 0x1BB9}, - {0x1BBA, 0x1BBF}, {0x1BC0, 0x1BE5}, {0x1BE6, 0x1BE6}, - {0x1BE7, 0x1BE7}, {0x1BE8, 0x1BE9}, {0x1BEA, 0x1BEC}, - {0x1BED, 0x1BED}, {0x1BEE, 0x1BEE}, {0x1BEF, 0x1BF1}, - {0x1BF2, 0x1BF3}, {0x1BFC, 0x1BFF}, {0x1C00, 0x1C23}, - {0x1C24, 0x1C2B}, {0x1C2C, 0x1C33}, {0x1C34, 0x1C35}, - {0x1C36, 0x1C37}, {0x1C3B, 0x1C3F}, {0x1C40, 0x1C49}, - {0x1C4D, 0x1C4F}, {0x1C50, 0x1C59}, {0x1C5A, 0x1C77}, - {0x1C78, 0x1C7D}, {0x1C7E, 0x1C7F}, {0x1C80, 0x1C88}, - {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CD2}, {0x1CD3, 0x1CD3}, - {0x1CD4, 0x1CE0}, {0x1CE1, 0x1CE1}, {0x1CE2, 0x1CE8}, - {0x1CE9, 0x1CEC}, {0x1CED, 0x1CED}, {0x1CEE, 0x1CF1}, - {0x1CF2, 0x1CF3}, {0x1CF4, 0x1CF4}, {0x1CF5, 0x1CF6}, - {0x1CF8, 0x1CF9}, {0x1D00, 0x1D2B}, {0x1D2C, 0x1D6A}, - {0x1D6B, 0x1D77}, {0x1D78, 0x1D78}, {0x1D79, 0x1D7F}, - {0x1D80, 0x1D9A}, {0x1D9B, 0x1DBF}, {0x1DC0, 0x1DF5}, - {0x1DFB, 0x1DFF}, {0x1E00, 0x1EFF}, {0x1F00, 0x1F15}, - {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, - {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, - {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, - {0x1FB6, 0x1FBC}, {0x1FBD, 0x1FBD}, {0x1FBE, 0x1FBE}, - {0x1FBF, 0x1FC1}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, - {0x1FCD, 0x1FCF}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, - {0x1FDD, 0x1FDF}, {0x1FE0, 0x1FEC}, {0x1FED, 0x1FEF}, - {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x1FFD, 0x1FFE}, - {0x2000, 0x200A}, {0x200B, 0x200F}, {0x2011, 0x2012}, - {0x2017, 0x2017}, {0x201A, 0x201A}, {0x201B, 0x201B}, - {0x201E, 0x201E}, {0x201F, 0x201F}, {0x2023, 0x2023}, - {0x2028, 0x2028}, {0x2029, 0x2029}, {0x202A, 0x202E}, - {0x202F, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, - {0x2036, 0x2038}, {0x2039, 0x2039}, {0x203A, 0x203A}, - {0x203C, 0x203D}, {0x203F, 0x2040}, {0x2041, 0x2043}, - {0x2044, 0x2044}, {0x2045, 0x2045}, {0x2046, 0x2046}, - {0x2047, 0x2051}, {0x2052, 0x2052}, {0x2053, 0x2053}, - {0x2054, 0x2054}, {0x2055, 0x205E}, {0x205F, 0x205F}, - {0x2060, 0x2064}, {0x2066, 0x206F}, {0x2070, 0x2070}, - {0x2071, 0x2071}, {0x2075, 0x2079}, {0x207A, 0x207C}, - {0x207D, 0x207D}, {0x207E, 0x207E}, {0x2080, 0x2080}, - {0x2085, 0x2089}, {0x208A, 0x208C}, {0x208D, 0x208D}, - {0x208E, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, - {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20DC}, - {0x20DD, 0x20E0}, {0x20E1, 0x20E1}, {0x20E2, 0x20E4}, - {0x20E5, 0x20F0}, {0x2100, 0x2101}, {0x2102, 0x2102}, - {0x2104, 0x2104}, {0x2106, 0x2106}, {0x2107, 0x2107}, - {0x2108, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2114}, - {0x2115, 0x2115}, {0x2117, 0x2117}, {0x2118, 0x2118}, - {0x2119, 0x211D}, {0x211E, 0x2120}, {0x2123, 0x2123}, - {0x2124, 0x2124}, {0x2125, 0x2125}, {0x2127, 0x2127}, - {0x2128, 0x2128}, {0x2129, 0x2129}, {0x212A, 0x212A}, - {0x212C, 0x212D}, {0x212E, 0x212E}, {0x212F, 0x2134}, - {0x2135, 0x2138}, {0x2139, 0x2139}, {0x213A, 0x213B}, - {0x213C, 0x213F}, {0x2140, 0x2144}, {0x2145, 0x2149}, - {0x214A, 0x214A}, {0x214B, 0x214B}, {0x214C, 0x214D}, - {0x214E, 0x214E}, {0x214F, 0x214F}, {0x2150, 0x2152}, - {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, - {0x217A, 0x2182}, {0x2183, 0x2184}, {0x2185, 0x2188}, - {0x218A, 0x218B}, {0x219A, 0x219B}, {0x219C, 0x219F}, - {0x21A0, 0x21A0}, {0x21A1, 0x21A2}, {0x21A3, 0x21A3}, - {0x21A4, 0x21A5}, {0x21A6, 0x21A6}, {0x21A7, 0x21AD}, - {0x21AE, 0x21AE}, {0x21AF, 0x21B7}, {0x21BA, 0x21CD}, - {0x21CE, 0x21CF}, {0x21D0, 0x21D1}, {0x21D3, 0x21D3}, - {0x21D5, 0x21E6}, {0x21E8, 0x21F3}, {0x21F4, 0x21FF}, - {0x2201, 0x2201}, {0x2204, 0x2206}, {0x2209, 0x220A}, - {0x220C, 0x220E}, {0x2210, 0x2210}, {0x2212, 0x2214}, - {0x2216, 0x2219}, {0x221B, 0x221C}, {0x2221, 0x2222}, - {0x2224, 0x2224}, {0x2226, 0x2226}, {0x222D, 0x222D}, - {0x222F, 0x2233}, {0x2238, 0x223B}, {0x223E, 0x2247}, - {0x2249, 0x224B}, {0x224D, 0x2251}, {0x2253, 0x225F}, - {0x2262, 0x2263}, {0x2268, 0x2269}, {0x226C, 0x226D}, - {0x2270, 0x2281}, {0x2284, 0x2285}, {0x2288, 0x2294}, - {0x2296, 0x2298}, {0x229A, 0x22A4}, {0x22A6, 0x22BE}, - {0x22C0, 0x22FF}, {0x2300, 0x2307}, {0x2308, 0x2308}, - {0x2309, 0x2309}, {0x230A, 0x230A}, {0x230B, 0x230B}, - {0x230C, 0x2311}, {0x2313, 0x2319}, {0x231C, 0x231F}, - {0x2320, 0x2321}, {0x2322, 0x2328}, {0x232B, 0x237B}, - {0x237C, 0x237C}, {0x237D, 0x239A}, {0x239B, 0x23B3}, - {0x23B4, 0x23DB}, {0x23DC, 0x23E1}, {0x23E2, 0x23E8}, - {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, - {0x2400, 0x2426}, {0x2440, 0x244A}, {0x24EA, 0x24EA}, - {0x254C, 0x254F}, {0x2574, 0x257F}, {0x2590, 0x2591}, - {0x2596, 0x259F}, {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, - {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, - {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, - {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, {0x25F0, 0x25F7}, - {0x25F8, 0x25FC}, {0x25FF, 0x25FF}, {0x2600, 0x2604}, - {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613}, - {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F}, - {0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F}, - {0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B}, - {0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692}, - {0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9}, - {0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2}, - {0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709}, - {0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B}, - {0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756}, - {0x2758, 0x2767}, {0x2768, 0x2768}, {0x2769, 0x2769}, - {0x276A, 0x276A}, {0x276B, 0x276B}, {0x276C, 0x276C}, - {0x276D, 0x276D}, {0x276E, 0x276E}, {0x276F, 0x276F}, - {0x2770, 0x2770}, {0x2771, 0x2771}, {0x2772, 0x2772}, - {0x2773, 0x2773}, {0x2774, 0x2774}, {0x2775, 0x2775}, - {0x2780, 0x2793}, {0x2794, 0x2794}, {0x2798, 0x27AF}, - {0x27B1, 0x27BE}, {0x27C0, 0x27C4}, {0x27C5, 0x27C5}, - {0x27C6, 0x27C6}, {0x27C7, 0x27E5}, {0x27EE, 0x27EE}, - {0x27EF, 0x27EF}, {0x27F0, 0x27FF}, {0x2800, 0x28FF}, - {0x2900, 0x297F}, {0x2980, 0x2982}, {0x2983, 0x2983}, - {0x2984, 0x2984}, {0x2987, 0x2987}, {0x2988, 0x2988}, - {0x2989, 0x2989}, {0x298A, 0x298A}, {0x298B, 0x298B}, - {0x298C, 0x298C}, {0x298D, 0x298D}, {0x298E, 0x298E}, - {0x298F, 0x298F}, {0x2990, 0x2990}, {0x2991, 0x2991}, - {0x2992, 0x2992}, {0x2993, 0x2993}, {0x2994, 0x2994}, - {0x2995, 0x2995}, {0x2996, 0x2996}, {0x2997, 0x2997}, - {0x2998, 0x2998}, {0x2999, 0x29D7}, {0x29D8, 0x29D8}, - {0x29D9, 0x29D9}, {0x29DA, 0x29DA}, {0x29DB, 0x29DB}, - {0x29DC, 0x29FB}, {0x29FC, 0x29FC}, {0x29FD, 0x29FD}, - {0x29FE, 0x29FF}, {0x2A00, 0x2AFF}, {0x2B00, 0x2B1A}, - {0x2B1D, 0x2B2F}, {0x2B30, 0x2B44}, {0x2B45, 0x2B46}, - {0x2B47, 0x2B4C}, {0x2B4D, 0x2B4F}, {0x2B51, 0x2B54}, - {0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9}, - {0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF}, - {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2C7B}, - {0x2C7C, 0x2C7D}, {0x2C7E, 0x2C7F}, {0x2C80, 0x2CE4}, - {0x2CE5, 0x2CEA}, {0x2CEB, 0x2CEE}, {0x2CEF, 0x2CF1}, - {0x2CF2, 0x2CF3}, {0x2CF9, 0x2CFC}, {0x2CFD, 0x2CFD}, - {0x2CFE, 0x2CFF}, {0x2D00, 0x2D25}, {0x2D27, 0x2D27}, - {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D6F}, - {0x2D70, 0x2D70}, {0x2D7F, 0x2D7F}, {0x2D80, 0x2D96}, - {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, - {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, - {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2DFF}, - {0x2E00, 0x2E01}, {0x2E02, 0x2E02}, {0x2E03, 0x2E03}, - {0x2E04, 0x2E04}, {0x2E05, 0x2E05}, {0x2E06, 0x2E08}, - {0x2E09, 0x2E09}, {0x2E0A, 0x2E0A}, {0x2E0B, 0x2E0B}, - {0x2E0C, 0x2E0C}, {0x2E0D, 0x2E0D}, {0x2E0E, 0x2E16}, - {0x2E17, 0x2E17}, {0x2E18, 0x2E19}, {0x2E1A, 0x2E1A}, - {0x2E1B, 0x2E1B}, {0x2E1C, 0x2E1C}, {0x2E1D, 0x2E1D}, - {0x2E1E, 0x2E1F}, {0x2E20, 0x2E20}, {0x2E21, 0x2E21}, - {0x2E22, 0x2E22}, {0x2E23, 0x2E23}, {0x2E24, 0x2E24}, - {0x2E25, 0x2E25}, {0x2E26, 0x2E26}, {0x2E27, 0x2E27}, - {0x2E28, 0x2E28}, {0x2E29, 0x2E29}, {0x2E2A, 0x2E2E}, - {0x2E2F, 0x2E2F}, {0x2E30, 0x2E39}, {0x2E3A, 0x2E3B}, - {0x2E3C, 0x2E3F}, {0x2E40, 0x2E40}, {0x2E41, 0x2E41}, - {0x2E42, 0x2E42}, {0x2E43, 0x2E44}, {0x303F, 0x303F}, - {0x4DC0, 0x4DFF}, {0xA4D0, 0xA4F7}, {0xA4F8, 0xA4FD}, - {0xA4FE, 0xA4FF}, {0xA500, 0xA60B}, {0xA60C, 0xA60C}, - {0xA60D, 0xA60F}, {0xA610, 0xA61F}, {0xA620, 0xA629}, - {0xA62A, 0xA62B}, {0xA640, 0xA66D}, {0xA66E, 0xA66E}, - {0xA66F, 0xA66F}, {0xA670, 0xA672}, {0xA673, 0xA673}, - {0xA674, 0xA67D}, {0xA67E, 0xA67E}, {0xA67F, 0xA67F}, - {0xA680, 0xA69B}, {0xA69C, 0xA69D}, {0xA69E, 0xA69F}, - {0xA6A0, 0xA6E5}, {0xA6E6, 0xA6EF}, {0xA6F0, 0xA6F1}, - {0xA6F2, 0xA6F7}, {0xA700, 0xA716}, {0xA717, 0xA71F}, - {0xA720, 0xA721}, {0xA722, 0xA76F}, {0xA770, 0xA770}, - {0xA771, 0xA787}, {0xA788, 0xA788}, {0xA789, 0xA78A}, - {0xA78B, 0xA78E}, {0xA78F, 0xA78F}, {0xA790, 0xA7AE}, - {0xA7B0, 0xA7B7}, {0xA7F7, 0xA7F7}, {0xA7F8, 0xA7F9}, - {0xA7FA, 0xA7FA}, {0xA7FB, 0xA7FF}, {0xA800, 0xA801}, - {0xA802, 0xA802}, {0xA803, 0xA805}, {0xA806, 0xA806}, - {0xA807, 0xA80A}, {0xA80B, 0xA80B}, {0xA80C, 0xA822}, - {0xA823, 0xA824}, {0xA825, 0xA826}, {0xA827, 0xA827}, - {0xA828, 0xA82B}, {0xA830, 0xA835}, {0xA836, 0xA837}, - {0xA838, 0xA838}, {0xA839, 0xA839}, {0xA840, 0xA873}, - {0xA874, 0xA877}, {0xA880, 0xA881}, {0xA882, 0xA8B3}, - {0xA8B4, 0xA8C3}, {0xA8C4, 0xA8C5}, {0xA8CE, 0xA8CF}, - {0xA8D0, 0xA8D9}, {0xA8E0, 0xA8F1}, {0xA8F2, 0xA8F7}, - {0xA8F8, 0xA8FA}, {0xA8FB, 0xA8FB}, {0xA8FC, 0xA8FC}, - {0xA8FD, 0xA8FD}, {0xA900, 0xA909}, {0xA90A, 0xA925}, - {0xA926, 0xA92D}, {0xA92E, 0xA92F}, {0xA930, 0xA946}, - {0xA947, 0xA951}, {0xA952, 0xA953}, {0xA95F, 0xA95F}, - {0xA980, 0xA982}, {0xA983, 0xA983}, {0xA984, 0xA9B2}, - {0xA9B3, 0xA9B3}, {0xA9B4, 0xA9B5}, {0xA9B6, 0xA9B9}, - {0xA9BA, 0xA9BB}, {0xA9BC, 0xA9BC}, {0xA9BD, 0xA9C0}, - {0xA9C1, 0xA9CD}, {0xA9CF, 0xA9CF}, {0xA9D0, 0xA9D9}, - {0xA9DE, 0xA9DF}, {0xA9E0, 0xA9E4}, {0xA9E5, 0xA9E5}, - {0xA9E6, 0xA9E6}, {0xA9E7, 0xA9EF}, {0xA9F0, 0xA9F9}, - {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA29, 0xAA2E}, - {0xAA2F, 0xAA30}, {0xAA31, 0xAA32}, {0xAA33, 0xAA34}, - {0xAA35, 0xAA36}, {0xAA40, 0xAA42}, {0xAA43, 0xAA43}, - {0xAA44, 0xAA4B}, {0xAA4C, 0xAA4C}, {0xAA4D, 0xAA4D}, - {0xAA50, 0xAA59}, {0xAA5C, 0xAA5F}, {0xAA60, 0xAA6F}, - {0xAA70, 0xAA70}, {0xAA71, 0xAA76}, {0xAA77, 0xAA79}, - {0xAA7A, 0xAA7A}, {0xAA7B, 0xAA7B}, {0xAA7C, 0xAA7C}, - {0xAA7D, 0xAA7D}, {0xAA7E, 0xAA7F}, {0xAA80, 0xAAAF}, - {0xAAB0, 0xAAB0}, {0xAAB1, 0xAAB1}, {0xAAB2, 0xAAB4}, - {0xAAB5, 0xAAB6}, {0xAAB7, 0xAAB8}, {0xAAB9, 0xAABD}, - {0xAABE, 0xAABF}, {0xAAC0, 0xAAC0}, {0xAAC1, 0xAAC1}, - {0xAAC2, 0xAAC2}, {0xAADB, 0xAADC}, {0xAADD, 0xAADD}, - {0xAADE, 0xAADF}, {0xAAE0, 0xAAEA}, {0xAAEB, 0xAAEB}, - {0xAAEC, 0xAAED}, {0xAAEE, 0xAAEF}, {0xAAF0, 0xAAF1}, - {0xAAF2, 0xAAF2}, {0xAAF3, 0xAAF4}, {0xAAF5, 0xAAF5}, - {0xAAF6, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, - {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, - {0xAB30, 0xAB5A}, {0xAB5B, 0xAB5B}, {0xAB5C, 0xAB5F}, - {0xAB60, 0xAB65}, {0xAB70, 0xABBF}, {0xABC0, 0xABE2}, - {0xABE3, 0xABE4}, {0xABE5, 0xABE5}, {0xABE6, 0xABE7}, - {0xABE8, 0xABE8}, {0xABE9, 0xABEA}, {0xABEB, 0xABEB}, - {0xABEC, 0xABEC}, {0xABED, 0xABED}, {0xABF0, 0xABF9}, - {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDB7F}, - {0xDB80, 0xDBFF}, {0xDC00, 0xDFFF}, {0xFB00, 0xFB06}, - {0xFB13, 0xFB17}, {0xFB1D, 0xFB1D}, {0xFB1E, 0xFB1E}, - {0xFB1F, 0xFB28}, {0xFB29, 0xFB29}, {0xFB2A, 0xFB36}, - {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, - {0xFB43, 0xFB44}, {0xFB46, 0xFB4F}, {0xFB50, 0xFBB1}, - {0xFBB2, 0xFBC1}, {0xFBD3, 0xFD3D}, {0xFD3E, 0xFD3E}, - {0xFD3F, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, - {0xFDF0, 0xFDFB}, {0xFDFC, 0xFDFC}, {0xFDFD, 0xFDFD}, - {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, - {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFC, 0xFFFC}, - {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, - {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D}, - {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133}, - {0x10137, 0x1013F}, {0x10140, 0x10174}, {0x10175, 0x10178}, - {0x10179, 0x10189}, {0x1018A, 0x1018B}, {0x1018C, 0x1018E}, - {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, - {0x101FD, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0}, - {0x102E0, 0x102E0}, {0x102E1, 0x102FB}, {0x10300, 0x1031F}, - {0x10320, 0x10323}, {0x10330, 0x10340}, {0x10341, 0x10341}, - {0x10342, 0x10349}, {0x1034A, 0x1034A}, {0x10350, 0x10375}, - {0x10376, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x1039F}, - {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x103D0, 0x103D0}, - {0x103D1, 0x103D5}, {0x10400, 0x1044F}, {0x10450, 0x1047F}, - {0x10480, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, - {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, - {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, - {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, - {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, - {0x1083F, 0x1083F}, {0x10840, 0x10855}, {0x10857, 0x10857}, - {0x10858, 0x1085F}, {0x10860, 0x10876}, {0x10877, 0x10878}, - {0x10879, 0x1087F}, {0x10880, 0x1089E}, {0x108A7, 0x108AF}, - {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x108FF}, - {0x10900, 0x10915}, {0x10916, 0x1091B}, {0x1091F, 0x1091F}, - {0x10920, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x1099F}, - {0x109A0, 0x109B7}, {0x109BC, 0x109BD}, {0x109BE, 0x109BF}, - {0x109C0, 0x109CF}, {0x109D2, 0x109FF}, {0x10A00, 0x10A00}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10A40, 0x10A47}, - {0x10A50, 0x10A58}, {0x10A60, 0x10A7C}, {0x10A7D, 0x10A7E}, - {0x10A7F, 0x10A7F}, {0x10A80, 0x10A9C}, {0x10A9D, 0x10A9F}, - {0x10AC0, 0x10AC7}, {0x10AC8, 0x10AC8}, {0x10AC9, 0x10AE4}, - {0x10AE5, 0x10AE6}, {0x10AEB, 0x10AEF}, {0x10AF0, 0x10AF6}, - {0x10B00, 0x10B35}, {0x10B39, 0x10B3F}, {0x10B40, 0x10B55}, - {0x10B58, 0x10B5F}, {0x10B60, 0x10B72}, {0x10B78, 0x10B7F}, - {0x10B80, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, - {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, - {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x11000}, - {0x11001, 0x11001}, {0x11002, 0x11002}, {0x11003, 0x11037}, - {0x11038, 0x11046}, {0x11047, 0x1104D}, {0x11052, 0x11065}, - {0x11066, 0x1106F}, {0x1107F, 0x1107F}, {0x11080, 0x11081}, - {0x11082, 0x11082}, {0x11083, 0x110AF}, {0x110B0, 0x110B2}, - {0x110B3, 0x110B6}, {0x110B7, 0x110B8}, {0x110B9, 0x110BA}, - {0x110BB, 0x110BC}, {0x110BD, 0x110BD}, {0x110BE, 0x110C1}, - {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11102}, - {0x11103, 0x11126}, {0x11127, 0x1112B}, {0x1112C, 0x1112C}, - {0x1112D, 0x11134}, {0x11136, 0x1113F}, {0x11140, 0x11143}, - {0x11150, 0x11172}, {0x11173, 0x11173}, {0x11174, 0x11175}, - {0x11176, 0x11176}, {0x11180, 0x11181}, {0x11182, 0x11182}, - {0x11183, 0x111B2}, {0x111B3, 0x111B5}, {0x111B6, 0x111BE}, - {0x111BF, 0x111C0}, {0x111C1, 0x111C4}, {0x111C5, 0x111C9}, - {0x111CA, 0x111CC}, {0x111CD, 0x111CD}, {0x111D0, 0x111D9}, - {0x111DA, 0x111DA}, {0x111DB, 0x111DB}, {0x111DC, 0x111DC}, - {0x111DD, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, - {0x11213, 0x1122B}, {0x1122C, 0x1122E}, {0x1122F, 0x11231}, - {0x11232, 0x11233}, {0x11234, 0x11234}, {0x11235, 0x11235}, - {0x11236, 0x11237}, {0x11238, 0x1123D}, {0x1123E, 0x1123E}, - {0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D}, - {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112A9, 0x112A9}, - {0x112B0, 0x112DE}, {0x112DF, 0x112DF}, {0x112E0, 0x112E2}, - {0x112E3, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11301}, - {0x11302, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, - {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, - {0x11335, 0x11339}, {0x1133C, 0x1133C}, {0x1133D, 0x1133D}, - {0x1133E, 0x1133F}, {0x11340, 0x11340}, {0x11341, 0x11344}, - {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350}, - {0x11357, 0x11357}, {0x1135D, 0x11361}, {0x11362, 0x11363}, - {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x11434}, - {0x11435, 0x11437}, {0x11438, 0x1143F}, {0x11440, 0x11441}, - {0x11442, 0x11444}, {0x11445, 0x11445}, {0x11446, 0x11446}, - {0x11447, 0x1144A}, {0x1144B, 0x1144F}, {0x11450, 0x11459}, - {0x1145B, 0x1145B}, {0x1145D, 0x1145D}, {0x11480, 0x114AF}, - {0x114B0, 0x114B2}, {0x114B3, 0x114B8}, {0x114B9, 0x114B9}, - {0x114BA, 0x114BA}, {0x114BB, 0x114BE}, {0x114BF, 0x114C0}, - {0x114C1, 0x114C1}, {0x114C2, 0x114C3}, {0x114C4, 0x114C5}, - {0x114C6, 0x114C6}, {0x114C7, 0x114C7}, {0x114D0, 0x114D9}, - {0x11580, 0x115AE}, {0x115AF, 0x115B1}, {0x115B2, 0x115B5}, - {0x115B8, 0x115BB}, {0x115BC, 0x115BD}, {0x115BE, 0x115BE}, - {0x115BF, 0x115C0}, {0x115C1, 0x115D7}, {0x115D8, 0x115DB}, - {0x115DC, 0x115DD}, {0x11600, 0x1162F}, {0x11630, 0x11632}, - {0x11633, 0x1163A}, {0x1163B, 0x1163C}, {0x1163D, 0x1163D}, - {0x1163E, 0x1163E}, {0x1163F, 0x11640}, {0x11641, 0x11643}, - {0x11644, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, - {0x11680, 0x116AA}, {0x116AB, 0x116AB}, {0x116AC, 0x116AC}, - {0x116AD, 0x116AD}, {0x116AE, 0x116AF}, {0x116B0, 0x116B5}, - {0x116B6, 0x116B6}, {0x116B7, 0x116B7}, {0x116C0, 0x116C9}, - {0x11700, 0x11719}, {0x1171D, 0x1171F}, {0x11720, 0x11721}, - {0x11722, 0x11725}, {0x11726, 0x11726}, {0x11727, 0x1172B}, - {0x11730, 0x11739}, {0x1173A, 0x1173B}, {0x1173C, 0x1173E}, - {0x1173F, 0x1173F}, {0x118A0, 0x118DF}, {0x118E0, 0x118E9}, - {0x118EA, 0x118F2}, {0x118FF, 0x118FF}, {0x11AC0, 0x11AF8}, - {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C2F, 0x11C2F}, - {0x11C30, 0x11C36}, {0x11C38, 0x11C3D}, {0x11C3E, 0x11C3E}, - {0x11C3F, 0x11C3F}, {0x11C40, 0x11C40}, {0x11C41, 0x11C45}, - {0x11C50, 0x11C59}, {0x11C5A, 0x11C6C}, {0x11C70, 0x11C71}, - {0x11C72, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CA9}, - {0x11CAA, 0x11CB0}, {0x11CB1, 0x11CB1}, {0x11CB2, 0x11CB3}, - {0x11CB4, 0x11CB4}, {0x11CB5, 0x11CB6}, {0x12000, 0x12399}, - {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, - {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, - {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F}, - {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF4}, {0x16AF5, 0x16AF5}, - {0x16B00, 0x16B2F}, {0x16B30, 0x16B36}, {0x16B37, 0x16B3B}, - {0x16B3C, 0x16B3F}, {0x16B40, 0x16B43}, {0x16B44, 0x16B44}, - {0x16B45, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, - {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, - {0x16F50, 0x16F50}, {0x16F51, 0x16F7E}, {0x16F8F, 0x16F92}, - {0x16F93, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, - {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9C}, - {0x1BC9D, 0x1BC9E}, {0x1BC9F, 0x1BC9F}, {0x1BCA0, 0x1BCA3}, - {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, - {0x1D165, 0x1D166}, {0x1D167, 0x1D169}, {0x1D16A, 0x1D16C}, - {0x1D16D, 0x1D172}, {0x1D173, 0x1D17A}, {0x1D17B, 0x1D182}, - {0x1D183, 0x1D184}, {0x1D185, 0x1D18B}, {0x1D18C, 0x1D1A9}, - {0x1D1AA, 0x1D1AD}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, - {0x1D242, 0x1D244}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, - {0x1D360, 0x1D371}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, - {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, - {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, - {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, - {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, - {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, - {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, - {0x1D6C1, 0x1D6C1}, {0x1D6C2, 0x1D6DA}, {0x1D6DB, 0x1D6DB}, - {0x1D6DC, 0x1D6FA}, {0x1D6FB, 0x1D6FB}, {0x1D6FC, 0x1D714}, - {0x1D715, 0x1D715}, {0x1D716, 0x1D734}, {0x1D735, 0x1D735}, - {0x1D736, 0x1D74E}, {0x1D74F, 0x1D74F}, {0x1D750, 0x1D76E}, - {0x1D76F, 0x1D76F}, {0x1D770, 0x1D788}, {0x1D789, 0x1D789}, - {0x1D78A, 0x1D7A8}, {0x1D7A9, 0x1D7A9}, {0x1D7AA, 0x1D7C2}, - {0x1D7C3, 0x1D7C3}, {0x1D7C4, 0x1D7CB}, {0x1D7CE, 0x1D7FF}, - {0x1D800, 0x1D9FF}, {0x1DA00, 0x1DA36}, {0x1DA37, 0x1DA3A}, - {0x1DA3B, 0x1DA6C}, {0x1DA6D, 0x1DA74}, {0x1DA75, 0x1DA75}, - {0x1DA76, 0x1DA83}, {0x1DA84, 0x1DA84}, {0x1DA85, 0x1DA86}, - {0x1DA87, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, - {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, - {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, - {0x1E8C7, 0x1E8CF}, {0x1E8D0, 0x1E8D6}, {0x1E900, 0x1E943}, - {0x1E944, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, - {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, - {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, - {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, - {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, - {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, - {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, - {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, - {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, - {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, - {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, - {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, - {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, - {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, - {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, - {0x1F12E, 0x1F12E}, {0x1F16A, 0x1F16B}, {0x1F1E6, 0x1F1FF}, - {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, - {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, - {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, - {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, - {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, - {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, - {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6E0, 0x1F6EA}, - {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D4}, - {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, - {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0xE0001, 0xE0001}, - {0xE0020, 0xE007F}, -} - -// Condition have flag EastAsianWidth whether the current locale is CJK or not. -type Condition struct { - EastAsianWidth bool -} - -// NewCondition return new instance of Condition which is current locale. -func NewCondition() *Condition { - return &Condition{EastAsianWidth} -} - -// RuneWidth returns the number of cells in r. -// See http://www.unicode.org/reports/tr11/ -func (c *Condition) RuneWidth(r rune) int { - switch { - case r < 0 || r > 0x10FFFF || - inTables(r, nonprint, combining, notassigned): - return 0 - case (c.EastAsianWidth && IsAmbiguousWidth(r)) || - inTables(r, doublewidth, emoji): - return 2 - default: - return 1 - } -} - -// StringWidth return width as you can see -func (c *Condition) StringWidth(s string) (width int) { - for _, r := range []rune(s) { - width += c.RuneWidth(r) - } - return width -} - -// Truncate return string truncated with w cells -func (c *Condition) Truncate(s string, w int, tail string) string { - if c.StringWidth(s) <= w { - return s - } - r := []rune(s) - tw := c.StringWidth(tail) - w -= tw - width := 0 - i := 0 - for ; i < len(r); i++ { - cw := c.RuneWidth(r[i]) - if width+cw > w { - break - } - width += cw - } - return string(r[0:i]) + tail -} - -// Wrap return string wrapped with w cells -func (c *Condition) Wrap(s string, w int) string { - width := 0 - out := "" - for _, r := range []rune(s) { - cw := RuneWidth(r) - if r == '\n' { - out += string(r) - width = 0 - continue - } else if width+cw > w { - out += "\n" - width = 0 - out += string(r) - width += cw - continue - } - out += string(r) - width += cw - } - return out -} - -// FillLeft return string filled in left by spaces in w cells -func (c *Condition) FillLeft(s string, w int) string { - width := c.StringWidth(s) - count := w - width - if count > 0 { - b := make([]byte, count) - for i := range b { - b[i] = ' ' - } - return string(b) + s - } - return s -} - -// FillRight return string filled in left by spaces in w cells -func (c *Condition) FillRight(s string, w int) string { - width := c.StringWidth(s) - count := w - width - if count > 0 { - b := make([]byte, count) - for i := range b { - b[i] = ' ' - } - return s + string(b) - } - return s -} - -// RuneWidth returns the number of cells in r. -// See http://www.unicode.org/reports/tr11/ -func RuneWidth(r rune) int { - return DefaultCondition.RuneWidth(r) -} - -// IsAmbiguousWidth returns whether is ambiguous width or not. -func IsAmbiguousWidth(r rune) bool { - return inTables(r, private, ambiguous) -} - -// IsNeutralWidth returns whether is neutral width or not. -func IsNeutralWidth(r rune) bool { - return inTable(r, neutral) -} - -// StringWidth return width as you can see -func StringWidth(s string) (width int) { - return DefaultCondition.StringWidth(s) -} - -// Truncate return string truncated with w cells -func Truncate(s string, w int, tail string) string { - return DefaultCondition.Truncate(s, w, tail) -} - -// Wrap return string wrapped with w cells -func Wrap(s string, w int) string { - return DefaultCondition.Wrap(s, w) -} - -// FillLeft return string filled in left by spaces in w cells -func FillLeft(s string, w int) string { - return DefaultCondition.FillLeft(s, w) -} - -// FillRight return string filled in left by spaces in w cells -func FillRight(s string, w int) string { - return DefaultCondition.FillRight(s, w) -} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go deleted file mode 100644 index 0ce32c5e7b..0000000000 --- a/vendor/github.com/mattn/go-runewidth/runewidth_js.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build js - -package runewidth - -func IsEastAsian() bool { - // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. - return false -} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go deleted file mode 100644 index c579e9a314..0000000000 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ /dev/null @@ -1,77 +0,0 @@ -// +build !windows,!js - -package runewidth - -import ( - "os" - "regexp" - "strings" -) - -var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) - -var mblenTable = map[string]int{ - "utf-8": 6, - "utf8": 6, - "jis": 8, - "eucjp": 3, - "euckr": 2, - "euccn": 2, - "sjis": 2, - "cp932": 2, - "cp51932": 2, - "cp936": 2, - "cp949": 2, - "cp950": 2, - "big5": 2, - "gbk": 2, - "gb2312": 2, -} - -func isEastAsian(locale string) bool { - charset := strings.ToLower(locale) - r := reLoc.FindStringSubmatch(locale) - if len(r) == 2 { - charset = strings.ToLower(r[1]) - } - - if strings.HasSuffix(charset, "@cjk_narrow") { - return false - } - - for pos, b := range []byte(charset) { - if b == '@' { - charset = charset[:pos] - break - } - } - max := 1 - if m, ok := mblenTable[charset]; ok { - max = m - } - if max > 1 && (charset[0] != 'u' || - strings.HasPrefix(locale, "ja") || - strings.HasPrefix(locale, "ko") || - strings.HasPrefix(locale, "zh")) { - return true - } - return false -} - -// IsEastAsian return true if the current locale is CJK -func IsEastAsian() bool { - locale := os.Getenv("LC_CTYPE") - if locale == "" { - locale = os.Getenv("LANG") - } - - // ignore C locale - if locale == "POSIX" || locale == "C" { - return false - } - if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { - return false - } - - return isEastAsian(locale) -} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go deleted file mode 100644 index 0258876b99..0000000000 --- a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go +++ /dev/null @@ -1,25 +0,0 @@ -package runewidth - -import ( - "syscall" -) - -var ( - kernel32 = syscall.NewLazyDLL("kernel32") - procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") -) - -// IsEastAsian return true if the current locale is CJK -func IsEastAsian() bool { - r1, _, _ := procGetConsoleOutputCP.Call() - if r1 == 0 { - return false - } - - switch int(r1) { - case 932, 51932, 936, 949, 950: - return true - } - - return false -} diff --git a/vendor/github.com/mattn/go-shellwords/LICENSE b/vendor/github.com/mattn/go-shellwords/LICENSE deleted file mode 100644 index 740fa93132..0000000000 --- a/vendor/github.com/mattn/go-shellwords/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/mattn/go-shellwords/shellwords.go b/vendor/github.com/mattn/go-shellwords/shellwords.go deleted file mode 100644 index 107803927a..0000000000 --- a/vendor/github.com/mattn/go-shellwords/shellwords.go +++ /dev/null @@ -1,145 +0,0 @@ -package shellwords - -import ( - "errors" - "os" - "regexp" -) - -var ( - ParseEnv bool = false - ParseBacktick bool = false -) - -var envRe = regexp.MustCompile(`\$({[a-zA-Z0-9_]+}|[a-zA-Z0-9_]+)`) - -func isSpace(r rune) bool { - switch r { - case ' ', '\t', '\r', '\n': - return true - } - return false -} - -func replaceEnv(s string) string { - return envRe.ReplaceAllStringFunc(s, func(s string) string { - s = s[1:] - if s[0] == '{' { - s = s[1 : len(s)-1] - } - return os.Getenv(s) - }) -} - -type Parser struct { - ParseEnv bool - ParseBacktick bool - Position int -} - -func NewParser() *Parser { - return &Parser{ParseEnv, ParseBacktick, 0} -} - -func (p *Parser) Parse(line string) ([]string, error) { - args := []string{} - buf := "" - var escaped, doubleQuoted, singleQuoted, backQuote bool - backtick := "" - - pos := -1 - got := false - -loop: - for i, r := range line { - if escaped { - buf += string(r) - escaped = false - continue - } - - if r == '\\' { - if singleQuoted { - buf += string(r) - } else { - escaped = true - } - continue - } - - if isSpace(r) { - if singleQuoted || doubleQuoted || backQuote { - buf += string(r) - backtick += string(r) - } else if got { - if p.ParseEnv { - buf = replaceEnv(buf) - } - args = append(args, buf) - buf = "" - got = false - } - continue - } - - switch r { - case '`': - if !singleQuoted && !doubleQuoted { - if p.ParseBacktick { - if backQuote { - out, err := shellRun(backtick) - if err != nil { - return nil, err - } - buf = out - } - backtick = "" - backQuote = !backQuote - continue - } - backtick = "" - backQuote = !backQuote - } - case '"': - if !singleQuoted { - doubleQuoted = !doubleQuoted - continue - } - case '\'': - if !doubleQuoted { - singleQuoted = !singleQuoted - continue - } - case ';', '&', '|', '<', '>': - if !(escaped || singleQuoted || doubleQuoted || backQuote) { - pos = i - break loop - } - } - - got = true - buf += string(r) - if backQuote { - backtick += string(r) - } - } - - if got { - if p.ParseEnv { - buf = replaceEnv(buf) - } - args = append(args, buf) - } - - if escaped || singleQuoted || doubleQuoted || backQuote { - return nil, errors.New("invalid command line string") - } - - p.Position = pos - - return args, nil -} - -func Parse(line string) ([]string, error) { - return NewParser().Parse(line) -} diff --git a/vendor/github.com/mattn/go-shellwords/util_posix.go b/vendor/github.com/mattn/go-shellwords/util_posix.go deleted file mode 100644 index 4f8ac55e47..0000000000 --- a/vendor/github.com/mattn/go-shellwords/util_posix.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package shellwords - -import ( - "errors" - "os" - "os/exec" - "strings" -) - -func shellRun(line string) (string, error) { - shell := os.Getenv("SHELL") - b, err := exec.Command(shell, "-c", line).Output() - if err != nil { - return "", errors.New(err.Error() + ":" + string(b)) - } - return strings.TrimSpace(string(b)), nil -} diff --git a/vendor/github.com/mattn/go-shellwords/util_windows.go b/vendor/github.com/mattn/go-shellwords/util_windows.go deleted file mode 100644 index 7cad4cf06f..0000000000 --- a/vendor/github.com/mattn/go-shellwords/util_windows.go +++ /dev/null @@ -1,17 +0,0 @@ -package shellwords - -import ( - "errors" - "os" - "os/exec" - "strings" -) - -func shellRun(line string) (string, error) { - shell := os.Getenv("COMSPEC") - b, err := exec.Command(shell, "/c", line).Output() - if err != nil { - return "", errors.New(err.Error() + ":" + string(b)) - } - return strings.TrimSpace(string(b)), nil -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE b/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE deleted file mode 100644 index 8dada3edaf..0000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE b/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE deleted file mode 100644 index 5d8cb5b72e..0000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE +++ /dev/null @@ -1 +0,0 @@ -Copyright 2012 Matt T. Proud (matt.proud@gmail.com) diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go deleted file mode 100644 index 258c0636aa..0000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "encoding/binary" - "errors" - "io" - - "github.com/golang/protobuf/proto" -) - -var errInvalidVarint = errors.New("invalid varint32 encountered") - -// ReadDelimited decodes a message from the provided length-delimited stream, -// where the length is encoded as 32-bit varint prefix to the message body. -// It returns the total number of bytes read and any applicable error. This is -// roughly equivalent to the companion Java API's -// MessageLite#parseDelimitedFrom. As per the reader contract, this function -// calls r.Read repeatedly as required until exactly one message including its -// prefix is read and decoded (or an error has occurred). The function never -// reads more bytes from the stream than required. The function never returns -// an error if a message has been read and decoded correctly, even if the end -// of the stream has been reached in doing so. In that case, any subsequent -// calls return (0, io.EOF). -func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { - // Per AbstractParser#parsePartialDelimitedFrom with - // CodedInputStream#readRawVarint32. - var headerBuf [binary.MaxVarintLen32]byte - var bytesRead, varIntBytes int - var messageLength uint64 - for varIntBytes == 0 { // i.e. no varint has been decoded yet. - if bytesRead >= len(headerBuf) { - return bytesRead, errInvalidVarint - } - // We have to read byte by byte here to avoid reading more bytes - // than required. Each read byte is appended to what we have - // read before. - newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) - if newBytesRead == 0 { - if err != nil { - return bytesRead, err - } - // A Reader should not return (0, nil), but if it does, - // it should be treated as no-op (according to the - // Reader contract). So let's go on... - continue - } - bytesRead += newBytesRead - // Now present everything read so far to the varint decoder and - // see if a varint can be decoded already. - messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) - } - - messageBuf := make([]byte, messageLength) - newBytesRead, err := io.ReadFull(r, messageBuf) - bytesRead += newBytesRead - if err != nil { - return bytesRead, err - } - - return bytesRead, proto.Unmarshal(messageBuf, m) -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go deleted file mode 100644 index 8fb59ad226..0000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "encoding/binary" - "io" - - "github.com/golang/protobuf/proto" -) - -// WriteDelimited encodes and dumps a message to the provided writer prefixed -// with a 32-bit varint indicating the length of the encoded message, producing -// a length-delimited record stream, which can be used to chain together -// encoded messages of the same type together in a file. It returns the total -// number of bytes written and any applicable error. This is roughly -// equivalent to the companion Java API's MessageLite#writeDelimitedTo. -func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { - buffer, err := proto.Marshal(m) - if err != nil { - return 0, err - } - - var buf [binary.MaxVarintLen32]byte - encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) - - sync, err := w.Write(buf[:encodedLength]) - if err != nil { - return sync, err - } - - n, err = w.Write(buffer) - return n + sync, err -} diff --git a/vendor/github.com/mistifyio/go-zfs/LICENSE b/vendor/github.com/mistifyio/go-zfs/LICENSE deleted file mode 100644 index f4c265cfec..0000000000 --- a/vendor/github.com/mistifyio/go-zfs/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2014, OmniTI Computer Consulting, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/mistifyio/go-zfs/error.go b/vendor/github.com/mistifyio/go-zfs/error.go deleted file mode 100644 index 5408ccdb55..0000000000 --- a/vendor/github.com/mistifyio/go-zfs/error.go +++ /dev/null @@ -1,18 +0,0 @@ -package zfs - -import ( - "fmt" -) - -// Error is an error which is returned when the `zfs` or `zpool` shell -// commands return with a non-zero exit code. -type Error struct { - Err error - Debug string - Stderr string -} - -// Error returns the string representation of an Error. -func (e Error) Error() string { - return fmt.Sprintf("%s: %q => %s", e.Err, e.Debug, e.Stderr) -} diff --git a/vendor/github.com/mistifyio/go-zfs/utils.go b/vendor/github.com/mistifyio/go-zfs/utils.go deleted file mode 100644 index d5b7353494..0000000000 --- a/vendor/github.com/mistifyio/go-zfs/utils.go +++ /dev/null @@ -1,320 +0,0 @@ -package zfs - -import ( - "bytes" - "fmt" - "io" - "os/exec" - "regexp" - "strconv" - "strings" -) - -type command struct { - Command string - Stdin io.Reader - Stdout io.Writer -} - -func (c *command) Run(arg ...string) ([][]string, error) { - - cmd := exec.Command(c.Command, arg...) - - var stdout, stderr bytes.Buffer - - if c.Stdout == nil { - cmd.Stdout = &stdout - } else { - cmd.Stdout = c.Stdout - } - - if c.Stdin != nil { - cmd.Stdin = c.Stdin - - } - cmd.Stderr = &stderr - - debug := strings.Join([]string{cmd.Path, strings.Join(cmd.Args, " ")}, " ") - if logger != nil { - logger.Log(cmd.Args) - } - err := cmd.Run() - - if err != nil { - return nil, &Error{ - Err: err, - Debug: debug, - Stderr: stderr.String(), - } - } - - // assume if you passed in something for stdout, that you know what to do with it - if c.Stdout != nil { - return nil, nil - } - - lines := strings.Split(stdout.String(), "\n") - - //last line is always blank - lines = lines[0 : len(lines)-1] - output := make([][]string, len(lines)) - - for i, l := range lines { - output[i] = strings.Fields(l) - } - - return output, nil -} - -func setString(field *string, value string) { - v := "" - if value != "-" { - v = value - } - *field = v -} - -func setUint(field *uint64, value string) error { - var v uint64 - if value != "-" { - var err error - v, err = strconv.ParseUint(value, 10, 64) - if err != nil { - return err - } - } - *field = v - return nil -} - -func (ds *Dataset) parseLine(line []string) error { - prop := line[1] - val := line[2] - - var err error - - switch prop { - case "available": - err = setUint(&ds.Avail, val) - case "compression": - setString(&ds.Compression, val) - case "mountpoint": - setString(&ds.Mountpoint, val) - case "quota": - err = setUint(&ds.Quota, val) - case "type": - setString(&ds.Type, val) - case "origin": - setString(&ds.Origin, val) - case "used": - err = setUint(&ds.Used, val) - case "volsize": - err = setUint(&ds.Volsize, val) - case "written": - err = setUint(&ds.Written, val) - case "logicalused": - err = setUint(&ds.Logicalused, val) - } - return err -} - -/* - * from zfs diff`s escape function: - * - * Prints a file name out a character at a time. If the character is - * not in the range of what we consider "printable" ASCII, display it - * as an escaped 3-digit octal value. ASCII values less than a space - * are all control characters and we declare the upper end as the - * DELete character. This also is the last 7-bit ASCII character. - * We choose to treat all 8-bit ASCII as not printable for this - * application. - */ -func unescapeFilepath(path string) (string, error) { - buf := make([]byte, 0, len(path)) - llen := len(path) - for i := 0; i < llen; { - if path[i] == '\\' { - if llen < i+4 { - return "", fmt.Errorf("Invalid octal code: too short") - } - octalCode := path[(i + 1):(i + 4)] - val, err := strconv.ParseUint(octalCode, 8, 8) - if err != nil { - return "", fmt.Errorf("Invalid octal code: %v", err) - } - buf = append(buf, byte(val)) - i += 4 - } else { - buf = append(buf, path[i]) - i++ - } - } - return string(buf), nil -} - -var changeTypeMap = map[string]ChangeType{ - "-": Removed, - "+": Created, - "M": Modified, - "R": Renamed, -} -var inodeTypeMap = map[string]InodeType{ - "B": BlockDevice, - "C": CharacterDevice, - "/": Directory, - ">": Door, - "|": NamedPipe, - "@": SymbolicLink, - "P": EventPort, - "=": Socket, - "F": File, -} - -// matches (+1) or (-1) -var referenceCountRegex = regexp.MustCompile("\\(([+-]\\d+?)\\)") - -func parseReferenceCount(field string) (int, error) { - matches := referenceCountRegex.FindStringSubmatch(field) - if matches == nil { - return 0, fmt.Errorf("Regexp does not match") - } - return strconv.Atoi(matches[1]) -} - -func parseInodeChange(line []string) (*InodeChange, error) { - llen := len(line) - if llen < 1 { - return nil, fmt.Errorf("Empty line passed") - } - - changeType := changeTypeMap[line[0]] - if changeType == 0 { - return nil, fmt.Errorf("Unknown change type '%s'", line[0]) - } - - switch changeType { - case Renamed: - if llen != 4 { - return nil, fmt.Errorf("Mismatching number of fields: expect 4, got: %d", llen) - } - case Modified: - if llen != 4 && llen != 3 { - return nil, fmt.Errorf("Mismatching number of fields: expect 3..4, got: %d", llen) - } - default: - if llen != 3 { - return nil, fmt.Errorf("Mismatching number of fields: expect 3, got: %d", llen) - } - } - - inodeType := inodeTypeMap[line[1]] - if inodeType == 0 { - return nil, fmt.Errorf("Unknown inode type '%s'", line[1]) - } - - path, err := unescapeFilepath(line[2]) - if err != nil { - return nil, fmt.Errorf("Failed to parse filename: %v", err) - } - - var newPath string - var referenceCount int - switch changeType { - case Renamed: - newPath, err = unescapeFilepath(line[3]) - if err != nil { - return nil, fmt.Errorf("Failed to parse filename: %v", err) - } - case Modified: - if llen == 4 { - referenceCount, err = parseReferenceCount(line[3]) - if err != nil { - return nil, fmt.Errorf("Failed to parse reference count: %v", err) - } - } - default: - newPath = "" - } - - return &InodeChange{ - Change: changeType, - Type: inodeType, - Path: path, - NewPath: newPath, - ReferenceCountChange: referenceCount, - }, nil -} - -// example input -//M / /testpool/bar/ -//+ F /testpool/bar/hello.txt -//M / /testpool/bar/hello.txt (+1) -//M / /testpool/bar/hello-hardlink -func parseInodeChanges(lines [][]string) ([]*InodeChange, error) { - changes := make([]*InodeChange, len(lines)) - - for i, line := range lines { - c, err := parseInodeChange(line) - if err != nil { - return nil, fmt.Errorf("Failed to parse line %d of zfs diff: %v, got: '%s'", i, err, line) - } - changes[i] = c - } - return changes, nil -} - -func listByType(t, filter string) ([]*Dataset, error) { - args := []string{"get", "-rHp", "-t", t, "all"} - if filter != "" { - args = append(args, filter) - } - out, err := zfs(args...) - if err != nil { - return nil, err - } - - var datasets []*Dataset - - name := "" - var ds *Dataset - for _, line := range out { - if name != line[0] { - name = line[0] - ds = &Dataset{Name: name} - datasets = append(datasets, ds) - } - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - - return datasets, nil -} - -func propsSlice(properties map[string]string) []string { - args := make([]string, 0, len(properties)*3) - for k, v := range properties { - args = append(args, "-o") - args = append(args, fmt.Sprintf("%s=%s", k, v)) - } - return args -} - -func (z *Zpool) parseLine(line []string) error { - prop := line[1] - val := line[2] - - var err error - - switch prop { - case "health": - setString(&z.Health, val) - case "allocated": - err = setUint(&z.Allocated, val) - case "size": - err = setUint(&z.Size, val) - case "free": - err = setUint(&z.Free, val) - } - return err -} diff --git a/vendor/github.com/mistifyio/go-zfs/zfs.go b/vendor/github.com/mistifyio/go-zfs/zfs.go deleted file mode 100644 index a1d740e07e..0000000000 --- a/vendor/github.com/mistifyio/go-zfs/zfs.go +++ /dev/null @@ -1,382 +0,0 @@ -// Package zfs provides wrappers around the ZFS command line tools. -package zfs - -import ( - "errors" - "fmt" - "io" - "strconv" - "strings" -) - -// ZFS dataset types, which can indicate if a dataset is a filesystem, -// snapshot, or volume. -const ( - DatasetFilesystem = "filesystem" - DatasetSnapshot = "snapshot" - DatasetVolume = "volume" -) - -// Dataset is a ZFS dataset. A dataset could be a clone, filesystem, snapshot, -// or volume. The Type struct member can be used to determine a dataset's type. -// -// The field definitions can be found in the ZFS manual: -// http://www.freebsd.org/cgi/man.cgi?zfs(8). -type Dataset struct { - Name string - Origin string - Used uint64 - Avail uint64 - Mountpoint string - Compression string - Type string - Written uint64 - Volsize uint64 - Usedbydataset uint64 - Logicalused uint64 - Quota uint64 -} - -// InodeType is the type of inode as reported by Diff -type InodeType int - -// Types of Inodes -const ( - _ = iota // 0 == unknown type - BlockDevice InodeType = iota - CharacterDevice - Directory - Door - NamedPipe - SymbolicLink - EventPort - Socket - File -) - -// ChangeType is the type of inode change as reported by Diff -type ChangeType int - -// Types of Changes -const ( - _ = iota // 0 == unknown type - Removed ChangeType = iota - Created - Modified - Renamed -) - -// DestroyFlag is the options flag passed to Destroy -type DestroyFlag int - -// Valid destroy options -const ( - DestroyDefault DestroyFlag = 1 << iota - DestroyRecursive = 1 << iota - DestroyRecursiveClones = 1 << iota - DestroyDeferDeletion = 1 << iota - DestroyForceUmount = 1 << iota -) - -// InodeChange represents a change as reported by Diff -type InodeChange struct { - Change ChangeType - Type InodeType - Path string - NewPath string - ReferenceCountChange int -} - -// Logger can be used to log commands/actions -type Logger interface { - Log(cmd []string) -} - -var logger Logger - -// SetLogger set a log handler to log all commands including arguments before -// they are executed -func SetLogger(l Logger) { - logger = l -} - -// zfs is a helper function to wrap typical calls to zfs. -func zfs(arg ...string) ([][]string, error) { - c := command{Command: "zfs"} - return c.Run(arg...) -} - -// Datasets returns a slice of ZFS datasets, regardless of type. -// A filter argument may be passed to select a dataset with the matching name, -// or empty string ("") may be used to select all datasets. -func Datasets(filter string) ([]*Dataset, error) { - return listByType("all", filter) -} - -// Snapshots returns a slice of ZFS snapshots. -// A filter argument may be passed to select a snapshot with the matching name, -// or empty string ("") may be used to select all snapshots. -func Snapshots(filter string) ([]*Dataset, error) { - return listByType(DatasetSnapshot, filter) -} - -// Filesystems returns a slice of ZFS filesystems. -// A filter argument may be passed to select a filesystem with the matching name, -// or empty string ("") may be used to select all filesystems. -func Filesystems(filter string) ([]*Dataset, error) { - return listByType(DatasetFilesystem, filter) -} - -// Volumes returns a slice of ZFS volumes. -// A filter argument may be passed to select a volume with the matching name, -// or empty string ("") may be used to select all volumes. -func Volumes(filter string) ([]*Dataset, error) { - return listByType(DatasetVolume, filter) -} - -// GetDataset retrieves a single ZFS dataset by name. This dataset could be -// any valid ZFS dataset type, such as a clone, filesystem, snapshot, or volume. -func GetDataset(name string) (*Dataset, error) { - out, err := zfs("get", "-Hp", "all", name) - if err != nil { - return nil, err - } - - ds := &Dataset{Name: name} - for _, line := range out { - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - - return ds, nil -} - -// Clone clones a ZFS snapshot and returns a clone dataset. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) Clone(dest string, properties map[string]string) (*Dataset, error) { - if d.Type != DatasetSnapshot { - return nil, errors.New("can only clone snapshots") - } - args := make([]string, 2, 4) - args[0] = "clone" - args[1] = "-p" - if properties != nil { - args = append(args, propsSlice(properties)...) - } - args = append(args, []string{d.Name, dest}...) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(dest) -} - -// ReceiveSnapshot receives a ZFS stream from the input io.Reader, creates a -// new snapshot with the specified name, and streams the input data into the -// newly-created snapshot. -func ReceiveSnapshot(input io.Reader, name string) (*Dataset, error) { - c := command{Command: "zfs", Stdin: input} - _, err := c.Run("receive", name) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// SendSnapshot sends a ZFS stream of a snapshot to the input io.Writer. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) SendSnapshot(output io.Writer) error { - if d.Type != DatasetSnapshot { - return errors.New("can only send snapshots") - } - - c := command{Command: "zfs", Stdout: output} - _, err := c.Run("send", d.Name) - return err -} - -// CreateVolume creates a new ZFS volume with the specified name, size, and -// properties. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateVolume(name string, size uint64, properties map[string]string) (*Dataset, error) { - args := make([]string, 4, 5) - args[0] = "create" - args[1] = "-p" - args[2] = "-V" - args[3] = strconv.FormatUint(size, 10) - if properties != nil { - args = append(args, propsSlice(properties)...) - } - args = append(args, name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// Destroy destroys a ZFS dataset. If the destroy bit flag is set, any -// descendents of the dataset will be recursively destroyed, including snapshots. -// If the deferred bit flag is set, the snapshot is marked for deferred -// deletion. -func (d *Dataset) Destroy(flags DestroyFlag) error { - args := make([]string, 1, 3) - args[0] = "destroy" - if flags&DestroyRecursive != 0 { - args = append(args, "-r") - } - - if flags&DestroyRecursiveClones != 0 { - args = append(args, "-R") - } - - if flags&DestroyDeferDeletion != 0 { - args = append(args, "-d") - } - - if flags&DestroyForceUmount != 0 { - args = append(args, "-f") - } - - args = append(args, d.Name) - _, err := zfs(args...) - return err -} - -// SetProperty sets a ZFS property on the receiving dataset. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func (d *Dataset) SetProperty(key, val string) error { - prop := strings.Join([]string{key, val}, "=") - _, err := zfs("set", prop, d.Name) - return err -} - -// GetProperty returns the current value of a ZFS property from the -// receiving dataset. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func (d *Dataset) GetProperty(key string) (string, error) { - out, err := zfs("get", key, d.Name) - if err != nil { - return "", err - } - - return out[0][2], nil -} - -// Snapshots returns a slice of all ZFS snapshots of a given dataset. -func (d *Dataset) Snapshots() ([]*Dataset, error) { - return Snapshots(d.Name) -} - -// CreateFilesystem creates a new ZFS filesystem with the specified name and -// properties. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateFilesystem(name string, properties map[string]string) (*Dataset, error) { - args := make([]string, 1, 4) - args[0] = "create" - - if properties != nil { - args = append(args, propsSlice(properties)...) - } - - args = append(args, name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// Snapshot creates a new ZFS snapshot of the receiving dataset, using the -// specified name. Optionally, the snapshot can be taken recursively, creating -// snapshots of all descendent filesystems in a single, atomic operation. -func (d *Dataset) Snapshot(name string, recursive bool) (*Dataset, error) { - args := make([]string, 1, 4) - args[0] = "snapshot" - if recursive { - args = append(args, "-r") - } - snapName := fmt.Sprintf("%s@%s", d.Name, name) - args = append(args, snapName) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(snapName) -} - -// Rollback rolls back the receiving ZFS dataset to a previous snapshot. -// Optionally, intermediate snapshots can be destroyed. A ZFS snapshot -// rollback cannot be completed without this option, if more recent -// snapshots exist. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) Rollback(destroyMoreRecent bool) error { - if d.Type != DatasetSnapshot { - return errors.New("can only rollback snapshots") - } - - args := make([]string, 1, 3) - args[0] = "rollback" - if destroyMoreRecent { - args = append(args, "-r") - } - args = append(args, d.Name) - - _, err := zfs(args...) - return err -} - -// Children returns a slice of children of the receiving ZFS dataset. -// A recursion depth may be specified, or a depth of 0 allows unlimited -// recursion. -func (d *Dataset) Children(depth uint64) ([]*Dataset, error) { - args := []string{"get", "-t", "all", "-Hp", "all"} - if depth > 0 { - args = append(args, "-d") - args = append(args, strconv.FormatUint(depth, 10)) - } else { - args = append(args, "-r") - } - args = append(args, d.Name) - - out, err := zfs(args...) - if err != nil { - return nil, err - } - - var datasets []*Dataset - name := "" - var ds *Dataset - for _, line := range out { - if name != line[0] { - name = line[0] - ds = &Dataset{Name: name} - datasets = append(datasets, ds) - } - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - return datasets[1:], nil -} - -// Diff returns changes between a snapshot and the given ZFS dataset. -// The snapshot name must include the filesystem part as it is possible to -// compare clones with their origin snapshots. -func (d *Dataset) Diff(snapshot string) ([]*InodeChange, error) { - args := []string{"diff", "-FH", snapshot, d.Name}[:] - out, err := zfs(args...) - if err != nil { - return nil, err - } - inodeChanges, err := parseInodeChanges(out) - if err != nil { - return nil, err - } - return inodeChanges, nil -} diff --git a/vendor/github.com/mistifyio/go-zfs/zpool.go b/vendor/github.com/mistifyio/go-zfs/zpool.go deleted file mode 100644 index 6ba52d30cb..0000000000 --- a/vendor/github.com/mistifyio/go-zfs/zpool.go +++ /dev/null @@ -1,105 +0,0 @@ -package zfs - -// ZFS zpool states, which can indicate if a pool is online, offline, -// degraded, etc. More information regarding zpool states can be found here: -// https://docs.oracle.com/cd/E19253-01/819-5461/gamno/index.html. -const ( - ZpoolOnline = "ONLINE" - ZpoolDegraded = "DEGRADED" - ZpoolFaulted = "FAULTED" - ZpoolOffline = "OFFLINE" - ZpoolUnavail = "UNAVAIL" - ZpoolRemoved = "REMOVED" -) - -// Zpool is a ZFS zpool. A pool is a top-level structure in ZFS, and can -// contain many descendent datasets. -type Zpool struct { - Name string - Health string - Allocated uint64 - Size uint64 - Free uint64 -} - -// zpool is a helper function to wrap typical calls to zpool. -func zpool(arg ...string) ([][]string, error) { - c := command{Command: "zpool"} - return c.Run(arg...) -} - -// GetZpool retrieves a single ZFS zpool by name. -func GetZpool(name string) (*Zpool, error) { - out, err := zpool("get", "all", "-p", name) - if err != nil { - return nil, err - } - - // there is no -H - out = out[1:] - - z := &Zpool{Name: name} - for _, line := range out { - if err := z.parseLine(line); err != nil { - return nil, err - } - } - - return z, nil -} - -// Datasets returns a slice of all ZFS datasets in a zpool. -func (z *Zpool) Datasets() ([]*Dataset, error) { - return Datasets(z.Name) -} - -// Snapshots returns a slice of all ZFS snapshots in a zpool. -func (z *Zpool) Snapshots() ([]*Dataset, error) { - return Snapshots(z.Name) -} - -// CreateZpool creates a new ZFS zpool with the specified name, properties, -// and optional arguments. -// A full list of available ZFS properties and command-line arguments may be -// found here: https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateZpool(name string, properties map[string]string, args ...string) (*Zpool, error) { - cli := make([]string, 1, 4) - cli[0] = "create" - if properties != nil { - cli = append(cli, propsSlice(properties)...) - } - cli = append(cli, name) - cli = append(cli, args...) - _, err := zpool(cli...) - if err != nil { - return nil, err - } - - return &Zpool{Name: name}, nil -} - -// Destroy destroys a ZFS zpool by name. -func (z *Zpool) Destroy() error { - _, err := zpool("destroy", z.Name) - return err -} - -// ListZpools list all ZFS zpools accessible on the current system. -func ListZpools() ([]*Zpool, error) { - args := []string{"list", "-Ho", "name"} - out, err := zpool(args...) - if err != nil { - return nil, err - } - - var pools []*Zpool - - for _, line := range out { - z, err := GetZpool(line[0]) - if err != nil { - return nil, err - } - pools = append(pools, z) - } - return pools, nil -} diff --git a/vendor/github.com/mtrmac/gpgme/LICENSE b/vendor/github.com/mtrmac/gpgme/LICENSE deleted file mode 100644 index 06d4ab7731..0000000000 --- a/vendor/github.com/mtrmac/gpgme/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -Copyright (c) 2015, James Fargher -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/mtrmac/gpgme/callbacks.go b/vendor/github.com/mtrmac/gpgme/callbacks.go deleted file mode 100644 index d1dc610d42..0000000000 --- a/vendor/github.com/mtrmac/gpgme/callbacks.go +++ /dev/null @@ -1,42 +0,0 @@ -package gpgme - -import ( - "sync" -) - -var callbacks struct { - sync.Mutex - m map[uintptr]interface{} - c uintptr -} - -func callbackAdd(v interface{}) uintptr { - callbacks.Lock() - defer callbacks.Unlock() - if callbacks.m == nil { - callbacks.m = make(map[uintptr]interface{}) - } - callbacks.c++ - ret := callbacks.c - callbacks.m[ret] = v - return ret -} - -func callbackLookup(c uintptr) interface{} { - callbacks.Lock() - defer callbacks.Unlock() - ret := callbacks.m[c] - if ret == nil { - panic("callback pointer not found") - } - return ret -} - -func callbackDelete(c uintptr) { - callbacks.Lock() - defer callbacks.Unlock() - if callbacks.m[c] == nil { - panic("callback pointer not found") - } - delete(callbacks.m, c) -} diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go deleted file mode 100644 index eebc972634..0000000000 --- a/vendor/github.com/mtrmac/gpgme/data.go +++ /dev/null @@ -1,191 +0,0 @@ -package gpgme - -// #include -// #include -// #include -// #include "go_gpgme.h" -import "C" - -import ( - "io" - "os" - "runtime" - "unsafe" -) - -const ( - SeekSet = C.SEEK_SET - SeekCur = C.SEEK_CUR - SeekEnd = C.SEEK_END -) - -//export gogpgme_readfunc -func gogpgme_readfunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t { - d := callbackLookup(uintptr(handle)).(*Data) - if len(d.buf) < int(size) { - d.buf = make([]byte, size) - } - n, err := d.r.Read(d.buf[:size]) - if err != nil && err != io.EOF { - C.gpgme_err_set_errno(C.EIO) - return -1 - } - C.memcpy(buffer, unsafe.Pointer(&d.buf[0]), C.size_t(n)) - return C.ssize_t(n) -} - -//export gogpgme_writefunc -func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t { - d := callbackLookup(uintptr(handle)).(*Data) - if len(d.buf) < int(size) { - d.buf = make([]byte, size) - } - C.memcpy(unsafe.Pointer(&d.buf[0]), buffer, C.size_t(size)) - n, err := d.w.Write(d.buf[:size]) - if err != nil && err != io.EOF { - C.gpgme_err_set_errno(C.EIO) - return -1 - } - return C.ssize_t(n) -} - -//export gogpgme_seekfunc -func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t { - d := callbackLookup(uintptr(handle)).(*Data) - n, err := d.s.Seek(int64(offset), int(whence)) - if err != nil { - C.gpgme_err_set_errno(C.EIO) - return -1 - } - return C.off_t(n) -} - -// The Data buffer used to communicate with GPGME -type Data struct { - dh C.gpgme_data_t - buf []byte - cbs C.struct_gpgme_data_cbs - r io.Reader - w io.Writer - s io.Seeker - cbc uintptr -} - -func newData() *Data { - d := &Data{} - runtime.SetFinalizer(d, (*Data).Close) - return d -} - -// NewData returns a new memory based data buffer -func NewData() (*Data, error) { - d := newData() - return d, handleError(C.gpgme_data_new(&d.dh)) -} - -// NewDataFile returns a new file based data buffer -func NewDataFile(f *os.File) (*Data, error) { - d := newData() - return d, handleError(C.gpgme_data_new_from_fd(&d.dh, C.int(f.Fd()))) -} - -// NewDataBytes returns a new memory based data buffer that contains `b` bytes -func NewDataBytes(b []byte) (*Data, error) { - d := newData() - var cb *C.char - if len(b) != 0 { - cb = (*C.char)(unsafe.Pointer(&b[0])) - } - return d, handleError(C.gpgme_data_new_from_mem(&d.dh, cb, C.size_t(len(b)), 1)) -} - -// NewDataReader returns a new callback based data buffer -func NewDataReader(r io.Reader) (*Data, error) { - d := newData() - d.r = r - d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc) - cbc := callbackAdd(d) - d.cbc = cbc - return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc))) -} - -// NewDataWriter returns a new callback based data buffer -func NewDataWriter(w io.Writer) (*Data, error) { - d := newData() - d.w = w - d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc) - cbc := callbackAdd(d) - d.cbc = cbc - return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc))) -} - -// NewDataReadWriter returns a new callback based data buffer -func NewDataReadWriter(rw io.ReadWriter) (*Data, error) { - d := newData() - d.r = rw - d.w = rw - d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc) - d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc) - cbc := callbackAdd(d) - d.cbc = cbc - return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc))) -} - -// NewDataReadWriteSeeker returns a new callback based data buffer -func NewDataReadWriteSeeker(rw io.ReadWriteSeeker) (*Data, error) { - d := newData() - d.r = rw - d.w = rw - d.s = rw - d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc) - d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc) - d.cbs.seek = C.gpgme_data_seek_cb_t(C.gogpgme_seekfunc) - cbc := callbackAdd(d) - d.cbc = cbc - return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc))) -} - -// Close releases any resources associated with the data buffer -func (d *Data) Close() error { - if d.dh == nil { - return nil - } - if d.cbc > 0 { - callbackDelete(d.cbc) - } - _, err := C.gpgme_data_release(d.dh) - d.dh = nil - return err -} - -func (d *Data) Write(p []byte) (int, error) { - n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p))) - if err != nil { - return 0, err - } - if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (d *Data) Read(p []byte) (int, error) { - n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p))) - if err != nil { - return 0, err - } - if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (d *Data) Seek(offset int64, whence int) (int64, error) { - n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence)) - return int64(n), err -} - -// Name returns the associated filename if any -func (d *Data) Name() string { - return C.GoString(C.gpgme_data_get_file_name(d.dh)) -} diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c deleted file mode 100644 index b887574e0c..0000000000 --- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "go_gpgme.h" - -gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle) { - return gpgme_data_new_from_cbs(dh, cbs, (void *)handle); -} - -void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle) { - gpgme_set_passphrase_cb(ctx, cb, (void *)handle); -} - -unsigned int key_revoked(gpgme_key_t k) { - return k->revoked; -} - -unsigned int key_expired(gpgme_key_t k) { - return k->expired; -} - -unsigned int key_disabled(gpgme_key_t k) { - return k->disabled; -} - -unsigned int key_invalid(gpgme_key_t k) { - return k->invalid; -} - -unsigned int key_can_encrypt(gpgme_key_t k) { - return k->can_encrypt; -} - -unsigned int key_can_sign(gpgme_key_t k) { - return k->can_sign; -} - -unsigned int key_can_certify(gpgme_key_t k) { - return k->can_certify; -} - -unsigned int key_secret(gpgme_key_t k) { - return k->secret; -} - -unsigned int key_can_authenticate(gpgme_key_t k) { - return k->can_authenticate; -} - -unsigned int key_is_qualified(gpgme_key_t k) { - return k->is_qualified; -} - -unsigned int signature_wrong_key_usage(gpgme_signature_t s) { - return s->wrong_key_usage; -} - -unsigned int signature_pka_trust(gpgme_signature_t s) { - return s->pka_trust; -} - -unsigned int signature_chain_model(gpgme_signature_t s) { - return s->chain_model; -} - -unsigned int subkey_revoked(gpgme_subkey_t k) { - return k->revoked; -} - -unsigned int subkey_expired(gpgme_subkey_t k) { - return k->expired; -} - -unsigned int subkey_disabled(gpgme_subkey_t k) { - return k->disabled; -} - -unsigned int subkey_invalid(gpgme_subkey_t k) { - return k->invalid; -} - -unsigned int subkey_secret(gpgme_subkey_t k) { - return k->secret; -} - -unsigned int uid_revoked(gpgme_user_id_t u) { - return u->revoked; -} - -unsigned int uid_invalid(gpgme_user_id_t u) { - return u->invalid; -} diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h deleted file mode 100644 index a3678b127a..0000000000 --- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef GO_GPGME_H -#define GO_GPGME_H - -#define _FILE_OFFSET_BITS 64 -#include - -#include - -extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size); -extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size); -extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence); -extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd); -extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle); -extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle); - -extern unsigned int key_revoked(gpgme_key_t k); -extern unsigned int key_expired(gpgme_key_t k); -extern unsigned int key_disabled(gpgme_key_t k); -extern unsigned int key_invalid(gpgme_key_t k); -extern unsigned int key_can_encrypt(gpgme_key_t k); -extern unsigned int key_can_sign(gpgme_key_t k); -extern unsigned int key_can_certify(gpgme_key_t k); -extern unsigned int key_secret(gpgme_key_t k); -extern unsigned int key_can_authenticate(gpgme_key_t k); -extern unsigned int key_is_qualified(gpgme_key_t k); -extern unsigned int signature_wrong_key_usage(gpgme_signature_t s); -extern unsigned int signature_pka_trust(gpgme_signature_t s); -extern unsigned int signature_chain_model(gpgme_signature_t s); -extern unsigned int subkey_revoked(gpgme_subkey_t k); -extern unsigned int subkey_expired(gpgme_subkey_t k); -extern unsigned int subkey_disabled(gpgme_subkey_t k); -extern unsigned int subkey_invalid(gpgme_subkey_t k); -extern unsigned int subkey_secret(gpgme_subkey_t k); -extern unsigned int uid_revoked(gpgme_user_id_t u); -extern unsigned int uid_invalid(gpgme_user_id_t u); - -#endif diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go deleted file mode 100644 index 20aad737c6..0000000000 --- a/vendor/github.com/mtrmac/gpgme/gpgme.go +++ /dev/null @@ -1,748 +0,0 @@ -// Package gpgme provides a Go wrapper for the GPGME library -package gpgme - -// #cgo LDFLAGS: -lgpgme -lassuan -lgpg-error -// #cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64 -// #include -// #include -// #include "go_gpgme.h" -import "C" - -import ( - "fmt" - "io" - "os" - "runtime" - "time" - "unsafe" -) - -var Version string - -func init() { - Version = C.GoString(C.gpgme_check_version(nil)) -} - -// Callback is the function that is called when a passphrase is required -type Callback func(uidHint string, prevWasBad bool, f *os.File) error - -//export gogpgme_passfunc -func gogpgme_passfunc(hook unsafe.Pointer, uid_hint, passphrase_info *C.char, prev_was_bad, fd C.int) C.gpgme_error_t { - c := callbackLookup(uintptr(hook)).(*Context) - go_uid_hint := C.GoString(uid_hint) - f := os.NewFile(uintptr(fd), go_uid_hint) - defer f.Close() - err := c.callback(go_uid_hint, prev_was_bad != 0, f) - if err != nil { - return C.GPG_ERR_CANCELED - } - return 0 -} - -type Protocol int - -const ( - ProtocolOpenPGP Protocol = C.GPGME_PROTOCOL_OpenPGP - ProtocolCMS Protocol = C.GPGME_PROTOCOL_CMS - ProtocolGPGConf Protocol = C.GPGME_PROTOCOL_GPGCONF - ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN - ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13 - ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER - // ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3 - ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT - ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN -) - -type PinEntryMode int - -// const ( // Unavailable in 1.3.2 -// PinEntryDefault PinEntryMode = C.GPGME_PINENTRY_MODE_DEFAULT -// PinEntryAsk PinEntryMode = C.GPGME_PINENTRY_MODE_ASK -// PinEntryCancel PinEntryMode = C.GPGME_PINENTRY_MODE_CANCEL -// PinEntryError PinEntryMode = C.GPGME_PINENTRY_MODE_ERROR -// PinEntryLoopback PinEntryMode = C.GPGME_PINENTRY_MODE_LOOPBACK -// ) - -type EncryptFlag uint - -const ( - EncryptAlwaysTrust EncryptFlag = C.GPGME_ENCRYPT_ALWAYS_TRUST - EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO - EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE - EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN - // EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3 -) - -type HashAlgo int - -// const values for HashAlgo values should be added when necessary. - -type KeyListMode uint - -const ( - KeyListModeLocal KeyListMode = C.GPGME_KEYLIST_MODE_LOCAL - KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN - KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS - KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS - // KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3 - KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL - KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE -) - -type PubkeyAlgo int - -// const values for PubkeyAlgo values should be added when necessary. - -type SigMode int - -const ( - SigModeNormal SigMode = C.GPGME_SIG_MODE_NORMAL - SigModeDetach SigMode = C.GPGME_SIG_MODE_DETACH - SigModeClear SigMode = C.GPGME_SIG_MODE_CLEAR -) - -type SigSum int - -const ( - SigSumValid SigSum = C.GPGME_SIGSUM_VALID - SigSumGreen SigSum = C.GPGME_SIGSUM_GREEN - SigSumRed SigSum = C.GPGME_SIGSUM_RED - SigSumKeyRevoked SigSum = C.GPGME_SIGSUM_KEY_REVOKED - SigSumKeyExpired SigSum = C.GPGME_SIGSUM_KEY_EXPIRED - SigSumSigExpired SigSum = C.GPGME_SIGSUM_SIG_EXPIRED - SigSumKeyMissing SigSum = C.GPGME_SIGSUM_KEY_MISSING - SigSumCRLMissing SigSum = C.GPGME_SIGSUM_CRL_MISSING - SigSumCRLTooOld SigSum = C.GPGME_SIGSUM_CRL_TOO_OLD - SigSumBadPolicy SigSum = C.GPGME_SIGSUM_BAD_POLICY - SigSumSysError SigSum = C.GPGME_SIGSUM_SYS_ERROR -) - -type Validity int - -const ( - ValidityUnknown Validity = C.GPGME_VALIDITY_UNKNOWN - ValidityUndefined Validity = C.GPGME_VALIDITY_UNDEFINED - ValidityNever Validity = C.GPGME_VALIDITY_NEVER - ValidityMarginal Validity = C.GPGME_VALIDITY_MARGINAL - ValidityFull Validity = C.GPGME_VALIDITY_FULL - ValidityUltimate Validity = C.GPGME_VALIDITY_ULTIMATE -) - -type ErrorCode int - -const ( - ErrorNoError ErrorCode = C.GPG_ERR_NO_ERROR - ErrorEOF ErrorCode = C.GPG_ERR_EOF -) - -// Error is a wrapper for GPGME errors -type Error struct { - err C.gpgme_error_t -} - -func (e Error) Code() ErrorCode { - return ErrorCode(C.gpgme_err_code(e.err)) -} - -func (e Error) Error() string { - return C.GoString(C.gpgme_strerror(e.err)) -} - -func handleError(err C.gpgme_error_t) error { - e := Error{err: err} - if e.Code() == ErrorNoError { - return nil - } - return e -} - -func cbool(b bool) C.int { - if b { - return 1 - } - return 0 -} - -func EngineCheckVersion(p Protocol) error { - return handleError(C.gpgme_engine_check_version(C.gpgme_protocol_t(p))) -} - -type EngineInfo struct { - info C.gpgme_engine_info_t -} - -func (e *EngineInfo) Next() *EngineInfo { - if e.info.next == nil { - return nil - } - return &EngineInfo{info: e.info.next} -} - -func (e *EngineInfo) Protocol() Protocol { - return Protocol(e.info.protocol) -} - -func (e *EngineInfo) FileName() string { - return C.GoString(e.info.file_name) -} - -func (e *EngineInfo) Version() string { - return C.GoString(e.info.version) -} - -func (e *EngineInfo) RequiredVersion() string { - return C.GoString(e.info.req_version) -} - -func (e *EngineInfo) HomeDir() string { - return C.GoString(e.info.home_dir) -} - -func GetEngineInfo() (*EngineInfo, error) { - info := &EngineInfo{} - return info, handleError(C.gpgme_get_engine_info(&info.info)) -} - -func SetEngineInfo(proto Protocol, fileName, homeDir string) error { - var cfn, chome *C.char - if fileName != "" { - cfn = C.CString(fileName) - defer C.free(unsafe.Pointer(cfn)) - } - if homeDir != "" { - chome = C.CString(homeDir) - defer C.free(unsafe.Pointer(chome)) - } - return handleError(C.gpgme_set_engine_info(C.gpgme_protocol_t(proto), cfn, chome)) -} - -func FindKeys(pattern string, secretOnly bool) ([]*Key, error) { - var keys []*Key - ctx, err := New() - if err != nil { - return keys, err - } - defer ctx.Release() - if err := ctx.KeyListStart(pattern, secretOnly); err != nil { - return keys, err - } - defer ctx.KeyListEnd() - for ctx.KeyListNext() { - keys = append(keys, ctx.Key) - } - if ctx.KeyError != nil { - return keys, ctx.KeyError - } - return keys, nil -} - -func Decrypt(r io.Reader) (*Data, error) { - ctx, err := New() - if err != nil { - return nil, err - } - defer ctx.Release() - cipher, err := NewDataReader(r) - if err != nil { - return nil, err - } - defer cipher.Close() - plain, err := NewData() - if err != nil { - return nil, err - } - err = ctx.Decrypt(cipher, plain) - plain.Seek(0, SeekSet) - return plain, err -} - -type Context struct { - Key *Key - KeyError error - - callback Callback - cbc uintptr - - ctx C.gpgme_ctx_t -} - -func New() (*Context, error) { - c := &Context{} - err := C.gpgme_new(&c.ctx) - runtime.SetFinalizer(c, (*Context).Release) - return c, handleError(err) -} - -func (c *Context) Release() { - if c.ctx == nil { - return - } - if c.cbc > 0 { - callbackDelete(c.cbc) - } - C.gpgme_release(c.ctx) - c.ctx = nil -} - -func (c *Context) SetArmor(yes bool) { - C.gpgme_set_armor(c.ctx, cbool(yes)) -} - -func (c *Context) Armor() bool { - return C.gpgme_get_armor(c.ctx) != 0 -} - -func (c *Context) SetTextMode(yes bool) { - C.gpgme_set_textmode(c.ctx, cbool(yes)) -} - -func (c *Context) TextMode() bool { - return C.gpgme_get_textmode(c.ctx) != 0 -} - -func (c *Context) SetProtocol(p Protocol) error { - return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p))) -} - -func (c *Context) Protocol() Protocol { - return Protocol(C.gpgme_get_protocol(c.ctx)) -} - -func (c *Context) SetKeyListMode(m KeyListMode) error { - return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m))) -} - -func (c *Context) KeyListMode() KeyListMode { - return KeyListMode(C.gpgme_get_keylist_mode(c.ctx)) -} - -// Unavailable in 1.3.2: -// func (c *Context) SetPinEntryMode(m PinEntryMode) error { -// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m))) -// } - -// Unavailable in 1.3.2: -// func (c *Context) PinEntryMode() PinEntryMode { -// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx)) -// } - -func (c *Context) SetCallback(callback Callback) error { - var err error - c.callback = callback - if c.cbc > 0 { - callbackDelete(c.cbc) - } - if callback != nil { - cbc := callbackAdd(c) - c.cbc = cbc - _, err = C.gogpgme_set_passphrase_cb(c.ctx, C.gpgme_passphrase_cb_t(C.gogpgme_passfunc), C.uintptr_t(cbc)) - } else { - c.cbc = 0 - _, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0) - } - return err -} - -func (c *Context) EngineInfo() *EngineInfo { - return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)} -} - -func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error { - var cfn, chome *C.char - if fileName != "" { - cfn = C.CString(fileName) - defer C.free(unsafe.Pointer(cfn)) - } - if homeDir != "" { - chome = C.CString(homeDir) - defer C.free(unsafe.Pointer(chome)) - } - return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome)) -} - -func (c *Context) KeyListStart(pattern string, secretOnly bool) error { - cpattern := C.CString(pattern) - defer C.free(unsafe.Pointer(cpattern)) - err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)) - return handleError(err) -} - -func (c *Context) KeyListNext() bool { - c.Key = newKey() - err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k)) - if err != nil { - if e, ok := err.(Error); ok && e.Code() == ErrorEOF { - c.KeyError = nil - } else { - c.KeyError = err - } - return false - } - c.KeyError = nil - return true -} - -func (c *Context) KeyListEnd() error { - return handleError(C.gpgme_op_keylist_end(c.ctx)) -} - -func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) { - key := newKey() - cfpr := C.CString(fingerprint) - defer C.free(unsafe.Pointer(cfpr)) - err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret))) - if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF { - return nil, fmt.Errorf("key %q not found", fingerprint) - } - if err != nil { - return nil, err - } - return key, nil -} - -func (c *Context) Decrypt(ciphertext, plaintext *Data) error { - return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh)) -} - -func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error { - return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh)) -} - -type Signature struct { - Summary SigSum - Fingerprint string - Status error - Timestamp time.Time - ExpTimestamp time.Time - WrongKeyUsage bool - PKATrust uint - ChainModel bool - Validity Validity - ValidityReason error - PubkeyAlgo PubkeyAlgo - HashAlgo HashAlgo -} - -func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, error) { - var signedTextPtr, plainPtr C.gpgme_data_t = nil, nil - if signedText != nil { - signedTextPtr = signedText.dh - } - if plain != nil { - plainPtr = plain.dh - } - err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr)) - if err != nil { - return "", nil, err - } - res := C.gpgme_op_verify_result(c.ctx) - sigs := []Signature{} - for s := res.signatures; s != nil; s = s.next { - sig := Signature{ - Summary: SigSum(s.summary), - Fingerprint: C.GoString(s.fpr), - Status: handleError(s.status), - // s.notations not implemented - Timestamp: time.Unix(int64(s.timestamp), 0), - ExpTimestamp: time.Unix(int64(s.exp_timestamp), 0), - WrongKeyUsage: C.signature_wrong_key_usage(s) != 0, - PKATrust: uint(C.signature_pka_trust(s)), - ChainModel: C.signature_chain_model(s) != 0, - Validity: Validity(s.validity), - ValidityReason: handleError(s.validity_reason), - PubkeyAlgo: PubkeyAlgo(s.pubkey_algo), - HashAlgo: HashAlgo(s.hash_algo), - } - sigs = append(sigs, sig) - } - return C.GoString(res.file_name), sigs, nil -} - -func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error { - size := unsafe.Sizeof(new(C.gpgme_key_t)) - recp := C.calloc(C.size_t(len(recipients)+1), C.size_t(size)) - defer C.free(recp) - for i := range recipients { - ptr := (*C.gpgme_key_t)(unsafe.Pointer(uintptr(recp) + size*uintptr(i))) - *ptr = recipients[i].k - } - err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh) - return handleError(err) -} - -func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error { - C.gpgme_signers_clear(c.ctx) - for _, k := range signers { - if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil { - C.gpgme_signers_clear(c.ctx) - return err - } - } - return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode))) -} - -// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned". -type ImportStatusFlags uint - -const ( - ImportNew ImportStatusFlags = C.GPGME_IMPORT_NEW - ImportUID ImportStatusFlags = C.GPGME_IMPORT_UID - ImportSIG ImportStatusFlags = C.GPGME_IMPORT_SIG - ImportSubKey ImportStatusFlags = C.GPGME_IMPORT_SUBKEY - ImportSecret ImportStatusFlags = C.GPGME_IMPORT_SECRET -) - -type ImportStatus struct { - Fingerprint string - Result error - Status ImportStatusFlags -} - -type ImportResult struct { - Considered int - NoUserID int - Imported int - ImportedRSA int - Unchanged int - NewUserIDs int - NewSubKeys int - NewSignatures int - NewRevocations int - SecretRead int - SecretImported int - SecretUnchanged int - NotImported int - Imports []ImportStatus -} - -func (c *Context) Import(keyData *Data) (*ImportResult, error) { - err := handleError(C.gpgme_op_import(c.ctx, keyData.dh)) - if err != nil { - return nil, err - } - res := C.gpgme_op_import_result(c.ctx) - imports := []ImportStatus{} - for s := res.imports; s != nil; s = s.next { - imports = append(imports, ImportStatus{ - Fingerprint: C.GoString(s.fpr), - Result: handleError(s.result), - Status: ImportStatusFlags(s.status), - }) - } - return &ImportResult{ - Considered: int(res.considered), - NoUserID: int(res.no_user_id), - Imported: int(res.imported), - ImportedRSA: int(res.imported_rsa), - Unchanged: int(res.unchanged), - NewUserIDs: int(res.new_user_ids), - NewSubKeys: int(res.new_sub_keys), - NewSignatures: int(res.new_signatures), - NewRevocations: int(res.new_revocations), - SecretRead: int(res.secret_read), - SecretImported: int(res.secret_imported), - SecretUnchanged: int(res.secret_unchanged), - NotImported: int(res.not_imported), - Imports: imports, - }, nil -} - -type Key struct { - k C.gpgme_key_t -} - -func newKey() *Key { - k := &Key{} - runtime.SetFinalizer(k, (*Key).Release) - return k -} - -func (k *Key) Release() { - C.gpgme_key_release(k.k) - k.k = nil -} - -func (k *Key) Revoked() bool { - return C.key_revoked(k.k) != 0 -} - -func (k *Key) Expired() bool { - return C.key_expired(k.k) != 0 -} - -func (k *Key) Disabled() bool { - return C.key_disabled(k.k) != 0 -} - -func (k *Key) Invalid() bool { - return C.key_invalid(k.k) != 0 -} - -func (k *Key) CanEncrypt() bool { - return C.key_can_encrypt(k.k) != 0 -} - -func (k *Key) CanSign() bool { - return C.key_can_sign(k.k) != 0 -} - -func (k *Key) CanCertify() bool { - return C.key_can_certify(k.k) != 0 -} - -func (k *Key) Secret() bool { - return C.key_secret(k.k) != 0 -} - -func (k *Key) CanAuthenticate() bool { - return C.key_can_authenticate(k.k) != 0 -} - -func (k *Key) IsQualified() bool { - return C.key_is_qualified(k.k) != 0 -} - -func (k *Key) Protocol() Protocol { - return Protocol(k.k.protocol) -} - -func (k *Key) IssuerSerial() string { - return C.GoString(k.k.issuer_serial) -} - -func (k *Key) IssuerName() string { - return C.GoString(k.k.issuer_name) -} - -func (k *Key) ChainID() string { - return C.GoString(k.k.chain_id) -} - -func (k *Key) OwnerTrust() Validity { - return Validity(k.k.owner_trust) -} - -func (k *Key) SubKeys() *SubKey { - if k.k.subkeys == nil { - return nil - } - return &SubKey{k: k.k.subkeys, parent: k} -} - -func (k *Key) UserIDs() *UserID { - if k.k.uids == nil { - return nil - } - return &UserID{u: k.k.uids, parent: k} -} - -func (k *Key) KeyListMode() KeyListMode { - return KeyListMode(k.k.keylist_mode) -} - -type SubKey struct { - k C.gpgme_subkey_t - parent *Key // make sure the key is not released when we have a reference to a subkey -} - -func (k *SubKey) Next() *SubKey { - if k.k.next == nil { - return nil - } - return &SubKey{k: k.k.next, parent: k.parent} -} - -func (k *SubKey) Revoked() bool { - return C.subkey_revoked(k.k) != 0 -} - -func (k *SubKey) Expired() bool { - return C.subkey_expired(k.k) != 0 -} - -func (k *SubKey) Disabled() bool { - return C.subkey_disabled(k.k) != 0 -} - -func (k *SubKey) Invalid() bool { - return C.subkey_invalid(k.k) != 0 -} - -func (k *SubKey) Secret() bool { - return C.subkey_secret(k.k) != 0 -} - -func (k *SubKey) KeyID() string { - return C.GoString(k.k.keyid) -} - -func (k *SubKey) Fingerprint() string { - return C.GoString(k.k.fpr) -} - -func (k *SubKey) Created() time.Time { - if k.k.timestamp <= 0 { - return time.Time{} - } - return time.Unix(int64(k.k.timestamp), 0) -} - -func (k *SubKey) Expires() time.Time { - if k.k.expires <= 0 { - return time.Time{} - } - return time.Unix(int64(k.k.expires), 0) -} - -func (k *SubKey) CardNumber() string { - return C.GoString(k.k.card_number) -} - -type UserID struct { - u C.gpgme_user_id_t - parent *Key // make sure the key is not released when we have a reference to a user ID -} - -func (u *UserID) Next() *UserID { - if u.u.next == nil { - return nil - } - return &UserID{u: u.u.next, parent: u.parent} -} - -func (u *UserID) Revoked() bool { - return C.uid_revoked(u.u) != 0 -} - -func (u *UserID) Invalid() bool { - return C.uid_invalid(u.u) != 0 -} - -func (u *UserID) Validity() Validity { - return Validity(u.u.validity) -} - -func (u *UserID) UID() string { - return C.GoString(u.u.uid) -} - -func (u *UserID) Name() string { - return C.GoString(u.u.name) -} - -func (u *UserID) Comment() string { - return C.GoString(u.u.comment) -} - -func (u *UserID) Email() string { - return C.GoString(u.u.email) -} - -// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG. -// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved -// - and cgo can't be used in tests. So, provide this helper for test initialization. -func unsetenvGPGAgentInfo() { - v := C.CString("GPG_AGENT_INFO") - defer C.free(unsafe.Pointer(v)) - C.unsetenv(v) -} diff --git a/vendor/github.com/opencontainers/selinux/LICENSE b/vendor/github.com/opencontainers/selinux/LICENSE deleted file mode 100644 index 8dada3edaf..0000000000 --- a/vendor/github.com/opencontainers/selinux/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go deleted file mode 100644 index 6cfc5fded8..0000000000 --- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build !selinux !linux - -package label - -// InitLabels returns the process label and file labels to be used within -// the container. A list of options can be passed into this function to alter -// the labels. -func InitLabels(options []string) (string, string, error) { - return "", "", nil -} - -func GetROMountLabel() string { - return "" -} - -func GenLabels(options string) (string, string, error) { - return "", "", nil -} - -func FormatMountLabel(src string, mountLabel string) string { - return src -} - -func SetProcessLabel(processLabel string) error { - return nil -} - -func GetFileLabel(path string) (string, error) { - return "", nil -} - -func SetFileLabel(path string, fileLabel string) error { - return nil -} - -func SetFileCreateLabel(fileLabel string) error { - return nil -} - -func Relabel(path string, fileLabel string, shared bool) error { - return nil -} - -func GetPidLabel(pid int) (string, error) { - return "", nil -} - -func Init() { -} - -func ReserveLabel(label string) error { - return nil -} - -func ReleaseLabel(label string) error { - return nil -} - -// DupSecOpt takes a process label and returns security options that -// can be used to set duplicate labels on future container processes -func DupSecOpt(src string) []string { - return nil -} - -// DisableSecOpt returns a security opt that can disable labeling -// support for future container processes -func DisableSecOpt() []string { - return nil -} - -// Validate checks that the label does not include unexpected options -func Validate(label string) error { - return nil -} - -// RelabelNeeded checks whether the user requested a relabel -func RelabelNeeded(label string) bool { - return false -} - -// IsShared checks that the label includes a "shared" mark -func IsShared(label string) bool { - return false -} diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go deleted file mode 100644 index 569dcf0841..0000000000 --- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go +++ /dev/null @@ -1,204 +0,0 @@ -// +build selinux,linux - -package label - -import ( - "fmt" - "strings" - - "github.com/opencontainers/selinux/go-selinux" -) - -// Valid Label Options -var validOptions = map[string]bool{ - "disable": true, - "type": true, - "user": true, - "role": true, - "level": true, -} - -var ErrIncompatibleLabel = fmt.Errorf("Bad SELinux option z and Z can not be used together") - -// InitLabels returns the process label and file labels to be used within -// the container. A list of options can be passed into this function to alter -// the labels. The labels returned will include a random MCS String, that is -// guaranteed to be unique. -func InitLabels(options []string) (string, string, error) { - if !selinux.GetEnabled() { - return "", "", nil - } - processLabel, mountLabel := selinux.ContainerLabels() - if processLabel != "" { - pcon := selinux.NewContext(processLabel) - mcon := selinux.NewContext(mountLabel) - for _, opt := range options { - if opt == "disable" { - return "", "", nil - } - if i := strings.Index(opt, ":"); i == -1 { - return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type' followed by ':' and a value", opt) - } - con := strings.SplitN(opt, ":", 2) - if !validOptions[con[0]] { - return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type'", con[0]) - - } - pcon[con[0]] = con[1] - if con[0] == "level" || con[0] == "user" { - mcon[con[0]] = con[1] - } - } - processLabel = pcon.Get() - mountLabel = mcon.Get() - } - return processLabel, mountLabel, nil -} - -func ROMountLabel() string { - return selinux.ROFileLabel() -} - -// DEPRECATED: The GenLabels function is only to be used during the transition to the official API. -func GenLabels(options string) (string, string, error) { - return InitLabels(strings.Fields(options)) -} - -// FormatMountLabel returns a string to be used by the mount command. -// The format of this string will be used to alter the labeling of the mountpoint. -// The string returned is suitable to be used as the options field of the mount command. -// If you need to have additional mount point options, you can pass them in as -// the first parameter. Second parameter is the label that you wish to apply -// to all content in the mount point. -func FormatMountLabel(src, mountLabel string) string { - if mountLabel != "" { - switch src { - case "": - src = fmt.Sprintf("context=%q", mountLabel) - default: - src = fmt.Sprintf("%s,context=%q", src, mountLabel) - } - } - return src -} - -// SetProcessLabel takes a process label and tells the kernel to assign the -// label to the next program executed by the current process. -func SetProcessLabel(processLabel string) error { - if processLabel == "" { - return nil - } - return selinux.SetExecLabel(processLabel) -} - -// ProcessLabel returns the process label that the kernel will assign -// to the next program executed by the current process. If "" is returned -// this indicates that the default labeling will happen for the process. -func ProcessLabel() (string, error) { - return selinux.ExecLabel() -} - -// GetFileLabel returns the label for specified path -func FileLabel(path string) (string, error) { - return selinux.FileLabel(path) -} - -// SetFileLabel modifies the "path" label to the specified file label -func SetFileLabel(path string, fileLabel string) error { - if selinux.GetEnabled() && fileLabel != "" { - return selinux.SetFileLabel(path, fileLabel) - } - return nil -} - -// SetFileCreateLabel tells the kernel the label for all files to be created -func SetFileCreateLabel(fileLabel string) error { - if selinux.GetEnabled() { - return selinux.SetFSCreateLabel(fileLabel) - } - return nil -} - -// Relabel changes the label of path to the filelabel string. -// It changes the MCS label to s0 if shared is true. -// This will allow all containers to share the content. -func Relabel(path string, fileLabel string, shared bool) error { - if !selinux.GetEnabled() { - return nil - } - - if fileLabel == "" { - return nil - } - - exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true} - if exclude_paths[path] { - return fmt.Errorf("SELinux relabeling of %s is not allowed", path) - } - - if shared { - c := selinux.NewContext(fileLabel) - c["level"] = "s0" - fileLabel = c.Get() - } - if err := selinux.Chcon(path, fileLabel, true); err != nil { - return err - } - return nil -} - -// PidLabel will return the label of the process running with the specified pid -func PidLabel(pid int) (string, error) { - return selinux.PidLabel(pid) -} - -// Init initialises the labeling system -func Init() { - selinux.GetEnabled() -} - -// ReserveLabel will record the fact that the MCS label has already been used. -// This will prevent InitLabels from using the MCS label in a newly created -// container -func ReserveLabel(label string) error { - selinux.ReserveLabel(label) - return nil -} - -// ReleaseLabel will remove the reservation of the MCS label. -// This will allow InitLabels to use the MCS label in a newly created -// containers -func ReleaseLabel(label string) error { - selinux.ReleaseLabel(label) - return nil -} - -// DupSecOpt takes a process label and returns security options that -// can be used to set duplicate labels on future container processes -func DupSecOpt(src string) []string { - return selinux.DupSecOpt(src) -} - -// DisableSecOpt returns a security opt that can disable labeling -// support for future container processes -func DisableSecOpt() []string { - return selinux.DisableSecOpt() -} - -// Validate checks that the label does not include unexpected options -func Validate(label string) error { - if strings.Contains(label, "z") && strings.Contains(label, "Z") { - return ErrIncompatibleLabel - } - return nil -} - -// RelabelNeeded checks whether the user requested a relabel -func RelabelNeeded(label string) bool { - return strings.Contains(label, "z") || strings.Contains(label, "Z") -} - -// IsShared checks that the label includes a "shared" mark -func IsShared(label string) bool { - return strings.Contains(label, "z") -} diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go deleted file mode 100644 index 4cf2c45de7..0000000000 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go +++ /dev/null @@ -1,593 +0,0 @@ -// +build linux - -package selinux - -import ( - "bufio" - "crypto/rand" - "encoding/binary" - "fmt" - "io" - "os" - "path/filepath" - "regexp" - "strconv" - "strings" - "sync" - "syscall" -) - -const ( - // Enforcing constant indicate SELinux is in enforcing mode - Enforcing = 1 - // Permissive constant to indicate SELinux is in permissive mode - Permissive = 0 - // Disabled constant to indicate SELinux is disabled - Disabled = -1 - selinuxDir = "/etc/selinux/" - selinuxConfig = selinuxDir + "config" - selinuxTypeTag = "SELINUXTYPE" - selinuxTag = "SELINUX" - selinuxPath = "/sys/fs/selinux" - xattrNameSelinux = "security.selinux" - stRdOnly = 0x01 -) - -type selinuxState struct { - enabledSet bool - enabled bool - selinuxfsSet bool - selinuxfs string - mcsList map[string]bool - sync.Mutex -} - -var ( - assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) - state = selinuxState{ - mcsList: make(map[string]bool), - } -) - -// Context is a representation of the SELinux label broken into 4 parts -type Context map[string]string - -func (s *selinuxState) setEnable(enabled bool) bool { - s.Lock() - defer s.Unlock() - s.enabledSet = true - s.enabled = enabled - return s.enabled -} - -func (s *selinuxState) getEnabled() bool { - s.Lock() - enabled := s.enabled - enabledSet := s.enabledSet - s.Unlock() - if enabledSet { - return enabled - } - - enabled = false - if fs := getSelinuxMountPoint(); fs != "" { - if con, _ := CurrentLabel(); con != "kernel" { - enabled = true - } - } - return s.setEnable(enabled) -} - -// SetDisabled disables selinux support for the package -func SetDisabled() { - state.setEnable(false) -} - -func (s *selinuxState) setSELinuxfs(selinuxfs string) string { - s.Lock() - defer s.Unlock() - s.selinuxfsSet = true - s.selinuxfs = selinuxfs - return s.selinuxfs -} - -func (s *selinuxState) getSELinuxfs() string { - s.Lock() - selinuxfs := s.selinuxfs - selinuxfsSet := s.selinuxfsSet - s.Unlock() - if selinuxfsSet { - return selinuxfs - } - - selinuxfs = "" - f, err := os.Open("/proc/self/mountinfo") - if err != nil { - return selinuxfs - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - txt := scanner.Text() - // Safe as mountinfo encodes mountpoints with spaces as \040. - sepIdx := strings.Index(txt, " - ") - if sepIdx == -1 { - continue - } - if !strings.Contains(txt[sepIdx:], "selinuxfs") { - continue - } - fields := strings.Split(txt, " ") - if len(fields) < 5 { - continue - } - selinuxfs = fields[4] - break - } - - if selinuxfs != "" { - var buf syscall.Statfs_t - syscall.Statfs(selinuxfs, &buf) - if (buf.Flags & stRdOnly) == 1 { - selinuxfs = "" - } - } - return s.setSELinuxfs(selinuxfs) -} - -// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs -// filesystem or an empty string if no mountpoint is found. Selinuxfs is -// a proc-like pseudo-filesystem that exposes the selinux policy API to -// processes. The existence of an selinuxfs mount is used to determine -// whether selinux is currently enabled or not. -func getSelinuxMountPoint() string { - return state.getSELinuxfs() -} - -// GetEnabled returns whether selinux is currently enabled. -func GetEnabled() bool { - return state.getEnabled() -} - -func readConfig(target string) (value string) { - var ( - val, key string - bufin *bufio.Reader - ) - - in, err := os.Open(selinuxConfig) - if err != nil { - return "" - } - defer in.Close() - - bufin = bufio.NewReader(in) - - for done := false; !done; { - var line string - if line, err = bufin.ReadString('\n'); err != nil { - if err != io.EOF { - return "" - } - done = true - } - line = strings.TrimSpace(line) - if len(line) == 0 { - // Skip blank lines - continue - } - if line[0] == ';' || line[0] == '#' { - // Skip comments - continue - } - if groups := assignRegex.FindStringSubmatch(line); groups != nil { - key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) - if key == target { - return strings.Trim(val, "\"") - } - } - } - return "" -} - -func getSELinuxPolicyRoot() string { - return selinuxDir + readConfig(selinuxTypeTag) -} - -func readCon(name string) (string, error) { - var val string - - in, err := os.Open(name) - if err != nil { - return "", err - } - defer in.Close() - - _, err = fmt.Fscanf(in, "%s", &val) - return val, err -} - -// SetFileLabel sets the SELinux label for this path or returns an error. -func SetFileLabel(path string, label string) error { - return lsetxattr(path, xattrNameSelinux, []byte(label), 0) -} - -// Filecon returns the SELinux label for this path or returns an error. -func FileLabel(path string) (string, error) { - label, err := lgetxattr(path, xattrNameSelinux) - if err != nil { - return "", err - } - // Trim the NUL byte at the end of the byte buffer, if present. - if len(label) > 0 && label[len(label)-1] == '\x00' { - label = label[:len(label)-1] - } - return string(label), nil -} - -/* -SetFSCreateLabel tells kernel the label to create all file system objects -created by this task. Setting label="" to return to default. -*/ -func SetFSCreateLabel(label string) error { - return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), label) -} - -/* -FSCreateLabel returns the default label the kernel which the kernel is using -for file system objects created by this task. "" indicates default. -*/ -func FSCreateLabel() (string, error) { - return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid())) -} - -// CurrentLabel returns the SELinux label of the current process thread, or an error. -func CurrentLabel() (string, error) { - return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid())) -} - -// PidLabel returns the SELinux label of the given pid, or an error. -func PidLabel(pid int) (string, error) { - return readCon(fmt.Sprintf("/proc/%d/attr/current", pid)) -} - -/* -ExecLabel returns the SELinux label that the kernel will use for any programs -that are executed by the current process thread, or an error. -*/ -func ExecLabel() (string, error) { - return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid())) -} - -func writeCon(name string, val string) error { - out, err := os.OpenFile(name, os.O_WRONLY, 0) - if err != nil { - return err - } - defer out.Close() - - if val != "" { - _, err = out.Write([]byte(val)) - } else { - _, err = out.Write(nil) - } - return err -} - -/* -SetExecLabel sets the SELinux label that the kernel will use for any programs -that are executed by the current process thread, or an error. -*/ -func SetExecLabel(label string) error { - return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), label) -} - -// Get returns the Context as a string -func (c Context) Get() string { - return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"]) -} - -// NewContext creates a new Context struct from the specified label -func NewContext(label string) Context { - c := make(Context) - - if len(label) != 0 { - con := strings.SplitN(label, ":", 4) - c["user"] = con[0] - c["role"] = con[1] - c["type"] = con[2] - c["level"] = con[3] - } - return c -} - -// ReserveLabel reserves the MLS/MCS level component of the specified label -func ReserveLabel(label string) { - if len(label) != 0 { - con := strings.SplitN(label, ":", 4) - mcsAdd(con[3]) - } -} - -func selinuxEnforcePath() string { - return fmt.Sprintf("%s/enforce", selinuxPath) -} - -// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled -func EnforceMode() int { - var enforce int - - enforceS, err := readCon(selinuxEnforcePath()) - if err != nil { - return -1 - } - - enforce, err = strconv.Atoi(string(enforceS)) - if err != nil { - return -1 - } - return enforce -} - -/* -SetEnforce sets the current SELinux mode Enforcing, Permissive. -Disabled is not valid, since this needs to be set at boot time. -*/ -func SetEnforceMode(mode int) error { - return writeCon(selinuxEnforcePath(), fmt.Sprintf("%d", mode)) -} - -/* -DefaultEnforceMode returns the systems default SELinux mode Enforcing, -Permissive or Disabled. Note this is is just the default at boot time. -EnforceMode tells you the systems current mode. -*/ -func DefaultEnforceMode() int { - switch readConfig(selinuxTag) { - case "enforcing": - return Enforcing - case "permissive": - return Permissive - } - return Disabled -} - -func mcsAdd(mcs string) error { - state.Lock() - defer state.Unlock() - if state.mcsList[mcs] { - return fmt.Errorf("MCS Label already exists") - } - state.mcsList[mcs] = true - return nil -} - -func mcsDelete(mcs string) { - state.Lock() - defer state.Unlock() - state.mcsList[mcs] = false -} - -func intToMcs(id int, catRange uint32) string { - var ( - SETSIZE = int(catRange) - TIER = SETSIZE - ORD = id - ) - - if id < 1 || id > 523776 { - return "" - } - - for ORD > TIER { - ORD = ORD - TIER - TIER-- - } - TIER = SETSIZE - TIER - ORD = ORD + TIER - return fmt.Sprintf("s0:c%d,c%d", TIER, ORD) -} - -func uniqMcs(catRange uint32) string { - var ( - n uint32 - c1, c2 uint32 - mcs string - ) - - for { - binary.Read(rand.Reader, binary.LittleEndian, &n) - c1 = n % catRange - binary.Read(rand.Reader, binary.LittleEndian, &n) - c2 = n % catRange - if c1 == c2 { - continue - } else { - if c1 > c2 { - c1, c2 = c2, c1 - } - } - mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) - if err := mcsAdd(mcs); err != nil { - continue - } - break - } - return mcs -} - -/* -ReleaseLabel will unreserve the MLS/MCS Level field of the specified label. -Allowing it to be used by another process. -*/ -func ReleaseLabel(label string) { - if len(label) != 0 { - con := strings.SplitN(label, ":", 4) - mcsDelete(con[3]) - } -} - -var roFileLabel string - -// ROFileLabel returns the specified SELinux readonly file label -func ROFileLabel() (fileLabel string) { - return roFileLabel -} - -/* -ContainerLabels returns an allocated processLabel and fileLabel to be used for -container labeling by the calling process. -*/ -func ContainerLabels() (processLabel string, fileLabel string) { - var ( - val, key string - bufin *bufio.Reader - ) - - if !GetEnabled() { - return "", "" - } - lxcPath := fmt.Sprintf("%s/contexts/lxc_contexts", getSELinuxPolicyRoot()) - in, err := os.Open(lxcPath) - if err != nil { - return "", "" - } - defer in.Close() - - bufin = bufio.NewReader(in) - - for done := false; !done; { - var line string - if line, err = bufin.ReadString('\n'); err != nil { - if err == io.EOF { - done = true - } else { - goto exit - } - } - line = strings.TrimSpace(line) - if len(line) == 0 { - // Skip blank lines - continue - } - if line[0] == ';' || line[0] == '#' { - // Skip comments - continue - } - if groups := assignRegex.FindStringSubmatch(line); groups != nil { - key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) - if key == "process" { - processLabel = strings.Trim(val, "\"") - } - if key == "file" { - fileLabel = strings.Trim(val, "\"") - } - if key == "ro_file" { - roFileLabel = strings.Trim(val, "\"") - } - } - } - - if processLabel == "" || fileLabel == "" { - return "", "" - } - - if roFileLabel == "" { - roFileLabel = fileLabel - } -exit: - mcs := uniqMcs(1024) - scon := NewContext(processLabel) - scon["level"] = mcs - processLabel = scon.Get() - scon = NewContext(fileLabel) - scon["level"] = mcs - fileLabel = scon.Get() - return processLabel, fileLabel -} - -// SecurityCheckContext validates that the SELinux label is understood by the kernel -func SecurityCheckContext(val string) error { - return writeCon(fmt.Sprintf("%s.context", selinuxPath), val) -} - -/* -CopyLevel returns a label with the MLS/MCS level from src label replaces on -the dest label. -*/ -func CopyLevel(src, dest string) (string, error) { - if src == "" { - return "", nil - } - if err := SecurityCheckContext(src); err != nil { - return "", err - } - if err := SecurityCheckContext(dest); err != nil { - return "", err - } - scon := NewContext(src) - tcon := NewContext(dest) - mcsDelete(tcon["level"]) - mcsAdd(scon["level"]) - tcon["level"] = scon["level"] - return tcon.Get(), nil -} - -// Prevent users from relabing system files -func badPrefix(fpath string) error { - var badprefixes = []string{"/usr"} - - for _, prefix := range badprefixes { - if fpath == prefix || strings.HasPrefix(fpath, fmt.Sprintf("%s/", prefix)) { - return fmt.Errorf("relabeling content in %s is not allowed", prefix) - } - } - return nil -} - -// Chcon changes the fpath file object to the SELinux label label. -// If the fpath is a directory and recurse is true Chcon will walk the -// directory tree setting the label -func Chcon(fpath string, label string, recurse bool) error { - if label == "" { - return nil - } - if err := badPrefix(fpath); err != nil { - return err - } - callback := func(p string, info os.FileInfo, err error) error { - return SetFileLabel(p, label) - } - - if recurse { - return filepath.Walk(fpath, callback) - } - - return SetFileLabel(fpath, label) -} - -// DupSecOpt takes an SELinux process label and returns security options that -// can will set the SELinux Type and Level for future container processes -func DupSecOpt(src string) []string { - if src == "" { - return nil - } - con := NewContext(src) - if con["user"] == "" || - con["role"] == "" || - con["type"] == "" || - con["level"] == "" { - return nil - } - return []string{"user:" + con["user"], - "role:" + con["role"], - "type:" + con["type"], - "level:" + con["level"]} -} - -// DisableSecOpt returns a security opt that can be used to disabling SELinux -// labeling support for future container processes -func DisableSecOpt() []string { - return []string{"disable"} -} diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go deleted file mode 100644 index 7f2ef85049..0000000000 --- a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go +++ /dev/null @@ -1,78 +0,0 @@ -// +build linux - -package selinux - -import ( - "syscall" - "unsafe" -) - -var _zero uintptr - -// Returns a []byte slice if the xattr is set and nil otherwise -// Requires path and its attribute as arguments -func lgetxattr(path string, attr string) ([]byte, error) { - var sz int - pathBytes, err := syscall.BytePtrFromString(path) - if err != nil { - return nil, err - } - attrBytes, err := syscall.BytePtrFromString(attr) - if err != nil { - return nil, err - } - - // Start with a 128 length byte array - sz = 128 - dest := make([]byte, sz) - destBytes := unsafe.Pointer(&dest[0]) - _sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) - - switch { - case errno == syscall.ENODATA: - return nil, errno - case errno == syscall.ENOTSUP: - return nil, errno - case errno == syscall.ERANGE: - // 128 byte array might just not be good enough, - // A dummy buffer is used ``uintptr(0)`` to get real size - // of the xattrs on disk - _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0) - sz = int(_sz) - if sz < 0 { - return nil, errno - } - dest = make([]byte, sz) - destBytes := unsafe.Pointer(&dest[0]) - _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) - if errno != 0 { - return nil, errno - } - case errno != 0: - return nil, errno - } - sz = int(_sz) - return dest[:sz], nil -} - -func lsetxattr(path string, attr string, data []byte, flags int) error { - pathBytes, err := syscall.BytePtrFromString(path) - if err != nil { - return err - } - attrBytes, err := syscall.BytePtrFromString(attr) - if err != nil { - return err - } - var dataBytes unsafe.Pointer - if len(data) > 0 { - dataBytes = unsafe.Pointer(&data[0]) - } else { - dataBytes = unsafe.Pointer(&_zero) - } - _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) - if errno != 0 { - return errno - } - return nil -} diff --git a/vendor/github.com/ostreedev/ostree-go/LICENSE b/vendor/github.com/ostreedev/ostree-go/LICENSE deleted file mode 100644 index aa93b4dab9..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Portions of this code are derived from: - -https://github.com/dradtke/gotk3 - -Copyright (c) 2013 Conformal Systems LLC. - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gboolean.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gboolean.go deleted file mode 100644 index a4ad0f0005..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gboolean.go +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -import ( - "unsafe" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" - -/* - * GBoolean - */ - -// GBoolean is a Go representation of glib's gboolean -type GBoolean C.gboolean - -func NewGBoolean() GBoolean { - return GBoolean(0) -} - -func GBool(b bool) GBoolean { - if b { - return GBoolean(1) - } - return GBoolean(0) -} - -func (b GBoolean) Ptr() unsafe.Pointer { - return unsafe.Pointer(&b) -} - -func GoBool(b GBoolean) bool { - if b != 0 { - return true - } - return false -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gcancellable.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gcancellable.go deleted file mode 100644 index 537db4720d..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gcancellable.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" - -import ( - "unsafe" -) - -// GIO types - -type GCancellable struct { - *GObject -} - -func (self *GCancellable) native() *C.GCancellable { - return (*C.GCancellable)(unsafe.Pointer(self)) -} - -func (self *GCancellable) Ptr() unsafe.Pointer { - return unsafe.Pointer(self) -} - -// At the moment, no cancellable API, just pass nil diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gerror.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gerror.go deleted file mode 100644 index 714b15d0bf..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gerror.go +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" -import ( - "errors" - "unsafe" -) - -/* - * GError - */ - -// GError is a representation of GLib's GError -type GError struct { - ptr unsafe.Pointer -} - -func NewGError() GError { - return GError{nil} -} - -func (e GError) Ptr() unsafe.Pointer { - if e.ptr == nil { - return nil - } - return e.ptr -} - -func (e GError) Nil() { - e.ptr = nil -} - -func (e *GError) native() *C.GError { - if e == nil || e.ptr == nil { - return nil - } - return (*C.GError)(e.ptr) -} - -func ToGError(ptr unsafe.Pointer) GError { - return GError{ptr} -} - -func ConvertGError(e GError) error { - defer C.g_error_free(e.native()) - return errors.New(C.GoString((*C.char)(C._g_error_get_message(e.native())))) -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfile.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfile.go deleted file mode 100644 index babe705096..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfile.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" -import ( - "unsafe" -) - -/* - * GFile - */ - -type GFile struct { - ptr unsafe.Pointer -} - -func (f GFile) Ptr() unsafe.Pointer { - return f.ptr -} - -func NewGFile() *GFile { - return &GFile{nil} -} - -func ToGFile(ptr unsafe.Pointer) *GFile { - gf := NewGFile() - gf.ptr = ptr - return gf -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfileinfo.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfileinfo.go deleted file mode 100644 index 9c155834a8..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gfileinfo.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" -import ( - "unsafe" -) - -/* - * GFileInfo - */ - -type GFileInfo struct { - ptr unsafe.Pointer -} - -func (fi GFileInfo) Ptr() unsafe.Pointer { - return fi.ptr -} - -func NewGFileInfo() GFileInfo { - var fi GFileInfo = GFileInfo{nil} - return fi -} - -func ToGFileInfo(p unsafe.Pointer) *GFileInfo { - var fi *GFileInfo = &GFileInfo{} - fi.ptr = p - return fi -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtable.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtable.go deleted file mode 100644 index 20cc321cbb..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtable.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -import ( - "unsafe" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" - -/* - * GHashTable - */ -type GHashTable struct { - ptr unsafe.Pointer -} - -func (ht *GHashTable) Ptr() unsafe.Pointer { - return ht.ptr -} - -func (ht *GHashTable) native() *C.GHashTable { - return (*C.GHashTable)(ht.ptr) -} - -func ToGHashTable(ptr unsafe.Pointer) *GHashTable { - return &GHashTable{ptr} -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtableiter.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtableiter.go deleted file mode 100644 index 1657edf5fc..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/ghashtableiter.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -import ( - "unsafe" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" - -/* - * GHashTableIter - */ -type GHashTableIter struct { - ptr unsafe.Pointer -} - -func (ht *GHashTableIter) Ptr() unsafe.Pointer { - return ht.ptr -} - -func (ht *GHashTableIter) native() *C.GHashTableIter { - return (*C.GHashTableIter)(ht.ptr) -} - -func ToGHashTableIter(ptr unsafe.Pointer) *GHashTableIter { - return &GHashTableIter{ptr} -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go deleted file mode 100644 index f3d3aa5266..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go.h b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go.h deleted file mode 100644 index a55bd242f9..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/glibobject.go.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -static char * -_g_error_get_message (GError *error) -{ - g_assert (error != NULL); - return error->message; -} - -static const char * -_g_variant_lookup_string (GVariant *v, const char *key) -{ - const char *r; - if (g_variant_lookup (v, key, "&s", &r)) - return r; - return NULL; -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gobject.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gobject.go deleted file mode 100644 index dedbe749a4..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gobject.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" -import ( - "unsafe" -) - -/* - * GObject - */ - -// IObject is an interface type implemented by Object and all types which embed -// an Object. It is meant to be used as a type for function arguments which -// require GObjects or any subclasses thereof. -type IObject interface { - toGObject() *C.GObject - ToObject() *GObject -} - -// GObject is a representation of GLib's GObject. -type GObject struct { - ptr unsafe.Pointer -} - -func (v *GObject) Ptr() unsafe.Pointer { - return v.ptr -} - -func (v *GObject) native() *C.GObject { - if v == nil { - return nil - } - return (*C.GObject)(v.ptr) -} - -func (v *GObject) Ref() { - C.g_object_ref(C.gpointer(v.Ptr())) -} - -func (v *GObject) Unref() { - C.g_object_unref(C.gpointer(v.Ptr())) -} - -func (v *GObject) RefSink() { - C.g_object_ref_sink(C.gpointer(v.native())) -} - -func (v *GObject) IsFloating() bool { - c := C.g_object_is_floating(C.gpointer(v.native())) - return GoBool(GBoolean(c)) -} - -func (v *GObject) ForceFloating() { - C.g_object_force_floating(v.native()) -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/goptioncontext.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/goptioncontext.go deleted file mode 100644 index 05fd54a1a4..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/goptioncontext.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -import ( - "unsafe" -) - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" - -/* - * GOptionContext - */ - -type GOptionContext struct { - ptr unsafe.Pointer -} - -func (oc *GOptionContext) Ptr() unsafe.Pointer { - return oc.ptr -} - -func (oc *GOptionContext) native() *C.GOptionContext { - return (*C.GOptionContext)(oc.ptr) -} - -func ToGOptionContext(ptr unsafe.Pointer) GOptionContext { - return GOptionContext{ptr} -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gvariant.go b/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gvariant.go deleted file mode 100644 index 30572ea87f..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/glibobject/gvariant.go +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2013 Conformal Systems - * - * This file originated from: http://opensource.conformal.com/ - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package glibobject - -// #cgo pkg-config: glib-2.0 gobject-2.0 -// #include -// #include -// #include -// #include "glibobject.go.h" -// #include -import "C" -import ( - "fmt" - "unsafe" -) - -/* - * GVariant - */ - -type GVariant struct { - ptr unsafe.Pointer -} - -//func GVariantNew(p unsafe.Pointer) *GVariant { -//o := &GVariant{p} -//runtime.SetFinalizer(o, (*GVariant).Unref) -//return o; -//} - -//func GVariantNewSink(p unsafe.Pointer) *GVariant { -//o := &GVariant{p} -//runtime.SetFinalizer(o, (*GVariant).Unref) -//o.RefSink() -//return o; -//} - -func (v *GVariant) native() *C.GVariant { - return (*C.GVariant)(v.ptr) -} - -func (v *GVariant) Ptr() unsafe.Pointer { - return v.ptr -} - -func (v *GVariant) Ref() { - C.g_variant_ref(v.native()) -} - -func (v *GVariant) Unref() { - C.g_variant_unref(v.native()) -} - -func (v *GVariant) RefSink() { - C.g_variant_ref_sink(v.native()) -} - -func (v *GVariant) TypeString() string { - cs := (*C.char)(C.g_variant_get_type_string(v.native())) - return C.GoString(cs) -} - -func (v *GVariant) GetChildValue(i int) *GVariant { - cchild := C.g_variant_get_child_value(v.native(), C.gsize(i)) - return (*GVariant)(unsafe.Pointer(cchild)) -} - -func (v *GVariant) LookupString(key string) (string, error) { - ckey := C.CString(key) - defer C.free(unsafe.Pointer(ckey)) - // TODO: Find a way to have constant C strings in golang - cstr := C._g_variant_lookup_string(v.native(), ckey) - if cstr == nil { - return "", fmt.Errorf("No such key: %s", key) - } - return C.GoString(cstr), nil -} - -func ToGVariant(ptr unsafe.Pointer) *GVariant { - return &GVariant{ptr} -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go deleted file mode 100644 index d3a8ae5fde..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go +++ /dev/null @@ -1,93 +0,0 @@ -// Package otbuiltin contains all of the basic commands for creating and -// interacting with an ostree repository -package otbuiltin - -import ( - "errors" - "fmt" - "runtime" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -type Repo struct { - //*glib.GObject - ptr unsafe.Pointer -} - -// Converts an ostree repo struct to its C equivalent -func (r *Repo) native() *C.OstreeRepo { - //return (*C.OstreeRepo)(r.Ptr()) - return (*C.OstreeRepo)(r.ptr) -} - -// Takes a C ostree repo and converts it to a Go struct -func repoFromNative(p *C.OstreeRepo) *Repo { - if p == nil { - return nil - } - //o := (*glib.GObject)(unsafe.Pointer(p)) - //r := &Repo{o} - r := &Repo{unsafe.Pointer(p)} - return r -} - -// Checks if the repo has been initialized -func (r *Repo) isInitialized() bool { - if r.ptr != nil { - return true - } - return false -} - -// Attempts to open the repo at the given path -func OpenRepo(path string) (*Repo, error) { - var cerr *C.GError = nil - cpath := C.CString(path) - pathc := C.g_file_new_for_path(cpath) - defer C.g_object_unref(C.gpointer(pathc)) - crepo := C.ostree_repo_new(pathc) - repo := repoFromNative(crepo) - r := glib.GoBool(glib.GBoolean(C.ostree_repo_open(crepo, nil, &cerr))) - if !r { - return nil, generateError(cerr) - } - return repo, nil -} - -// Enable support for tombstone commits, which allow the repo to distinguish between -// commits that were intentionally deleted and commits that were removed accidentally -func enableTombstoneCommits(repo *Repo) error { - var tombstoneCommits bool - var config *C.GKeyFile = C.ostree_repo_get_config(repo.native()) - var cerr *C.GError - - tombstoneCommits = glib.GoBool(glib.GBoolean(C.g_key_file_get_boolean(config, (*C.gchar)(C.CString("core")), (*C.gchar)(C.CString("tombstone-commits")), nil))) - - //tombstoneCommits is false only if it really is false or if it is set to FALSE in the config file - if !tombstoneCommits { - C.g_key_file_set_boolean(config, (*C.gchar)(C.CString("core")), (*C.gchar)(C.CString("tombstone-commits")), C.TRUE) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_config(repo.native(), config, &cerr))) { - return generateError(cerr) - } - } - return nil -} - -func generateError(err *C.GError) error { - goErr := glib.ConvertGError(glib.ToGError(unsafe.Pointer(err))) - _, file, line, ok := runtime.Caller(1) - if ok { - return errors.New(fmt.Sprintf("%s:%d - %s", file, line, goErr)) - } else { - return goErr - } -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go.h b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go.h deleted file mode 100644 index 734de98219..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/builtin.go.h +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef BUILTIN_GO_H -#define BUILTIN_GO_H - -#include -#include -#include -#include - -static guint32 owner_uid; -static guint32 owner_gid; - -static void -_ostree_repo_append_modifier_flags(OstreeRepoCommitModifierFlags *flags, int flag) { - *flags |= flag; -} - -struct CommitFilterData { - GHashTable *mode_adds; - GHashTable *skip_list; -}; - -typedef struct CommitFilterData CommitFilterData; - -static char* _gptr_to_str(gpointer p) -{ - return (char*)p; -} - -// The following 3 functions are wrapper functions for macros since CGO can't parse macros -static OstreeRepoFile* -_ostree_repo_file(GFile *file) -{ - return OSTREE_REPO_FILE (file); -} - -static guint -_gpointer_to_uint (gpointer ptr) -{ - return GPOINTER_TO_UINT (ptr); -} - -static gpointer -_guint_to_pointer (guint u) -{ - return GUINT_TO_POINTER (u); -} - -static void -_g_clear_object (volatile GObject **object_ptr) -{ - g_clear_object(object_ptr); -} - -static const GVariantType* -_g_variant_type (char *type) -{ - return G_VARIANT_TYPE (type); -} - -static int -_at_fdcwd () -{ - return AT_FDCWD; -} - -static guint64 -_guint64_from_be (guint64 val) -{ - return GUINT64_FROM_BE (val); -} - - - -// These functions are wrappers for variadic functions since CGO can't parse variadic functions -static void -_g_printerr_onearg (char* msg, - char* arg) -{ - g_printerr("%s %s\n", msg, arg); -} - -static void -_g_set_error_onearg (GError *err, - char* msg, - char* arg) -{ - g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED, "%s %s", msg, arg); -} - -static void -_g_variant_builder_add_twoargs (GVariantBuilder* builder, - const char *format_string, - char *arg1, - GVariant *arg2) -{ - g_variant_builder_add(builder, format_string, arg1, arg2); -} - -static GHashTable* -_g_hash_table_new_full () -{ - return g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); -} - -static void -_g_variant_get_commit_dump (GVariant *variant, - const char *format, - char **subject, - char **body, - guint64 *timestamp) -{ - return g_variant_get (variant, format, NULL, NULL, NULL, subject, body, timestamp, NULL, NULL); -} - -static guint32 -_binary_or (guint32 a, guint32 b) -{ - return a | b; -} - -static void -_cleanup (OstreeRepo *self, - OstreeRepoCommitModifier *modifier, - GCancellable *cancellable, - GError **out_error) -{ - if (self) - ostree_repo_abort_transaction(self, cancellable, out_error); - if (modifier) - ostree_repo_commit_modifier_unref (modifier); -} - -// The following functions make up a commit_filter function that gets passed into -// another C function (and thus can't be a go function) as well as its helpers -static OstreeRepoCommitFilterResult -_commit_filter (OstreeRepo *self, - const char *path, - GFileInfo *file_info, - gpointer user_data) -{ - struct CommitFilterData *data = user_data; - GHashTable *mode_adds = data->mode_adds; - GHashTable *skip_list = data->skip_list; - gpointer value; - - if (owner_uid >= 0) - g_file_info_set_attribute_uint32 (file_info, "unix::uid", owner_uid); - if (owner_gid >= 0) - g_file_info_set_attribute_uint32 (file_info, "unix::gid", owner_gid); - - if (mode_adds && g_hash_table_lookup_extended (mode_adds, path, NULL, &value)) - { - guint current_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); - guint mode_add = GPOINTER_TO_UINT (value); - g_file_info_set_attribute_uint32 (file_info, "unix::mode", - current_mode | mode_add); - g_hash_table_remove (mode_adds, path); - } - - if (skip_list && g_hash_table_contains (skip_list, path)) - { - g_hash_table_remove (skip_list, path); - return OSTREE_REPO_COMMIT_FILTER_SKIP; - } - - return OSTREE_REPO_COMMIT_FILTER_ALLOW; -} - - -static void -_set_owner_uid (guint32 uid) -{ - owner_uid = uid; -} - -static void _set_owner_gid (guint32 gid) -{ - owner_gid = gid; -} - -// Wrapper function for a function that takes a C function as a parameter. -// That translation doesn't work in go -static OstreeRepoCommitModifier* -_ostree_repo_commit_modifier_new_wrapper (OstreeRepoCommitModifierFlags flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - return ostree_repo_commit_modifier_new(flags, _commit_filter, user_data, destroy_notify); -} - -#endif diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/cat.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/cat.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/cat.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checkout.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checkout.go deleted file mode 100644 index 55b51bfbd0..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checkout.go +++ /dev/null @@ -1,102 +0,0 @@ -package otbuiltin - -import ( - "strings" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -// Global variable for options -var checkoutOpts checkoutOptions - -// Contains all of the options for checking commits out of -// an ostree repo -type checkoutOptions struct { - UserMode bool // Do not change file ownership or initialize extended attributes - Union bool // Keep existing directories and unchanged files, overwriting existing filesystem - AllowNoent bool // Do nothing if the specified filepath does not exist - DisableCache bool // Do not update or use the internal repository uncompressed object caceh - Whiteouts bool // Process 'whiteout' (docker style) entries - RequireHardlinks bool // Do not fall back to full copies if hard linking fails - Subpath string // Checkout sub-directory path - FromFile string // Process many checkouts from the given file -} - -// Instantiates and returns a checkoutOptions struct with default values set -func NewCheckoutOptions() checkoutOptions { - return checkoutOptions{} -} - -// Checks out a commit with the given ref from a repository at the location of repo path to to the destination. Returns an error if the checkout could not be processed -func Checkout(repoPath, destination, commit string, opts checkoutOptions) error { - checkoutOpts = opts - - var cancellable *glib.GCancellable - ccommit := C.CString(commit) - defer C.free(unsafe.Pointer(ccommit)) - var gerr = glib.NewGError() - cerr := (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - - repoPathc := C.g_file_new_for_path(C.CString(repoPath)) - defer C.g_object_unref(C.gpointer(repoPathc)) - crepo := C.ostree_repo_new(repoPathc) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_open(crepo, (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - - if strings.Compare(checkoutOpts.FromFile, "") != 0 { - err := processManyCheckouts(crepo, destination, cancellable) - if err != nil { - return err - } - } else { - var resolvedCommit *C.char - defer C.free(unsafe.Pointer(resolvedCommit)) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_resolve_rev(crepo, ccommit, C.FALSE, &resolvedCommit, &cerr))) { - return generateError(cerr) - } - err := processOneCheckout(crepo, resolvedCommit, checkoutOpts.Subpath, destination, cancellable) - if err != nil { - return err - } - } - return nil -} - -// Processes one checkout from the repo -func processOneCheckout(crepo *C.OstreeRepo, resolvedCommit *C.char, subpath, destination string, cancellable *glib.GCancellable) error { - cdest := C.CString(destination) - defer C.free(unsafe.Pointer(cdest)) - var gerr = glib.NewGError() - cerr := (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - var repoCheckoutAtOptions C.OstreeRepoCheckoutAtOptions - - if checkoutOpts.UserMode { - repoCheckoutAtOptions.mode = C.OSTREE_REPO_CHECKOUT_MODE_USER - } - if checkoutOpts.Union { - repoCheckoutAtOptions.overwrite_mode = C.OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES - } - - checkedOut := glib.GoBool(glib.GBoolean(C.ostree_repo_checkout_at(crepo, &repoCheckoutAtOptions, C._at_fdcwd(), cdest, resolvedCommit, nil, &cerr))) - if !checkedOut { - return generateError(cerr) - } - - return nil -} - -// process many checkouts -func processManyCheckouts(crepo *C.OstreeRepo, target string, cancellable *glib.GCancellable) error { - return nil -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checksum.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checksum.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/checksum.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/commit.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/commit.go deleted file mode 100644 index 9550f802c8..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/commit.go +++ /dev/null @@ -1,482 +0,0 @@ -package otbuiltin - -import ( - "bytes" - "errors" - "fmt" - "strings" - "time" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -// Declare global variable to store commitOptions -var options commitOptions - -// Declare a function prototype for being passed into another function -type handleLineFunc func(string, *glib.GHashTable) error - -// Contains all of the options for commmiting to an ostree repo. Initialize -// with NewCommitOptions() -type commitOptions struct { - Subject string // One line subject - Body string // Full description - Parent string // Parent of the commit - Tree []string // 'dir=PATH' or 'tar=TARFILE' or 'ref=COMMIT': overlay the given argument as a tree - AddMetadataString []string // Add a key/value pair to metadata - AddDetachedMetadataString []string // Add a key/value pair to detached metadata - OwnerUID int // Set file ownership to user id - OwnerGID int // Set file ownership to group id - NoXattrs bool // Do not import extended attributes - LinkCheckoutSpeedup bool // Optimize for commits of trees composed of hardlinks in the repository - TarAutoCreateParents bool // When loading tar archives, automatically create parent directories as needed - SkipIfUnchanged bool // If the contents are unchanged from a previous commit, do nothing - StatOverrideFile string // File containing list of modifications to make permissions - SkipListFile string // File containing list of file paths to skip - GenerateSizes bool // Generate size information along with commit metadata - GpgSign []string // GPG Key ID with which to sign the commit (if you have GPGME - GNU Privacy Guard Made Easy) - GpgHomedir string // GPG home directory to use when looking for keyrings (if you have GPGME - GNU Privacy Guard Made Easy) - Timestamp time.Time // Override the timestamp of the commit - Orphan bool // Commit does not belong to a branch - Fsync bool // Specify whether fsync should be used or not. Default to true -} - -// Initializes a commitOptions struct and sets default values -func NewCommitOptions() commitOptions { - var co commitOptions - co.OwnerUID = -1 - co.OwnerGID = -1 - co.Fsync = true - return co -} - -type OstreeRepoTransactionStats struct { - metadata_objects_total int32 - metadata_objects_written int32 - content_objects_total int32 - content_objects_written int32 - content_bytes_written uint64 -} - -func (repo *Repo) PrepareTransaction() (bool, error) { - var cerr *C.GError = nil - var resume C.gboolean - - r := glib.GoBool(glib.GBoolean(C.ostree_repo_prepare_transaction(repo.native(), &resume, nil, &cerr))) - if !r { - return false, generateError(cerr) - } - return glib.GoBool(glib.GBoolean(resume)), nil -} - -func (repo *Repo) CommitTransaction() (*OstreeRepoTransactionStats, error) { - var cerr *C.GError = nil - var stats OstreeRepoTransactionStats = OstreeRepoTransactionStats{} - statsPtr := (*C.OstreeRepoTransactionStats)(unsafe.Pointer(&stats)) - r := glib.GoBool(glib.GBoolean(C.ostree_repo_commit_transaction(repo.native(), statsPtr, nil, &cerr))) - if !r { - return nil, generateError(cerr) - } - return &stats, nil -} - -func (repo *Repo) TransactionSetRef(remote string, ref string, checksum string) { - var cRemote *C.char = nil - var cRef *C.char = nil - var cChecksum *C.char = nil - - if remote != "" { - cRemote = C.CString(remote) - } - if ref != "" { - cRef = C.CString(ref) - } - if checksum != "" { - cChecksum = C.CString(checksum) - } - C.ostree_repo_transaction_set_ref(repo.native(), cRemote, cRef, cChecksum) -} - -func (repo *Repo) AbortTransaction() error { - var cerr *C.GError = nil - r := glib.GoBool(glib.GBoolean(C.ostree_repo_abort_transaction(repo.native(), nil, &cerr))) - if !r { - return generateError(cerr) - } - return nil -} - -func (repo *Repo) RegenerateSummary() error { - var cerr *C.GError = nil - r := glib.GoBool(glib.GBoolean(C.ostree_repo_regenerate_summary(repo.native(), nil, nil, &cerr))) - if !r { - return generateError(cerr) - } - return nil -} - -// Commits a directory, specified by commitPath, to an ostree repo as a given branch -func (repo *Repo) Commit(commitPath, branch string, opts commitOptions) (string, error) { - options = opts - - var err error - var modeAdds *glib.GHashTable - var skipList *glib.GHashTable - var objectToCommit *glib.GFile - var skipCommit bool = false - var ccommitChecksum *C.char - defer C.free(unsafe.Pointer(ccommitChecksum)) - var flags C.OstreeRepoCommitModifierFlags = 0 - var filter_data C.CommitFilterData - - var cerr *C.GError - defer C.free(unsafe.Pointer(cerr)) - var metadata *C.GVariant = nil - defer func(){ - if metadata != nil { - defer C.g_variant_unref(metadata) - } - }() - - var detachedMetadata *C.GVariant = nil - defer C.free(unsafe.Pointer(detachedMetadata)) - var mtree *C.OstreeMutableTree - defer C.free(unsafe.Pointer(mtree)) - var root *C.GFile - defer C.free(unsafe.Pointer(root)) - var modifier *C.OstreeRepoCommitModifier - defer C.free(unsafe.Pointer(modifier)) - var cancellable *C.GCancellable - defer C.free(unsafe.Pointer(cancellable)) - - cpath := C.CString(commitPath) - defer C.free(unsafe.Pointer(cpath)) - csubject := C.CString(options.Subject) - defer C.free(unsafe.Pointer(csubject)) - cbody := C.CString(options.Body) - defer C.free(unsafe.Pointer(cbody)) - cbranch := C.CString(branch) - defer C.free(unsafe.Pointer(cbranch)) - cparent := C.CString(options.Parent) - defer C.free(unsafe.Pointer(cparent)) - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_is_writable(repo.native(), &cerr))) { - goto out - } - - // If the user provided a stat override file - if strings.Compare(options.StatOverrideFile, "") != 0 { - modeAdds = glib.ToGHashTable(unsafe.Pointer(C._g_hash_table_new_full())) - if err = parseFileByLine(options.StatOverrideFile, handleStatOverrideLine, modeAdds, cancellable); err != nil { - goto out - } - } - - // If the user provided a skiplist file - if strings.Compare(options.SkipListFile, "") != 0 { - skipList = glib.ToGHashTable(unsafe.Pointer(C._g_hash_table_new_full())) - if err = parseFileByLine(options.SkipListFile, handleSkipListline, skipList, cancellable); err != nil { - goto out - } - } - - if options.AddMetadataString != nil { - metadata, err = parseKeyValueStrings(options.AddMetadataString) - if err != nil { - goto out - } - } - - if options.AddDetachedMetadataString != nil { - _, err := parseKeyValueStrings(options.AddDetachedMetadataString) - if err != nil { - goto out - } - } - - if strings.Compare(branch, "") == 0 && !options.Orphan { - err = errors.New("A branch must be specified or use commitOptions.Orphan") - goto out - } - - if options.NoXattrs { - C._ostree_repo_append_modifier_flags(&flags, C.OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) - } - if options.GenerateSizes { - C._ostree_repo_append_modifier_flags(&flags, C.OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES) - } - if !options.Fsync { - C.ostree_repo_set_disable_fsync(repo.native(), C.TRUE) - } - - if flags != 0 || options.OwnerUID >= 0 || options.OwnerGID >= 0 || strings.Compare(options.StatOverrideFile, "") != 0 || options.NoXattrs { - filter_data.mode_adds = (*C.GHashTable)(modeAdds.Ptr()) - filter_data.skip_list = (*C.GHashTable)(skipList.Ptr()) - C._set_owner_uid((C.guint32)(options.OwnerUID)) - C._set_owner_gid((C.guint32)(options.OwnerGID)) - modifier = C._ostree_repo_commit_modifier_new_wrapper(flags, C.gpointer(&filter_data), nil) - } - - if strings.Compare(options.Parent, "") != 0 { - if strings.Compare(options.Parent, "none") == 0 { - options.Parent = "" - } - } else if !options.Orphan { - cerr = nil - if !glib.GoBool(glib.GBoolean(C.ostree_repo_resolve_rev(repo.native(), cbranch, C.TRUE, &cparent, &cerr))) { - goto out - } - } - - if options.LinkCheckoutSpeedup && !glib.GoBool(glib.GBoolean(C.ostree_repo_scan_hardlinks(repo.native(), cancellable, &cerr))) { - goto out - } - - mtree = C.ostree_mutable_tree_new() - - if len(commitPath) == 0 && (len(options.Tree) == 0 || len(options.Tree[0]) == 0) { - currentDir := (*C.char)(C.g_get_current_dir()) - objectToCommit = glib.ToGFile(unsafe.Pointer(C.g_file_new_for_path(currentDir))) - C.g_free(C.gpointer(currentDir)) - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_directory_to_mtree(repo.native(), (*C.GFile)(objectToCommit.Ptr()), mtree, modifier, cancellable, &cerr))) { - goto out - } - } else if len(options.Tree) != 0 { - var eq int = -1 - cerr = nil - for tree := range options.Tree { - eq = strings.Index(options.Tree[tree], "=") - if eq == -1 { - C._g_set_error_onearg(cerr, C.CString("Missing type in tree specification"), C.CString(options.Tree[tree])) - goto out - } - treeType := options.Tree[tree][:eq] - treeVal := options.Tree[tree][eq+1:] - - if strings.Compare(treeType, "dir") == 0 { - objectToCommit = glib.ToGFile(unsafe.Pointer(C.g_file_new_for_path(C.CString(treeVal)))) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_directory_to_mtree(repo.native(), (*C.GFile)(objectToCommit.Ptr()), mtree, modifier, cancellable, &cerr))) { - goto out - } - } else if strings.Compare(treeType, "tar") == 0 { - objectToCommit = glib.ToGFile(unsafe.Pointer(C.g_file_new_for_path(C.CString(treeVal)))) - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_archive_to_mtree(repo.native(), (*C.GFile)(objectToCommit.Ptr()), mtree, modifier, (C.gboolean)(glib.GBool(opts.TarAutoCreateParents)), cancellable, &cerr))) { - fmt.Println("error 1") - goto out - } - } else if strings.Compare(treeType, "ref") == 0 { - if !glib.GoBool(glib.GBoolean(C.ostree_repo_read_commit(repo.native(), C.CString(treeVal), (**C.GFile)(objectToCommit.Ptr()), nil, cancellable, &cerr))) { - goto out - } - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_directory_to_mtree(repo.native(), (*C.GFile)(objectToCommit.Ptr()), mtree, modifier, cancellable, &cerr))) { - goto out - } - } else { - C._g_set_error_onearg(cerr, C.CString("Missing type in tree specification"), C.CString(treeVal)) - goto out - } - } - } else { - objectToCommit = glib.ToGFile(unsafe.Pointer(C.g_file_new_for_path(cpath))) - cerr = nil - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_directory_to_mtree(repo.native(), (*C.GFile)(objectToCommit.Ptr()), mtree, modifier, cancellable, &cerr))) { - goto out - } - } - - if modeAdds != nil && C.g_hash_table_size((*C.GHashTable)(modeAdds.Ptr())) > 0 { - var hashIter *C.GHashTableIter - - var key, value C.gpointer - - C.g_hash_table_iter_init(hashIter, (*C.GHashTable)(modeAdds.Ptr())) - - for glib.GoBool(glib.GBoolean(C.g_hash_table_iter_next(hashIter, &key, &value))) { - C._g_printerr_onearg(C.CString("Unmatched StatOverride path: "), C._gptr_to_str(key)) - } - err = errors.New("Unmatched StatOverride paths") - C.free(unsafe.Pointer(hashIter)) - C.free(unsafe.Pointer(key)) - C.free(unsafe.Pointer(value)) - goto out - } - - if skipList != nil && C.g_hash_table_size((*C.GHashTable)(skipList.Ptr())) > 0 { - var hashIter *C.GHashTableIter - var key, value C.gpointer - - C.g_hash_table_iter_init(hashIter, (*C.GHashTable)(skipList.Ptr())) - - for glib.GoBool(glib.GBoolean(C.g_hash_table_iter_next(hashIter, &key, &value))) { - C._g_printerr_onearg(C.CString("Unmatched SkipList path: "), C._gptr_to_str(key)) - } - err = errors.New("Unmatched SkipList paths") - C.free(unsafe.Pointer(hashIter)) - C.free(unsafe.Pointer(key)) - C.free(unsafe.Pointer(value)) - goto out - } - - cerr = nil - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_mtree(repo.native(), mtree, &root, cancellable, &cerr))) { - goto out - } - - if options.SkipIfUnchanged && strings.Compare(options.Parent, "") != 0 { - var parentRoot *C.GFile - - cerr = nil - if !glib.GoBool(glib.GBoolean(C.ostree_repo_read_commit(repo.native(), cparent, &parentRoot, nil, cancellable, &cerr))) { - C.free(unsafe.Pointer(parentRoot)) - goto out - } - - if glib.GoBool(glib.GBoolean(C.g_file_equal(root, parentRoot))) { - skipCommit = true - } - C.free(unsafe.Pointer(parentRoot)) - } - - if !skipCommit { - var timestamp C.guint64 - - if options.Timestamp.IsZero() { - var now *C.GDateTime = C.g_date_time_new_now_utc() - timestamp = (C.guint64)(C.g_date_time_to_unix(now)) - C.g_date_time_unref(now) - - cerr = nil - ret := C.ostree_repo_write_commit(repo.native(), cparent, csubject, cbody, metadata, C._ostree_repo_file(root), &ccommitChecksum, cancellable, &cerr) - if !glib.GoBool(glib.GBoolean(ret)) { - goto out - } - } else { - timestamp = (C.guint64)(options.Timestamp.Unix()) - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_write_commit_with_time(repo.native(), cparent, csubject, cbody, - metadata, C._ostree_repo_file(root), timestamp, &ccommitChecksum, cancellable, &cerr))) { - goto out - } - } - - if detachedMetadata != nil { - C.ostree_repo_write_commit_detached_metadata(repo.native(), ccommitChecksum, detachedMetadata, cancellable, &cerr) - } - - if len(options.GpgSign) != 0 { - for key := range options.GpgSign { - if !glib.GoBool(glib.GBoolean(C.ostree_repo_sign_commit(repo.native(), (*C.gchar)(ccommitChecksum), (*C.gchar)(C.CString(options.GpgSign[key])), (*C.gchar)(C.CString(options.GpgHomedir)), cancellable, &cerr))) { - goto out - } - } - } - - if strings.Compare(branch, "") != 0 { - C.ostree_repo_transaction_set_ref(repo.native(), nil, cbranch, ccommitChecksum) - } else if !options.Orphan { - goto out - } else { - // TODO: Looks like I forgot to implement this. - } - } else { - ccommitChecksum = C.CString(options.Parent) - } - - return C.GoString(ccommitChecksum), nil -out: - if repo.native() != nil { - C.ostree_repo_abort_transaction(repo.native(), cancellable, nil) - //C.free(unsafe.Pointer(repo.native())) - } - if modifier != nil { - C.ostree_repo_commit_modifier_unref(modifier) - } - if err != nil { - return "", err - } - return "", generateError(cerr) -} - -// Parse an array of key value pairs of the format KEY=VALUE and add them to a GVariant -func parseKeyValueStrings(pairs []string) (*C.GVariant, error) { - builder := C.g_variant_builder_new(C._g_variant_type(C.CString("a{sv}"))) - defer C.g_variant_builder_unref(builder) - - for iter := range pairs { - index := strings.Index(pairs[iter], "=") - if index <= 0 { - var buffer bytes.Buffer - buffer.WriteString("Missing '=' in KEY=VALUE metadata '%s'") - buffer.WriteString(pairs[iter]) - return nil, errors.New(buffer.String()) - } - - key := C.CString(pairs[iter][:index]) - value := C.CString(pairs[iter][index+1:]) - - valueVariant := C.g_variant_new_string((*C.gchar)(value)) - - C._g_variant_builder_add_twoargs(builder, C.CString("{sv}"), key, valueVariant) - } - - metadata := C.g_variant_builder_end(builder) - return C.g_variant_ref_sink(metadata), nil -} - -// Parse a file linue by line and handle the line with the handleLineFunc -func parseFileByLine(path string, fn handleLineFunc, table *glib.GHashTable, cancellable *C.GCancellable) error { - var contents *C.char - var file *glib.GFile - var lines []string - var gerr = glib.NewGError() - cerr := (*C.GError)(gerr.Ptr()) - - file = glib.ToGFile(unsafe.Pointer(C.g_file_new_for_path(C.CString(path)))) - if !glib.GoBool(glib.GBoolean(C.g_file_load_contents((*C.GFile)(file.Ptr()), cancellable, &contents, nil, nil, &cerr))) { - return generateError(cerr) - } - - lines = strings.Split(C.GoString(contents), "\n") - for line := range lines { - if strings.Compare(lines[line], "") == 0 { - continue - } - - if err := fn(lines[line], table); err != nil { - return generateError(cerr) - } - } - return nil -} - -// Handle an individual line from a Statoverride file -func handleStatOverrideLine(line string, table *glib.GHashTable) error { - var space int - var modeAdd C.guint - - if space = strings.IndexRune(line, ' '); space == -1 { - return errors.New("Malformed StatOverrideFile (no space found)") - } - - modeAdd = (C.guint)(C.g_ascii_strtod((*C.gchar)(C.CString(line)), nil)) - C.g_hash_table_insert((*C.GHashTable)(table.Ptr()), C.gpointer(C.g_strdup((*C.gchar)(C.CString(line[space+1:])))), C._guint_to_pointer(modeAdd)) - - return nil -} - -// Handle an individual line from a Skiplist file -func handleSkipListline(line string, table *glib.GHashTable) error { - C.g_hash_table_add((*C.GHashTable)(table.Ptr()), C.gpointer( C.g_strdup((*C.gchar)(C.CString(line))))) - - return nil -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/config.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/config.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/config.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/diff.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/diff.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/diff.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/export.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/export.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/export.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/fsck.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/fsck.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/fsck.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/gpgsign.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/gpgsign.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/gpgsign.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/init.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/init.go deleted file mode 100644 index 9f2527927f..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/init.go +++ /dev/null @@ -1,91 +0,0 @@ -package otbuiltin - -import ( - "errors" - "strings" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -// Declare variables for options -var initOpts initOptions - -// Contains all of the options for initializing an ostree repo -type initOptions struct { - Mode string // either bare, archive-z2, or bare-user - - repoMode C.OstreeRepoMode -} - -// Instantiates and returns an initOptions struct with default values set -func NewInitOptions() initOptions { - io := initOptions{} - io.Mode = "bare" - io.repoMode = C.OSTREE_REPO_MODE_BARE - return io -} - -// Initializes a new ostree repository at the given path. Returns true -// if the repo exists at the location, regardless of whether it was initialized -// by the function or if it already existed. Returns an error if the repo could -// not be initialized -func Init(path string, options initOptions) (bool, error) { - initOpts = options - err := parseMode() - if err != nil { - return false, err - } - - // Create a repo struct from the path - var cerr *C.GError - defer C.free(unsafe.Pointer(cerr)) - cpath := C.CString(path) - defer C.free(unsafe.Pointer(cpath)) - pathc := C.g_file_new_for_path(cpath) - defer C.g_object_unref(C.gpointer(pathc)) - crepo := C.ostree_repo_new(pathc) - - // If the repo exists in the filesystem, return an error but set exists to true - /* var exists C.gboolean = 0 - success := glib.GoBool(glib.GBoolean(C.ostree_repo_exists(crepo, &exists, &cerr))) - if exists != 0 { - err = errors.New("repository already exists") - return true, err - } else if !success { - return false, generateError(cerr) - }*/ - - cerr = nil - created := glib.GoBool(glib.GBoolean(C.ostree_repo_create(crepo, initOpts.repoMode, nil, &cerr))) - if !created { - err := generateError(cerr) - errString := err.Error() - if strings.Contains(errString, "File exists") { - return true, err - } - return false, err - } - return true, nil -} - -// Converts the mode string to a C.OSTREE_REPO_MODE enum value -func parseMode() error { - if strings.EqualFold(initOpts.Mode, "bare") { - initOpts.repoMode = C.OSTREE_REPO_MODE_BARE - } else if strings.EqualFold(initOpts.Mode, "bare-user") { - initOpts.repoMode = C.OSTREE_REPO_MODE_BARE_USER - } else if strings.EqualFold(initOpts.Mode, "archive-z2") { - initOpts.repoMode = C.OSTREE_REPO_MODE_ARCHIVE_Z2 - } else { - return errors.New("Invalid option for mode") - } - return nil -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/log.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/log.go deleted file mode 100644 index 2ceea09257..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/log.go +++ /dev/null @@ -1,167 +0,0 @@ -package otbuiltin - -import ( - "fmt" - "strings" - "time" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -// Declare variables for options -var logOpts logOptions - -// Set the format of the strings in the log -const formatString = "2006-01-02 03:04;05 -0700" - -// Struct for the various pieces of data in a log entry -type LogEntry struct { - Checksum []byte - Variant []byte - Timestamp time.Time - Subject string - Body string -} - -// Convert the log entry to a string -func (l LogEntry) String() string { - if len(l.Variant) == 0 { - return fmt.Sprintf("%s\n%s\n\n\t%s\n\n\t%s\n\n", l.Checksum, l.Timestamp, l.Subject, l.Body) - } - return fmt.Sprintf("%s\n%s\n\n", l.Checksum, l.Variant) -} - -type OstreeDumpFlags uint - -const ( - OSTREE_DUMP_NONE OstreeDumpFlags = 0 - OSTREE_DUMP_RAW OstreeDumpFlags = 1 << iota -) - -// Contains all of the options for initializing an ostree repo -type logOptions struct { - Raw bool // Show raw variant data -} - -//Instantiates and returns a logOptions struct with default values set -func NewLogOptions() logOptions { - return logOptions{} -} - -// Show the logs of a branch starting with a given commit or ref. Returns a -// slice of log entries on success and an error otherwise -func Log(repoPath, branch string, options logOptions) ([]LogEntry, error) { - // attempt to open the repository - repo, err := OpenRepo(repoPath) - if err != nil { - return nil, err - } - - cbranch := C.CString(branch) - defer C.free(unsafe.Pointer(cbranch)) - var checksum *C.char - defer C.free(unsafe.Pointer(checksum)) - var flags OstreeDumpFlags = OSTREE_DUMP_NONE - var cerr *C.GError - defer C.free(unsafe.Pointer(cerr)) - - if logOpts.Raw { - flags |= OSTREE_DUMP_RAW - } - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_resolve_rev(repo.native(), cbranch, C.FALSE, &checksum, &cerr))) { - return nil, generateError(cerr) - } - - return logCommit(repo, checksum, false, flags) -} - -func logCommit(repo *Repo, checksum *C.char, isRecursive bool, flags OstreeDumpFlags) ([]LogEntry, error) { - var variant *C.GVariant - var parent *C.char - defer C.free(unsafe.Pointer(parent)) - var gerr = glib.NewGError() - var cerr = (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - entries := make([]LogEntry, 0, 1) - var err error - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_load_variant(repo.native(), C.OSTREE_OBJECT_TYPE_COMMIT, checksum, &variant, &cerr))) { - if isRecursive && glib.GoBool(glib.GBoolean(C.g_error_matches(cerr, C.g_io_error_quark(), C.G_IO_ERROR_NOT_FOUND))) { - return nil, nil - } - return entries, generateError(cerr) - } - - nextLogEntry := dumpLogObject(C.OSTREE_OBJECT_TYPE_COMMIT, checksum, variant, flags) - - // get the parent of this commit - parent = (*C.char)(C.ostree_commit_get_parent(variant)) - defer C.free(unsafe.Pointer(parent)) - if parent != nil { - entries, err = logCommit(repo, parent, true, flags) - if err != nil { - return nil, err - } - } - entries = append(entries, *nextLogEntry) - return entries, nil -} - -func dumpLogObject(objectType C.OstreeObjectType, checksum *C.char, variant *C.GVariant, flags OstreeDumpFlags) *LogEntry { - objLog := new(LogEntry) - objLog.Checksum = []byte(C.GoString(checksum)) - - if (flags & OSTREE_DUMP_RAW) != 0 { - dumpVariant(objLog, variant) - return objLog - } - - switch objectType { - case C.OSTREE_OBJECT_TYPE_COMMIT: - dumpCommit(objLog, variant, flags) - return objLog - default: - return objLog - } -} - -func dumpVariant(log *LogEntry, variant *C.GVariant) { - var byteswappedVariant *C.GVariant - - if C.G_BYTE_ORDER != C.G_BIG_ENDIAN { - byteswappedVariant = C.g_variant_byteswap(variant) - log.Variant = []byte(C.GoString((*C.char)(C.g_variant_print(byteswappedVariant, C.TRUE)))) - } else { - log.Variant = []byte(C.GoString((*C.char)(C.g_variant_print(byteswappedVariant, C.TRUE)))) - } -} - -func dumpCommit(log *LogEntry, variant *C.GVariant, flags OstreeDumpFlags) { - var subject, body *C.char - defer C.free(unsafe.Pointer(subject)) - defer C.free(unsafe.Pointer(body)) - var timestamp C.guint64 - - C._g_variant_get_commit_dump(variant, C.CString("(a{sv}aya(say)&s&stayay)"), &subject, &body, ×tamp) - - // Timestamp is now a Unix formatted timestamp as a guint64 - timestamp = C._guint64_from_be(timestamp) - log.Timestamp = time.Unix((int64)(timestamp), 0) - - if strings.Compare(C.GoString(subject), "") != 0 { - log.Subject = C.GoString(subject) - } - - if strings.Compare(C.GoString(body), "") != 0 { - log.Body = C.GoString(body) - } -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/ls.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/ls.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/ls.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/prune.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/prune.go deleted file mode 100644 index 8dfa40a55b..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/prune.go +++ /dev/null @@ -1,217 +0,0 @@ -package otbuiltin - -import ( - "bytes" - "errors" - "strconv" - "strings" - "time" - "unsafe" - - glib "github.com/ostreedev/ostree-go/pkg/glibobject" -) - -// #cgo pkg-config: ostree-1 -// #include -// #include -// #include -// #include "builtin.go.h" -import "C" - -// Declare gobal variable for options -var pruneOpts pruneOptions - -// Contains all of the options for pruning an ostree repo. Use -// NewPruneOptions() to initialize -type pruneOptions struct { - NoPrune bool // Only display unreachable objects; don't delete - RefsOnly bool // Only compute reachability via refs - DeleteCommit string // Specify a commit to delete - KeepYoungerThan time.Time // All commits older than this date will be pruned - Depth int // Only traverse depths (integer) parents for each commit (default: -1=infinite) - StaticDeltasOnly int // Change the behavior of --keep-younger-than and --delete-commit to prune only the static delta files -} - -// Instantiates and returns a pruneOptions struct with default values set -func NewPruneOptions() pruneOptions { - po := new(pruneOptions) - po.Depth = -1 - return *po -} - -// Search for unreachable objects in the repository given by repoPath. Removes the -// objects unless pruneOptions.NoPrune is specified -func Prune(repoPath string, options pruneOptions) (string, error) { - pruneOpts = options - // attempt to open the repository - repo, err := OpenRepo(repoPath) - if err != nil { - return "", err - } - - var pruneFlags C.OstreeRepoPruneFlags - var numObjectsTotal int - var numObjectsPruned int - var objSizeTotal uint64 - var gerr = glib.NewGError() - var cerr = (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - var cancellable *glib.GCancellable - - if !pruneOpts.NoPrune && !glib.GoBool(glib.GBoolean(C.ostree_repo_is_writable(repo.native(), &cerr))) { - return "", generateError(cerr) - } - - cerr = nil - if strings.Compare(pruneOpts.DeleteCommit, "") != 0 { - if pruneOpts.NoPrune { - return "", errors.New("Cannot specify both pruneOptions.DeleteCommit and pruneOptions.NoPrune") - } - - if pruneOpts.StaticDeltasOnly > 0 { - if glib.GoBool(glib.GBoolean(C.ostree_repo_prune_static_deltas(repo.native(), C.CString(pruneOpts.DeleteCommit), (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return "", generateError(cerr) - } - } else if err = deleteCommit(repo, pruneOpts.DeleteCommit, cancellable); err != nil { - return "", err - } - } - - if !pruneOpts.KeepYoungerThan.IsZero() { - if pruneOpts.NoPrune { - return "", errors.New("Cannot specify both pruneOptions.KeepYoungerThan and pruneOptions.NoPrune") - } - - if err = pruneCommitsKeepYoungerThanDate(repo, pruneOpts.KeepYoungerThan, cancellable); err != nil { - return "", err - } - } - - if pruneOpts.RefsOnly { - pruneFlags |= C.OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY - } - if pruneOpts.NoPrune { - pruneFlags |= C.OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE - } - - formattedFreedSize := C.GoString((*C.char)(C.g_format_size_full((C.guint64)(objSizeTotal), 0))) - - var buffer bytes.Buffer - - buffer.WriteString("Total objects: ") - buffer.WriteString(strconv.Itoa(numObjectsTotal)) - if numObjectsPruned == 0 { - buffer.WriteString("\nNo unreachable objects") - } else if pruneOpts.NoPrune { - buffer.WriteString("\nWould delete: ") - buffer.WriteString(strconv.Itoa(numObjectsPruned)) - buffer.WriteString(" objects, freeing ") - buffer.WriteString(formattedFreedSize) - } else { - buffer.WriteString("\nDeleted ") - buffer.WriteString(strconv.Itoa(numObjectsPruned)) - buffer.WriteString(" objects, ") - buffer.WriteString(formattedFreedSize) - buffer.WriteString(" freed") - } - - return buffer.String(), nil -} - -// Delete an unreachable commit from the repo -func deleteCommit(repo *Repo, commitToDelete string, cancellable *glib.GCancellable) error { - var refs *glib.GHashTable - var hashIter glib.GHashTableIter - var hashkey, hashvalue C.gpointer - var gerr = glib.NewGError() - var cerr = (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - - if glib.GoBool(glib.GBoolean(C.ostree_repo_list_refs(repo.native(), nil, (**C.GHashTable)(refs.Ptr()), (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - - C.g_hash_table_iter_init((*C.GHashTableIter)(hashIter.Ptr()), (*C.GHashTable)(refs.Ptr())) - for C.g_hash_table_iter_next((*C.GHashTableIter)(hashIter.Ptr()), &hashkey, &hashvalue) != 0 { - var ref string = C.GoString((*C.char)(hashkey)) - var commit string = C.GoString((*C.char)(hashvalue)) - if strings.Compare(commitToDelete, commit) == 0 { - var buffer bytes.Buffer - buffer.WriteString("Commit ") - buffer.WriteString(commitToDelete) - buffer.WriteString(" is referenced by ") - buffer.WriteString(ref) - return errors.New(buffer.String()) - } - } - - if err := enableTombstoneCommits(repo); err != nil { - return err - } - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_delete_object(repo.native(), C.OSTREE_OBJECT_TYPE_COMMIT, C.CString(commitToDelete), (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - - return nil -} - -// Prune commits but keep any younger than the given date regardless of whether they -// are reachable -func pruneCommitsKeepYoungerThanDate(repo *Repo, date time.Time, cancellable *glib.GCancellable) error { - var objects *glib.GHashTable - defer C.free(unsafe.Pointer(objects)) - var hashIter glib.GHashTableIter - var key, value C.gpointer - defer C.free(unsafe.Pointer(key)) - defer C.free(unsafe.Pointer(value)) - var gerr = glib.NewGError() - var cerr = (*C.GError)(gerr.Ptr()) - defer C.free(unsafe.Pointer(cerr)) - - if err := enableTombstoneCommits(repo); err != nil { - return err - } - - if !glib.GoBool(glib.GBoolean(C.ostree_repo_list_objects(repo.native(), C.OSTREE_REPO_LIST_OBJECTS_ALL, (**C.GHashTable)(objects.Ptr()), (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - - C.g_hash_table_iter_init((*C.GHashTableIter)(hashIter.Ptr()), (*C.GHashTable)(objects.Ptr())) - for C.g_hash_table_iter_next((*C.GHashTableIter)(hashIter.Ptr()), &key, &value) != 0 { - var serializedKey *glib.GVariant - defer C.free(unsafe.Pointer(serializedKey)) - var checksum *C.char - defer C.free(unsafe.Pointer(checksum)) - var objType C.OstreeObjectType - var commitTimestamp uint64 - var commit *glib.GVariant = nil - - C.ostree_object_name_deserialize((*C.GVariant)(serializedKey.Ptr()), &checksum, &objType) - - if objType != C.OSTREE_OBJECT_TYPE_COMMIT { - continue - } - - cerr = nil - if !glib.GoBool(glib.GBoolean(C.ostree_repo_load_variant(repo.native(), C.OSTREE_OBJECT_TYPE_COMMIT, checksum, (**C.GVariant)(commit.Ptr()), &cerr))) { - return generateError(cerr) - } - - commitTimestamp = (uint64)(C.ostree_commit_get_timestamp((*C.GVariant)(commit.Ptr()))) - if commitTimestamp < (uint64)(date.Unix()) { - cerr = nil - if pruneOpts.StaticDeltasOnly != 0 { - if !glib.GoBool(glib.GBoolean(C.ostree_repo_prune_static_deltas(repo.native(), checksum, (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - } else { - if !glib.GoBool(glib.GBoolean(C.ostree_repo_delete_object(repo.native(), C.OSTREE_OBJECT_TYPE_COMMIT, checksum, (*C.GCancellable)(cancellable.Ptr()), &cerr))) { - return generateError(cerr) - } - } - } - } - - return nil -} diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pull.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pull.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pull.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pulllocal.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pulllocal.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/pulllocal.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/refs.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/refs.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/refs.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/remote.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/remote.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/remote.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/reset.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/reset.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/reset.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/revparse.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/revparse.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/revparse.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/show.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/show.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/show.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/staticdelta.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/staticdelta.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/staticdelta.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/summary.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/summary.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/summary.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/trivialhttpd.go b/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/trivialhttpd.go deleted file mode 100644 index d43ea07c74..0000000000 --- a/vendor/github.com/ostreedev/ostree-go/pkg/otbuiltin/trivialhttpd.go +++ /dev/null @@ -1 +0,0 @@ -package otbuiltin diff --git a/vendor/github.com/pquerna/ffjson/LICENSE b/vendor/github.com/pquerna/ffjson/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/github.com/pquerna/ffjson/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/pquerna/ffjson/NOTICE b/vendor/github.com/pquerna/ffjson/NOTICE deleted file mode 100644 index 405a49618b..0000000000 --- a/vendor/github.com/pquerna/ffjson/NOTICE +++ /dev/null @@ -1,8 +0,0 @@ -ffjson -Copyright (c) 2014, Paul Querna - -This product includes software developed by -Paul Querna (http://paul.querna.org/). - -Portions of this software were developed as -part of Go, Copyright (c) 2012 The Go Authors. \ No newline at end of file diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer.go b/vendor/github.com/pquerna/ffjson/fflib/v1/buffer.go deleted file mode 100644 index 7f63a8582d..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer.go +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -// Simple byte buffer for marshaling data. - -import ( - "bytes" - "encoding/json" - "errors" - "io" - "unicode/utf8" -) - -type grower interface { - Grow(n int) -} - -type truncater interface { - Truncate(n int) - Reset() -} - -type bytesReader interface { - Bytes() []byte - String() string -} - -type runeWriter interface { - WriteRune(r rune) (n int, err error) -} - -type stringWriter interface { - WriteString(s string) (n int, err error) -} - -type lener interface { - Len() int -} - -type rewinder interface { - Rewind(n int) (err error) -} - -type encoder interface { - Encode(interface{}) error -} - -// TODO(pquerna): continue to reduce these interfaces - -type EncodingBuffer interface { - io.Writer - io.WriterTo - io.ByteWriter - stringWriter - truncater - grower - rewinder - encoder -} - -type DecodingBuffer interface { - io.ReadWriter - io.ByteWriter - stringWriter - runeWriter - truncater - grower - bytesReader - lener -} - -// A Buffer is a variable-sized buffer of bytes with Read and Write methods. -// The zero value for Buffer is an empty buffer ready to use. -type Buffer struct { - buf []byte // contents are the bytes buf[off : len(buf)] - off int // read at &buf[off], write at &buf[len(buf)] - runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune - encoder *json.Encoder - skipTrailingByte bool -} - -// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer. -var ErrTooLarge = errors.New("fflib.v1.Buffer: too large") - -// Bytes returns a slice of the contents of the unread portion of the buffer; -// len(b.Bytes()) == b.Len(). If the caller changes the contents of the -// returned slice, the contents of the buffer will change provided there -// are no intervening method calls on the Buffer. -func (b *Buffer) Bytes() []byte { return b.buf[b.off:] } - -// String returns the contents of the unread portion of the buffer -// as a string. If the Buffer is a nil pointer, it returns "". -func (b *Buffer) String() string { - if b == nil { - // Special case, useful in debugging. - return "" - } - return string(b.buf[b.off:]) -} - -// Len returns the number of bytes of the unread portion of the buffer; -// b.Len() == len(b.Bytes()). -func (b *Buffer) Len() int { return len(b.buf) - b.off } - -// Truncate discards all but the first n unread bytes from the buffer. -// It panics if n is negative or greater than the length of the buffer. -func (b *Buffer) Truncate(n int) { - if n == 0 { - b.off = 0 - b.buf = b.buf[0:0] - } else { - b.buf = b.buf[0 : b.off+n] - } -} - -// Reset resets the buffer so it has no content. -// b.Reset() is the same as b.Truncate(0). -func (b *Buffer) Reset() { b.Truncate(0) } - -// grow grows the buffer to guarantee space for n more bytes. -// It returns the index where bytes should be written. -// If the buffer can't grow it will panic with ErrTooLarge. -func (b *Buffer) grow(n int) int { - // If we have no buffer, get one from the pool - m := b.Len() - if m == 0 { - if b.buf == nil { - b.buf = makeSlice(2 * n) - b.off = 0 - } else if b.off != 0 { - // If buffer is empty, reset to recover space. - b.Truncate(0) - } - } - if len(b.buf)+n > cap(b.buf) { - var buf []byte - if m+n <= cap(b.buf)/2 { - // We can slide things down instead of allocating a new - // slice. We only need m+n <= cap(b.buf) to slide, but - // we instead let capacity get twice as large so we - // don't spend all our time copying. - copy(b.buf[:], b.buf[b.off:]) - buf = b.buf[:m] - } else { - // not enough space anywhere - buf = makeSlice(2*cap(b.buf) + n) - copy(buf, b.buf[b.off:]) - Pool(b.buf) - b.buf = buf - } - b.off = 0 - } - b.buf = b.buf[0 : b.off+m+n] - return b.off + m -} - -// Grow grows the buffer's capacity, if necessary, to guarantee space for -// another n bytes. After Grow(n), at least n bytes can be written to the -// buffer without another allocation. -// If n is negative, Grow will panic. -// If the buffer can't grow it will panic with ErrTooLarge. -func (b *Buffer) Grow(n int) { - if n < 0 { - panic("bytes.Buffer.Grow: negative count") - } - m := b.grow(n) - b.buf = b.buf[0:m] -} - -// Write appends the contents of p to the buffer, growing the buffer as -// needed. The return value n is the length of p; err is always nil. If the -// buffer becomes too large, Write will panic with ErrTooLarge. -func (b *Buffer) Write(p []byte) (n int, err error) { - if b.skipTrailingByte { - p = p[:len(p)-1] - } - m := b.grow(len(p)) - return copy(b.buf[m:], p), nil -} - -// WriteString appends the contents of s to the buffer, growing the buffer as -// needed. The return value n is the length of s; err is always nil. If the -// buffer becomes too large, WriteString will panic with ErrTooLarge. -func (b *Buffer) WriteString(s string) (n int, err error) { - m := b.grow(len(s)) - return copy(b.buf[m:], s), nil -} - -// MinRead is the minimum slice size passed to a Read call by -// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond -// what is required to hold the contents of r, ReadFrom will not grow the -// underlying buffer. -const minRead = 512 - -// ReadFrom reads data from r until EOF and appends it to the buffer, growing -// the buffer as needed. The return value n is the number of bytes read. Any -// error except io.EOF encountered during the read is also returned. If the -// buffer becomes too large, ReadFrom will panic with ErrTooLarge. -func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { - // If buffer is empty, reset to recover space. - if b.off >= len(b.buf) { - b.Truncate(0) - } - for { - if free := cap(b.buf) - len(b.buf); free < minRead { - // not enough space at end - newBuf := b.buf - if b.off+free < minRead { - // not enough space using beginning of buffer; - // double buffer capacity - newBuf = makeSlice(2*cap(b.buf) + minRead) - } - copy(newBuf, b.buf[b.off:]) - Pool(b.buf) - b.buf = newBuf[:len(b.buf)-b.off] - b.off = 0 - } - m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]) - b.buf = b.buf[0 : len(b.buf)+m] - n += int64(m) - if e == io.EOF { - break - } - if e != nil { - return n, e - } - } - return n, nil // err is EOF, so return nil explicitly -} - -// WriteTo writes data to w until the buffer is drained or an error occurs. -// The return value n is the number of bytes written; it always fits into an -// int, but it is int64 to match the io.WriterTo interface. Any error -// encountered during the write is also returned. -func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) { - if b.off < len(b.buf) { - nBytes := b.Len() - m, e := w.Write(b.buf[b.off:]) - if m > nBytes { - panic("bytes.Buffer.WriteTo: invalid Write count") - } - b.off += m - n = int64(m) - if e != nil { - return n, e - } - // all bytes should have been written, by definition of - // Write method in io.Writer - if m != nBytes { - return n, io.ErrShortWrite - } - } - // Buffer is now empty; reset. - b.Truncate(0) - return -} - -// WriteByte appends the byte c to the buffer, growing the buffer as needed. -// The returned error is always nil, but is included to match bufio.Writer's -// WriteByte. If the buffer becomes too large, WriteByte will panic with -// ErrTooLarge. -func (b *Buffer) WriteByte(c byte) error { - m := b.grow(1) - b.buf[m] = c - return nil -} - -func (b *Buffer) Rewind(n int) error { - b.buf = b.buf[:len(b.buf)-n] - return nil -} - -func (b *Buffer) Encode(v interface{}) error { - if b.encoder == nil { - b.encoder = json.NewEncoder(b) - } - b.skipTrailingByte = true - err := b.encoder.Encode(v) - b.skipTrailingByte = false - return err -} - -// WriteRune appends the UTF-8 encoding of Unicode code point r to the -// buffer, returning its length and an error, which is always nil but is -// included to match bufio.Writer's WriteRune. The buffer is grown as needed; -// if it becomes too large, WriteRune will panic with ErrTooLarge. -func (b *Buffer) WriteRune(r rune) (n int, err error) { - if r < utf8.RuneSelf { - b.WriteByte(byte(r)) - return 1, nil - } - n = utf8.EncodeRune(b.runeBytes[0:], r) - b.Write(b.runeBytes[0:n]) - return n, nil -} - -// Read reads the next len(p) bytes from the buffer or until the buffer -// is drained. The return value n is the number of bytes read. If the -// buffer has no data to return, err is io.EOF (unless len(p) is zero); -// otherwise it is nil. -func (b *Buffer) Read(p []byte) (n int, err error) { - if b.off >= len(b.buf) { - // Buffer is empty, reset to recover space. - b.Truncate(0) - if len(p) == 0 { - return - } - return 0, io.EOF - } - n = copy(p, b.buf[b.off:]) - b.off += n - return -} - -// Next returns a slice containing the next n bytes from the buffer, -// advancing the buffer as if the bytes had been returned by Read. -// If there are fewer than n bytes in the buffer, Next returns the entire buffer. -// The slice is only valid until the next call to a read or write method. -func (b *Buffer) Next(n int) []byte { - m := b.Len() - if n > m { - n = m - } - data := b.buf[b.off : b.off+n] - b.off += n - return data -} - -// ReadByte reads and returns the next byte from the buffer. -// If no byte is available, it returns error io.EOF. -func (b *Buffer) ReadByte() (c byte, err error) { - if b.off >= len(b.buf) { - // Buffer is empty, reset to recover space. - b.Truncate(0) - return 0, io.EOF - } - c = b.buf[b.off] - b.off++ - return c, nil -} - -// ReadRune reads and returns the next UTF-8-encoded -// Unicode code point from the buffer. -// If no bytes are available, the error returned is io.EOF. -// If the bytes are an erroneous UTF-8 encoding, it -// consumes one byte and returns U+FFFD, 1. -func (b *Buffer) ReadRune() (r rune, size int, err error) { - if b.off >= len(b.buf) { - // Buffer is empty, reset to recover space. - b.Truncate(0) - return 0, 0, io.EOF - } - c := b.buf[b.off] - if c < utf8.RuneSelf { - b.off++ - return rune(c), 1, nil - } - r, n := utf8.DecodeRune(b.buf[b.off:]) - b.off += n - return r, n, nil -} - -// ReadBytes reads until the first occurrence of delim in the input, -// returning a slice containing the data up to and including the delimiter. -// If ReadBytes encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often io.EOF). -// ReadBytes returns err != nil if and only if the returned data does not end in -// delim. -func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) { - slice, err := b.readSlice(delim) - // return a copy of slice. The buffer's backing array may - // be overwritten by later calls. - line = append(line, slice...) - return -} - -// readSlice is like ReadBytes but returns a reference to internal buffer data. -func (b *Buffer) readSlice(delim byte) (line []byte, err error) { - i := bytes.IndexByte(b.buf[b.off:], delim) - end := b.off + i + 1 - if i < 0 { - end = len(b.buf) - err = io.EOF - } - line = b.buf[b.off:end] - b.off = end - return line, err -} - -// ReadString reads until the first occurrence of delim in the input, -// returning a string containing the data up to and including the delimiter. -// If ReadString encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often io.EOF). -// ReadString returns err != nil if and only if the returned data does not end -// in delim. -func (b *Buffer) ReadString(delim byte) (line string, err error) { - slice, err := b.readSlice(delim) - return string(slice), err -} - -// NewBuffer creates and initializes a new Buffer using buf as its initial -// contents. It is intended to prepare a Buffer to read existing data. It -// can also be used to size the internal buffer for writing. To do that, -// buf should have the desired capacity but a length of zero. -// -// In most cases, new(Buffer) (or just declaring a Buffer variable) is -// sufficient to initialize a Buffer. -func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } - -// NewBufferString creates and initializes a new Buffer using string s as its -// initial contents. It is intended to prepare a buffer to read an existing -// string. -// -// In most cases, new(Buffer) (or just declaring a Buffer variable) is -// sufficient to initialize a Buffer. -func NewBufferString(s string) *Buffer { - return &Buffer{buf: []byte(s)} -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_nopool.go b/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_nopool.go deleted file mode 100644 index b84af6ff96..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_nopool.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !go1.3 - -package v1 - -// Stub version of buffer_pool.go for Go 1.2, which doesn't have sync.Pool. - -func Pool(b []byte) {} - -func makeSlice(n int) []byte { - return make([]byte, n) -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_pool.go b/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_pool.go deleted file mode 100644 index a021c57cf4..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/buffer_pool.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.3 - -package v1 - -// Allocation pools for Buffers. - -import "sync" - -var pools [14]sync.Pool -var pool64 *sync.Pool - -func init() { - var i uint - // TODO(pquerna): add science here around actual pool sizes. - for i = 6; i < 20; i++ { - n := 1 << i - pools[poolNum(n)].New = func() interface{} { return make([]byte, 0, n) } - } - pool64 = &pools[0] -} - -// This returns the pool number that will give a buffer of -// at least 'i' bytes. -func poolNum(i int) int { - // TODO(pquerna): convert to log2 w/ bsr asm instruction: - // - if i <= 64 { - return 0 - } else if i <= 128 { - return 1 - } else if i <= 256 { - return 2 - } else if i <= 512 { - return 3 - } else if i <= 1024 { - return 4 - } else if i <= 2048 { - return 5 - } else if i <= 4096 { - return 6 - } else if i <= 8192 { - return 7 - } else if i <= 16384 { - return 8 - } else if i <= 32768 { - return 9 - } else if i <= 65536 { - return 10 - } else if i <= 131072 { - return 11 - } else if i <= 262144 { - return 12 - } else if i <= 524288 { - return 13 - } else { - return -1 - } -} - -// Send a buffer to the Pool to reuse for other instances. -// You may no longer utilize the content of the buffer, since it may be used -// by other goroutines. -func Pool(b []byte) { - if b == nil { - return - } - c := cap(b) - - // Our smallest buffer is 64 bytes, so we discard smaller buffers. - if c < 64 { - return - } - - // We need to put the incoming buffer into the NEXT buffer, - // since a buffer guarantees AT LEAST the number of bytes available - // that is the top of this buffer. - // That is the reason for dividing the cap by 2, so it gets into the NEXT bucket. - // We add 2 to avoid rounding down if size is exactly power of 2. - pn := poolNum((c + 2) >> 1) - if pn != -1 { - pools[pn].Put(b[0:0]) - } - // if we didn't have a slot for this []byte, we just drop it and let the GC - // take care of it. -} - -// makeSlice allocates a slice of size n -- it will attempt to use a pool'ed -// instance whenever possible. -func makeSlice(n int) []byte { - if n <= 64 { - return pool64.Get().([]byte)[0:n] - } - - pn := poolNum(n) - - if pn != -1 { - return pools[pn].Get().([]byte)[0:n] - } else { - return make([]byte, n) - } -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/bytenum.go b/vendor/github.com/pquerna/ffjson/fflib/v1/bytenum.go deleted file mode 100644 index 08477409ac..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/bytenum.go +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's strconv/iota.go */ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -import ( - "github.com/pquerna/ffjson/fflib/v1/internal" -) - -func ParseFloat(s []byte, bitSize int) (f float64, err error) { - return internal.ParseFloat(s, bitSize) -} - -// ParseUint is like ParseInt but for unsigned numbers, and oeprating on []byte -func ParseUint(s []byte, base int, bitSize int) (n uint64, err error) { - if len(s) == 1 { - switch s[0] { - case '0': - return 0, nil - case '1': - return 1, nil - case '2': - return 2, nil - case '3': - return 3, nil - case '4': - return 4, nil - case '5': - return 5, nil - case '6': - return 6, nil - case '7': - return 7, nil - case '8': - return 8, nil - case '9': - return 9, nil - } - } - return internal.ParseUint(s, base, bitSize) -} - -func ParseInt(s []byte, base int, bitSize int) (i int64, err error) { - if len(s) == 1 { - switch s[0] { - case '0': - return 0, nil - case '1': - return 1, nil - case '2': - return 2, nil - case '3': - return 3, nil - case '4': - return 4, nil - case '5': - return 5, nil - case '6': - return 6, nil - case '7': - return 7, nil - case '8': - return 8, nil - case '9': - return 9, nil - } - } - return internal.ParseInt(s, base, bitSize) -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/decimal.go b/vendor/github.com/pquerna/ffjson/fflib/v1/decimal.go deleted file mode 100644 index 069df7a02a..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/decimal.go +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Multiprecision decimal numbers. -// For floating-point formatting only; not general purpose. -// Only operations are assign and (binary) left/right shift. -// Can do binary floating point in multiprecision decimal precisely -// because 2 divides 10; cannot do decimal floating point -// in multiprecision binary precisely. - -package v1 - -type decimal struct { - d [800]byte // digits - nd int // number of digits used - dp int // decimal point - neg bool - trunc bool // discarded nonzero digits beyond d[:nd] -} - -func (a *decimal) String() string { - n := 10 + a.nd - if a.dp > 0 { - n += a.dp - } - if a.dp < 0 { - n += -a.dp - } - - buf := make([]byte, n) - w := 0 - switch { - case a.nd == 0: - return "0" - - case a.dp <= 0: - // zeros fill space between decimal point and digits - buf[w] = '0' - w++ - buf[w] = '.' - w++ - w += digitZero(buf[w : w+-a.dp]) - w += copy(buf[w:], a.d[0:a.nd]) - - case a.dp < a.nd: - // decimal point in middle of digits - w += copy(buf[w:], a.d[0:a.dp]) - buf[w] = '.' - w++ - w += copy(buf[w:], a.d[a.dp:a.nd]) - - default: - // zeros fill space between digits and decimal point - w += copy(buf[w:], a.d[0:a.nd]) - w += digitZero(buf[w : w+a.dp-a.nd]) - } - return string(buf[0:w]) -} - -func digitZero(dst []byte) int { - for i := range dst { - dst[i] = '0' - } - return len(dst) -} - -// trim trailing zeros from number. -// (They are meaningless; the decimal point is tracked -// independent of the number of digits.) -func trim(a *decimal) { - for a.nd > 0 && a.d[a.nd-1] == '0' { - a.nd-- - } - if a.nd == 0 { - a.dp = 0 - } -} - -// Assign v to a. -func (a *decimal) Assign(v uint64) { - var buf [24]byte - - // Write reversed decimal in buf. - n := 0 - for v > 0 { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n++ - v = v1 - } - - // Reverse again to produce forward decimal in a.d. - a.nd = 0 - for n--; n >= 0; n-- { - a.d[a.nd] = buf[n] - a.nd++ - } - a.dp = a.nd - trim(a) -} - -// Maximum shift that we can do in one pass without overflow. -// Signed int has 31 bits, and we have to be able to accommodate 9<>k == 0; r++ { - if r >= a.nd { - if n == 0 { - // a == 0; shouldn't get here, but handle anyway. - a.nd = 0 - return - } - for n>>k == 0 { - n = n * 10 - r++ - } - break - } - c := int(a.d[r]) - n = n*10 + c - '0' - } - a.dp -= r - 1 - - // Pick up a digit, put down a digit. - for ; r < a.nd; r++ { - c := int(a.d[r]) - dig := n >> k - n -= dig << k - a.d[w] = byte(dig + '0') - w++ - n = n*10 + c - '0' - } - - // Put down extra digits. - for n > 0 { - dig := n >> k - n -= dig << k - if w < len(a.d) { - a.d[w] = byte(dig + '0') - w++ - } else if dig > 0 { - a.trunc = true - } - n = n * 10 - } - - a.nd = w - trim(a) -} - -// Cheat sheet for left shift: table indexed by shift count giving -// number of new digits that will be introduced by that shift. -// -// For example, leftcheats[4] = {2, "625"}. That means that -// if we are shifting by 4 (multiplying by 16), it will add 2 digits -// when the string prefix is "625" through "999", and one fewer digit -// if the string prefix is "000" through "624". -// -// Credit for this trick goes to Ken. - -type leftCheat struct { - delta int // number of new digits - cutoff string // minus one digit if original < a. -} - -var leftcheats = []leftCheat{ - // Leading digits of 1/2^i = 5^i. - // 5^23 is not an exact 64-bit floating point number, - // so have to use bc for the math. - /* - seq 27 | sed 's/^/5^/' | bc | - awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," } - { - log2 = log(2)/log(10) - printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n", - int(log2*NR+1), $0, 2**NR) - }' - */ - {0, ""}, - {1, "5"}, // * 2 - {1, "25"}, // * 4 - {1, "125"}, // * 8 - {2, "625"}, // * 16 - {2, "3125"}, // * 32 - {2, "15625"}, // * 64 - {3, "78125"}, // * 128 - {3, "390625"}, // * 256 - {3, "1953125"}, // * 512 - {4, "9765625"}, // * 1024 - {4, "48828125"}, // * 2048 - {4, "244140625"}, // * 4096 - {4, "1220703125"}, // * 8192 - {5, "6103515625"}, // * 16384 - {5, "30517578125"}, // * 32768 - {5, "152587890625"}, // * 65536 - {6, "762939453125"}, // * 131072 - {6, "3814697265625"}, // * 262144 - {6, "19073486328125"}, // * 524288 - {7, "95367431640625"}, // * 1048576 - {7, "476837158203125"}, // * 2097152 - {7, "2384185791015625"}, // * 4194304 - {7, "11920928955078125"}, // * 8388608 - {8, "59604644775390625"}, // * 16777216 - {8, "298023223876953125"}, // * 33554432 - {8, "1490116119384765625"}, // * 67108864 - {9, "7450580596923828125"}, // * 134217728 -} - -// Is the leading prefix of b lexicographically less than s? -func prefixIsLessThan(b []byte, s string) bool { - for i := 0; i < len(s); i++ { - if i >= len(b) { - return true - } - if b[i] != s[i] { - return b[i] < s[i] - } - } - return false -} - -// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow. -func leftShift(a *decimal, k uint) { - delta := leftcheats[k].delta - if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { - delta-- - } - - r := a.nd // read index - w := a.nd + delta // write index - n := 0 - - // Pick up a digit, put down a digit. - for r--; r >= 0; r-- { - n += (int(a.d[r]) - '0') << k - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - // Put down extra digits. - for n > 0 { - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - a.nd += delta - if a.nd >= len(a.d) { - a.nd = len(a.d) - } - a.dp += delta - trim(a) -} - -// Binary shift left (k > 0) or right (k < 0). -func (a *decimal) Shift(k int) { - switch { - case a.nd == 0: - // nothing to do: a == 0 - case k > 0: - for k > maxShift { - leftShift(a, maxShift) - k -= maxShift - } - leftShift(a, uint(k)) - case k < 0: - for k < -maxShift { - rightShift(a, maxShift) - k += maxShift - } - rightShift(a, uint(-k)) - } -} - -// If we chop a at nd digits, should we round up? -func shouldRoundUp(a *decimal, nd int) bool { - if nd < 0 || nd >= a.nd { - return false - } - if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even - // if we truncated, a little higher than what's recorded - always round up - if a.trunc { - return true - } - return nd > 0 && (a.d[nd-1]-'0')%2 != 0 - } - // not halfway - digit tells all - return a.d[nd] >= '5' -} - -// Round a to nd digits (or fewer). -// If nd is zero, it means we're rounding -// just to the left of the digits, as in -// 0.09 -> 0.1. -func (a *decimal) Round(nd int) { - if nd < 0 || nd >= a.nd { - return - } - if shouldRoundUp(a, nd) { - a.RoundUp(nd) - } else { - a.RoundDown(nd) - } -} - -// Round a down to nd digits (or fewer). -func (a *decimal) RoundDown(nd int) { - if nd < 0 || nd >= a.nd { - return - } - a.nd = nd - trim(a) -} - -// Round a up to nd digits (or fewer). -func (a *decimal) RoundUp(nd int) { - if nd < 0 || nd >= a.nd { - return - } - - // round up - for i := nd - 1; i >= 0; i-- { - c := a.d[i] - if c < '9' { // can stop after this digit - a.d[i]++ - a.nd = i + 1 - return - } - } - - // Number is all 9s. - // Change to single 1 with adjusted decimal point. - a.d[0] = '1' - a.nd = 1 - a.dp++ -} - -// Extract integer part, rounded appropriately. -// No guarantees about overflow. -func (a *decimal) RoundedInteger() uint64 { - if a.dp > 20 { - return 0xFFFFFFFFFFFFFFFF - } - var i int - n := uint64(0) - for i = 0; i < a.dp && i < a.nd; i++ { - n = n*10 + uint64(a.d[i]-'0') - } - for ; i < a.dp; i++ { - n *= 10 - } - if shouldRoundUp(a, a.dp) { - n++ - } - return n -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/extfloat.go b/vendor/github.com/pquerna/ffjson/fflib/v1/extfloat.go deleted file mode 100644 index 508ddc6bed..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/extfloat.go +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -// An extFloat represents an extended floating-point number, with more -// precision than a float64. It does not try to save bits: the -// number represented by the structure is mant*(2^exp), with a negative -// sign if neg is true. -type extFloat struct { - mant uint64 - exp int - neg bool -} - -// Powers of ten taken from double-conversion library. -// http://code.google.com/p/double-conversion/ -const ( - firstPowerOfTen = -348 - stepPowerOfTen = 8 -) - -var smallPowersOfTen = [...]extFloat{ - {1 << 63, -63, false}, // 1 - {0xa << 60, -60, false}, // 1e1 - {0x64 << 57, -57, false}, // 1e2 - {0x3e8 << 54, -54, false}, // 1e3 - {0x2710 << 50, -50, false}, // 1e4 - {0x186a0 << 47, -47, false}, // 1e5 - {0xf4240 << 44, -44, false}, // 1e6 - {0x989680 << 40, -40, false}, // 1e7 -} - -var powersOfTen = [...]extFloat{ - {0xfa8fd5a0081c0288, -1220, false}, // 10^-348 - {0xbaaee17fa23ebf76, -1193, false}, // 10^-340 - {0x8b16fb203055ac76, -1166, false}, // 10^-332 - {0xcf42894a5dce35ea, -1140, false}, // 10^-324 - {0x9a6bb0aa55653b2d, -1113, false}, // 10^-316 - {0xe61acf033d1a45df, -1087, false}, // 10^-308 - {0xab70fe17c79ac6ca, -1060, false}, // 10^-300 - {0xff77b1fcbebcdc4f, -1034, false}, // 10^-292 - {0xbe5691ef416bd60c, -1007, false}, // 10^-284 - {0x8dd01fad907ffc3c, -980, false}, // 10^-276 - {0xd3515c2831559a83, -954, false}, // 10^-268 - {0x9d71ac8fada6c9b5, -927, false}, // 10^-260 - {0xea9c227723ee8bcb, -901, false}, // 10^-252 - {0xaecc49914078536d, -874, false}, // 10^-244 - {0x823c12795db6ce57, -847, false}, // 10^-236 - {0xc21094364dfb5637, -821, false}, // 10^-228 - {0x9096ea6f3848984f, -794, false}, // 10^-220 - {0xd77485cb25823ac7, -768, false}, // 10^-212 - {0xa086cfcd97bf97f4, -741, false}, // 10^-204 - {0xef340a98172aace5, -715, false}, // 10^-196 - {0xb23867fb2a35b28e, -688, false}, // 10^-188 - {0x84c8d4dfd2c63f3b, -661, false}, // 10^-180 - {0xc5dd44271ad3cdba, -635, false}, // 10^-172 - {0x936b9fcebb25c996, -608, false}, // 10^-164 - {0xdbac6c247d62a584, -582, false}, // 10^-156 - {0xa3ab66580d5fdaf6, -555, false}, // 10^-148 - {0xf3e2f893dec3f126, -529, false}, // 10^-140 - {0xb5b5ada8aaff80b8, -502, false}, // 10^-132 - {0x87625f056c7c4a8b, -475, false}, // 10^-124 - {0xc9bcff6034c13053, -449, false}, // 10^-116 - {0x964e858c91ba2655, -422, false}, // 10^-108 - {0xdff9772470297ebd, -396, false}, // 10^-100 - {0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92 - {0xf8a95fcf88747d94, -343, false}, // 10^-84 - {0xb94470938fa89bcf, -316, false}, // 10^-76 - {0x8a08f0f8bf0f156b, -289, false}, // 10^-68 - {0xcdb02555653131b6, -263, false}, // 10^-60 - {0x993fe2c6d07b7fac, -236, false}, // 10^-52 - {0xe45c10c42a2b3b06, -210, false}, // 10^-44 - {0xaa242499697392d3, -183, false}, // 10^-36 - {0xfd87b5f28300ca0e, -157, false}, // 10^-28 - {0xbce5086492111aeb, -130, false}, // 10^-20 - {0x8cbccc096f5088cc, -103, false}, // 10^-12 - {0xd1b71758e219652c, -77, false}, // 10^-4 - {0x9c40000000000000, -50, false}, // 10^4 - {0xe8d4a51000000000, -24, false}, // 10^12 - {0xad78ebc5ac620000, 3, false}, // 10^20 - {0x813f3978f8940984, 30, false}, // 10^28 - {0xc097ce7bc90715b3, 56, false}, // 10^36 - {0x8f7e32ce7bea5c70, 83, false}, // 10^44 - {0xd5d238a4abe98068, 109, false}, // 10^52 - {0x9f4f2726179a2245, 136, false}, // 10^60 - {0xed63a231d4c4fb27, 162, false}, // 10^68 - {0xb0de65388cc8ada8, 189, false}, // 10^76 - {0x83c7088e1aab65db, 216, false}, // 10^84 - {0xc45d1df942711d9a, 242, false}, // 10^92 - {0x924d692ca61be758, 269, false}, // 10^100 - {0xda01ee641a708dea, 295, false}, // 10^108 - {0xa26da3999aef774a, 322, false}, // 10^116 - {0xf209787bb47d6b85, 348, false}, // 10^124 - {0xb454e4a179dd1877, 375, false}, // 10^132 - {0x865b86925b9bc5c2, 402, false}, // 10^140 - {0xc83553c5c8965d3d, 428, false}, // 10^148 - {0x952ab45cfa97a0b3, 455, false}, // 10^156 - {0xde469fbd99a05fe3, 481, false}, // 10^164 - {0xa59bc234db398c25, 508, false}, // 10^172 - {0xf6c69a72a3989f5c, 534, false}, // 10^180 - {0xb7dcbf5354e9bece, 561, false}, // 10^188 - {0x88fcf317f22241e2, 588, false}, // 10^196 - {0xcc20ce9bd35c78a5, 614, false}, // 10^204 - {0x98165af37b2153df, 641, false}, // 10^212 - {0xe2a0b5dc971f303a, 667, false}, // 10^220 - {0xa8d9d1535ce3b396, 694, false}, // 10^228 - {0xfb9b7cd9a4a7443c, 720, false}, // 10^236 - {0xbb764c4ca7a44410, 747, false}, // 10^244 - {0x8bab8eefb6409c1a, 774, false}, // 10^252 - {0xd01fef10a657842c, 800, false}, // 10^260 - {0x9b10a4e5e9913129, 827, false}, // 10^268 - {0xe7109bfba19c0c9d, 853, false}, // 10^276 - {0xac2820d9623bf429, 880, false}, // 10^284 - {0x80444b5e7aa7cf85, 907, false}, // 10^292 - {0xbf21e44003acdd2d, 933, false}, // 10^300 - {0x8e679c2f5e44ff8f, 960, false}, // 10^308 - {0xd433179d9c8cb841, 986, false}, // 10^316 - {0x9e19db92b4e31ba9, 1013, false}, // 10^324 - {0xeb96bf6ebadf77d9, 1039, false}, // 10^332 - {0xaf87023b9bf0ee6b, 1066, false}, // 10^340 -} - -// floatBits returns the bits of the float64 that best approximates -// the extFloat passed as receiver. Overflow is set to true if -// the resulting float64 is ±Inf. -func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) { - f.Normalize() - - exp := f.exp + 63 - - // Exponent too small. - if exp < flt.bias+1 { - n := flt.bias + 1 - exp - f.mant >>= uint(n) - exp += n - } - - // Extract 1+flt.mantbits bits from the 64-bit mantissa. - mant := f.mant >> (63 - flt.mantbits) - if f.mant&(1<<(62-flt.mantbits)) != 0 { - // Round up. - mant += 1 - } - - // Rounding might have added a bit; shift down. - if mant == 2<>= 1 - exp++ - } - - // Infinities. - if exp-flt.bias >= 1<>uint(-f.exp))<>= uint(-f.exp) - f.exp = 0 - return *f, *f - } - expBiased := exp - flt.bias - - upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg} - if mant != 1<>(64-32) == 0 { - mant <<= 32 - exp -= 32 - } - if mant>>(64-16) == 0 { - mant <<= 16 - exp -= 16 - } - if mant>>(64-8) == 0 { - mant <<= 8 - exp -= 8 - } - if mant>>(64-4) == 0 { - mant <<= 4 - exp -= 4 - } - if mant>>(64-2) == 0 { - mant <<= 2 - exp -= 2 - } - if mant>>(64-1) == 0 { - mant <<= 1 - exp -= 1 - } - shift = uint(f.exp - exp) - f.mant, f.exp = mant, exp - return -} - -// Multiply sets f to the product f*g: the result is correctly rounded, -// but not normalized. -func (f *extFloat) Multiply(g extFloat) { - fhi, flo := f.mant>>32, uint64(uint32(f.mant)) - ghi, glo := g.mant>>32, uint64(uint32(g.mant)) - - // Cross products. - cross1 := fhi * glo - cross2 := flo * ghi - - // f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo - f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32) - rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32) - // Round up. - rem += (1 << 31) - - f.mant += (rem >> 32) - f.exp = f.exp + g.exp + 64 -} - -var uint64pow10 = [...]uint64{ - 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, -} - -// AssignDecimal sets f to an approximate value mantissa*10^exp. It -// returns true if the value represented by f is guaranteed to be the -// best approximation of d after being rounded to a float64 or -// float32 depending on flt. -func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) { - const uint64digits = 19 - const errorscale = 8 - errors := 0 // An upper bound for error, computed in errorscale*ulp. - if trunc { - // the decimal number was truncated. - errors += errorscale / 2 - } - - f.mant = mantissa - f.exp = 0 - f.neg = neg - - // Multiply by powers of ten. - i := (exp10 - firstPowerOfTen) / stepPowerOfTen - if exp10 < firstPowerOfTen || i >= len(powersOfTen) { - return false - } - adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen - - // We multiply by exp%step - if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] { - // We can multiply the mantissa exactly. - f.mant *= uint64pow10[adjExp] - f.Normalize() - } else { - f.Normalize() - f.Multiply(smallPowersOfTen[adjExp]) - errors += errorscale / 2 - } - - // We multiply by 10 to the exp - exp%step. - f.Multiply(powersOfTen[i]) - if errors > 0 { - errors += 1 - } - errors += errorscale / 2 - - // Normalize - shift := f.Normalize() - errors <<= shift - - // Now f is a good approximation of the decimal. - // Check whether the error is too large: that is, if the mantissa - // is perturbated by the error, the resulting float64 will change. - // The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits. - // - // In many cases the approximation will be good enough. - denormalExp := flt.bias - 63 - var extrabits uint - if f.exp <= denormalExp { - // f.mant * 2^f.exp is smaller than 2^(flt.bias+1). - extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp)) - } else { - extrabits = uint(63 - flt.mantbits) - } - - halfway := uint64(1) << (extrabits - 1) - mant_extra := f.mant & (1< expMax: - i-- - default: - break Loop - } - } - // Apply the desired decimal shift on f. It will have exponent - // in the desired range. This is multiplication by 10^-exp10. - f.Multiply(powersOfTen[i]) - - return -(firstPowerOfTen + i*stepPowerOfTen), i -} - -// frexp10Many applies a common shift by a power of ten to a, b, c. -func frexp10Many(a, b, c *extFloat) (exp10 int) { - exp10, i := c.frexp10() - a.Multiply(powersOfTen[i]) - b.Multiply(powersOfTen[i]) - return -} - -// FixedDecimal stores in d the first n significant digits -// of the decimal representation of f. It returns false -// if it cannot be sure of the answer. -func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if n == 0 { - panic("strconv: internal error: extFloat.FixedDecimal called with n == 0") - } - // Multiply by an appropriate power of ten to have a reasonable - // number to process. - f.Normalize() - exp10, _ := f.frexp10() - - shift := uint(-f.exp) - integer := uint32(f.mant >> shift) - fraction := f.mant - (uint64(integer) << shift) - ε := uint64(1) // ε is the uncertainty we have on the mantissa of f. - - // Write exactly n digits to d. - needed := n // how many digits are left to write. - integerDigits := 0 // the number of decimal digits of integer. - pow10 := uint64(1) // the power of ten by which f was scaled. - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - rest := integer - if integerDigits > needed { - // the integral part is already large, trim the last digits. - pow10 = uint64pow10[integerDigits-needed] - integer /= uint32(pow10) - rest -= integer * uint32(pow10) - } else { - rest = 0 - } - - // Write the digits of integer: the digits of rest are omitted. - var buf [32]byte - pos := len(buf) - for v := integer; v > 0; { - v1 := v / 10 - v -= 10 * v1 - pos-- - buf[pos] = byte(v + '0') - v = v1 - } - for i := pos; i < len(buf); i++ { - d.d[i-pos] = buf[i] - } - nd := len(buf) - pos - d.nd = nd - d.dp = integerDigits + exp10 - needed -= nd - - if needed > 0 { - if rest != 0 || pow10 != 1 { - panic("strconv: internal error, rest != 0 but needed > 0") - } - // Emit digits for the fractional part. Each time, 10*fraction - // fits in a uint64 without overflow. - for needed > 0 { - fraction *= 10 - ε *= 10 // the uncertainty scales as we multiply by ten. - if 2*ε > 1<> shift - d.d[nd] = byte(digit + '0') - fraction -= digit << shift - nd++ - needed-- - } - d.nd = nd - } - - // We have written a truncation of f (a numerator / 10^d.dp). The remaining part - // can be interpreted as a small number (< 1) to be added to the last digit of the - // numerator. - // - // If rest > 0, the amount is: - // (rest< 0 guarantees that pow10 << shift does not overflow a uint64. - // - // If rest = 0, pow10 == 1 and the amount is - // fraction / (1 << shift) - // fraction being known with a ±ε uncertainty. - // - // We pass this information to the rounding routine for adjustment. - - ok := adjustLastDigitFixed(d, uint64(rest)<= 0; i-- { - if d.d[i] != '0' { - d.nd = i + 1 - break - } - } - return true -} - -// adjustLastDigitFixed assumes d contains the representation of the integral part -// of some number, whose fractional part is num / (den << shift). The numerator -// num is only known up to an uncertainty of size ε, assumed to be less than -// (den << shift)/2. -// -// It will increase the last digit by one to account for correct rounding, typically -// when the fractional part is greater than 1/2, and will return false if ε is such -// that no correct answer can be given. -func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool { - if num > den< den< den< (den< den<= 0; i-- { - if d.d[i] == '9' { - d.nd-- - } else { - break - } - } - if i < 0 { - d.d[0] = '1' - d.nd = 1 - d.dp++ - } else { - d.d[i]++ - } - return true - } - return false -} - -// ShortestDecimal stores in d the shortest decimal representation of f -// which belongs to the open interval (lower, upper), where f is supposed -// to lie. It returns false whenever the result is unsure. The implementation -// uses the Grisu3 algorithm. -func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if f.exp == 0 && *lower == *f && *lower == *upper { - // an exact integer. - var buf [24]byte - n := len(buf) - 1 - for v := f.mant; v > 0; { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n-- - v = v1 - } - nd := len(buf) - n - 1 - for i := 0; i < nd; i++ { - d.d[i] = buf[n+1+i] - } - d.nd, d.dp = nd, nd - for d.nd > 0 && d.d[d.nd-1] == '0' { - d.nd-- - } - if d.nd == 0 { - d.dp = 0 - } - d.neg = f.neg - return true - } - upper.Normalize() - // Uniformize exponents. - if f.exp > upper.exp { - f.mant <<= uint(f.exp - upper.exp) - f.exp = upper.exp - } - if lower.exp > upper.exp { - lower.mant <<= uint(lower.exp - upper.exp) - lower.exp = upper.exp - } - - exp10 := frexp10Many(lower, f, upper) - // Take a safety margin due to rounding in frexp10Many, but we lose precision. - upper.mant++ - lower.mant-- - - // The shortest representation of f is either rounded up or down, but - // in any case, it is a truncation of upper. - shift := uint(-upper.exp) - integer := uint32(upper.mant >> shift) - fraction := upper.mant - (uint64(integer) << shift) - - // How far we can go down from upper until the result is wrong. - allowance := upper.mant - lower.mant - // How far we should go to get a very precise result. - targetDiff := upper.mant - f.mant - - // Count integral digits: there are at most 10. - var integerDigits int - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - for i := 0; i < integerDigits; i++ { - pow := uint64pow10[integerDigits-i-1] - digit := integer / uint32(pow) - d.d[i] = byte(digit + '0') - integer -= digit * uint32(pow) - // evaluate whether we should stop. - if currentDiff := uint64(integer)<> shift) - d.d[d.nd] = byte(digit + '0') - d.nd++ - fraction -= uint64(digit) << shift - if fraction < allowance*multiplier { - // We are in the admissible range. Note that if allowance is about to - // overflow, that is, allowance > 2^64/10, the condition is automatically - // true due to the limited range of fraction. - return adjustLastDigit(d, - fraction, targetDiff*multiplier, allowance*multiplier, - 1< maxDiff-ulpBinary { - // we went too far - return false - } - if d.nd == 1 && d.d[0] == '0' { - // the number has actually reached zero. - d.nd = 0 - d.dp = 0 - } - return true -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/fold.go b/vendor/github.com/pquerna/ffjson/fflib/v1/fold.go deleted file mode 100644 index 4d33e6f77d..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/fold.go +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's encoding/json/fold.go */ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -import ( - "unicode/utf8" -) - -const ( - caseMask = ^byte(0x20) // Mask to ignore case in ASCII. - kelvin = '\u212a' - smallLongEss = '\u017f' -) - -// equalFoldRight is a specialization of bytes.EqualFold when s is -// known to be all ASCII (including punctuation), but contains an 's', -// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. -// See comments on foldFunc. -func EqualFoldRight(s, t []byte) bool { - for _, sb := range s { - if len(t) == 0 { - return false - } - tb := t[0] - if tb < utf8.RuneSelf { - if sb != tb { - sbUpper := sb & caseMask - if 'A' <= sbUpper && sbUpper <= 'Z' { - if sbUpper != tb&caseMask { - return false - } - } else { - return false - } - } - t = t[1:] - continue - } - // sb is ASCII and t is not. t must be either kelvin - // sign or long s; sb must be s, S, k, or K. - tr, size := utf8.DecodeRune(t) - switch sb { - case 's', 'S': - if tr != smallLongEss { - return false - } - case 'k', 'K': - if tr != kelvin { - return false - } - default: - return false - } - t = t[size:] - - } - if len(t) > 0 { - return false - } - return true -} - -// asciiEqualFold is a specialization of bytes.EqualFold for use when -// s is all ASCII (but may contain non-letters) and contains no -// special-folding letters. -// See comments on foldFunc. -func AsciiEqualFold(s, t []byte) bool { - if len(s) != len(t) { - return false - } - for i, sb := range s { - tb := t[i] - if sb == tb { - continue - } - if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { - if sb&caseMask != tb&caseMask { - return false - } - } else { - return false - } - } - return true -} - -// simpleLetterEqualFold is a specialization of bytes.EqualFold for -// use when s is all ASCII letters (no underscores, etc) and also -// doesn't contain 'k', 'K', 's', or 'S'. -// See comments on foldFunc. -func SimpleLetterEqualFold(s, t []byte) bool { - if len(s) != len(t) { - return false - } - for i, b := range s { - if b&caseMask != t[i]&caseMask { - return false - } - } - return true -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/ftoa.go b/vendor/github.com/pquerna/ffjson/fflib/v1/ftoa.go deleted file mode 100644 index 360d6dbcf9..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/ftoa.go +++ /dev/null @@ -1,542 +0,0 @@ -package v1 - -/** - * Copyright 2015 Paul Querna, Klaus Post - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Most of this file are on Go stdlib's strconv/ftoa.go */ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -import "math" - -// TODO: move elsewhere? -type floatInfo struct { - mantbits uint - expbits uint - bias int -} - -var optimize = true // can change for testing - -var float32info = floatInfo{23, 8, -127} -var float64info = floatInfo{52, 11, -1023} - -// AppendFloat appends the string form of the floating-point number f, -// as generated by FormatFloat -func AppendFloat(dst EncodingBuffer, val float64, fmt byte, prec, bitSize int) { - var bits uint64 - var flt *floatInfo - switch bitSize { - case 32: - bits = uint64(math.Float32bits(float32(val))) - flt = &float32info - case 64: - bits = math.Float64bits(val) - flt = &float64info - default: - panic("strconv: illegal AppendFloat/FormatFloat bitSize") - } - - neg := bits>>(flt.expbits+flt.mantbits) != 0 - exp := int(bits>>flt.mantbits) & (1< digs.nd && digs.nd >= digs.dp { - eprec = digs.nd - } - // %e is used if the exponent from the conversion - // is less than -4 or greater than or equal to the precision. - // if precision was the shortest possible, use precision 6 for this decision. - if shortest { - eprec = 6 - } - exp := digs.dp - 1 - if exp < -4 || exp >= eprec { - if prec > digs.nd { - prec = digs.nd - } - fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') - return - } - if prec > digs.dp { - prec = digs.nd - } - fmtF(dst, neg, digs, max(prec-digs.dp, 0)) - return - } - - // unknown format - dst.Write([]byte{'%', fmt}) - return -} - -// Round d (= mant * 2^exp) to the shortest number of digits -// that will let the original floating point value be precisely -// reconstructed. Size is original floating point size (64 or 32). -func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { - // If mantissa is zero, the number is zero; stop now. - if mant == 0 { - d.nd = 0 - return - } - - // Compute upper and lower such that any decimal number - // between upper and lower (possibly inclusive) - // will round to the original floating point number. - - // We may see at once that the number is already shortest. - // - // Suppose d is not denormal, so that 2^exp <= d < 10^dp. - // The closest shorter number is at least 10^(dp-nd) away. - // The lower/upper bounds computed below are at distance - // at most 2^(exp-mantbits). - // - // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), - // or equivalently log2(10)*(dp-nd) > exp-mantbits. - // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). - minexp := flt.bias + 1 // minimum possible exponent - if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { - // The number is already shortest. - return - } - - // d = mant << (exp - mantbits) - // Next highest floating point number is mant+1 << exp-mantbits. - // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. - upper := new(decimal) - upper.Assign(mant*2 + 1) - upper.Shift(exp - int(flt.mantbits) - 1) - - // d = mant << (exp - mantbits) - // Next lowest floating point number is mant-1 << exp-mantbits, - // unless mant-1 drops the significant bit and exp is not the minimum exp, - // in which case the next lowest is mant*2-1 << exp-mantbits-1. - // Either way, call it mantlo << explo-mantbits. - // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. - var mantlo uint64 - var explo int - if mant > 1< 0 { - dst.WriteByte('.') - i := 1 - m := min(d.nd, prec+1) - if i < m { - dst.Write(d.d[i:m]) - i = m - } - for i <= prec { - dst.WriteByte('0') - i++ - } - } - - // e± - dst.WriteByte(fmt) - exp := d.dp - 1 - if d.nd == 0 { // special case: 0 has exponent 0 - exp = 0 - } - if exp < 0 { - ch = '-' - exp = -exp - } else { - ch = '+' - } - dst.WriteByte(ch) - - // dd or ddd - switch { - case exp < 10: - dst.WriteByte('0') - dst.WriteByte(byte(exp) + '0') - case exp < 100: - dst.WriteByte(byte(exp/10) + '0') - dst.WriteByte(byte(exp%10) + '0') - default: - dst.WriteByte(byte(exp/100) + '0') - dst.WriteByte(byte(exp/10)%10 + '0') - dst.WriteByte(byte(exp%10) + '0') - } - - return -} - -// %f: -ddddddd.ddddd -func fmtF(dst EncodingBuffer, neg bool, d decimalSlice, prec int) { - // sign - if neg { - dst.WriteByte('-') - } - - // integer, padded with zeros as needed. - if d.dp > 0 { - m := min(d.nd, d.dp) - dst.Write(d.d[:m]) - for ; m < d.dp; m++ { - dst.WriteByte('0') - } - } else { - dst.WriteByte('0') - } - - // fraction - if prec > 0 { - dst.WriteByte('.') - for i := 0; i < prec; i++ { - ch := byte('0') - if j := d.dp + i; 0 <= j && j < d.nd { - ch = d.d[j] - } - dst.WriteByte(ch) - } - } - - return -} - -// %b: -ddddddddp±ddd -func fmtB(dst EncodingBuffer, neg bool, mant uint64, exp int, flt *floatInfo) { - // sign - if neg { - dst.WriteByte('-') - } - - // mantissa - formatBits(dst, mant, 10, false) - - // p - dst.WriteByte('p') - - // ±exponent - exp -= int(flt.mantbits) - if exp >= 0 { - dst.WriteByte('+') - } - formatBits(dst, uint64(exp), 10, exp < 0) - - return -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -// formatBits computes the string representation of u in the given base. -// If neg is set, u is treated as negative int64 value. -func formatBits(dst EncodingBuffer, u uint64, base int, neg bool) { - if base < 2 || base > len(digits) { - panic("strconv: illegal AppendInt/FormatInt base") - } - // 2 <= base && base <= len(digits) - - var a [64 + 1]byte // +1 for sign of 64bit value in base 2 - i := len(a) - - if neg { - u = -u - } - - // convert bits - if base == 10 { - // common case: use constants for / because - // the compiler can optimize it into a multiply+shift - - if ^uintptr(0)>>32 == 0 { - for u > uint64(^uintptr(0)) { - q := u / 1e9 - us := uintptr(u - q*1e9) // us % 1e9 fits into a uintptr - for j := 9; j > 0; j-- { - i-- - qs := us / 10 - a[i] = byte(us - qs*10 + '0') - us = qs - } - u = q - } - } - - // u guaranteed to fit into a uintptr - us := uintptr(u) - for us >= 10 { - i-- - q := us / 10 - a[i] = byte(us - q*10 + '0') - us = q - } - // u < 10 - i-- - a[i] = byte(us + '0') - - } else if s := shifts[base]; s > 0 { - // base is power of 2: use shifts and masks instead of / and % - b := uint64(base) - m := uintptr(b) - 1 // == 1<= b { - i-- - a[i] = digits[uintptr(u)&m] - u >>= s - } - // u < base - i-- - a[i] = digits[uintptr(u)] - - } else { - // general case - b := uint64(base) - for u >= b { - i-- - q := u / b - a[i] = digits[uintptr(u-q*b)] - u = q - } - // u < base - i-- - a[i] = digits[uintptr(u)] - } - - // add sign, if any - if neg { - i-- - a[i] = '-' - } - - dst.Write(a[i:]) -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atof.go b/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atof.go deleted file mode 100644 index 46c1289ec4..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atof.go +++ /dev/null @@ -1,936 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's strconv/atof.go */ - -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// decimal to binary floating point conversion. -// Algorithm: -// 1) Store input in multiprecision decimal. -// 2) Multiply/divide decimal by powers of two until in range [0.5, 1) -// 3) Multiply by 2^precision and round to get mantissa. - -import "math" - -var optimize = true // can change for testing - -func equalIgnoreCase(s1 []byte, s2 []byte) bool { - if len(s1) != len(s2) { - return false - } - for i := 0; i < len(s1); i++ { - c1 := s1[i] - if 'A' <= c1 && c1 <= 'Z' { - c1 += 'a' - 'A' - } - c2 := s2[i] - if 'A' <= c2 && c2 <= 'Z' { - c2 += 'a' - 'A' - } - if c1 != c2 { - return false - } - } - return true -} - -func special(s []byte) (f float64, ok bool) { - if len(s) == 0 { - return - } - switch s[0] { - default: - return - case '+': - if equalIgnoreCase(s, []byte("+inf")) || equalIgnoreCase(s, []byte("+infinity")) { - return math.Inf(1), true - } - case '-': - if equalIgnoreCase(s, []byte("-inf")) || equalIgnoreCase(s, []byte("-infinity")) { - return math.Inf(-1), true - } - case 'n', 'N': - if equalIgnoreCase(s, []byte("nan")) { - return math.NaN(), true - } - case 'i', 'I': - if equalIgnoreCase(s, []byte("inf")) || equalIgnoreCase(s, []byte("infinity")) { - return math.Inf(1), true - } - } - return -} - -func (b *decimal) set(s []byte) (ok bool) { - i := 0 - b.neg = false - b.trunc = false - - // optional sign - if i >= len(s) { - return - } - switch { - case s[i] == '+': - i++ - case s[i] == '-': - b.neg = true - i++ - } - - // digits - sawdot := false - sawdigits := false - for ; i < len(s); i++ { - switch { - case s[i] == '.': - if sawdot { - return - } - sawdot = true - b.dp = b.nd - continue - - case '0' <= s[i] && s[i] <= '9': - sawdigits = true - if s[i] == '0' && b.nd == 0 { // ignore leading zeros - b.dp-- - continue - } - if b.nd < len(b.d) { - b.d[b.nd] = s[i] - b.nd++ - } else if s[i] != '0' { - b.trunc = true - } - continue - } - break - } - if !sawdigits { - return - } - if !sawdot { - b.dp = b.nd - } - - // optional exponent moves decimal point. - // if we read a very large, very long number, - // just be sure to move the decimal point by - // a lot (say, 100000). it doesn't matter if it's - // not the exact number. - if i < len(s) && (s[i] == 'e' || s[i] == 'E') { - i++ - if i >= len(s) { - return - } - esign := 1 - if s[i] == '+' { - i++ - } else if s[i] == '-' { - i++ - esign = -1 - } - if i >= len(s) || s[i] < '0' || s[i] > '9' { - return - } - e := 0 - for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { - if e < 10000 { - e = e*10 + int(s[i]) - '0' - } - } - b.dp += e * esign - } - - if i != len(s) { - return - } - - ok = true - return -} - -// readFloat reads a decimal mantissa and exponent from a float -// string representation. It sets ok to false if the number could -// not fit return types or is invalid. -func readFloat(s []byte) (mantissa uint64, exp int, neg, trunc, ok bool) { - const uint64digits = 19 - i := 0 - - // optional sign - if i >= len(s) { - return - } - switch { - case s[i] == '+': - i++ - case s[i] == '-': - neg = true - i++ - } - - // digits - sawdot := false - sawdigits := false - nd := 0 - ndMant := 0 - dp := 0 - for ; i < len(s); i++ { - switch c := s[i]; true { - case c == '.': - if sawdot { - return - } - sawdot = true - dp = nd - continue - - case '0' <= c && c <= '9': - sawdigits = true - if c == '0' && nd == 0 { // ignore leading zeros - dp-- - continue - } - nd++ - if ndMant < uint64digits { - mantissa *= 10 - mantissa += uint64(c - '0') - ndMant++ - } else if s[i] != '0' { - trunc = true - } - continue - } - break - } - if !sawdigits { - return - } - if !sawdot { - dp = nd - } - - // optional exponent moves decimal point. - // if we read a very large, very long number, - // just be sure to move the decimal point by - // a lot (say, 100000). it doesn't matter if it's - // not the exact number. - if i < len(s) && (s[i] == 'e' || s[i] == 'E') { - i++ - if i >= len(s) { - return - } - esign := 1 - if s[i] == '+' { - i++ - } else if s[i] == '-' { - i++ - esign = -1 - } - if i >= len(s) || s[i] < '0' || s[i] > '9' { - return - } - e := 0 - for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { - if e < 10000 { - e = e*10 + int(s[i]) - '0' - } - } - dp += e * esign - } - - if i != len(s) { - return - } - - exp = dp - ndMant - ok = true - return - -} - -// decimal power of ten to binary power of two. -var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26} - -func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) { - var exp int - var mant uint64 - - // Zero is always a special case. - if d.nd == 0 { - mant = 0 - exp = flt.bias - goto out - } - - // Obvious overflow/underflow. - // These bounds are for 64-bit floats. - // Will have to change if we want to support 80-bit floats in the future. - if d.dp > 310 { - goto overflow - } - if d.dp < -330 { - // zero - mant = 0 - exp = flt.bias - goto out - } - - // Scale by powers of two until in range [0.5, 1.0) - exp = 0 - for d.dp > 0 { - var n int - if d.dp >= len(powtab) { - n = 27 - } else { - n = powtab[d.dp] - } - d.Shift(-n) - exp += n - } - for d.dp < 0 || d.dp == 0 && d.d[0] < '5' { - var n int - if -d.dp >= len(powtab) { - n = 27 - } else { - n = powtab[-d.dp] - } - d.Shift(n) - exp -= n - } - - // Our range is [0.5,1) but floating point range is [1,2). - exp-- - - // Minimum representable exponent is flt.bias+1. - // If the exponent is smaller, move it up and - // adjust d accordingly. - if exp < flt.bias+1 { - n := flt.bias + 1 - exp - d.Shift(-n) - exp += n - } - - if exp-flt.bias >= 1<>= 1 - exp++ - if exp-flt.bias >= 1<>float64info.mantbits != 0 { - return - } - f = float64(mantissa) - if neg { - f = -f - } - switch { - case exp == 0: - // an integer. - return f, true - // Exact integers are <= 10^15. - // Exact powers of ten are <= 10^22. - case exp > 0 && exp <= 15+22: // int * 10^k - // If exponent is big but number of digits is not, - // can move a few zeros into the integer part. - if exp > 22 { - f *= float64pow10[exp-22] - exp = 22 - } - if f > 1e15 || f < -1e15 { - // the exponent was really too large. - return - } - return f * float64pow10[exp], true - case exp < 0 && exp >= -22: // int / 10^k - return f / float64pow10[-exp], true - } - return -} - -// If possible to compute mantissa*10^exp to 32-bit float f exactly, -// entirely in floating-point math, do so, avoiding the machinery above. -func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) { - if mantissa>>float32info.mantbits != 0 { - return - } - f = float32(mantissa) - if neg { - f = -f - } - switch { - case exp == 0: - return f, true - // Exact integers are <= 10^7. - // Exact powers of ten are <= 10^10. - case exp > 0 && exp <= 7+10: // int * 10^k - // If exponent is big but number of digits is not, - // can move a few zeros into the integer part. - if exp > 10 { - f *= float32pow10[exp-10] - exp = 10 - } - if f > 1e7 || f < -1e7 { - // the exponent was really too large. - return - } - return f * float32pow10[exp], true - case exp < 0 && exp >= -10: // int / 10^k - return f / float32pow10[-exp], true - } - return -} - -const fnParseFloat = "ParseFloat" - -func atof32(s []byte) (f float32, err error) { - if val, ok := special(s); ok { - return float32(val), nil - } - - if optimize { - // Parse mantissa and exponent. - mantissa, exp, neg, trunc, ok := readFloat(s) - if ok { - // Try pure floating-point arithmetic conversion. - if !trunc { - if f, ok := atof32exact(mantissa, exp, neg); ok { - return f, nil - } - } - // Try another fast path. - ext := new(extFloat) - if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok { - b, ovf := ext.floatBits(&float32info) - f = math.Float32frombits(uint32(b)) - if ovf { - err = rangeError(fnParseFloat, string(s)) - } - return f, err - } - } - } - var d decimal - if !d.set(s) { - return 0, syntaxError(fnParseFloat, string(s)) - } - b, ovf := d.floatBits(&float32info) - f = math.Float32frombits(uint32(b)) - if ovf { - err = rangeError(fnParseFloat, string(s)) - } - return f, err -} - -func atof64(s []byte) (f float64, err error) { - if val, ok := special(s); ok { - return val, nil - } - - if optimize { - // Parse mantissa and exponent. - mantissa, exp, neg, trunc, ok := readFloat(s) - if ok { - // Try pure floating-point arithmetic conversion. - if !trunc { - if f, ok := atof64exact(mantissa, exp, neg); ok { - return f, nil - } - } - // Try another fast path. - ext := new(extFloat) - if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok { - b, ovf := ext.floatBits(&float64info) - f = math.Float64frombits(b) - if ovf { - err = rangeError(fnParseFloat, string(s)) - } - return f, err - } - } - } - var d decimal - if !d.set(s) { - return 0, syntaxError(fnParseFloat, string(s)) - } - b, ovf := d.floatBits(&float64info) - f = math.Float64frombits(b) - if ovf { - err = rangeError(fnParseFloat, string(s)) - } - return f, err -} - -// ParseFloat converts the string s to a floating-point number -// with the precision specified by bitSize: 32 for float32, or 64 for float64. -// When bitSize=32, the result still has type float64, but it will be -// convertible to float32 without changing its value. -// -// If s is well-formed and near a valid floating point number, -// ParseFloat returns the nearest floating point number rounded -// using IEEE754 unbiased rounding. -// -// The errors that ParseFloat returns have concrete type *NumError -// and include err.Num = s. -// -// If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax. -// -// If s is syntactically well-formed but is more than 1/2 ULP -// away from the largest floating point number of the given size, -// ParseFloat returns f = ±Inf, err.Err = ErrRange. -func ParseFloat(s []byte, bitSize int) (f float64, err error) { - if bitSize == 32 { - f1, err1 := atof32(s) - return float64(f1), err1 - } - f1, err1 := atof64(s) - return f1, err1 -} - -// oroginal: strconv/decimal.go, but not exported, and needed for PareFloat. - -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Multiprecision decimal numbers. -// For floating-point formatting only; not general purpose. -// Only operations are assign and (binary) left/right shift. -// Can do binary floating point in multiprecision decimal precisely -// because 2 divides 10; cannot do decimal floating point -// in multiprecision binary precisely. - -type decimal struct { - d [800]byte // digits - nd int // number of digits used - dp int // decimal point - neg bool - trunc bool // discarded nonzero digits beyond d[:nd] -} - -func (a *decimal) String() string { - n := 10 + a.nd - if a.dp > 0 { - n += a.dp - } - if a.dp < 0 { - n += -a.dp - } - - buf := make([]byte, n) - w := 0 - switch { - case a.nd == 0: - return "0" - - case a.dp <= 0: - // zeros fill space between decimal point and digits - buf[w] = '0' - w++ - buf[w] = '.' - w++ - w += digitZero(buf[w : w+-a.dp]) - w += copy(buf[w:], a.d[0:a.nd]) - - case a.dp < a.nd: - // decimal point in middle of digits - w += copy(buf[w:], a.d[0:a.dp]) - buf[w] = '.' - w++ - w += copy(buf[w:], a.d[a.dp:a.nd]) - - default: - // zeros fill space between digits and decimal point - w += copy(buf[w:], a.d[0:a.nd]) - w += digitZero(buf[w : w+a.dp-a.nd]) - } - return string(buf[0:w]) -} - -func digitZero(dst []byte) int { - for i := range dst { - dst[i] = '0' - } - return len(dst) -} - -// trim trailing zeros from number. -// (They are meaningless; the decimal point is tracked -// independent of the number of digits.) -func trim(a *decimal) { - for a.nd > 0 && a.d[a.nd-1] == '0' { - a.nd-- - } - if a.nd == 0 { - a.dp = 0 - } -} - -// Assign v to a. -func (a *decimal) Assign(v uint64) { - var buf [24]byte - - // Write reversed decimal in buf. - n := 0 - for v > 0 { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n++ - v = v1 - } - - // Reverse again to produce forward decimal in a.d. - a.nd = 0 - for n--; n >= 0; n-- { - a.d[a.nd] = buf[n] - a.nd++ - } - a.dp = a.nd - trim(a) -} - -// Maximum shift that we can do in one pass without overflow. -// Signed int has 31 bits, and we have to be able to accommodate 9<>k == 0; r++ { - if r >= a.nd { - if n == 0 { - // a == 0; shouldn't get here, but handle anyway. - a.nd = 0 - return - } - for n>>k == 0 { - n = n * 10 - r++ - } - break - } - c := int(a.d[r]) - n = n*10 + c - '0' - } - a.dp -= r - 1 - - // Pick up a digit, put down a digit. - for ; r < a.nd; r++ { - c := int(a.d[r]) - dig := n >> k - n -= dig << k - a.d[w] = byte(dig + '0') - w++ - n = n*10 + c - '0' - } - - // Put down extra digits. - for n > 0 { - dig := n >> k - n -= dig << k - if w < len(a.d) { - a.d[w] = byte(dig + '0') - w++ - } else if dig > 0 { - a.trunc = true - } - n = n * 10 - } - - a.nd = w - trim(a) -} - -// Cheat sheet for left shift: table indexed by shift count giving -// number of new digits that will be introduced by that shift. -// -// For example, leftcheats[4] = {2, "625"}. That means that -// if we are shifting by 4 (multiplying by 16), it will add 2 digits -// when the string prefix is "625" through "999", and one fewer digit -// if the string prefix is "000" through "624". -// -// Credit for this trick goes to Ken. - -type leftCheat struct { - delta int // number of new digits - cutoff string // minus one digit if original < a. -} - -var leftcheats = []leftCheat{ - // Leading digits of 1/2^i = 5^i. - // 5^23 is not an exact 64-bit floating point number, - // so have to use bc for the math. - /* - seq 27 | sed 's/^/5^/' | bc | - awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," } - { - log2 = log(2)/log(10) - printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n", - int(log2*NR+1), $0, 2**NR) - }' - */ - {0, ""}, - {1, "5"}, // * 2 - {1, "25"}, // * 4 - {1, "125"}, // * 8 - {2, "625"}, // * 16 - {2, "3125"}, // * 32 - {2, "15625"}, // * 64 - {3, "78125"}, // * 128 - {3, "390625"}, // * 256 - {3, "1953125"}, // * 512 - {4, "9765625"}, // * 1024 - {4, "48828125"}, // * 2048 - {4, "244140625"}, // * 4096 - {4, "1220703125"}, // * 8192 - {5, "6103515625"}, // * 16384 - {5, "30517578125"}, // * 32768 - {5, "152587890625"}, // * 65536 - {6, "762939453125"}, // * 131072 - {6, "3814697265625"}, // * 262144 - {6, "19073486328125"}, // * 524288 - {7, "95367431640625"}, // * 1048576 - {7, "476837158203125"}, // * 2097152 - {7, "2384185791015625"}, // * 4194304 - {7, "11920928955078125"}, // * 8388608 - {8, "59604644775390625"}, // * 16777216 - {8, "298023223876953125"}, // * 33554432 - {8, "1490116119384765625"}, // * 67108864 - {9, "7450580596923828125"}, // * 134217728 -} - -// Is the leading prefix of b lexicographically less than s? -func prefixIsLessThan(b []byte, s string) bool { - for i := 0; i < len(s); i++ { - if i >= len(b) { - return true - } - if b[i] != s[i] { - return b[i] < s[i] - } - } - return false -} - -// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow. -func leftShift(a *decimal, k uint) { - delta := leftcheats[k].delta - if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { - delta-- - } - - r := a.nd // read index - w := a.nd + delta // write index - n := 0 - - // Pick up a digit, put down a digit. - for r--; r >= 0; r-- { - n += (int(a.d[r]) - '0') << k - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - // Put down extra digits. - for n > 0 { - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - a.nd += delta - if a.nd >= len(a.d) { - a.nd = len(a.d) - } - a.dp += delta - trim(a) -} - -// Binary shift left (k > 0) or right (k < 0). -func (a *decimal) Shift(k int) { - switch { - case a.nd == 0: - // nothing to do: a == 0 - case k > 0: - for k > maxShift { - leftShift(a, maxShift) - k -= maxShift - } - leftShift(a, uint(k)) - case k < 0: - for k < -maxShift { - rightShift(a, maxShift) - k += maxShift - } - rightShift(a, uint(-k)) - } -} - -// If we chop a at nd digits, should we round up? -func shouldRoundUp(a *decimal, nd int) bool { - if nd < 0 || nd >= a.nd { - return false - } - if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even - // if we truncated, a little higher than what's recorded - always round up - if a.trunc { - return true - } - return nd > 0 && (a.d[nd-1]-'0')%2 != 0 - } - // not halfway - digit tells all - return a.d[nd] >= '5' -} - -// Round a to nd digits (or fewer). -// If nd is zero, it means we're rounding -// just to the left of the digits, as in -// 0.09 -> 0.1. -func (a *decimal) Round(nd int) { - if nd < 0 || nd >= a.nd { - return - } - if shouldRoundUp(a, nd) { - a.RoundUp(nd) - } else { - a.RoundDown(nd) - } -} - -// Round a down to nd digits (or fewer). -func (a *decimal) RoundDown(nd int) { - if nd < 0 || nd >= a.nd { - return - } - a.nd = nd - trim(a) -} - -// Round a up to nd digits (or fewer). -func (a *decimal) RoundUp(nd int) { - if nd < 0 || nd >= a.nd { - return - } - - // round up - for i := nd - 1; i >= 0; i-- { - c := a.d[i] - if c < '9' { // can stop after this digit - a.d[i]++ - a.nd = i + 1 - return - } - } - - // Number is all 9s. - // Change to single 1 with adjusted decimal point. - a.d[0] = '1' - a.nd = 1 - a.dp++ -} - -// Extract integer part, rounded appropriately. -// No guarantees about overflow. -func (a *decimal) RoundedInteger() uint64 { - if a.dp > 20 { - return 0xFFFFFFFFFFFFFFFF - } - var i int - n := uint64(0) - for i = 0; i < a.dp && i < a.nd; i++ { - n = n*10 + uint64(a.d[i]-'0') - } - for ; i < a.dp; i++ { - n *= 10 - } - if shouldRoundUp(a, a.dp) { - n++ - } - return n -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atoi.go b/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atoi.go deleted file mode 100644 index 06eb2ec29f..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/atoi.go +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's strconv/atoi.go */ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "errors" - "strconv" -) - -// ErrRange indicates that a value is out of range for the target type. -var ErrRange = errors.New("value out of range") - -// ErrSyntax indicates that a value does not have the right syntax for the target type. -var ErrSyntax = errors.New("invalid syntax") - -// A NumError records a failed conversion. -type NumError struct { - Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat) - Num string // the input - Err error // the reason the conversion failed (ErrRange, ErrSyntax) -} - -func (e *NumError) Error() string { - return "strconv." + e.Func + ": " + "parsing " + strconv.Quote(e.Num) + ": " + e.Err.Error() -} - -func syntaxError(fn, str string) *NumError { - return &NumError{fn, str, ErrSyntax} -} - -func rangeError(fn, str string) *NumError { - return &NumError{fn, str, ErrRange} -} - -const intSize = 32 << uint(^uint(0)>>63) - -// IntSize is the size in bits of an int or uint value. -const IntSize = intSize - -// Return the first number n such that n*base >= 1<<64. -func cutoff64(base int) uint64 { - if base < 2 { - return 0 - } - return (1<<64-1)/uint64(base) + 1 -} - -// ParseUint is like ParseInt but for unsigned numbers, and oeprating on []byte -func ParseUint(s []byte, base int, bitSize int) (n uint64, err error) { - var cutoff, maxVal uint64 - - if bitSize == 0 { - bitSize = int(IntSize) - } - - s0 := s - switch { - case len(s) < 1: - err = ErrSyntax - goto Error - - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - switch { - case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): - base = 16 - s = s[2:] - if len(s) < 1 { - err = ErrSyntax - goto Error - } - case s[0] == '0': - base = 8 - default: - base = 10 - } - - default: - err = errors.New("invalid base " + strconv.Itoa(base)) - goto Error - } - - n = 0 - cutoff = cutoff64(base) - maxVal = 1<= base { - n = 0 - err = ErrSyntax - goto Error - } - - if n >= cutoff { - // n*base overflows - n = 1<<64 - 1 - err = ErrRange - goto Error - } - n *= uint64(base) - - n1 := n + uint64(v) - if n1 < n || n1 > maxVal { - // n+v overflows - n = 1<<64 - 1 - err = ErrRange - goto Error - } - n = n1 - } - - return n, nil - -Error: - return n, &NumError{"ParseUint", string(s0), err} -} - -// ParseInt interprets a string s in the given base (2 to 36) and -// returns the corresponding value i. If base == 0, the base is -// implied by the string's prefix: base 16 for "0x", base 8 for -// "0", and base 10 otherwise. -// -// The bitSize argument specifies the integer type -// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 -// correspond to int, int8, int16, int32, and int64. -// -// The errors that ParseInt returns have concrete type *NumError -// and include err.Num = s. If s is empty or contains invalid -// digits, err.Err = ErrSyntax and the returned value is 0; -// if the value corresponding to s cannot be represented by a -// signed integer of the given size, err.Err = ErrRange and the -// returned value is the maximum magnitude integer of the -// appropriate bitSize and sign. -func ParseInt(s []byte, base int, bitSize int) (i int64, err error) { - const fnParseInt = "ParseInt" - - if bitSize == 0 { - bitSize = int(IntSize) - } - - // Empty string bad. - if len(s) == 0 { - return 0, syntaxError(fnParseInt, string(s)) - } - - // Pick off leading sign. - s0 := s - neg := false - if s[0] == '+' { - s = s[1:] - } else if s[0] == '-' { - neg = true - s = s[1:] - } - - // Convert unsigned and check range. - var un uint64 - un, err = ParseUint(s, base, bitSize) - if err != nil && err.(*NumError).Err != ErrRange { - err.(*NumError).Func = fnParseInt - err.(*NumError).Num = string(s0) - return 0, err - } - cutoff := uint64(1 << uint(bitSize-1)) - if !neg && un >= cutoff { - return int64(cutoff - 1), rangeError(fnParseInt, string(s0)) - } - if neg && un > cutoff { - return -int64(cutoff), rangeError(fnParseInt, string(s0)) - } - n := int64(un) - if neg { - n = -n - } - return n, nil -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/extfloat.go b/vendor/github.com/pquerna/ffjson/fflib/v1/internal/extfloat.go deleted file mode 100644 index ab791085a4..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/extfloat.go +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// An extFloat represents an extended floating-point number, with more -// precision than a float64. It does not try to save bits: the -// number represented by the structure is mant*(2^exp), with a negative -// sign if neg is true. -type extFloat struct { - mant uint64 - exp int - neg bool -} - -// Powers of ten taken from double-conversion library. -// http://code.google.com/p/double-conversion/ -const ( - firstPowerOfTen = -348 - stepPowerOfTen = 8 -) - -var smallPowersOfTen = [...]extFloat{ - {1 << 63, -63, false}, // 1 - {0xa << 60, -60, false}, // 1e1 - {0x64 << 57, -57, false}, // 1e2 - {0x3e8 << 54, -54, false}, // 1e3 - {0x2710 << 50, -50, false}, // 1e4 - {0x186a0 << 47, -47, false}, // 1e5 - {0xf4240 << 44, -44, false}, // 1e6 - {0x989680 << 40, -40, false}, // 1e7 -} - -var powersOfTen = [...]extFloat{ - {0xfa8fd5a0081c0288, -1220, false}, // 10^-348 - {0xbaaee17fa23ebf76, -1193, false}, // 10^-340 - {0x8b16fb203055ac76, -1166, false}, // 10^-332 - {0xcf42894a5dce35ea, -1140, false}, // 10^-324 - {0x9a6bb0aa55653b2d, -1113, false}, // 10^-316 - {0xe61acf033d1a45df, -1087, false}, // 10^-308 - {0xab70fe17c79ac6ca, -1060, false}, // 10^-300 - {0xff77b1fcbebcdc4f, -1034, false}, // 10^-292 - {0xbe5691ef416bd60c, -1007, false}, // 10^-284 - {0x8dd01fad907ffc3c, -980, false}, // 10^-276 - {0xd3515c2831559a83, -954, false}, // 10^-268 - {0x9d71ac8fada6c9b5, -927, false}, // 10^-260 - {0xea9c227723ee8bcb, -901, false}, // 10^-252 - {0xaecc49914078536d, -874, false}, // 10^-244 - {0x823c12795db6ce57, -847, false}, // 10^-236 - {0xc21094364dfb5637, -821, false}, // 10^-228 - {0x9096ea6f3848984f, -794, false}, // 10^-220 - {0xd77485cb25823ac7, -768, false}, // 10^-212 - {0xa086cfcd97bf97f4, -741, false}, // 10^-204 - {0xef340a98172aace5, -715, false}, // 10^-196 - {0xb23867fb2a35b28e, -688, false}, // 10^-188 - {0x84c8d4dfd2c63f3b, -661, false}, // 10^-180 - {0xc5dd44271ad3cdba, -635, false}, // 10^-172 - {0x936b9fcebb25c996, -608, false}, // 10^-164 - {0xdbac6c247d62a584, -582, false}, // 10^-156 - {0xa3ab66580d5fdaf6, -555, false}, // 10^-148 - {0xf3e2f893dec3f126, -529, false}, // 10^-140 - {0xb5b5ada8aaff80b8, -502, false}, // 10^-132 - {0x87625f056c7c4a8b, -475, false}, // 10^-124 - {0xc9bcff6034c13053, -449, false}, // 10^-116 - {0x964e858c91ba2655, -422, false}, // 10^-108 - {0xdff9772470297ebd, -396, false}, // 10^-100 - {0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92 - {0xf8a95fcf88747d94, -343, false}, // 10^-84 - {0xb94470938fa89bcf, -316, false}, // 10^-76 - {0x8a08f0f8bf0f156b, -289, false}, // 10^-68 - {0xcdb02555653131b6, -263, false}, // 10^-60 - {0x993fe2c6d07b7fac, -236, false}, // 10^-52 - {0xe45c10c42a2b3b06, -210, false}, // 10^-44 - {0xaa242499697392d3, -183, false}, // 10^-36 - {0xfd87b5f28300ca0e, -157, false}, // 10^-28 - {0xbce5086492111aeb, -130, false}, // 10^-20 - {0x8cbccc096f5088cc, -103, false}, // 10^-12 - {0xd1b71758e219652c, -77, false}, // 10^-4 - {0x9c40000000000000, -50, false}, // 10^4 - {0xe8d4a51000000000, -24, false}, // 10^12 - {0xad78ebc5ac620000, 3, false}, // 10^20 - {0x813f3978f8940984, 30, false}, // 10^28 - {0xc097ce7bc90715b3, 56, false}, // 10^36 - {0x8f7e32ce7bea5c70, 83, false}, // 10^44 - {0xd5d238a4abe98068, 109, false}, // 10^52 - {0x9f4f2726179a2245, 136, false}, // 10^60 - {0xed63a231d4c4fb27, 162, false}, // 10^68 - {0xb0de65388cc8ada8, 189, false}, // 10^76 - {0x83c7088e1aab65db, 216, false}, // 10^84 - {0xc45d1df942711d9a, 242, false}, // 10^92 - {0x924d692ca61be758, 269, false}, // 10^100 - {0xda01ee641a708dea, 295, false}, // 10^108 - {0xa26da3999aef774a, 322, false}, // 10^116 - {0xf209787bb47d6b85, 348, false}, // 10^124 - {0xb454e4a179dd1877, 375, false}, // 10^132 - {0x865b86925b9bc5c2, 402, false}, // 10^140 - {0xc83553c5c8965d3d, 428, false}, // 10^148 - {0x952ab45cfa97a0b3, 455, false}, // 10^156 - {0xde469fbd99a05fe3, 481, false}, // 10^164 - {0xa59bc234db398c25, 508, false}, // 10^172 - {0xf6c69a72a3989f5c, 534, false}, // 10^180 - {0xb7dcbf5354e9bece, 561, false}, // 10^188 - {0x88fcf317f22241e2, 588, false}, // 10^196 - {0xcc20ce9bd35c78a5, 614, false}, // 10^204 - {0x98165af37b2153df, 641, false}, // 10^212 - {0xe2a0b5dc971f303a, 667, false}, // 10^220 - {0xa8d9d1535ce3b396, 694, false}, // 10^228 - {0xfb9b7cd9a4a7443c, 720, false}, // 10^236 - {0xbb764c4ca7a44410, 747, false}, // 10^244 - {0x8bab8eefb6409c1a, 774, false}, // 10^252 - {0xd01fef10a657842c, 800, false}, // 10^260 - {0x9b10a4e5e9913129, 827, false}, // 10^268 - {0xe7109bfba19c0c9d, 853, false}, // 10^276 - {0xac2820d9623bf429, 880, false}, // 10^284 - {0x80444b5e7aa7cf85, 907, false}, // 10^292 - {0xbf21e44003acdd2d, 933, false}, // 10^300 - {0x8e679c2f5e44ff8f, 960, false}, // 10^308 - {0xd433179d9c8cb841, 986, false}, // 10^316 - {0x9e19db92b4e31ba9, 1013, false}, // 10^324 - {0xeb96bf6ebadf77d9, 1039, false}, // 10^332 - {0xaf87023b9bf0ee6b, 1066, false}, // 10^340 -} - -// floatBits returns the bits of the float64 that best approximates -// the extFloat passed as receiver. Overflow is set to true if -// the resulting float64 is ±Inf. -func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) { - f.Normalize() - - exp := f.exp + 63 - - // Exponent too small. - if exp < flt.bias+1 { - n := flt.bias + 1 - exp - f.mant >>= uint(n) - exp += n - } - - // Extract 1+flt.mantbits bits from the 64-bit mantissa. - mant := f.mant >> (63 - flt.mantbits) - if f.mant&(1<<(62-flt.mantbits)) != 0 { - // Round up. - mant += 1 - } - - // Rounding might have added a bit; shift down. - if mant == 2<>= 1 - exp++ - } - - // Infinities. - if exp-flt.bias >= 1<>uint(-f.exp))<>= uint(-f.exp) - f.exp = 0 - return *f, *f - } - expBiased := exp - flt.bias - - upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg} - if mant != 1<>(64-32) == 0 { - mant <<= 32 - exp -= 32 - } - if mant>>(64-16) == 0 { - mant <<= 16 - exp -= 16 - } - if mant>>(64-8) == 0 { - mant <<= 8 - exp -= 8 - } - if mant>>(64-4) == 0 { - mant <<= 4 - exp -= 4 - } - if mant>>(64-2) == 0 { - mant <<= 2 - exp -= 2 - } - if mant>>(64-1) == 0 { - mant <<= 1 - exp -= 1 - } - shift = uint(f.exp - exp) - f.mant, f.exp = mant, exp - return -} - -// Multiply sets f to the product f*g: the result is correctly rounded, -// but not normalized. -func (f *extFloat) Multiply(g extFloat) { - fhi, flo := f.mant>>32, uint64(uint32(f.mant)) - ghi, glo := g.mant>>32, uint64(uint32(g.mant)) - - // Cross products. - cross1 := fhi * glo - cross2 := flo * ghi - - // f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo - f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32) - rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32) - // Round up. - rem += (1 << 31) - - f.mant += (rem >> 32) - f.exp = f.exp + g.exp + 64 -} - -var uint64pow10 = [...]uint64{ - 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, -} - -// AssignDecimal sets f to an approximate value mantissa*10^exp. It -// returns true if the value represented by f is guaranteed to be the -// best approximation of d after being rounded to a float64 or -// float32 depending on flt. -func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) { - const uint64digits = 19 - const errorscale = 8 - errors := 0 // An upper bound for error, computed in errorscale*ulp. - if trunc { - // the decimal number was truncated. - errors += errorscale / 2 - } - - f.mant = mantissa - f.exp = 0 - f.neg = neg - - // Multiply by powers of ten. - i := (exp10 - firstPowerOfTen) / stepPowerOfTen - if exp10 < firstPowerOfTen || i >= len(powersOfTen) { - return false - } - adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen - - // We multiply by exp%step - if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] { - // We can multiply the mantissa exactly. - f.mant *= uint64pow10[adjExp] - f.Normalize() - } else { - f.Normalize() - f.Multiply(smallPowersOfTen[adjExp]) - errors += errorscale / 2 - } - - // We multiply by 10 to the exp - exp%step. - f.Multiply(powersOfTen[i]) - if errors > 0 { - errors += 1 - } - errors += errorscale / 2 - - // Normalize - shift := f.Normalize() - errors <<= shift - - // Now f is a good approximation of the decimal. - // Check whether the error is too large: that is, if the mantissa - // is perturbated by the error, the resulting float64 will change. - // The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits. - // - // In many cases the approximation will be good enough. - denormalExp := flt.bias - 63 - var extrabits uint - if f.exp <= denormalExp { - // f.mant * 2^f.exp is smaller than 2^(flt.bias+1). - extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp)) - } else { - extrabits = uint(63 - flt.mantbits) - } - - halfway := uint64(1) << (extrabits - 1) - mant_extra := f.mant & (1< expMax: - i-- - default: - break Loop - } - } - // Apply the desired decimal shift on f. It will have exponent - // in the desired range. This is multiplication by 10^-exp10. - f.Multiply(powersOfTen[i]) - - return -(firstPowerOfTen + i*stepPowerOfTen), i -} - -// frexp10Many applies a common shift by a power of ten to a, b, c. -func frexp10Many(a, b, c *extFloat) (exp10 int) { - exp10, i := c.frexp10() - a.Multiply(powersOfTen[i]) - b.Multiply(powersOfTen[i]) - return -} - -// FixedDecimal stores in d the first n significant digits -// of the decimal representation of f. It returns false -// if it cannot be sure of the answer. -func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if n == 0 { - panic("strconv: internal error: extFloat.FixedDecimal called with n == 0") - } - // Multiply by an appropriate power of ten to have a reasonable - // number to process. - f.Normalize() - exp10, _ := f.frexp10() - - shift := uint(-f.exp) - integer := uint32(f.mant >> shift) - fraction := f.mant - (uint64(integer) << shift) - ε := uint64(1) // ε is the uncertainty we have on the mantissa of f. - - // Write exactly n digits to d. - needed := n // how many digits are left to write. - integerDigits := 0 // the number of decimal digits of integer. - pow10 := uint64(1) // the power of ten by which f was scaled. - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - rest := integer - if integerDigits > needed { - // the integral part is already large, trim the last digits. - pow10 = uint64pow10[integerDigits-needed] - integer /= uint32(pow10) - rest -= integer * uint32(pow10) - } else { - rest = 0 - } - - // Write the digits of integer: the digits of rest are omitted. - var buf [32]byte - pos := len(buf) - for v := integer; v > 0; { - v1 := v / 10 - v -= 10 * v1 - pos-- - buf[pos] = byte(v + '0') - v = v1 - } - for i := pos; i < len(buf); i++ { - d.d[i-pos] = buf[i] - } - nd := len(buf) - pos - d.nd = nd - d.dp = integerDigits + exp10 - needed -= nd - - if needed > 0 { - if rest != 0 || pow10 != 1 { - panic("strconv: internal error, rest != 0 but needed > 0") - } - // Emit digits for the fractional part. Each time, 10*fraction - // fits in a uint64 without overflow. - for needed > 0 { - fraction *= 10 - ε *= 10 // the uncertainty scales as we multiply by ten. - if 2*ε > 1<> shift - d.d[nd] = byte(digit + '0') - fraction -= digit << shift - nd++ - needed-- - } - d.nd = nd - } - - // We have written a truncation of f (a numerator / 10^d.dp). The remaining part - // can be interpreted as a small number (< 1) to be added to the last digit of the - // numerator. - // - // If rest > 0, the amount is: - // (rest< 0 guarantees that pow10 << shift does not overflow a uint64. - // - // If rest = 0, pow10 == 1 and the amount is - // fraction / (1 << shift) - // fraction being known with a ±ε uncertainty. - // - // We pass this information to the rounding routine for adjustment. - - ok := adjustLastDigitFixed(d, uint64(rest)<= 0; i-- { - if d.d[i] != '0' { - d.nd = i + 1 - break - } - } - return true -} - -// adjustLastDigitFixed assumes d contains the representation of the integral part -// of some number, whose fractional part is num / (den << shift). The numerator -// num is only known up to an uncertainty of size ε, assumed to be less than -// (den << shift)/2. -// -// It will increase the last digit by one to account for correct rounding, typically -// when the fractional part is greater than 1/2, and will return false if ε is such -// that no correct answer can be given. -func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool { - if num > den< den< den< (den< den<= 0; i-- { - if d.d[i] == '9' { - d.nd-- - } else { - break - } - } - if i < 0 { - d.d[0] = '1' - d.nd = 1 - d.dp++ - } else { - d.d[i]++ - } - return true - } - return false -} - -// ShortestDecimal stores in d the shortest decimal representation of f -// which belongs to the open interval (lower, upper), where f is supposed -// to lie. It returns false whenever the result is unsure. The implementation -// uses the Grisu3 algorithm. -func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if f.exp == 0 && *lower == *f && *lower == *upper { - // an exact integer. - var buf [24]byte - n := len(buf) - 1 - for v := f.mant; v > 0; { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n-- - v = v1 - } - nd := len(buf) - n - 1 - for i := 0; i < nd; i++ { - d.d[i] = buf[n+1+i] - } - d.nd, d.dp = nd, nd - for d.nd > 0 && d.d[d.nd-1] == '0' { - d.nd-- - } - if d.nd == 0 { - d.dp = 0 - } - d.neg = f.neg - return true - } - upper.Normalize() - // Uniformize exponents. - if f.exp > upper.exp { - f.mant <<= uint(f.exp - upper.exp) - f.exp = upper.exp - } - if lower.exp > upper.exp { - lower.mant <<= uint(lower.exp - upper.exp) - lower.exp = upper.exp - } - - exp10 := frexp10Many(lower, f, upper) - // Take a safety margin due to rounding in frexp10Many, but we lose precision. - upper.mant++ - lower.mant-- - - // The shortest representation of f is either rounded up or down, but - // in any case, it is a truncation of upper. - shift := uint(-upper.exp) - integer := uint32(upper.mant >> shift) - fraction := upper.mant - (uint64(integer) << shift) - - // How far we can go down from upper until the result is wrong. - allowance := upper.mant - lower.mant - // How far we should go to get a very precise result. - targetDiff := upper.mant - f.mant - - // Count integral digits: there are at most 10. - var integerDigits int - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - for i := 0; i < integerDigits; i++ { - pow := uint64pow10[integerDigits-i-1] - digit := integer / uint32(pow) - d.d[i] = byte(digit + '0') - integer -= digit * uint32(pow) - // evaluate whether we should stop. - if currentDiff := uint64(integer)<> shift) - d.d[d.nd] = byte(digit + '0') - d.nd++ - fraction -= uint64(digit) << shift - if fraction < allowance*multiplier { - // We are in the admissible range. Note that if allowance is about to - // overflow, that is, allowance > 2^64/10, the condition is automatically - // true due to the limited range of fraction. - return adjustLastDigit(d, - fraction, targetDiff*multiplier, allowance*multiplier, - 1< maxDiff-ulpBinary { - // we went too far - return false - } - if d.nd == 1 && d.d[0] == '0' { - // the number has actually reached zero. - d.nd = 0 - d.dp = 0 - } - return true -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/ftoa.go b/vendor/github.com/pquerna/ffjson/fflib/v1/internal/ftoa.go deleted file mode 100644 index 253f83b45a..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/internal/ftoa.go +++ /dev/null @@ -1,475 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Binary to decimal floating point conversion. -// Algorithm: -// 1) store mantissa in multiprecision decimal -// 2) shift decimal by exponent -// 3) read digits out & format - -package internal - -import "math" - -// TODO: move elsewhere? -type floatInfo struct { - mantbits uint - expbits uint - bias int -} - -var float32info = floatInfo{23, 8, -127} -var float64info = floatInfo{52, 11, -1023} - -// FormatFloat converts the floating-point number f to a string, -// according to the format fmt and precision prec. It rounds the -// result assuming that the original was obtained from a floating-point -// value of bitSize bits (32 for float32, 64 for float64). -// -// The format fmt is one of -// 'b' (-ddddp±ddd, a binary exponent), -// 'e' (-d.dddde±dd, a decimal exponent), -// 'E' (-d.ddddE±dd, a decimal exponent), -// 'f' (-ddd.dddd, no exponent), -// 'g' ('e' for large exponents, 'f' otherwise), or -// 'G' ('E' for large exponents, 'f' otherwise). -// -// The precision prec controls the number of digits -// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats. -// For 'e', 'E', and 'f' it is the number of digits after the decimal point. -// For 'g' and 'G' it is the total number of digits. -// The special precision -1 uses the smallest number of digits -// necessary such that ParseFloat will return f exactly. -func formatFloat(f float64, fmt byte, prec, bitSize int) string { - return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) -} - -// AppendFloat appends the string form of the floating-point number f, -// as generated by FormatFloat, to dst and returns the extended buffer. -func appendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte { - return genericFtoa(dst, f, fmt, prec, bitSize) -} - -func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { - var bits uint64 - var flt *floatInfo - switch bitSize { - case 32: - bits = uint64(math.Float32bits(float32(val))) - flt = &float32info - case 64: - bits = math.Float64bits(val) - flt = &float64info - default: - panic("strconv: illegal AppendFloat/FormatFloat bitSize") - } - - neg := bits>>(flt.expbits+flt.mantbits) != 0 - exp := int(bits>>flt.mantbits) & (1< digs.nd && digs.nd >= digs.dp { - eprec = digs.nd - } - // %e is used if the exponent from the conversion - // is less than -4 or greater than or equal to the precision. - // if precision was the shortest possible, use precision 6 for this decision. - if shortest { - eprec = 6 - } - exp := digs.dp - 1 - if exp < -4 || exp >= eprec { - if prec > digs.nd { - prec = digs.nd - } - return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') - } - if prec > digs.dp { - prec = digs.nd - } - return fmtF(dst, neg, digs, max(prec-digs.dp, 0)) - } - - // unknown format - return append(dst, '%', fmt) -} - -// Round d (= mant * 2^exp) to the shortest number of digits -// that will let the original floating point value be precisely -// reconstructed. Size is original floating point size (64 or 32). -func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { - // If mantissa is zero, the number is zero; stop now. - if mant == 0 { - d.nd = 0 - return - } - - // Compute upper and lower such that any decimal number - // between upper and lower (possibly inclusive) - // will round to the original floating point number. - - // We may see at once that the number is already shortest. - // - // Suppose d is not denormal, so that 2^exp <= d < 10^dp. - // The closest shorter number is at least 10^(dp-nd) away. - // The lower/upper bounds computed below are at distance - // at most 2^(exp-mantbits). - // - // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), - // or equivalently log2(10)*(dp-nd) > exp-mantbits. - // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). - minexp := flt.bias + 1 // minimum possible exponent - if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { - // The number is already shortest. - return - } - - // d = mant << (exp - mantbits) - // Next highest floating point number is mant+1 << exp-mantbits. - // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. - upper := new(decimal) - upper.Assign(mant*2 + 1) - upper.Shift(exp - int(flt.mantbits) - 1) - - // d = mant << (exp - mantbits) - // Next lowest floating point number is mant-1 << exp-mantbits, - // unless mant-1 drops the significant bit and exp is not the minimum exp, - // in which case the next lowest is mant*2-1 << exp-mantbits-1. - // Either way, call it mantlo << explo-mantbits. - // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. - var mantlo uint64 - var explo int - if mant > 1< 0 { - dst = append(dst, '.') - i := 1 - m := d.nd + prec + 1 - max(d.nd, prec+1) - for i < m { - dst = append(dst, d.d[i]) - i++ - } - for i <= prec { - dst = append(dst, '0') - i++ - } - } - - // e± - dst = append(dst, fmt) - exp := d.dp - 1 - if d.nd == 0 { // special case: 0 has exponent 0 - exp = 0 - } - if exp < 0 { - ch = '-' - exp = -exp - } else { - ch = '+' - } - dst = append(dst, ch) - - // dddd - var buf [3]byte - i := len(buf) - for exp >= 10 { - i-- - buf[i] = byte(exp%10 + '0') - exp /= 10 - } - // exp < 10 - i-- - buf[i] = byte(exp + '0') - - switch i { - case 0: - dst = append(dst, buf[0], buf[1], buf[2]) - case 1: - dst = append(dst, buf[1], buf[2]) - case 2: - // leading zeroes - dst = append(dst, '0', buf[2]) - } - return dst -} - -// %f: -ddddddd.ddddd -func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte { - // sign - if neg { - dst = append(dst, '-') - } - - // integer, padded with zeros as needed. - if d.dp > 0 { - var i int - for i = 0; i < d.dp && i < d.nd; i++ { - dst = append(dst, d.d[i]) - } - for ; i < d.dp; i++ { - dst = append(dst, '0') - } - } else { - dst = append(dst, '0') - } - - // fraction - if prec > 0 { - dst = append(dst, '.') - for i := 0; i < prec; i++ { - ch := byte('0') - if j := d.dp + i; 0 <= j && j < d.nd { - ch = d.d[j] - } - dst = append(dst, ch) - } - } - - return dst -} - -// %b: -ddddddddp+ddd -func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { - var buf [50]byte - w := len(buf) - exp -= int(flt.mantbits) - esign := byte('+') - if exp < 0 { - esign = '-' - exp = -exp - } - n := 0 - for exp > 0 || n < 1 { - n++ - w-- - buf[w] = byte(exp%10 + '0') - exp /= 10 - } - w-- - buf[w] = esign - w-- - buf[w] = 'p' - n = 0 - for mant > 0 || n < 1 { - n++ - w-- - buf[w] = byte(mant%10 + '0') - mant /= 10 - } - if neg { - w-- - buf[w] = '-' - } - return append(dst, buf[w:]...) -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/iota.go b/vendor/github.com/pquerna/ffjson/fflib/v1/iota.go deleted file mode 100644 index 3e50f0c418..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/iota.go +++ /dev/null @@ -1,161 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's strconv/iota.go */ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -import ( - "io" -) - -const ( - digits = "0123456789abcdefghijklmnopqrstuvwxyz" - digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" - digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" -) - -var shifts = [len(digits) + 1]uint{ - 1 << 1: 1, - 1 << 2: 2, - 1 << 3: 3, - 1 << 4: 4, - 1 << 5: 5, -} - -var smallNumbers = [][]byte{ - []byte("0"), - []byte("1"), - []byte("2"), - []byte("3"), - []byte("4"), - []byte("5"), - []byte("6"), - []byte("7"), - []byte("8"), - []byte("9"), - []byte("10"), -} - -type FormatBitsWriter interface { - io.Writer - io.ByteWriter -} - -type FormatBitsScratch struct{} - -// -// DEPRECIATED: `scratch` is no longer used, FormatBits2 is available. -// -// FormatBits computes the string representation of u in the given base. -// If neg is set, u is treated as negative int64 value. If append_ is -// set, the string is appended to dst and the resulting byte slice is -// returned as the first result value; otherwise the string is returned -// as the second result value. -// -func FormatBits(scratch *FormatBitsScratch, dst FormatBitsWriter, u uint64, base int, neg bool) { - FormatBits2(dst, u, base, neg) -} - -// FormatBits2 computes the string representation of u in the given base. -// If neg is set, u is treated as negative int64 value. If append_ is -// set, the string is appended to dst and the resulting byte slice is -// returned as the first result value; otherwise the string is returned -// as the second result value. -// -func FormatBits2(dst FormatBitsWriter, u uint64, base int, neg bool) { - if base < 2 || base > len(digits) { - panic("strconv: illegal AppendInt/FormatInt base") - } - // fast path for small common numbers - if u <= 10 { - if neg { - dst.WriteByte('-') - } - dst.Write(smallNumbers[u]) - return - } - - // 2 <= base && base <= len(digits) - - var a = makeSlice(65) - // var a [64 + 1]byte // +1 for sign of 64bit value in base 2 - i := len(a) - - if neg { - u = -u - } - - // convert bits - if base == 10 { - // common case: use constants for / and % because - // the compiler can optimize it into a multiply+shift, - // and unroll loop - for u >= 100 { - i -= 2 - q := u / 100 - j := uintptr(u - q*100) - a[i+1] = digits01[j] - a[i+0] = digits10[j] - u = q - } - if u >= 10 { - i-- - q := u / 10 - a[i] = digits[uintptr(u-q*10)] - u = q - } - - } else if s := shifts[base]; s > 0 { - // base is power of 2: use shifts and masks instead of / and % - b := uint64(base) - m := uintptr(b) - 1 // == 1<= b { - i-- - a[i] = digits[uintptr(u)&m] - u >>= s - } - - } else { - // general case - b := uint64(base) - for u >= b { - i-- - a[i] = digits[uintptr(u%b)] - u /= b - } - } - - // u < base - i-- - a[i] = digits[uintptr(u)] - - // add sign, if any - if neg { - i-- - a[i] = '-' - } - - dst.Write(a[i:]) - - Pool(a) - - return -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/jsonstring.go b/vendor/github.com/pquerna/ffjson/fflib/v1/jsonstring.go deleted file mode 100644 index 513b45d570..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/jsonstring.go +++ /dev/null @@ -1,512 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on Go stdlib's encoding/json/encode.go */ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package v1 - -import ( - "io" - "unicode/utf8" - "strconv" - "unicode/utf16" - "unicode" -) - -const hex = "0123456789abcdef" - -type JsonStringWriter interface { - io.Writer - io.ByteWriter - stringWriter -} - -func WriteJsonString(buf JsonStringWriter, s string) { - WriteJson(buf, []byte(s)) -} - -/** - * Function ported from encoding/json: func (e *encodeState) string(s string) (int, error) - */ -func WriteJson(buf JsonStringWriter, s []byte) { - buf.WriteByte('"') - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - /* - if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { - i++ - continue - } - */ - if lt[b] == true { - i++ - continue - } - - if start < i { - buf.Write(s[start:i]) - } - switch b { - case '\\', '"': - buf.WriteByte('\\') - buf.WriteByte(b) - case '\n': - buf.WriteByte('\\') - buf.WriteByte('n') - case '\r': - buf.WriteByte('\\') - buf.WriteByte('r') - default: - // This encodes bytes < 0x20 except for \n and \r, - // as well as < and >. The latter are escaped because they - // can lead to security holes when user-controlled strings - // are rendered into JSON and served to some browsers. - buf.WriteString(`\u00`) - buf.WriteByte(hex[b>>4]) - buf.WriteByte(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRune(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - buf.Write(s[start:i]) - } - buf.WriteString(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - buf.Write(s[start:i]) - } - buf.WriteString(`\u202`) - buf.WriteByte(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - buf.Write(s[start:]) - } - buf.WriteByte('"') -} - -// UnquoteBytes will decode []byte containing json string to go string -// ported from encoding/json/decode.go -func UnquoteBytes(s []byte) (t []byte, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - s = s[1 : len(s)-1] - - // Check for unusual characters. If there are none, - // then no unquoting is needed, so return a slice of the - // original bytes. - r := 0 - for r < len(s) { - c := s[r] - if c == '\\' || c == '"' || c < ' ' { - break - } - if c < utf8.RuneSelf { - r++ - continue - } - rr, size := utf8.DecodeRune(s[r:]) - if rr == utf8.RuneError && size == 1 { - break - } - r += size - } - if r == len(s) { - return s, true - } - - b := make([]byte, len(s)+2*utf8.UTFMax) - w := copy(b, s[0:r]) - for r < len(s) { - // Out of room? Can only happen if s is full of - // malformed UTF-8 and we're replacing each - // byte with RuneError. - if w >= len(b)-2*utf8.UTFMax { - nb := make([]byte, (len(b)+utf8.UTFMax)*2) - copy(nb, b[0:w]) - b = nb - } - switch c := s[r]; { - case c == '\\': - r++ - if r >= len(s) { - return - } - switch s[r] { - default: - return - case '"', '\\', '/', '\'': - b[w] = s[r] - r++ - w++ - case 'b': - b[w] = '\b' - r++ - w++ - case 'f': - b[w] = '\f' - r++ - w++ - case 'n': - b[w] = '\n' - r++ - w++ - case 'r': - b[w] = '\r' - r++ - w++ - case 't': - b[w] = '\t' - r++ - w++ - case 'u': - r-- - rr := getu4(s[r:]) - if rr < 0 { - return - } - r += 6 - if utf16.IsSurrogate(rr) { - rr1 := getu4(s[r:]) - if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { - // A valid pair; consume. - r += 6 - w += utf8.EncodeRune(b[w:], dec) - break - } - // Invalid surrogate; fall back to replacement rune. - rr = unicode.ReplacementChar - } - w += utf8.EncodeRune(b[w:], rr) - } - - // Quote, control characters are invalid. - case c == '"', c < ' ': - return - - // ASCII - case c < utf8.RuneSelf: - b[w] = c - r++ - w++ - - // Coerce to well-formed UTF-8. - default: - rr, size := utf8.DecodeRune(s[r:]) - r += size - w += utf8.EncodeRune(b[w:], rr) - } - } - return b[0:w], true -} - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) rune { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - r, err := strconv.ParseUint(string(s[2:6]), 16, 64) - if err != nil { - return -1 - } - return rune(r) -} - -// TODO(pquerna): consider combining wibth the normal byte mask. -var lt [256]bool = [256]bool{ - false, /* 0 */ - false, /* 1 */ - false, /* 2 */ - false, /* 3 */ - false, /* 4 */ - false, /* 5 */ - false, /* 6 */ - false, /* 7 */ - false, /* 8 */ - false, /* 9 */ - false, /* 10 */ - false, /* 11 */ - false, /* 12 */ - false, /* 13 */ - false, /* 14 */ - false, /* 15 */ - false, /* 16 */ - false, /* 17 */ - false, /* 18 */ - false, /* 19 */ - false, /* 20 */ - false, /* 21 */ - false, /* 22 */ - false, /* 23 */ - false, /* 24 */ - false, /* 25 */ - false, /* 26 */ - false, /* 27 */ - false, /* 28 */ - false, /* 29 */ - false, /* 30 */ - false, /* 31 */ - true, /* 32 */ - true, /* 33 */ - false, /* 34 */ - true, /* 35 */ - true, /* 36 */ - true, /* 37 */ - false, /* 38 */ - true, /* 39 */ - true, /* 40 */ - true, /* 41 */ - true, /* 42 */ - true, /* 43 */ - true, /* 44 */ - true, /* 45 */ - true, /* 46 */ - true, /* 47 */ - true, /* 48 */ - true, /* 49 */ - true, /* 50 */ - true, /* 51 */ - true, /* 52 */ - true, /* 53 */ - true, /* 54 */ - true, /* 55 */ - true, /* 56 */ - true, /* 57 */ - true, /* 58 */ - true, /* 59 */ - false, /* 60 */ - true, /* 61 */ - false, /* 62 */ - true, /* 63 */ - true, /* 64 */ - true, /* 65 */ - true, /* 66 */ - true, /* 67 */ - true, /* 68 */ - true, /* 69 */ - true, /* 70 */ - true, /* 71 */ - true, /* 72 */ - true, /* 73 */ - true, /* 74 */ - true, /* 75 */ - true, /* 76 */ - true, /* 77 */ - true, /* 78 */ - true, /* 79 */ - true, /* 80 */ - true, /* 81 */ - true, /* 82 */ - true, /* 83 */ - true, /* 84 */ - true, /* 85 */ - true, /* 86 */ - true, /* 87 */ - true, /* 88 */ - true, /* 89 */ - true, /* 90 */ - true, /* 91 */ - false, /* 92 */ - true, /* 93 */ - true, /* 94 */ - true, /* 95 */ - true, /* 96 */ - true, /* 97 */ - true, /* 98 */ - true, /* 99 */ - true, /* 100 */ - true, /* 101 */ - true, /* 102 */ - true, /* 103 */ - true, /* 104 */ - true, /* 105 */ - true, /* 106 */ - true, /* 107 */ - true, /* 108 */ - true, /* 109 */ - true, /* 110 */ - true, /* 111 */ - true, /* 112 */ - true, /* 113 */ - true, /* 114 */ - true, /* 115 */ - true, /* 116 */ - true, /* 117 */ - true, /* 118 */ - true, /* 119 */ - true, /* 120 */ - true, /* 121 */ - true, /* 122 */ - true, /* 123 */ - true, /* 124 */ - true, /* 125 */ - true, /* 126 */ - true, /* 127 */ - true, /* 128 */ - true, /* 129 */ - true, /* 130 */ - true, /* 131 */ - true, /* 132 */ - true, /* 133 */ - true, /* 134 */ - true, /* 135 */ - true, /* 136 */ - true, /* 137 */ - true, /* 138 */ - true, /* 139 */ - true, /* 140 */ - true, /* 141 */ - true, /* 142 */ - true, /* 143 */ - true, /* 144 */ - true, /* 145 */ - true, /* 146 */ - true, /* 147 */ - true, /* 148 */ - true, /* 149 */ - true, /* 150 */ - true, /* 151 */ - true, /* 152 */ - true, /* 153 */ - true, /* 154 */ - true, /* 155 */ - true, /* 156 */ - true, /* 157 */ - true, /* 158 */ - true, /* 159 */ - true, /* 160 */ - true, /* 161 */ - true, /* 162 */ - true, /* 163 */ - true, /* 164 */ - true, /* 165 */ - true, /* 166 */ - true, /* 167 */ - true, /* 168 */ - true, /* 169 */ - true, /* 170 */ - true, /* 171 */ - true, /* 172 */ - true, /* 173 */ - true, /* 174 */ - true, /* 175 */ - true, /* 176 */ - true, /* 177 */ - true, /* 178 */ - true, /* 179 */ - true, /* 180 */ - true, /* 181 */ - true, /* 182 */ - true, /* 183 */ - true, /* 184 */ - true, /* 185 */ - true, /* 186 */ - true, /* 187 */ - true, /* 188 */ - true, /* 189 */ - true, /* 190 */ - true, /* 191 */ - true, /* 192 */ - true, /* 193 */ - true, /* 194 */ - true, /* 195 */ - true, /* 196 */ - true, /* 197 */ - true, /* 198 */ - true, /* 199 */ - true, /* 200 */ - true, /* 201 */ - true, /* 202 */ - true, /* 203 */ - true, /* 204 */ - true, /* 205 */ - true, /* 206 */ - true, /* 207 */ - true, /* 208 */ - true, /* 209 */ - true, /* 210 */ - true, /* 211 */ - true, /* 212 */ - true, /* 213 */ - true, /* 214 */ - true, /* 215 */ - true, /* 216 */ - true, /* 217 */ - true, /* 218 */ - true, /* 219 */ - true, /* 220 */ - true, /* 221 */ - true, /* 222 */ - true, /* 223 */ - true, /* 224 */ - true, /* 225 */ - true, /* 226 */ - true, /* 227 */ - true, /* 228 */ - true, /* 229 */ - true, /* 230 */ - true, /* 231 */ - true, /* 232 */ - true, /* 233 */ - true, /* 234 */ - true, /* 235 */ - true, /* 236 */ - true, /* 237 */ - true, /* 238 */ - true, /* 239 */ - true, /* 240 */ - true, /* 241 */ - true, /* 242 */ - true, /* 243 */ - true, /* 244 */ - true, /* 245 */ - true, /* 246 */ - true, /* 247 */ - true, /* 248 */ - true, /* 249 */ - true, /* 250 */ - true, /* 251 */ - true, /* 252 */ - true, /* 253 */ - true, /* 254 */ - true, /* 255 */ -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/lexer.go b/vendor/github.com/pquerna/ffjson/fflib/v1/lexer.go deleted file mode 100644 index 8ffd54be53..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/lexer.go +++ /dev/null @@ -1,937 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Portions of this file are on derived from yajl: */ -/* - * Copyright (c) 2007-2014, Lloyd Hilaiel - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package v1 - -import ( - "errors" - "fmt" - "io" -) - -type FFParseState int - -const ( - FFParse_map_start FFParseState = iota - FFParse_want_key - FFParse_want_colon - FFParse_want_value - FFParse_after_value -) - -type FFTok int - -const ( - FFTok_init FFTok = iota - FFTok_bool FFTok = iota - FFTok_colon FFTok = iota - FFTok_comma FFTok = iota - FFTok_eof FFTok = iota - FFTok_error FFTok = iota - FFTok_left_brace FFTok = iota - FFTok_left_bracket FFTok = iota - FFTok_null FFTok = iota - FFTok_right_brace FFTok = iota - FFTok_right_bracket FFTok = iota - - /* we differentiate between integers and doubles to allow the - * parser to interpret the number without re-scanning */ - FFTok_integer FFTok = iota - FFTok_double FFTok = iota - - FFTok_string FFTok = iota - - /* comment tokens are not currently returned to the parser, ever */ - FFTok_comment FFTok = iota -) - -type FFErr int - -const ( - FFErr_e_ok FFErr = iota - FFErr_io FFErr = iota - FFErr_string_invalid_utf8 FFErr = iota - FFErr_string_invalid_escaped_char FFErr = iota - FFErr_string_invalid_json_char FFErr = iota - FFErr_string_invalid_hex_char FFErr = iota - FFErr_invalid_char FFErr = iota - FFErr_invalid_string FFErr = iota - FFErr_missing_integer_after_decimal FFErr = iota - FFErr_missing_integer_after_exponent FFErr = iota - FFErr_missing_integer_after_minus FFErr = iota - FFErr_unallowed_comment FFErr = iota - FFErr_incomplete_comment FFErr = iota - FFErr_unexpected_token_type FFErr = iota // TODO: improve this error -) - -type FFLexer struct { - reader *ffReader - Output DecodingBuffer - Token FFTok - Error FFErr - BigError error - // TODO: convert all of this to an interface - lastCurrentChar int - captureAll bool - buf Buffer -} - -func NewFFLexer(input []byte) *FFLexer { - fl := &FFLexer{ - Token: FFTok_init, - Error: FFErr_e_ok, - reader: newffReader(input), - Output: &Buffer{}, - } - // TODO: guess size? - //fl.Output.Grow(64) - return fl -} - -type LexerError struct { - offset int - line int - char int - err error -} - -// Reset the Lexer and add new input. -func (ffl *FFLexer) Reset(input []byte) { - ffl.Token = FFTok_init - ffl.Error = FFErr_e_ok - ffl.BigError = nil - ffl.reader.Reset(input) - ffl.lastCurrentChar = 0 - ffl.Output.Reset() -} - -func (le *LexerError) Error() string { - return fmt.Sprintf(`ffjson error: (%T)%s offset=%d line=%d char=%d`, - le.err, le.err.Error(), - le.offset, le.line, le.char) -} - -func (ffl *FFLexer) WrapErr(err error) error { - line, char := ffl.reader.PosWithLine() - // TOOD: calcualte lines/characters based on offset - return &LexerError{ - offset: ffl.reader.Pos(), - line: line, - char: char, - err: err, - } -} - -func (ffl *FFLexer) scanReadByte() (byte, error) { - var c byte - var err error - if ffl.captureAll { - c, err = ffl.reader.ReadByte() - } else { - c, err = ffl.reader.ReadByteNoWS() - } - - if err != nil { - ffl.Error = FFErr_io - ffl.BigError = err - return 0, err - } - - return c, nil -} - -func (ffl *FFLexer) readByte() (byte, error) { - - c, err := ffl.reader.ReadByte() - if err != nil { - ffl.Error = FFErr_io - ffl.BigError = err - return 0, err - } - - return c, nil -} - -func (ffl *FFLexer) unreadByte() { - ffl.reader.UnreadByte() -} - -func (ffl *FFLexer) wantBytes(want []byte, iftrue FFTok) FFTok { - startPos := ffl.reader.Pos() - for _, b := range want { - c, err := ffl.readByte() - - if err != nil { - return FFTok_error - } - - if c != b { - ffl.unreadByte() - // fmt.Printf("wanted bytes: %s\n", string(want)) - // TODO(pquerna): thsi is a bad error message - ffl.Error = FFErr_invalid_string - return FFTok_error - } - } - - endPos := ffl.reader.Pos() - ffl.Output.Write(ffl.reader.Slice(startPos, endPos)) - return iftrue -} - -func (ffl *FFLexer) lexComment() FFTok { - c, err := ffl.readByte() - if err != nil { - return FFTok_error - } - - if c == '/' { - // a // comment, scan until line ends. - for { - c, err := ffl.readByte() - if err != nil { - return FFTok_error - } - - if c == '\n' { - return FFTok_comment - } - } - } else if c == '*' { - // a /* */ comment, scan */ - for { - c, err := ffl.readByte() - if err != nil { - return FFTok_error - } - - if c == '*' { - c, err := ffl.readByte() - - if err != nil { - return FFTok_error - } - - if c == '/' { - return FFTok_comment - } - - ffl.Error = FFErr_incomplete_comment - return FFTok_error - } - } - } else { - ffl.Error = FFErr_incomplete_comment - return FFTok_error - } -} - -func (ffl *FFLexer) lexString() FFTok { - if ffl.captureAll { - ffl.buf.Reset() - err := ffl.reader.SliceString(&ffl.buf) - - if err != nil { - ffl.BigError = err - return FFTok_error - } - - WriteJson(ffl.Output, ffl.buf.Bytes()) - - return FFTok_string - } else { - err := ffl.reader.SliceString(ffl.Output) - - if err != nil { - ffl.BigError = err - return FFTok_error - } - - return FFTok_string - } -} - -func (ffl *FFLexer) lexNumber() FFTok { - var numRead int = 0 - tok := FFTok_integer - startPos := ffl.reader.Pos() - - c, err := ffl.readByte() - if err != nil { - return FFTok_error - } - - /* optional leading minus */ - if c == '-' { - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } - - /* a single zero, or a series of integers */ - if c == '0' { - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } else if c >= '1' && c <= '9' { - for c >= '0' && c <= '9' { - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } - } else { - ffl.unreadByte() - ffl.Error = FFErr_missing_integer_after_minus - return FFTok_error - } - - if c == '.' { - numRead = 0 - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - - for c >= '0' && c <= '9' { - numRead++ - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } - - if numRead == 0 { - ffl.unreadByte() - - ffl.Error = FFErr_missing_integer_after_decimal - return FFTok_error - } - - tok = FFTok_double - } - - /* optional exponent (indicates this is floating point) */ - if c == 'e' || c == 'E' { - numRead = 0 - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - - /* optional sign */ - if c == '+' || c == '-' { - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } - - for c >= '0' && c <= '9' { - numRead++ - c, err = ffl.readByte() - if err != nil { - return FFTok_error - } - } - - if numRead == 0 { - ffl.Error = FFErr_missing_integer_after_exponent - return FFTok_error - } - - tok = FFTok_double - } - - ffl.unreadByte() - - endPos := ffl.reader.Pos() - ffl.Output.Write(ffl.reader.Slice(startPos, endPos)) - return tok -} - -var true_bytes = []byte{'r', 'u', 'e'} -var false_bytes = []byte{'a', 'l', 's', 'e'} -var null_bytes = []byte{'u', 'l', 'l'} - -func (ffl *FFLexer) Scan() FFTok { - tok := FFTok_error - if ffl.captureAll == false { - ffl.Output.Reset() - } - ffl.Token = FFTok_init - - for { - c, err := ffl.scanReadByte() - if err != nil { - if err == io.EOF { - return FFTok_eof - } else { - return FFTok_error - } - } - - switch c { - case '{': - tok = FFTok_left_bracket - if ffl.captureAll { - ffl.Output.WriteByte('{') - } - goto lexed - case '}': - tok = FFTok_right_bracket - if ffl.captureAll { - ffl.Output.WriteByte('}') - } - goto lexed - case '[': - tok = FFTok_left_brace - if ffl.captureAll { - ffl.Output.WriteByte('[') - } - goto lexed - case ']': - tok = FFTok_right_brace - if ffl.captureAll { - ffl.Output.WriteByte(']') - } - goto lexed - case ',': - tok = FFTok_comma - if ffl.captureAll { - ffl.Output.WriteByte(',') - } - goto lexed - case ':': - tok = FFTok_colon - if ffl.captureAll { - ffl.Output.WriteByte(':') - } - goto lexed - case '\t', '\n', '\v', '\f', '\r', ' ': - if ffl.captureAll { - ffl.Output.WriteByte(c) - } - break - case 't': - ffl.Output.WriteByte('t') - tok = ffl.wantBytes(true_bytes, FFTok_bool) - goto lexed - case 'f': - ffl.Output.WriteByte('f') - tok = ffl.wantBytes(false_bytes, FFTok_bool) - goto lexed - case 'n': - ffl.Output.WriteByte('n') - tok = ffl.wantBytes(null_bytes, FFTok_null) - goto lexed - case '"': - tok = ffl.lexString() - goto lexed - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - ffl.unreadByte() - tok = ffl.lexNumber() - goto lexed - case '/': - tok = ffl.lexComment() - goto lexed - default: - tok = FFTok_error - ffl.Error = FFErr_invalid_char - } - } - -lexed: - ffl.Token = tok - return tok -} - -func (ffl *FFLexer) scanField(start FFTok, capture bool) ([]byte, error) { - switch start { - case FFTok_left_brace, - FFTok_left_bracket: - { - end := FFTok_right_brace - if start == FFTok_left_bracket { - end = FFTok_right_bracket - if capture { - ffl.Output.WriteByte('{') - } - } else { - if capture { - ffl.Output.WriteByte('[') - } - } - - depth := 1 - if capture { - ffl.captureAll = true - } - // TODO: work. - scanloop: - for { - tok := ffl.Scan() - //fmt.Printf("capture-token: %v end: %v depth: %v\n", tok, end, depth) - switch tok { - case FFTok_eof: - return nil, errors.New("ffjson: unexpected EOF") - case FFTok_error: - if ffl.BigError != nil { - return nil, ffl.BigError - } - return nil, ffl.Error.ToError() - case end: - depth-- - if depth == 0 { - break scanloop - } - case start: - depth++ - } - } - - if capture { - ffl.captureAll = false - } - - if capture { - return ffl.Output.Bytes(), nil - } else { - return nil, nil - } - } - case FFTok_bool, - FFTok_integer, - FFTok_null, - FFTok_double: - // simple value, return it. - if capture { - return ffl.Output.Bytes(), nil - } else { - return nil, nil - } - - case FFTok_string: - //TODO(pquerna): so, other users expect this to be a quoted string :( - if capture { - ffl.buf.Reset() - WriteJson(&ffl.buf, ffl.Output.Bytes()) - return ffl.buf.Bytes(), nil - } else { - return nil, nil - } - } - - return nil, fmt.Errorf("ffjson: invalid capture type: %v", start) -} - -// Captures an entire field value, including recursive objects, -// and converts them to a []byte suitable to pass to a sub-object's -// UnmarshalJSON -func (ffl *FFLexer) CaptureField(start FFTok) ([]byte, error) { - return ffl.scanField(start, true) -} - -func (ffl *FFLexer) SkipField(start FFTok) error { - _, err := ffl.scanField(start, false) - return err -} - -// TODO(pquerna): return line number and offset. -func (err FFErr) ToError() error { - switch err { - case FFErr_e_ok: - return nil - case FFErr_io: - return errors.New("ffjson: IO error") - case FFErr_string_invalid_utf8: - return errors.New("ffjson: string with invalid UTF-8 sequence") - case FFErr_string_invalid_escaped_char: - return errors.New("ffjson: string with invalid escaped character") - case FFErr_string_invalid_json_char: - return errors.New("ffjson: string with invalid JSON character") - case FFErr_string_invalid_hex_char: - return errors.New("ffjson: string with invalid hex character") - case FFErr_invalid_char: - return errors.New("ffjson: invalid character") - case FFErr_invalid_string: - return errors.New("ffjson: invalid string") - case FFErr_missing_integer_after_decimal: - return errors.New("ffjson: missing integer after decimal") - case FFErr_missing_integer_after_exponent: - return errors.New("ffjson: missing integer after exponent") - case FFErr_missing_integer_after_minus: - return errors.New("ffjson: missing integer after minus") - case FFErr_unallowed_comment: - return errors.New("ffjson: unallowed comment") - case FFErr_incomplete_comment: - return errors.New("ffjson: incomplete comment") - case FFErr_unexpected_token_type: - return errors.New("ffjson: unexpected token sequence") - } - - panic(fmt.Sprintf("unknown error type: %v ", err)) -} - -func (state FFParseState) String() string { - switch state { - case FFParse_map_start: - return "map:start" - case FFParse_want_key: - return "want_key" - case FFParse_want_colon: - return "want_colon" - case FFParse_want_value: - return "want_value" - case FFParse_after_value: - return "after_value" - } - - panic(fmt.Sprintf("unknown parse state: %d", int(state))) -} - -func (tok FFTok) String() string { - switch tok { - case FFTok_init: - return "tok:init" - case FFTok_bool: - return "tok:bool" - case FFTok_colon: - return "tok:colon" - case FFTok_comma: - return "tok:comma" - case FFTok_eof: - return "tok:eof" - case FFTok_error: - return "tok:error" - case FFTok_left_brace: - return "tok:left_brace" - case FFTok_left_bracket: - return "tok:left_bracket" - case FFTok_null: - return "tok:null" - case FFTok_right_brace: - return "tok:right_brace" - case FFTok_right_bracket: - return "tok:right_bracket" - case FFTok_integer: - return "tok:integer" - case FFTok_double: - return "tok:double" - case FFTok_string: - return "tok:string" - case FFTok_comment: - return "comment" - } - - panic(fmt.Sprintf("unknown token: %d", int(tok))) -} - -/* a lookup table which lets us quickly determine three things: - * cVEC - valid escaped control char - * note. the solidus '/' may be escaped or not. - * cIJC - invalid json char - * cVHC - valid hex char - * cNFP - needs further processing (from a string scanning perspective) - * cNUC - needs utf8 checking when enabled (from a string scanning perspective) - */ - -const ( - cVEC int8 = 0x01 - cIJC int8 = 0x02 - cVHC int8 = 0x04 - cNFP int8 = 0x08 - cNUC int8 = 0x10 -) - -var byteLookupTable [256]int8 = [256]int8{ - cIJC, /* 0 */ - cIJC, /* 1 */ - cIJC, /* 2 */ - cIJC, /* 3 */ - cIJC, /* 4 */ - cIJC, /* 5 */ - cIJC, /* 6 */ - cIJC, /* 7 */ - cIJC, /* 8 */ - cIJC, /* 9 */ - cIJC, /* 10 */ - cIJC, /* 11 */ - cIJC, /* 12 */ - cIJC, /* 13 */ - cIJC, /* 14 */ - cIJC, /* 15 */ - cIJC, /* 16 */ - cIJC, /* 17 */ - cIJC, /* 18 */ - cIJC, /* 19 */ - cIJC, /* 20 */ - cIJC, /* 21 */ - cIJC, /* 22 */ - cIJC, /* 23 */ - cIJC, /* 24 */ - cIJC, /* 25 */ - cIJC, /* 26 */ - cIJC, /* 27 */ - cIJC, /* 28 */ - cIJC, /* 29 */ - cIJC, /* 30 */ - cIJC, /* 31 */ - 0, /* 32 */ - 0, /* 33 */ - cVEC | cIJC | cNFP, /* 34 */ - 0, /* 35 */ - 0, /* 36 */ - 0, /* 37 */ - 0, /* 38 */ - 0, /* 39 */ - 0, /* 40 */ - 0, /* 41 */ - 0, /* 42 */ - 0, /* 43 */ - 0, /* 44 */ - 0, /* 45 */ - 0, /* 46 */ - cVEC, /* 47 */ - cVHC, /* 48 */ - cVHC, /* 49 */ - cVHC, /* 50 */ - cVHC, /* 51 */ - cVHC, /* 52 */ - cVHC, /* 53 */ - cVHC, /* 54 */ - cVHC, /* 55 */ - cVHC, /* 56 */ - cVHC, /* 57 */ - 0, /* 58 */ - 0, /* 59 */ - 0, /* 60 */ - 0, /* 61 */ - 0, /* 62 */ - 0, /* 63 */ - 0, /* 64 */ - cVHC, /* 65 */ - cVHC, /* 66 */ - cVHC, /* 67 */ - cVHC, /* 68 */ - cVHC, /* 69 */ - cVHC, /* 70 */ - 0, /* 71 */ - 0, /* 72 */ - 0, /* 73 */ - 0, /* 74 */ - 0, /* 75 */ - 0, /* 76 */ - 0, /* 77 */ - 0, /* 78 */ - 0, /* 79 */ - 0, /* 80 */ - 0, /* 81 */ - 0, /* 82 */ - 0, /* 83 */ - 0, /* 84 */ - 0, /* 85 */ - 0, /* 86 */ - 0, /* 87 */ - 0, /* 88 */ - 0, /* 89 */ - 0, /* 90 */ - 0, /* 91 */ - cVEC | cIJC | cNFP, /* 92 */ - 0, /* 93 */ - 0, /* 94 */ - 0, /* 95 */ - 0, /* 96 */ - cVHC, /* 97 */ - cVEC | cVHC, /* 98 */ - cVHC, /* 99 */ - cVHC, /* 100 */ - cVHC, /* 101 */ - cVEC | cVHC, /* 102 */ - 0, /* 103 */ - 0, /* 104 */ - 0, /* 105 */ - 0, /* 106 */ - 0, /* 107 */ - 0, /* 108 */ - 0, /* 109 */ - cVEC, /* 110 */ - 0, /* 111 */ - 0, /* 112 */ - 0, /* 113 */ - cVEC, /* 114 */ - 0, /* 115 */ - cVEC, /* 116 */ - 0, /* 117 */ - 0, /* 118 */ - 0, /* 119 */ - 0, /* 120 */ - 0, /* 121 */ - 0, /* 122 */ - 0, /* 123 */ - 0, /* 124 */ - 0, /* 125 */ - 0, /* 126 */ - 0, /* 127 */ - cNUC, /* 128 */ - cNUC, /* 129 */ - cNUC, /* 130 */ - cNUC, /* 131 */ - cNUC, /* 132 */ - cNUC, /* 133 */ - cNUC, /* 134 */ - cNUC, /* 135 */ - cNUC, /* 136 */ - cNUC, /* 137 */ - cNUC, /* 138 */ - cNUC, /* 139 */ - cNUC, /* 140 */ - cNUC, /* 141 */ - cNUC, /* 142 */ - cNUC, /* 143 */ - cNUC, /* 144 */ - cNUC, /* 145 */ - cNUC, /* 146 */ - cNUC, /* 147 */ - cNUC, /* 148 */ - cNUC, /* 149 */ - cNUC, /* 150 */ - cNUC, /* 151 */ - cNUC, /* 152 */ - cNUC, /* 153 */ - cNUC, /* 154 */ - cNUC, /* 155 */ - cNUC, /* 156 */ - cNUC, /* 157 */ - cNUC, /* 158 */ - cNUC, /* 159 */ - cNUC, /* 160 */ - cNUC, /* 161 */ - cNUC, /* 162 */ - cNUC, /* 163 */ - cNUC, /* 164 */ - cNUC, /* 165 */ - cNUC, /* 166 */ - cNUC, /* 167 */ - cNUC, /* 168 */ - cNUC, /* 169 */ - cNUC, /* 170 */ - cNUC, /* 171 */ - cNUC, /* 172 */ - cNUC, /* 173 */ - cNUC, /* 174 */ - cNUC, /* 175 */ - cNUC, /* 176 */ - cNUC, /* 177 */ - cNUC, /* 178 */ - cNUC, /* 179 */ - cNUC, /* 180 */ - cNUC, /* 181 */ - cNUC, /* 182 */ - cNUC, /* 183 */ - cNUC, /* 184 */ - cNUC, /* 185 */ - cNUC, /* 186 */ - cNUC, /* 187 */ - cNUC, /* 188 */ - cNUC, /* 189 */ - cNUC, /* 190 */ - cNUC, /* 191 */ - cNUC, /* 192 */ - cNUC, /* 193 */ - cNUC, /* 194 */ - cNUC, /* 195 */ - cNUC, /* 196 */ - cNUC, /* 197 */ - cNUC, /* 198 */ - cNUC, /* 199 */ - cNUC, /* 200 */ - cNUC, /* 201 */ - cNUC, /* 202 */ - cNUC, /* 203 */ - cNUC, /* 204 */ - cNUC, /* 205 */ - cNUC, /* 206 */ - cNUC, /* 207 */ - cNUC, /* 208 */ - cNUC, /* 209 */ - cNUC, /* 210 */ - cNUC, /* 211 */ - cNUC, /* 212 */ - cNUC, /* 213 */ - cNUC, /* 214 */ - cNUC, /* 215 */ - cNUC, /* 216 */ - cNUC, /* 217 */ - cNUC, /* 218 */ - cNUC, /* 219 */ - cNUC, /* 220 */ - cNUC, /* 221 */ - cNUC, /* 222 */ - cNUC, /* 223 */ - cNUC, /* 224 */ - cNUC, /* 225 */ - cNUC, /* 226 */ - cNUC, /* 227 */ - cNUC, /* 228 */ - cNUC, /* 229 */ - cNUC, /* 230 */ - cNUC, /* 231 */ - cNUC, /* 232 */ - cNUC, /* 233 */ - cNUC, /* 234 */ - cNUC, /* 235 */ - cNUC, /* 236 */ - cNUC, /* 237 */ - cNUC, /* 238 */ - cNUC, /* 239 */ - cNUC, /* 240 */ - cNUC, /* 241 */ - cNUC, /* 242 */ - cNUC, /* 243 */ - cNUC, /* 244 */ - cNUC, /* 245 */ - cNUC, /* 246 */ - cNUC, /* 247 */ - cNUC, /* 248 */ - cNUC, /* 249 */ - cNUC, /* 250 */ - cNUC, /* 251 */ - cNUC, /* 252 */ - cNUC, /* 253 */ - cNUC, /* 254 */ - cNUC, /* 255 */ -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/reader.go b/vendor/github.com/pquerna/ffjson/fflib/v1/reader.go deleted file mode 100644 index 0f22c469d6..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/reader.go +++ /dev/null @@ -1,512 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package v1 - -import ( - "fmt" - "io" - "unicode" - "unicode/utf16" -) - -const sliceStringMask = cIJC | cNFP - -type ffReader struct { - s []byte - i int - l int -} - -func newffReader(d []byte) *ffReader { - return &ffReader{ - s: d, - i: 0, - l: len(d), - } -} - -func (r *ffReader) Slice(start, stop int) []byte { - return r.s[start:stop] -} - -func (r *ffReader) Pos() int { - return r.i -} - -// Reset the reader, and add new input. -func (r *ffReader) Reset(d []byte) { - r.s = d - r.i = 0 - r.l = len(d) -} - -// Calcuates the Position with line and line offset, -// because this isn't counted for performance reasons, -// it will iterate the buffer from the beginning, and should -// only be used in error-paths. -func (r *ffReader) PosWithLine() (int, int) { - currentLine := 1 - currentChar := 0 - - for i := 0; i < r.i; i++ { - c := r.s[i] - currentChar++ - if c == '\n' { - currentLine++ - currentChar = 0 - } - } - - return currentLine, currentChar -} - -func (r *ffReader) ReadByteNoWS() (byte, error) { - if r.i >= r.l { - return 0, io.EOF - } - - j := r.i - - for { - c := r.s[j] - j++ - - // inline whitespace parsing gives another ~8% performance boost - // for many kinds of nicely indented JSON. - // ... and using a [255]bool instead of multiple ifs, gives another 2% - /* - if c != '\t' && - c != '\n' && - c != '\v' && - c != '\f' && - c != '\r' && - c != ' ' { - r.i = j - return c, nil - } - */ - if whitespaceLookupTable[c] == false { - r.i = j - return c, nil - } - - if j >= r.l { - return 0, io.EOF - } - } -} - -func (r *ffReader) ReadByte() (byte, error) { - if r.i >= r.l { - return 0, io.EOF - } - - r.i++ - - return r.s[r.i-1], nil -} - -func (r *ffReader) UnreadByte() error { - if r.i <= 0 { - panic("ffReader.UnreadByte: at beginning of slice") - } - r.i-- - return nil -} - -func (r *ffReader) readU4(j int) (rune, error) { - - var u4 [4]byte - for i := 0; i < 4; i++ { - if j >= r.l { - return -1, io.EOF - } - c := r.s[j] - if byteLookupTable[c]&cVHC != 0 { - u4[i] = c - j++ - continue - } else { - // TODO(pquerna): handle errors better. layering violation. - return -1, fmt.Errorf("lex_string_invalid_hex_char: %v %v", c, string(u4[:])) - } - } - - // TODO(pquerna): utf16.IsSurrogate - rr, err := ParseUint(u4[:], 16, 64) - if err != nil { - return -1, err - } - return rune(rr), nil -} - -func (r *ffReader) handleEscaped(c byte, j int, out DecodingBuffer) (int, error) { - if j >= r.l { - return 0, io.EOF - } - - c = r.s[j] - j++ - - if c == 'u' { - ru, err := r.readU4(j) - if err != nil { - return 0, err - } - - if utf16.IsSurrogate(ru) { - ru2, err := r.readU4(j + 6) - if err != nil { - return 0, err - } - out.Write(r.s[r.i : j-2]) - r.i = j + 10 - j = r.i - rval := utf16.DecodeRune(ru, ru2) - if rval != unicode.ReplacementChar { - out.WriteRune(rval) - } else { - return 0, fmt.Errorf("lex_string_invalid_unicode_surrogate: %v %v", ru, ru2) - } - } else { - out.Write(r.s[r.i : j-2]) - r.i = j + 4 - j = r.i - out.WriteRune(ru) - } - return j, nil - } else if byteLookupTable[c]&cVEC == 0 { - return 0, fmt.Errorf("lex_string_invalid_escaped_char: %v", c) - } else { - out.Write(r.s[r.i : j-2]) - r.i = j - j = r.i - - switch c { - case '"': - out.WriteByte('"') - case '\\': - out.WriteByte('\\') - case '/': - out.WriteByte('/') - case 'b': - out.WriteByte('\b') - case 'f': - out.WriteByte('\f') - case 'n': - out.WriteByte('\n') - case 'r': - out.WriteByte('\r') - case 't': - out.WriteByte('\t') - } - } - - return j, nil -} - -func (r *ffReader) SliceString(out DecodingBuffer) error { - var c byte - // TODO(pquerna): string_with_escapes? de-escape here? - j := r.i - - for { - if j >= r.l { - return io.EOF - } - - j, c = scanString(r.s, j) - - if c == '"' { - if j != r.i { - out.Write(r.s[r.i : j-1]) - r.i = j - } - return nil - } else if c == '\\' { - var err error - j, err = r.handleEscaped(c, j, out) - if err != nil { - return err - } - } else if byteLookupTable[c]&cIJC != 0 { - return fmt.Errorf("lex_string_invalid_json_char: %v", c) - } - continue - } -} - -// TODO(pquerna): consider combining wibth the normal byte mask. -var whitespaceLookupTable [256]bool = [256]bool{ - false, /* 0 */ - false, /* 1 */ - false, /* 2 */ - false, /* 3 */ - false, /* 4 */ - false, /* 5 */ - false, /* 6 */ - false, /* 7 */ - false, /* 8 */ - true, /* 9 */ - true, /* 10 */ - true, /* 11 */ - true, /* 12 */ - true, /* 13 */ - false, /* 14 */ - false, /* 15 */ - false, /* 16 */ - false, /* 17 */ - false, /* 18 */ - false, /* 19 */ - false, /* 20 */ - false, /* 21 */ - false, /* 22 */ - false, /* 23 */ - false, /* 24 */ - false, /* 25 */ - false, /* 26 */ - false, /* 27 */ - false, /* 28 */ - false, /* 29 */ - false, /* 30 */ - false, /* 31 */ - true, /* 32 */ - false, /* 33 */ - false, /* 34 */ - false, /* 35 */ - false, /* 36 */ - false, /* 37 */ - false, /* 38 */ - false, /* 39 */ - false, /* 40 */ - false, /* 41 */ - false, /* 42 */ - false, /* 43 */ - false, /* 44 */ - false, /* 45 */ - false, /* 46 */ - false, /* 47 */ - false, /* 48 */ - false, /* 49 */ - false, /* 50 */ - false, /* 51 */ - false, /* 52 */ - false, /* 53 */ - false, /* 54 */ - false, /* 55 */ - false, /* 56 */ - false, /* 57 */ - false, /* 58 */ - false, /* 59 */ - false, /* 60 */ - false, /* 61 */ - false, /* 62 */ - false, /* 63 */ - false, /* 64 */ - false, /* 65 */ - false, /* 66 */ - false, /* 67 */ - false, /* 68 */ - false, /* 69 */ - false, /* 70 */ - false, /* 71 */ - false, /* 72 */ - false, /* 73 */ - false, /* 74 */ - false, /* 75 */ - false, /* 76 */ - false, /* 77 */ - false, /* 78 */ - false, /* 79 */ - false, /* 80 */ - false, /* 81 */ - false, /* 82 */ - false, /* 83 */ - false, /* 84 */ - false, /* 85 */ - false, /* 86 */ - false, /* 87 */ - false, /* 88 */ - false, /* 89 */ - false, /* 90 */ - false, /* 91 */ - false, /* 92 */ - false, /* 93 */ - false, /* 94 */ - false, /* 95 */ - false, /* 96 */ - false, /* 97 */ - false, /* 98 */ - false, /* 99 */ - false, /* 100 */ - false, /* 101 */ - false, /* 102 */ - false, /* 103 */ - false, /* 104 */ - false, /* 105 */ - false, /* 106 */ - false, /* 107 */ - false, /* 108 */ - false, /* 109 */ - false, /* 110 */ - false, /* 111 */ - false, /* 112 */ - false, /* 113 */ - false, /* 114 */ - false, /* 115 */ - false, /* 116 */ - false, /* 117 */ - false, /* 118 */ - false, /* 119 */ - false, /* 120 */ - false, /* 121 */ - false, /* 122 */ - false, /* 123 */ - false, /* 124 */ - false, /* 125 */ - false, /* 126 */ - false, /* 127 */ - false, /* 128 */ - false, /* 129 */ - false, /* 130 */ - false, /* 131 */ - false, /* 132 */ - false, /* 133 */ - false, /* 134 */ - false, /* 135 */ - false, /* 136 */ - false, /* 137 */ - false, /* 138 */ - false, /* 139 */ - false, /* 140 */ - false, /* 141 */ - false, /* 142 */ - false, /* 143 */ - false, /* 144 */ - false, /* 145 */ - false, /* 146 */ - false, /* 147 */ - false, /* 148 */ - false, /* 149 */ - false, /* 150 */ - false, /* 151 */ - false, /* 152 */ - false, /* 153 */ - false, /* 154 */ - false, /* 155 */ - false, /* 156 */ - false, /* 157 */ - false, /* 158 */ - false, /* 159 */ - false, /* 160 */ - false, /* 161 */ - false, /* 162 */ - false, /* 163 */ - false, /* 164 */ - false, /* 165 */ - false, /* 166 */ - false, /* 167 */ - false, /* 168 */ - false, /* 169 */ - false, /* 170 */ - false, /* 171 */ - false, /* 172 */ - false, /* 173 */ - false, /* 174 */ - false, /* 175 */ - false, /* 176 */ - false, /* 177 */ - false, /* 178 */ - false, /* 179 */ - false, /* 180 */ - false, /* 181 */ - false, /* 182 */ - false, /* 183 */ - false, /* 184 */ - false, /* 185 */ - false, /* 186 */ - false, /* 187 */ - false, /* 188 */ - false, /* 189 */ - false, /* 190 */ - false, /* 191 */ - false, /* 192 */ - false, /* 193 */ - false, /* 194 */ - false, /* 195 */ - false, /* 196 */ - false, /* 197 */ - false, /* 198 */ - false, /* 199 */ - false, /* 200 */ - false, /* 201 */ - false, /* 202 */ - false, /* 203 */ - false, /* 204 */ - false, /* 205 */ - false, /* 206 */ - false, /* 207 */ - false, /* 208 */ - false, /* 209 */ - false, /* 210 */ - false, /* 211 */ - false, /* 212 */ - false, /* 213 */ - false, /* 214 */ - false, /* 215 */ - false, /* 216 */ - false, /* 217 */ - false, /* 218 */ - false, /* 219 */ - false, /* 220 */ - false, /* 221 */ - false, /* 222 */ - false, /* 223 */ - false, /* 224 */ - false, /* 225 */ - false, /* 226 */ - false, /* 227 */ - false, /* 228 */ - false, /* 229 */ - false, /* 230 */ - false, /* 231 */ - false, /* 232 */ - false, /* 233 */ - false, /* 234 */ - false, /* 235 */ - false, /* 236 */ - false, /* 237 */ - false, /* 238 */ - false, /* 239 */ - false, /* 240 */ - false, /* 241 */ - false, /* 242 */ - false, /* 243 */ - false, /* 244 */ - false, /* 245 */ - false, /* 246 */ - false, /* 247 */ - false, /* 248 */ - false, /* 249 */ - false, /* 250 */ - false, /* 251 */ - false, /* 252 */ - false, /* 253 */ - false, /* 254 */ - false, /* 255 */ -} diff --git a/vendor/github.com/pquerna/ffjson/fflib/v1/reader_scan_generic.go b/vendor/github.com/pquerna/ffjson/fflib/v1/reader_scan_generic.go deleted file mode 100644 index 47c2607708..0000000000 --- a/vendor/github.com/pquerna/ffjson/fflib/v1/reader_scan_generic.go +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package v1 - -func scanString(s []byte, j int) (int, byte) { - for { - if j >= len(s) { - return j, 0 - } - - c := s[j] - j++ - if byteLookupTable[c]&sliceStringMask == 0 { - continue - } - - return j, c - } -} diff --git a/vendor/github.com/prometheus/client_golang/NOTICE b/vendor/github.com/prometheus/client_golang/NOTICE deleted file mode 100644 index dd878a30ee..0000000000 --- a/vendor/github.com/prometheus/client_golang/NOTICE +++ /dev/null @@ -1,23 +0,0 @@ -Prometheus instrumentation library for Go applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - - -The following components are included in this product: - -perks - a fork of https://github.com/bmizerany/perks -https://github.com/beorn7/perks -Copyright 2013-2015 Blake Mizerany, Björn Rabenstein -See https://github.com/beorn7/perks/blob/master/README.md for license details. - -Go support for Protocol Buffers - Google's data interchange format -http://github.com/golang/protobuf/ -Copyright 2010 The Go Authors -See source code for license details. - -Support for streaming Protocol Buffer messages for the Go language (golang). -https://github.com/matttproud/golang_protobuf_extensions -Copyright 2013 Matt T. Proud -Licensed under the Apache License, Version 2.0 diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go deleted file mode 100644 index 623d3d83fe..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -// Collector is the interface implemented by anything that can be used by -// Prometheus to collect metrics. A Collector has to be registered for -// collection. See Registerer.Register. -// -// The stock metrics provided by this package (Gauge, Counter, Summary, -// Histogram, Untyped) are also Collectors (which only ever collect one metric, -// namely itself). An implementer of Collector may, however, collect multiple -// metrics in a coordinated fashion and/or create metrics on the fly. Examples -// for collectors already implemented in this library are the metric vectors -// (i.e. collection of multiple instances of the same Metric but with different -// label values) like GaugeVec or SummaryVec, and the ExpvarCollector. -type Collector interface { - // Describe sends the super-set of all possible descriptors of metrics - // collected by this Collector to the provided channel and returns once - // the last descriptor has been sent. The sent descriptors fulfill the - // consistency and uniqueness requirements described in the Desc - // documentation. (It is valid if one and the same Collector sends - // duplicate descriptors. Those duplicates are simply ignored. However, - // two different Collectors must not send duplicate descriptors.) This - // method idempotently sends the same descriptors throughout the - // lifetime of the Collector. If a Collector encounters an error while - // executing this method, it must send an invalid descriptor (created - // with NewInvalidDesc) to signal the error to the registry. - Describe(chan<- *Desc) - // Collect is called by the Prometheus registry when collecting - // metrics. The implementation sends each collected metric via the - // provided channel and returns once the last metric has been sent. The - // descriptor of each sent metric is one of those returned by - // Describe. Returned metrics that share the same descriptor must differ - // in their variable label values. This method may be called - // concurrently and must therefore be implemented in a concurrency safe - // way. Blocking occurs at the expense of total performance of rendering - // all registered metrics. Ideally, Collector implementations support - // concurrent readers. - Collect(chan<- Metric) -} - -// selfCollector implements Collector for a single Metric so that the Metric -// collects itself. Add it as an anonymous field to a struct that implements -// Metric, and call init with the Metric itself as an argument. -type selfCollector struct { - self Metric -} - -// init provides the selfCollector with a reference to the metric it is supposed -// to collect. It is usually called within the factory function to create a -// metric. See example. -func (c *selfCollector) init(self Metric) { - c.self = self -} - -// Describe implements Collector. -func (c *selfCollector) Describe(ch chan<- *Desc) { - ch <- c.self.Desc() -} - -// Collect implements Collector. -func (c *selfCollector) Collect(ch chan<- Metric) { - ch <- c.self -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go deleted file mode 100644 index 765e4550c6..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "errors" - "math" - "sync/atomic" - - dto "github.com/prometheus/client_model/go" -) - -// Counter is a Metric that represents a single numerical value that only ever -// goes up. That implies that it cannot be used to count items whose number can -// also go down, e.g. the number of currently running goroutines. Those -// "counters" are represented by Gauges. -// -// A Counter is typically used to count requests served, tasks completed, errors -// occurred, etc. -// -// To create Counter instances, use NewCounter. -type Counter interface { - Metric - Collector - - // Inc increments the counter by 1. Use Add to increment it by arbitrary - // non-negative values. - Inc() - // Add adds the given value to the counter. It panics if the value is < - // 0. - Add(float64) -} - -// CounterOpts is an alias for Opts. See there for doc comments. -type CounterOpts Opts - -// NewCounter creates a new Counter based on the provided CounterOpts. -// -// The returned implementation tracks the counter value in two separate -// variables, a float64 and a uint64. The latter is used to track calls of the -// Inc method and calls of the Add method with a value that can be represented -// as a uint64. This allows atomic increments of the counter with optimal -// performance. (It is common to have an Inc call in very hot execution paths.) -// Both internal tracking values are added up in the Write method. This has to -// be taken into account when it comes to precision and overflow behavior. -func NewCounter(opts CounterOpts) Counter { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ) - result := &counter{desc: desc, labelPairs: desc.constLabelPairs} - result.init(result) // Init self-collection. - return result -} - -type counter struct { - // valBits contains the bits of the represented float64 value, while - // valInt stores values that are exact integers. Both have to go first - // in the struct to guarantee alignment for atomic operations. - // http://golang.org/pkg/sync/atomic/#pkg-note-BUG - valBits uint64 - valInt uint64 - - selfCollector - desc *Desc - - labelPairs []*dto.LabelPair -} - -func (c *counter) Desc() *Desc { - return c.desc -} - -func (c *counter) Add(v float64) { - if v < 0 { - panic(errors.New("counter cannot decrease in value")) - } - ival := uint64(v) - if float64(ival) == v { - atomic.AddUint64(&c.valInt, ival) - return - } - - for { - oldBits := atomic.LoadUint64(&c.valBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + v) - if atomic.CompareAndSwapUint64(&c.valBits, oldBits, newBits) { - return - } - } -} - -func (c *counter) Inc() { - atomic.AddUint64(&c.valInt, 1) -} - -func (c *counter) Write(out *dto.Metric) error { - fval := math.Float64frombits(atomic.LoadUint64(&c.valBits)) - ival := atomic.LoadUint64(&c.valInt) - val := fval + float64(ival) - - return populateMetric(CounterValue, val, c.labelPairs, out) -} - -// CounterVec is a Collector that bundles a set of Counters that all share the -// same Desc, but have different values for their variable labels. This is used -// if you want to count the same thing partitioned by various dimensions -// (e.g. number of HTTP requests, partitioned by response code and -// method). Create instances with NewCounterVec. -type CounterVec struct { - *metricVec -} - -// NewCounterVec creates a new CounterVec based on the provided CounterOpts and -// partitioned by the given label names. -func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - labelNames, - opts.ConstLabels, - ) - return &CounterVec{ - metricVec: newMetricVec(desc, func(lvs ...string) Metric { - if len(lvs) != len(desc.variableLabels) { - panic(errInconsistentCardinality) - } - result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} - result.init(result) // Init self-collection. - return result - }), - } -} - -// GetMetricWithLabelValues returns the Counter for the given slice of label -// values (same order as the VariableLabels in Desc). If that combination of -// label values is accessed for the first time, a new Counter is created. -// -// It is possible to call this method without using the returned Counter to only -// create the new Counter but leave it at its starting value 0. See also the -// SummaryVec example. -// -// Keeping the Counter for later use is possible (and should be considered if -// performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Counter from the CounterVec. In that case, -// the Counter will still exist, but it will not be exported anymore, even if a -// Counter with the same label values is created later. -// -// An error is returned if the number of label values is not the same as the -// number of VariableLabels in Desc (minus any curried labels). -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as -// an alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the GaugeVec example. -func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) { - metric, err := v.metricVec.getMetricWithLabelValues(lvs...) - if metric != nil { - return metric.(Counter), err - } - return nil, err -} - -// GetMetricWith returns the Counter for the given Labels map (the label names -// must match those of the VariableLabels in Desc). If that label map is -// accessed for the first time, a new Counter is created. Implications of -// creating a Counter without using it and keeping the Counter for later use are -// the same as for GetMetricWithLabelValues. -// -// An error is returned if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc (minus any curried labels). -// -// This method is used for the same purpose as -// GetMetricWithLabelValues(...string). See there for pros and cons of the two -// methods. -func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) { - metric, err := v.metricVec.getMetricWith(labels) - if metric != nil { - return metric.(Counter), err - } - return nil, err -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. Not returning an -// error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) -func (v *CounterVec) WithLabelValues(lvs ...string) Counter { - c, err := v.GetMetricWithLabelValues(lvs...) - if err != nil { - panic(err) - } - return c -} - -// With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) -func (v *CounterVec) With(labels Labels) Counter { - c, err := v.GetMetricWith(labels) - if err != nil { - panic(err) - } - return c -} - -// CurryWith returns a vector curried with the provided labels, i.e. the -// returned vector has those labels pre-set for all labeled operations performed -// on it. The cardinality of the curried vector is reduced accordingly. The -// order of the remaining labels stays the same (just with the curried labels -// taken out of the sequence – which is relevant for the -// (GetMetric)WithLabelValues methods). It is possible to curry a curried -// vector, but only with labels not yet used for currying before. -// -// The metrics contained in the CounterVec are shared between the curried and -// uncurried vectors. They are just accessed differently. Curried and uncurried -// vectors behave identically in terms of collection. Only one must be -// registered with a given registry (usually the uncurried version). The Reset -// method deletes all metrics, even if called on a curried vector. -func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) { - vec, err := v.curryWith(labels) - if vec != nil { - return &CounterVec{vec}, err - } - return nil, err -} - -// MustCurryWith works as CurryWith but panics where CurryWith would have -// returned an error. -func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec { - vec, err := v.CurryWith(labels) - if err != nil { - panic(err) - } - return vec -} - -// CounterFunc is a Counter whose value is determined at collect time by calling a -// provided function. -// -// To create CounterFunc instances, use NewCounterFunc. -type CounterFunc interface { - Metric - Collector -} - -// NewCounterFunc creates a new CounterFunc based on the provided -// CounterOpts. The value reported is determined by calling the given function -// from within the Write method. Take into account that metric collection may -// happen concurrently. If that results in concurrent calls to Write, like in -// the case where a CounterFunc is directly registered with Prometheus, the -// provided function must be concurrency-safe. The function should also honor -// the contract for a Counter (values only go up, not down), but compliance will -// not be checked. -func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc { - return newValueFunc(NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), CounterValue, function) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go deleted file mode 100644 index 4a755b0fa5..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "errors" - "fmt" - "sort" - "strings" - - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/model" - - dto "github.com/prometheus/client_model/go" -) - -// Desc is the descriptor used by every Prometheus Metric. It is essentially -// the immutable meta-data of a Metric. The normal Metric implementations -// included in this package manage their Desc under the hood. Users only have to -// deal with Desc if they use advanced features like the ExpvarCollector or -// custom Collectors and Metrics. -// -// Descriptors registered with the same registry have to fulfill certain -// consistency and uniqueness criteria if they share the same fully-qualified -// name: They must have the same help string and the same label names (aka label -// dimensions) in each, constLabels and variableLabels, but they must differ in -// the values of the constLabels. -// -// Descriptors that share the same fully-qualified names and the same label -// values of their constLabels are considered equal. -// -// Use NewDesc to create new Desc instances. -type Desc struct { - // fqName has been built from Namespace, Subsystem, and Name. - fqName string - // help provides some helpful information about this metric. - help string - // constLabelPairs contains precalculated DTO label pairs based on - // the constant labels. - constLabelPairs []*dto.LabelPair - // VariableLabels contains names of labels for which the metric - // maintains variable values. - variableLabels []string - // id is a hash of the values of the ConstLabels and fqName. This - // must be unique among all registered descriptors and can therefore be - // used as an identifier of the descriptor. - id uint64 - // dimHash is a hash of the label names (preset and variable) and the - // Help string. Each Desc with the same fqName must have the same - // dimHash. - dimHash uint64 - // err is an error that occurred during construction. It is reported on - // registration time. - err error -} - -// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc -// and will be reported on registration time. variableLabels and constLabels can -// be nil if no such labels should be set. fqName and help must not be empty. -// -// variableLabels only contain the label names. Their label values are variable -// and therefore not part of the Desc. (They are managed within the Metric.) -// -// For constLabels, the label values are constant. Therefore, they are fully -// specified in the Desc. See the Collector example for a usage pattern. -func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { - d := &Desc{ - fqName: fqName, - help: help, - variableLabels: variableLabels, - } - if help == "" { - d.err = errors.New("empty help string") - return d - } - if !model.IsValidMetricName(model.LabelValue(fqName)) { - d.err = fmt.Errorf("%q is not a valid metric name", fqName) - return d - } - // labelValues contains the label values of const labels (in order of - // their sorted label names) plus the fqName (at position 0). - labelValues := make([]string, 1, len(constLabels)+1) - labelValues[0] = fqName - labelNames := make([]string, 0, len(constLabels)+len(variableLabels)) - labelNameSet := map[string]struct{}{} - // First add only the const label names and sort them... - for labelName := range constLabels { - if !checkLabelName(labelName) { - d.err = fmt.Errorf("%q is not a valid label name", labelName) - return d - } - labelNames = append(labelNames, labelName) - labelNameSet[labelName] = struct{}{} - } - sort.Strings(labelNames) - // ... so that we can now add const label values in the order of their names. - for _, labelName := range labelNames { - labelValues = append(labelValues, constLabels[labelName]) - } - // Validate the const label values. They can't have a wrong cardinality, so - // use in len(labelValues) as expectedNumberOfValues. - if err := validateLabelValues(labelValues, len(labelValues)); err != nil { - d.err = err - return d - } - // Now add the variable label names, but prefix them with something that - // cannot be in a regular label name. That prevents matching the label - // dimension with a different mix between preset and variable labels. - for _, labelName := range variableLabels { - if !checkLabelName(labelName) { - d.err = fmt.Errorf("%q is not a valid label name", labelName) - return d - } - labelNames = append(labelNames, "$"+labelName) - labelNameSet[labelName] = struct{}{} - } - if len(labelNames) != len(labelNameSet) { - d.err = errors.New("duplicate label names") - return d - } - - vh := hashNew() - for _, val := range labelValues { - vh = hashAdd(vh, val) - vh = hashAddByte(vh, separatorByte) - } - d.id = vh - // Sort labelNames so that order doesn't matter for the hash. - sort.Strings(labelNames) - // Now hash together (in this order) the help string and the sorted - // label names. - lh := hashNew() - lh = hashAdd(lh, help) - lh = hashAddByte(lh, separatorByte) - for _, labelName := range labelNames { - lh = hashAdd(lh, labelName) - lh = hashAddByte(lh, separatorByte) - } - d.dimHash = lh - - d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels)) - for n, v := range constLabels { - d.constLabelPairs = append(d.constLabelPairs, &dto.LabelPair{ - Name: proto.String(n), - Value: proto.String(v), - }) - } - sort.Sort(LabelPairSorter(d.constLabelPairs)) - return d -} - -// NewInvalidDesc returns an invalid descriptor, i.e. a descriptor with the -// provided error set. If a collector returning such a descriptor is registered, -// registration will fail with the provided error. NewInvalidDesc can be used by -// a Collector to signal inability to describe itself. -func NewInvalidDesc(err error) *Desc { - return &Desc{ - err: err, - } -} - -func (d *Desc) String() string { - lpStrings := make([]string, 0, len(d.constLabelPairs)) - for _, lp := range d.constLabelPairs { - lpStrings = append( - lpStrings, - fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()), - ) - } - return fmt.Sprintf( - "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}", - d.fqName, - d.help, - strings.Join(lpStrings, ","), - d.variableLabels, - ) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go deleted file mode 100644 index 36ef155670..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package prometheus provides metrics primitives to instrument code for -// monitoring. It also offers a registry for metrics. Sub-packages allow to -// expose the registered metrics via HTTP (package promhttp) or push them to a -// Pushgateway (package push). -// -// All exported functions and methods are safe to be used concurrently unless -// specified otherwise. -// -// A Basic Example -// -// As a starting point, a very basic usage example: -// -// package main -// -// import ( -// "log" -// "net/http" -// -// "github.com/prometheus/client_golang/prometheus" -// "github.com/prometheus/client_golang/prometheus/promhttp" -// ) -// -// var ( -// cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ -// Name: "cpu_temperature_celsius", -// Help: "Current temperature of the CPU.", -// }) -// hdFailures = prometheus.NewCounterVec( -// prometheus.CounterOpts{ -// Name: "hd_errors_total", -// Help: "Number of hard-disk errors.", -// }, -// []string{"device"}, -// ) -// ) -// -// func init() { -// // Metrics have to be registered to be exposed: -// prometheus.MustRegister(cpuTemp) -// prometheus.MustRegister(hdFailures) -// } -// -// func main() { -// cpuTemp.Set(65.3) -// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() -// -// // The Handler function provides a default handler to expose metrics -// // via an HTTP server. "/metrics" is the usual endpoint for that. -// http.Handle("/metrics", promhttp.Handler()) -// log.Fatal(http.ListenAndServe(":8080", nil)) -// } -// -// -// This is a complete program that exports two metrics, a Gauge and a Counter, -// the latter with a label attached to turn it into a (one-dimensional) vector. -// -// Metrics -// -// The number of exported identifiers in this package might appear a bit -// overwhelming. However, in addition to the basic plumbing shown in the example -// above, you only need to understand the different metric types and their -// vector versions for basic usage. -// -// Above, you have already touched the Counter and the Gauge. There are two more -// advanced metric types: the Summary and Histogram. A more thorough description -// of those four metric types can be found in the Prometheus docs: -// https://prometheus.io/docs/concepts/metric_types/ -// -// A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the -// Prometheus server not to assume anything about its type. -// -// In addition to the fundamental metric types Gauge, Counter, Summary, -// Histogram, and Untyped, a very important part of the Prometheus data model is -// the partitioning of samples along dimensions called labels, which results in -// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec, -// HistogramVec, and UntypedVec. -// -// While only the fundamental metric types implement the Metric interface, both -// the metrics and their vector versions implement the Collector interface. A -// Collector manages the collection of a number of Metrics, but for convenience, -// a Metric can also “collect itself”. Note that Gauge, Counter, Summary, -// Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec, -// SummaryVec, HistogramVec, and UntypedVec are not. -// -// To create instances of Metrics and their vector versions, you need a suitable -// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, HistogramOpts, or -// UntypedOpts. -// -// Custom Collectors and constant Metrics -// -// While you could create your own implementations of Metric, most likely you -// will only ever implement the Collector interface on your own. At a first -// glance, a custom Collector seems handy to bundle Metrics for common -// registration (with the prime example of the different metric vectors above, -// which bundle all the metrics of the same name but with different labels). -// -// There is a more involved use case, too: If you already have metrics -// available, created outside of the Prometheus context, you don't need the -// interface of the various Metric types. You essentially want to mirror the -// existing numbers into Prometheus Metrics during collection. An own -// implementation of the Collector interface is perfect for that. You can create -// Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and -// NewConstSummary (and their respective Must… versions). That will happen in -// the Collect method. The Describe method has to return separate Desc -// instances, representative of the “throw-away” metrics to be created later. -// NewDesc comes in handy to create those Desc instances. -// -// The Collector example illustrates the use case. You can also look at the -// source code of the processCollector (mirroring process metrics), the -// goCollector (mirroring Go metrics), or the expvarCollector (mirroring expvar -// metrics) as examples that are used in this package itself. -// -// If you just need to call a function to get a single float value to collect as -// a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting -// shortcuts. -// -// Advanced Uses of the Registry -// -// While MustRegister is the by far most common way of registering a Collector, -// sometimes you might want to handle the errors the registration might cause. -// As suggested by the name, MustRegister panics if an error occurs. With the -// Register function, the error is returned and can be handled. -// -// An error is returned if the registered Collector is incompatible or -// inconsistent with already registered metrics. The registry aims for -// consistency of the collected metrics according to the Prometheus data model. -// Inconsistencies are ideally detected at registration time, not at collect -// time. The former will usually be detected at start-up time of a program, -// while the latter will only happen at scrape time, possibly not even on the -// first scrape if the inconsistency only becomes relevant later. That is the -// main reason why a Collector and a Metric have to describe themselves to the -// registry. -// -// So far, everything we did operated on the so-called default registry, as it -// can be found in the global DefaultRegisterer variable. With NewRegistry, you -// can create a custom registry, or you can even implement the Registerer or -// Gatherer interfaces yourself. The methods Register and Unregister work in the -// same way on a custom registry as the global functions Register and Unregister -// on the default registry. -// -// There are a number of uses for custom registries: You can use registries with -// special properties, see NewPedanticRegistry. You can avoid global state, as -// it is imposed by the DefaultRegisterer. You can use multiple registries at -// the same time to expose different metrics in different ways. You can use -// separate registries for testing purposes. -// -// Also note that the DefaultRegisterer comes registered with a Collector for Go -// runtime metrics (via NewGoCollector) and a Collector for process metrics (via -// NewProcessCollector). With a custom registry, you are in control and decide -// yourself about the Collectors to register. -// -// HTTP Exposition -// -// The Registry implements the Gatherer interface. The caller of the Gather -// method can then expose the gathered metrics in some way. Usually, the metrics -// are served via HTTP on the /metrics endpoint. That's happening in the example -// above. The tools to expose metrics via HTTP are in the promhttp sub-package. -// (The top-level functions in the prometheus package are deprecated.) -// -// Pushing to the Pushgateway -// -// Function for pushing to the Pushgateway can be found in the push sub-package. -// -// Graphite Bridge -// -// Functions and examples to push metrics from a Gatherer to Graphite can be -// found in the graphite sub-package. -// -// Other Means of Exposition -// -// More ways of exposing metrics can easily be added by following the approaches -// of the existing implementations. -package prometheus diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go deleted file mode 100644 index 18a99d5faa..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "encoding/json" - "expvar" -) - -type expvarCollector struct { - exports map[string]*Desc -} - -// NewExpvarCollector returns a newly allocated expvar Collector that still has -// to be registered with a Prometheus registry. -// -// An expvar Collector collects metrics from the expvar interface. It provides a -// quick way to expose numeric values that are already exported via expvar as -// Prometheus metrics. Note that the data models of expvar and Prometheus are -// fundamentally different, and that the expvar Collector is inherently slower -// than native Prometheus metrics. Thus, the expvar Collector is probably great -// for experiments and prototying, but you should seriously consider a more -// direct implementation of Prometheus metrics for monitoring production -// systems. -// -// The exports map has the following meaning: -// -// The keys in the map correspond to expvar keys, i.e. for every expvar key you -// want to export as Prometheus metric, you need an entry in the exports -// map. The descriptor mapped to each key describes how to export the expvar -// value. It defines the name and the help string of the Prometheus metric -// proxying the expvar value. The type will always be Untyped. -// -// For descriptors without variable labels, the expvar value must be a number or -// a bool. The number is then directly exported as the Prometheus sample -// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values -// that are not numbers or bools are silently ignored. -// -// If the descriptor has one variable label, the expvar value must be an expvar -// map. The keys in the expvar map become the various values of the one -// Prometheus label. The values in the expvar map must be numbers or bools again -// as above. -// -// For descriptors with more than one variable label, the expvar must be a -// nested expvar map, i.e. where the values of the topmost map are maps again -// etc. until a depth is reached that corresponds to the number of labels. The -// leaves of that structure must be numbers or bools as above to serve as the -// sample values. -// -// Anything that does not fit into the scheme above is silently ignored. -func NewExpvarCollector(exports map[string]*Desc) Collector { - return &expvarCollector{ - exports: exports, - } -} - -// Describe implements Collector. -func (e *expvarCollector) Describe(ch chan<- *Desc) { - for _, desc := range e.exports { - ch <- desc - } -} - -// Collect implements Collector. -func (e *expvarCollector) Collect(ch chan<- Metric) { - for name, desc := range e.exports { - var m Metric - expVar := expvar.Get(name) - if expVar == nil { - continue - } - var v interface{} - labels := make([]string, len(desc.variableLabels)) - if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil { - ch <- NewInvalidMetric(desc, err) - continue - } - var processValue func(v interface{}, i int) - processValue = func(v interface{}, i int) { - if i >= len(labels) { - copiedLabels := append(make([]string, 0, len(labels)), labels...) - switch v := v.(type) { - case float64: - m = MustNewConstMetric(desc, UntypedValue, v, copiedLabels...) - case bool: - if v { - m = MustNewConstMetric(desc, UntypedValue, 1, copiedLabels...) - } else { - m = MustNewConstMetric(desc, UntypedValue, 0, copiedLabels...) - } - default: - return - } - ch <- m - return - } - vm, ok := v.(map[string]interface{}) - if !ok { - return - } - for lv, val := range vm { - labels[i] = lv - processValue(val, i+1) - } - } - processValue(v, 0) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/fnv.go b/vendor/github.com/prometheus/client_golang/prometheus/fnv.go deleted file mode 100644 index e3b67df8ac..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/fnv.go +++ /dev/null @@ -1,29 +0,0 @@ -package prometheus - -// Inline and byte-free variant of hash/fnv's fnv64a. - -const ( - offset64 = 14695981039346656037 - prime64 = 1099511628211 -) - -// hashNew initializies a new fnv64a hash value. -func hashNew() uint64 { - return offset64 -} - -// hashAdd adds a string to a fnv64a hash value, returning the updated hash. -func hashAdd(h uint64, s string) uint64 { - for i := 0; i < len(s); i++ { - h ^= uint64(s[i]) - h *= prime64 - } - return h -} - -// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. -func hashAddByte(h uint64, b byte) uint64 { - h ^= uint64(b) - h *= prime64 - return h -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go deleted file mode 100644 index 17c72d7eb0..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "math" - "sync/atomic" - "time" - - dto "github.com/prometheus/client_model/go" -) - -// Gauge is a Metric that represents a single numerical value that can -// arbitrarily go up and down. -// -// A Gauge is typically used for measured values like temperatures or current -// memory usage, but also "counts" that can go up and down, like the number of -// running goroutines. -// -// To create Gauge instances, use NewGauge. -type Gauge interface { - Metric - Collector - - // Set sets the Gauge to an arbitrary value. - Set(float64) - // Inc increments the Gauge by 1. Use Add to increment it by arbitrary - // values. - Inc() - // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary - // values. - Dec() - // Add adds the given value to the Gauge. (The value can be negative, - // resulting in a decrease of the Gauge.) - Add(float64) - // Sub subtracts the given value from the Gauge. (The value can be - // negative, resulting in an increase of the Gauge.) - Sub(float64) - - // SetToCurrentTime sets the Gauge to the current Unix time in seconds. - SetToCurrentTime() -} - -// GaugeOpts is an alias for Opts. See there for doc comments. -type GaugeOpts Opts - -// NewGauge creates a new Gauge based on the provided GaugeOpts. -// -// The returned implementation is optimized for a fast Set method. If you have a -// choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick -// the former. For example, the Inc method of the returned Gauge is slower than -// the Inc method of a Counter returned by NewCounter. This matches the typical -// scenarios for Gauges and Counters, where the former tends to be Set-heavy and -// the latter Inc-heavy. -func NewGauge(opts GaugeOpts) Gauge { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ) - result := &gauge{desc: desc, labelPairs: desc.constLabelPairs} - result.init(result) // Init self-collection. - return result -} - -type gauge struct { - // valBits contains the bits of the represented float64 value. It has - // to go first in the struct to guarantee alignment for atomic - // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG - valBits uint64 - - selfCollector - - desc *Desc - labelPairs []*dto.LabelPair -} - -func (g *gauge) Desc() *Desc { - return g.desc -} - -func (g *gauge) Set(val float64) { - atomic.StoreUint64(&g.valBits, math.Float64bits(val)) -} - -func (g *gauge) SetToCurrentTime() { - g.Set(float64(time.Now().UnixNano()) / 1e9) -} - -func (g *gauge) Inc() { - g.Add(1) -} - -func (g *gauge) Dec() { - g.Add(-1) -} - -func (g *gauge) Add(val float64) { - for { - oldBits := atomic.LoadUint64(&g.valBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + val) - if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) { - return - } - } -} - -func (g *gauge) Sub(val float64) { - g.Add(val * -1) -} - -func (g *gauge) Write(out *dto.Metric) error { - val := math.Float64frombits(atomic.LoadUint64(&g.valBits)) - return populateMetric(GaugeValue, val, g.labelPairs, out) -} - -// GaugeVec is a Collector that bundles a set of Gauges that all share the same -// Desc, but have different values for their variable labels. This is used if -// you want to count the same thing partitioned by various dimensions -// (e.g. number of operations queued, partitioned by user and operation -// type). Create instances with NewGaugeVec. -type GaugeVec struct { - *metricVec -} - -// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and -// partitioned by the given label names. -func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - labelNames, - opts.ConstLabels, - ) - return &GaugeVec{ - metricVec: newMetricVec(desc, func(lvs ...string) Metric { - if len(lvs) != len(desc.variableLabels) { - panic(errInconsistentCardinality) - } - result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} - result.init(result) // Init self-collection. - return result - }), - } -} - -// GetMetricWithLabelValues returns the Gauge for the given slice of label -// values (same order as the VariableLabels in Desc). If that combination of -// label values is accessed for the first time, a new Gauge is created. -// -// It is possible to call this method without using the returned Gauge to only -// create the new Gauge but leave it at its starting value 0. See also the -// SummaryVec example. -// -// Keeping the Gauge for later use is possible (and should be considered if -// performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Gauge from the GaugeVec. In that case, the -// Gauge will still exist, but it will not be exported anymore, even if a -// Gauge with the same label values is created later. See also the CounterVec -// example. -// -// An error is returned if the number of label values is not the same as the -// number of VariableLabels in Desc (minus any curried labels). -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as -// an alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { - metric, err := v.metricVec.getMetricWithLabelValues(lvs...) - if metric != nil { - return metric.(Gauge), err - } - return nil, err -} - -// GetMetricWith returns the Gauge for the given Labels map (the label names -// must match those of the VariableLabels in Desc). If that label map is -// accessed for the first time, a new Gauge is created. Implications of -// creating a Gauge without using it and keeping the Gauge for later use are -// the same as for GetMetricWithLabelValues. -// -// An error is returned if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc (minus any curried labels). -// -// This method is used for the same purpose as -// GetMetricWithLabelValues(...string). See there for pros and cons of the two -// methods. -func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { - metric, err := v.metricVec.getMetricWith(labels) - if metric != nil { - return metric.(Gauge), err - } - return nil, err -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. Not returning an -// error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) -func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { - g, err := v.GetMetricWithLabelValues(lvs...) - if err != nil { - panic(err) - } - return g -} - -// With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) -func (v *GaugeVec) With(labels Labels) Gauge { - g, err := v.GetMetricWith(labels) - if err != nil { - panic(err) - } - return g -} - -// CurryWith returns a vector curried with the provided labels, i.e. the -// returned vector has those labels pre-set for all labeled operations performed -// on it. The cardinality of the curried vector is reduced accordingly. The -// order of the remaining labels stays the same (just with the curried labels -// taken out of the sequence – which is relevant for the -// (GetMetric)WithLabelValues methods). It is possible to curry a curried -// vector, but only with labels not yet used for currying before. -// -// The metrics contained in the GaugeVec are shared between the curried and -// uncurried vectors. They are just accessed differently. Curried and uncurried -// vectors behave identically in terms of collection. Only one must be -// registered with a given registry (usually the uncurried version). The Reset -// method deletes all metrics, even if called on a curried vector. -func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) { - vec, err := v.curryWith(labels) - if vec != nil { - return &GaugeVec{vec}, err - } - return nil, err -} - -// MustCurryWith works as CurryWith but panics where CurryWith would have -// returned an error. -func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec { - vec, err := v.CurryWith(labels) - if err != nil { - panic(err) - } - return vec -} - -// GaugeFunc is a Gauge whose value is determined at collect time by calling a -// provided function. -// -// To create GaugeFunc instances, use NewGaugeFunc. -type GaugeFunc interface { - Metric - Collector -} - -// NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The -// value reported is determined by calling the given function from within the -// Write method. Take into account that metric collection may happen -// concurrently. If that results in concurrent calls to Write, like in the case -// where a GaugeFunc is directly registered with Prometheus, the provided -// function must be concurrency-safe. -func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc { - return newValueFunc(NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), GaugeValue, function) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go deleted file mode 100644 index 096454af91..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ /dev/null @@ -1,284 +0,0 @@ -package prometheus - -import ( - "fmt" - "runtime" - "runtime/debug" - "time" -) - -type goCollector struct { - goroutinesDesc *Desc - threadsDesc *Desc - gcDesc *Desc - goInfoDesc *Desc - - // metrics to describe and collect - metrics memStatsMetrics -} - -// NewGoCollector returns a collector which exports metrics about the current -// go process. -func NewGoCollector() Collector { - return &goCollector{ - goroutinesDesc: NewDesc( - "go_goroutines", - "Number of goroutines that currently exist.", - nil, nil), - threadsDesc: NewDesc( - "go_threads", - "Number of OS threads created.", - nil, nil), - gcDesc: NewDesc( - "go_gc_duration_seconds", - "A summary of the GC invocation durations.", - nil, nil), - goInfoDesc: NewDesc( - "go_info", - "Information about the Go environment.", - nil, Labels{"version": runtime.Version()}), - metrics: memStatsMetrics{ - { - desc: NewDesc( - memstatNamespace("alloc_bytes"), - "Number of bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("alloc_bytes_total"), - "Total number of bytes allocated, even if freed.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("sys_bytes"), - "Number of bytes obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("lookups_total"), - "Total number of pointer lookups.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("mallocs_total"), - "Total number of mallocs.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("frees_total"), - "Total number of frees.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("heap_alloc_bytes"), - "Number of heap bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_sys_bytes"), - "Number of heap bytes obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_idle_bytes"), - "Number of heap bytes waiting to be used.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_inuse_bytes"), - "Number of heap bytes that are in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_released_bytes"), - "Number of heap bytes released to OS.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_objects"), - "Number of allocated objects.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_inuse_bytes"), - "Number of bytes in use by the stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_sys_bytes"), - "Number of bytes obtained from system for stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_inuse_bytes"), - "Number of bytes in use by mspan structures.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_sys_bytes"), - "Number of bytes used for mspan structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_inuse_bytes"), - "Number of bytes in use by mcache structures.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_sys_bytes"), - "Number of bytes used for mcache structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("buck_hash_sys_bytes"), - "Number of bytes used by the profiling bucket hash table.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("gc_sys_bytes"), - "Number of bytes used for garbage collection system metadata.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("other_sys_bytes"), - "Number of bytes used for other system allocations.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("next_gc_bytes"), - "Number of heap bytes when next garbage collection will take place.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("last_gc_time_seconds"), - "Number of seconds since 1970 of last garbage collection.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("gc_cpu_fraction"), - "The fraction of this program's available CPU time used by the GC since the program started.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, - valType: GaugeValue, - }, - }, - } -} - -func memstatNamespace(s string) string { - return fmt.Sprintf("go_memstats_%s", s) -} - -// Describe returns all descriptions of the collector. -func (c *goCollector) Describe(ch chan<- *Desc) { - ch <- c.goroutinesDesc - ch <- c.threadsDesc - ch <- c.gcDesc - ch <- c.goInfoDesc - for _, i := range c.metrics { - ch <- i.desc - } -} - -// Collect returns the current state of all metrics of the collector. -func (c *goCollector) Collect(ch chan<- Metric) { - ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine())) - n, _ := runtime.ThreadCreateProfile(nil) - ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n)) - - var stats debug.GCStats - stats.PauseQuantiles = make([]time.Duration, 5) - debug.ReadGCStats(&stats) - - quantiles := make(map[float64]float64) - for idx, pq := range stats.PauseQuantiles[1:] { - quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds() - } - quantiles[0.0] = stats.PauseQuantiles[0].Seconds() - ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) - - ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) - - ms := &runtime.MemStats{} - runtime.ReadMemStats(ms) - for _, i := range c.metrics { - ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) - } -} - -// memStatsMetrics provide description, value, and value type for memstat metrics. -type memStatsMetrics []struct { - desc *Desc - eval func(*runtime.MemStats) float64 - valType ValueType -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go deleted file mode 100644 index 331783a75c..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "math" - "sort" - "sync/atomic" - - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -// A Histogram counts individual observations from an event or sample stream in -// configurable buckets. Similar to a summary, it also provides a sum of -// observations and an observation count. -// -// On the Prometheus server, quantiles can be calculated from a Histogram using -// the histogram_quantile function in the query language. -// -// Note that Histograms, in contrast to Summaries, can be aggregated with the -// Prometheus query language (see the documentation for detailed -// procedures). However, Histograms require the user to pre-define suitable -// buckets, and they are in general less accurate. The Observe method of a -// Histogram has a very low performance overhead in comparison with the Observe -// method of a Summary. -// -// To create Histogram instances, use NewHistogram. -type Histogram interface { - Metric - Collector - - // Observe adds a single observation to the histogram. - Observe(float64) -} - -// bucketLabel is used for the label that defines the upper bound of a -// bucket of a histogram ("le" -> "less or equal"). -const bucketLabel = "le" - -// DefBuckets are the default Histogram buckets. The default buckets are -// tailored to broadly measure the response time (in seconds) of a network -// service. Most likely, however, you will be required to define buckets -// customized to your use case. -var ( - DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} - - errBucketLabelNotAllowed = fmt.Errorf( - "%q is not allowed as label name in histograms", bucketLabel, - ) -) - -// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest -// bucket has an upper bound of 'start'. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. -// -// The function panics if 'count' is zero or negative. -func LinearBuckets(start, width float64, count int) []float64 { - if count < 1 { - panic("LinearBuckets needs a positive count") - } - buckets := make([]float64, count) - for i := range buckets { - buckets[i] = start - start += width - } - return buckets -} - -// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an -// upper bound of 'start' and each following bucket's upper bound is 'factor' -// times the previous bucket's upper bound. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. -// -// The function panics if 'count' is 0 or negative, if 'start' is 0 or negative, -// or if 'factor' is less than or equal 1. -func ExponentialBuckets(start, factor float64, count int) []float64 { - if count < 1 { - panic("ExponentialBuckets needs a positive count") - } - if start <= 0 { - panic("ExponentialBuckets needs a positive start value") - } - if factor <= 1 { - panic("ExponentialBuckets needs a factor greater than 1") - } - buckets := make([]float64, count) - for i := range buckets { - buckets[i] = start - start *= factor - } - return buckets -} - -// HistogramOpts bundles the options for creating a Histogram metric. It is -// mandatory to set Name and Help to a non-empty string. All other fields are -// optional and can safely be left at their zero value. -type HistogramOpts struct { - // Namespace, Subsystem, and Name are components of the fully-qualified - // name of the Histogram (created by joining these components with - // "_"). Only Name is mandatory, the others merely help structuring the - // name. Note that the fully-qualified name of the Histogram must be a - // valid Prometheus metric name. - Namespace string - Subsystem string - Name string - - // Help provides information about this Histogram. Mandatory! - // - // Metrics with the same fully-qualified name must have the same Help - // string. - Help string - - // ConstLabels are used to attach fixed labels to this metric. Metrics - // with the same fully-qualified name must have the same label names in - // their ConstLabels. - // - // ConstLabels are only used rarely. In particular, do not use them to - // attach the same labels to all your metrics. Those use cases are - // better covered by target labels set by the scraping Prometheus - // server, or by one specific metric (e.g. a build_info or a - // machine_role metric). See also - // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels - ConstLabels Labels - - // Buckets defines the buckets into which observations are counted. Each - // element in the slice is the upper inclusive bound of a bucket. The - // values must be sorted in strictly increasing order. There is no need - // to add a highest bucket with +Inf bound, it will be added - // implicitly. The default value is DefBuckets. - Buckets []float64 -} - -// NewHistogram creates a new Histogram based on the provided HistogramOpts. It -// panics if the buckets in HistogramOpts are not in strictly increasing order. -func NewHistogram(opts HistogramOpts) Histogram { - return newHistogram( - NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), - opts, - ) -} - -func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { - if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) - } - - for _, n := range desc.variableLabels { - if n == bucketLabel { - panic(errBucketLabelNotAllowed) - } - } - for _, lp := range desc.constLabelPairs { - if lp.GetName() == bucketLabel { - panic(errBucketLabelNotAllowed) - } - } - - if len(opts.Buckets) == 0 { - opts.Buckets = DefBuckets - } - - h := &histogram{ - desc: desc, - upperBounds: opts.Buckets, - labelPairs: makeLabelPairs(desc, labelValues), - } - for i, upperBound := range h.upperBounds { - if i < len(h.upperBounds)-1 { - if upperBound >= h.upperBounds[i+1] { - panic(fmt.Errorf( - "histogram buckets must be in increasing order: %f >= %f", - upperBound, h.upperBounds[i+1], - )) - } - } else { - if math.IsInf(upperBound, +1) { - // The +Inf bucket is implicit. Remove it here. - h.upperBounds = h.upperBounds[:i] - } - } - } - // Finally we know the final length of h.upperBounds and can make counts. - h.counts = make([]uint64, len(h.upperBounds)) - - h.init(h) // Init self-collection. - return h -} - -type histogram struct { - // sumBits contains the bits of the float64 representing the sum of all - // observations. sumBits and count have to go first in the struct to - // guarantee alignment for atomic operations. - // http://golang.org/pkg/sync/atomic/#pkg-note-BUG - sumBits uint64 - count uint64 - - selfCollector - // Note that there is no mutex required. - - desc *Desc - - upperBounds []float64 - counts []uint64 - - labelPairs []*dto.LabelPair -} - -func (h *histogram) Desc() *Desc { - return h.desc -} - -func (h *histogram) Observe(v float64) { - // TODO(beorn7): For small numbers of buckets (<30), a linear search is - // slightly faster than the binary search. If we really care, we could - // switch from one search strategy to the other depending on the number - // of buckets. - // - // Microbenchmarks (BenchmarkHistogramNoLabels): - // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op - // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op - // 300 buckets: 154 ns/op linear - binary 61.6 ns/op - i := sort.SearchFloat64s(h.upperBounds, v) - if i < len(h.counts) { - atomic.AddUint64(&h.counts[i], 1) - } - atomic.AddUint64(&h.count, 1) - for { - oldBits := atomic.LoadUint64(&h.sumBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + v) - if atomic.CompareAndSwapUint64(&h.sumBits, oldBits, newBits) { - break - } - } -} - -func (h *histogram) Write(out *dto.Metric) error { - his := &dto.Histogram{} - buckets := make([]*dto.Bucket, len(h.upperBounds)) - - his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&h.sumBits))) - his.SampleCount = proto.Uint64(atomic.LoadUint64(&h.count)) - var count uint64 - for i, upperBound := range h.upperBounds { - count += atomic.LoadUint64(&h.counts[i]) - buckets[i] = &dto.Bucket{ - CumulativeCount: proto.Uint64(count), - UpperBound: proto.Float64(upperBound), - } - } - his.Bucket = buckets - out.Histogram = his - out.Label = h.labelPairs - return nil -} - -// HistogramVec is a Collector that bundles a set of Histograms that all share the -// same Desc, but have different values for their variable labels. This is used -// if you want to count the same thing partitioned by various dimensions -// (e.g. HTTP request latencies, partitioned by status code and method). Create -// instances with NewHistogramVec. -type HistogramVec struct { - *metricVec -} - -// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and -// partitioned by the given label names. -func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - labelNames, - opts.ConstLabels, - ) - return &HistogramVec{ - metricVec: newMetricVec(desc, func(lvs ...string) Metric { - return newHistogram(desc, opts, lvs...) - }), - } -} - -// GetMetricWithLabelValues returns the Histogram for the given slice of label -// values (same order as the VariableLabels in Desc). If that combination of -// label values is accessed for the first time, a new Histogram is created. -// -// It is possible to call this method without using the returned Histogram to only -// create the new Histogram but leave it at its starting value, a Histogram without -// any observations. -// -// Keeping the Histogram for later use is possible (and should be considered if -// performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Histogram from the HistogramVec. In that case, the -// Histogram will still exist, but it will not be exported anymore, even if a -// Histogram with the same label values is created later. See also the CounterVec -// example. -// -// An error is returned if the number of label values is not the same as the -// number of VariableLabels in Desc (minus any curried labels). -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as -// an alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the GaugeVec example. -func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { - metric, err := v.metricVec.getMetricWithLabelValues(lvs...) - if metric != nil { - return metric.(Observer), err - } - return nil, err -} - -// GetMetricWith returns the Histogram for the given Labels map (the label names -// must match those of the VariableLabels in Desc). If that label map is -// accessed for the first time, a new Histogram is created. Implications of -// creating a Histogram without using it and keeping the Histogram for later use -// are the same as for GetMetricWithLabelValues. -// -// An error is returned if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc (minus any curried labels). -// -// This method is used for the same purpose as -// GetMetricWithLabelValues(...string). See there for pros and cons of the two -// methods. -func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { - metric, err := v.metricVec.getMetricWith(labels) - if metric != nil { - return metric.(Observer), err - } - return nil, err -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. Not returning an -// error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) -func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { - h, err := v.GetMetricWithLabelValues(lvs...) - if err != nil { - panic(err) - } - return h -} - -// With works as GetMetricWith but panics where GetMetricWithLabels would have -// returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) -func (v *HistogramVec) With(labels Labels) Observer { - h, err := v.GetMetricWith(labels) - if err != nil { - panic(err) - } - return h -} - -// CurryWith returns a vector curried with the provided labels, i.e. the -// returned vector has those labels pre-set for all labeled operations performed -// on it. The cardinality of the curried vector is reduced accordingly. The -// order of the remaining labels stays the same (just with the curried labels -// taken out of the sequence – which is relevant for the -// (GetMetric)WithLabelValues methods). It is possible to curry a curried -// vector, but only with labels not yet used for currying before. -// -// The metrics contained in the HistogramVec are shared between the curried and -// uncurried vectors. They are just accessed differently. Curried and uncurried -// vectors behave identically in terms of collection. Only one must be -// registered with a given registry (usually the uncurried version). The Reset -// method deletes all metrics, even if called on a curried vector. -func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) { - vec, err := v.curryWith(labels) - if vec != nil { - return &HistogramVec{vec}, err - } - return nil, err -} - -// MustCurryWith works as CurryWith but panics where CurryWith would have -// returned an error. -func (v *HistogramVec) MustCurryWith(labels Labels) ObserverVec { - vec, err := v.CurryWith(labels) - if err != nil { - panic(err) - } - return vec -} - -type constHistogram struct { - desc *Desc - count uint64 - sum float64 - buckets map[float64]uint64 - labelPairs []*dto.LabelPair -} - -func (h *constHistogram) Desc() *Desc { - return h.desc -} - -func (h *constHistogram) Write(out *dto.Metric) error { - his := &dto.Histogram{} - buckets := make([]*dto.Bucket, 0, len(h.buckets)) - - his.SampleCount = proto.Uint64(h.count) - his.SampleSum = proto.Float64(h.sum) - - for upperBound, count := range h.buckets { - buckets = append(buckets, &dto.Bucket{ - CumulativeCount: proto.Uint64(count), - UpperBound: proto.Float64(upperBound), - }) - } - - if len(buckets) > 0 { - sort.Sort(buckSort(buckets)) - } - his.Bucket = buckets - - out.Histogram = his - out.Label = h.labelPairs - - return nil -} - -// NewConstHistogram returns a metric representing a Prometheus histogram with -// fixed values for the count, sum, and bucket counts. As those parameters -// cannot be changed, the returned value does not implement the Histogram -// interface (but only the Metric interface). Users of this package will not -// have much use for it in regular operations. However, when implementing custom -// Collectors, it is useful as a throw-away metric that is generated on the fly -// to send it to Prometheus in the Collect method. -// -// buckets is a map of upper bounds to cumulative counts, excluding the +Inf -// bucket. -// -// NewConstHistogram returns an error if the length of labelValues is not -// consistent with the variable labels in Desc. -func NewConstHistogram( - desc *Desc, - count uint64, - sum float64, - buckets map[float64]uint64, - labelValues ...string, -) (Metric, error) { - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { - return nil, err - } - return &constHistogram{ - desc: desc, - count: count, - sum: sum, - buckets: buckets, - labelPairs: makeLabelPairs(desc, labelValues), - }, nil -} - -// MustNewConstHistogram is a version of NewConstHistogram that panics where -// NewConstMetric would have returned an error. -func MustNewConstHistogram( - desc *Desc, - count uint64, - sum float64, - buckets map[float64]uint64, - labelValues ...string, -) Metric { - m, err := NewConstHistogram(desc, count, sum, buckets, labelValues...) - if err != nil { - panic(err) - } - return m -} - -type buckSort []*dto.Bucket - -func (s buckSort) Len() int { - return len(s) -} - -func (s buckSort) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s buckSort) Less(i, j int) bool { - return s[i].GetUpperBound() < s[j].GetUpperBound() -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go deleted file mode 100644 index dd0f8197f9..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/http.go +++ /dev/null @@ -1,523 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "bufio" - "bytes" - "compress/gzip" - "fmt" - "io" - "net" - "net/http" - "strconv" - "strings" - "sync" - "time" - - "github.com/prometheus/common/expfmt" -) - -// TODO(beorn7): Remove this whole file. It is a partial mirror of -// promhttp/http.go (to avoid circular import chains) where everything HTTP -// related should live. The functions here are just for avoiding -// breakage. Everything is deprecated. - -const ( - contentTypeHeader = "Content-Type" - contentLengthHeader = "Content-Length" - contentEncodingHeader = "Content-Encoding" - acceptEncodingHeader = "Accept-Encoding" -) - -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) -} - -// Handler returns an HTTP handler for the DefaultGatherer. It is -// already instrumented with InstrumentHandler (using "prometheus" as handler -// name). -// -// Deprecated: Please note the issues described in the doc comment of -// InstrumentHandler. You might want to consider using -// promhttp.InstrumentedHandler instead. -func Handler() http.Handler { - return InstrumentHandler("prometheus", UninstrumentedHandler()) -} - -// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer. -// -// Deprecated: Use promhttp.Handler instead. See there for further documentation. -func UninstrumentedHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - mfs, err := DefaultGatherer.Gather() - if err != nil { - http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - - contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf) - enc := expfmt.NewEncoder(writer, contentType) - var lastErr error - for _, mf := range mfs { - if err := enc.Encode(mf); err != nil { - lastErr = err - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - w.Write(buf.Bytes()) - }) -} - -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) { - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") - for _, part := range parts { - part := strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" - } - } - return writer, "" -} - -var instLabels = []string{"method", "code"} - -type nower interface { - Now() time.Time -} - -type nowFunc func() time.Time - -func (n nowFunc) Now() time.Time { - return n() -} - -var now nower = nowFunc(func() time.Time { - return time.Now() -}) - -func nowSeries(t ...time.Time) nower { - return nowFunc(func() time.Time { - defer func() { - t = t[1:] - }() - - return t[0] - }) -} - -// InstrumentHandler wraps the given HTTP handler for instrumentation. It -// registers four metric collectors (if not already done) and reports HTTP -// metrics to the (newly or already) registered collectors: http_requests_total -// (CounterVec), http_request_duration_microseconds (Summary), -// http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each -// has a constant label named "handler" with the provided handlerName as -// value. http_requests_total is a metric vector partitioned by HTTP method -// (label name "method") and HTTP status code (label name "code"). -// -// Deprecated: InstrumentHandler has several issues. Use the tooling provided in -// package promhttp instead. The issues are the following: -// -// - It uses Summaries rather than Histograms. Summaries are not useful if -// aggregation across multiple instances is required. -// -// - It uses microseconds as unit, which is deprecated and should be replaced by -// seconds. -// -// - The size of the request is calculated in a separate goroutine. Since this -// calculator requires access to the request header, it creates a race with -// any writes to the header performed during request handling. -// httputil.ReverseProxy is a prominent example for a handler -// performing such writes. -// -// - It has additional issues with HTTP/2, cf. -// https://github.com/prometheus/client_golang/issues/272. -func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc { - return InstrumentHandlerFunc(handlerName, handler.ServeHTTP) -} - -// InstrumentHandlerFunc wraps the given function for instrumentation. It -// otherwise works in the same way as InstrumentHandler (and shares the same -// issues). -// -// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as -// InstrumentHandler is. Use the tooling provided in package promhttp instead. -func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - return InstrumentHandlerFuncWithOpts( - SummaryOpts{ - Subsystem: "http", - ConstLabels: Labels{"handler": handlerName}, - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }, - handlerFunc, - ) -} - -// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same -// issues) but provides more flexibility (at the cost of a more complex call -// syntax). As InstrumentHandler, this function registers four metric -// collectors, but it uses the provided SummaryOpts to create them. However, the -// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced -// by "requests_total", "request_duration_microseconds", "request_size_bytes", -// and "response_size_bytes", respectively. "Help" is replaced by an appropriate -// help string. The names of the variable labels of the http_requests_total -// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code). -// -// If InstrumentHandlerWithOpts is called as follows, it mimics exactly the -// behavior of InstrumentHandler: -// -// prometheus.InstrumentHandlerWithOpts( -// prometheus.SummaryOpts{ -// Subsystem: "http", -// ConstLabels: prometheus.Labels{"handler": handlerName}, -// }, -// handler, -// ) -// -// Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it -// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally, -// and all its fields are set to the equally named fields in the provided -// SummaryOpts. -// -// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as -// InstrumentHandler is. Use the tooling provided in package promhttp instead. -func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc { - return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP) -} - -// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares -// the same issues) but provides more flexibility (at the cost of a more complex -// call syntax). See InstrumentHandlerWithOpts for details how the provided -// SummaryOpts are used. -// -// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons -// as InstrumentHandler is. Use the tooling provided in package promhttp instead. -func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - reqCnt := NewCounterVec( - CounterOpts{ - Namespace: opts.Namespace, - Subsystem: opts.Subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: opts.ConstLabels, - }, - instLabels, - ) - if err := Register(reqCnt); err != nil { - if are, ok := err.(AlreadyRegisteredError); ok { - reqCnt = are.ExistingCollector.(*CounterVec) - } else { - panic(err) - } - } - - opts.Name = "request_duration_microseconds" - opts.Help = "The HTTP request latencies in microseconds." - reqDur := NewSummary(opts) - if err := Register(reqDur); err != nil { - if are, ok := err.(AlreadyRegisteredError); ok { - reqDur = are.ExistingCollector.(Summary) - } else { - panic(err) - } - } - - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - reqSz := NewSummary(opts) - if err := Register(reqSz); err != nil { - if are, ok := err.(AlreadyRegisteredError); ok { - reqSz = are.ExistingCollector.(Summary) - } else { - panic(err) - } - } - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - resSz := NewSummary(opts) - if err := Register(resSz); err != nil { - if are, ok := err.(AlreadyRegisteredError); ok { - resSz = are.ExistingCollector.(Summary) - } else { - panic(err) - } - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - - delegate := &responseWriterDelegator{ResponseWriter: w} - out := computeApproximateRequestSize(r) - - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, rf := w.(io.ReaderFrom) - var rw http.ResponseWriter - if cn && fl && hj && rf { - rw = &fancyResponseWriterDelegator{delegate} - } else { - rw = delegate - } - handlerFunc(rw, r) - - elapsed := float64(time.Since(now)) / float64(time.Microsecond) - - method := sanitizeMethod(r.Method) - code := sanitizeCode(delegate.status) - reqCnt.WithLabelValues(method, code).Inc() - reqDur.Observe(elapsed) - resSz.Observe(float64(delegate.written)) - reqSz.Observe(float64(<-out)) - }) -} - -func computeApproximateRequestSize(r *http.Request) <-chan int { - // Get URL length in current go routine for avoiding a race condition. - // HandlerFunc that runs in parallel may modify the URL. - s := 0 - if r.URL != nil { - s += len(r.URL.String()) - } - - out := make(chan int, 1) - - go func() { - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - out <- s - close(out) - }() - - return out -} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type fancyResponseWriterDelegator struct { - *responseWriterDelegator -} - -func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool { - return f.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -func (f *fancyResponseWriterDelegator) Flush() { - f.ResponseWriter.(http.Flusher).Flush() -} - -func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return f.ResponseWriter.(http.Hijacker).Hijack() -} - -func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) { - if !f.wroteHeader { - f.WriteHeader(http.StatusOK) - } - n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r) - f.written += n - return n, err -} - -func sanitizeMethod(m string) string { - switch m { - case "GET", "get": - return "get" - case "PUT", "put": - return "put" - case "HEAD", "head": - return "head" - case "POST", "post": - return "post" - case "DELETE", "delete": - return "delete" - case "CONNECT", "connect": - return "connect" - case "OPTIONS", "options": - return "options" - case "NOTIFY", "notify": - return "notify" - default: - return strings.ToLower(m) - } -} - -func sanitizeCode(s int) string { - switch s { - case 100: - return "100" - case 101: - return "101" - - case 200: - return "200" - case 201: - return "201" - case 202: - return "202" - case 203: - return "203" - case 204: - return "204" - case 205: - return "205" - case 206: - return "206" - - case 300: - return "300" - case 301: - return "301" - case 302: - return "302" - case 304: - return "304" - case 305: - return "305" - case 307: - return "307" - - case 400: - return "400" - case 401: - return "401" - case 402: - return "402" - case 403: - return "403" - case 404: - return "404" - case 405: - return "405" - case 406: - return "406" - case 407: - return "407" - case 408: - return "408" - case 409: - return "409" - case 410: - return "410" - case 411: - return "411" - case 412: - return "412" - case 413: - return "413" - case 414: - return "414" - case 415: - return "415" - case 416: - return "416" - case 417: - return "417" - case 418: - return "418" - - case 500: - return "500" - case 501: - return "501" - case 502: - return "502" - case 503: - return "503" - case 504: - return "504" - case 505: - return "505" - - case 428: - return "428" - case 429: - return "429" - case 431: - return "431" - case 511: - return "511" - - default: - return strconv.Itoa(s) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go deleted file mode 100644 index 2502e37348..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/labels.go +++ /dev/null @@ -1,57 +0,0 @@ -package prometheus - -import ( - "errors" - "fmt" - "strings" - "unicode/utf8" - - "github.com/prometheus/common/model" -) - -// Labels represents a collection of label name -> value mappings. This type is -// commonly used with the With(Labels) and GetMetricWith(Labels) methods of -// metric vector Collectors, e.g.: -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) -// -// The other use-case is the specification of constant label pairs in Opts or to -// create a Desc. -type Labels map[string]string - -// reservedLabelPrefix is a prefix which is not legal in user-supplied -// label names. -const reservedLabelPrefix = "__" - -var errInconsistentCardinality = errors.New("inconsistent label cardinality") - -func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { - if len(labels) != expectedNumberOfValues { - return errInconsistentCardinality - } - - for name, val := range labels { - if !utf8.ValidString(val) { - return fmt.Errorf("label %s: value %q is not valid UTF-8", name, val) - } - } - - return nil -} - -func validateLabelValues(vals []string, expectedNumberOfValues int) error { - if len(vals) != expectedNumberOfValues { - return errInconsistentCardinality - } - - for _, val := range vals { - if !utf8.ValidString(val) { - return fmt.Errorf("label value %q is not valid UTF-8", val) - } - } - - return nil -} - -func checkLabelName(l string) bool { - return model.LabelName(l).IsValid() && !strings.HasPrefix(l, reservedLabelPrefix) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go deleted file mode 100644 index 6213ee8127..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "strings" - - dto "github.com/prometheus/client_model/go" -) - -const separatorByte byte = 255 - -// A Metric models a single sample value with its meta data being exported to -// Prometheus. Implementations of Metric in this package are Gauge, Counter, -// Histogram, Summary, and Untyped. -type Metric interface { - // Desc returns the descriptor for the Metric. This method idempotently - // returns the same descriptor throughout the lifetime of the - // Metric. The returned descriptor is immutable by contract. A Metric - // unable to describe itself must return an invalid descriptor (created - // with NewInvalidDesc). - Desc() *Desc - // Write encodes the Metric into a "Metric" Protocol Buffer data - // transmission object. - // - // Metric implementations must observe concurrency safety as reads of - // this metric may occur at any time, and any blocking occurs at the - // expense of total performance of rendering all registered - // metrics. Ideally, Metric implementations should support concurrent - // readers. - // - // While populating dto.Metric, it is the responsibility of the - // implementation to ensure validity of the Metric protobuf (like valid - // UTF-8 strings or syntactically valid metric and label names). It is - // recommended to sort labels lexicographically. (Implementers may find - // LabelPairSorter useful for that.) Callers of Write should still make - // sure of sorting if they depend on it. - Write(*dto.Metric) error - // TODO(beorn7): The original rationale of passing in a pre-allocated - // dto.Metric protobuf to save allocations has disappeared. The - // signature of this method should be changed to "Write() (*dto.Metric, - // error)". -} - -// Opts bundles the options for creating most Metric types. Each metric -// implementation XXX has its own XXXOpts type, but in most cases, it is just be -// an alias of this type (which might change when the requirement arises.) -// -// It is mandatory to set Name and Help to a non-empty string. All other fields -// are optional and can safely be left at their zero value. -type Opts struct { - // Namespace, Subsystem, and Name are components of the fully-qualified - // name of the Metric (created by joining these components with - // "_"). Only Name is mandatory, the others merely help structuring the - // name. Note that the fully-qualified name of the metric must be a - // valid Prometheus metric name. - Namespace string - Subsystem string - Name string - - // Help provides information about this metric. Mandatory! - // - // Metrics with the same fully-qualified name must have the same Help - // string. - Help string - - // ConstLabels are used to attach fixed labels to this metric. Metrics - // with the same fully-qualified name must have the same label names in - // their ConstLabels. - // - // ConstLabels are only used rarely. In particular, do not use them to - // attach the same labels to all your metrics. Those use cases are - // better covered by target labels set by the scraping Prometheus - // server, or by one specific metric (e.g. a build_info or a - // machine_role metric). See also - // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels - ConstLabels Labels -} - -// BuildFQName joins the given three name components by "_". Empty name -// components are ignored. If the name parameter itself is empty, an empty -// string is returned, no matter what. Metric implementations included in this -// library use this function internally to generate the fully-qualified metric -// name from the name component in their Opts. Users of the library will only -// need this function if they implement their own Metric or instantiate a Desc -// (with NewDesc) directly. -func BuildFQName(namespace, subsystem, name string) string { - if name == "" { - return "" - } - switch { - case namespace != "" && subsystem != "": - return strings.Join([]string{namespace, subsystem, name}, "_") - case namespace != "": - return strings.Join([]string{namespace, name}, "_") - case subsystem != "": - return strings.Join([]string{subsystem, name}, "_") - } - return name -} - -// LabelPairSorter implements sort.Interface. It is used to sort a slice of -// dto.LabelPair pointers. This is useful for implementing the Write method of -// custom metrics. -type LabelPairSorter []*dto.LabelPair - -func (s LabelPairSorter) Len() int { - return len(s) -} - -func (s LabelPairSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s LabelPairSorter) Less(i, j int) bool { - return s[i].GetName() < s[j].GetName() -} - -type hashSorter []uint64 - -func (s hashSorter) Len() int { - return len(s) -} - -func (s hashSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s hashSorter) Less(i, j int) bool { - return s[i] < s[j] -} - -type invalidMetric struct { - desc *Desc - err error -} - -// NewInvalidMetric returns a metric whose Write method always returns the -// provided error. It is useful if a Collector finds itself unable to collect -// a metric and wishes to report an error to the registry. -func NewInvalidMetric(desc *Desc, err error) Metric { - return &invalidMetric{desc, err} -} - -func (m *invalidMetric) Desc() *Desc { return m.desc } - -func (m *invalidMetric) Write(*dto.Metric) error { return m.err } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/observer.go b/vendor/github.com/prometheus/client_golang/prometheus/observer.go deleted file mode 100644 index 5806cd09e3..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/observer.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -// Observer is the interface that wraps the Observe method, which is used by -// Histogram and Summary to add observations. -type Observer interface { - Observe(float64) -} - -// The ObserverFunc type is an adapter to allow the use of ordinary -// functions as Observers. If f is a function with the appropriate -// signature, ObserverFunc(f) is an Observer that calls f. -// -// This adapter is usually used in connection with the Timer type, and there are -// two general use cases: -// -// The most common one is to use a Gauge as the Observer for a Timer. -// See the "Gauge" Timer example. -// -// The more advanced use case is to create a function that dynamically decides -// which Observer to use for observing the duration. See the "Complex" Timer -// example. -type ObserverFunc func(float64) - -// Observe calls f(value). It implements Observer. -func (f ObserverFunc) Observe(value float64) { - f(value) -} - -// ObserverVec is an interface implemented by `HistogramVec` and `SummaryVec`. -type ObserverVec interface { - GetMetricWith(Labels) (Observer, error) - GetMetricWithLabelValues(lvs ...string) (Observer, error) - With(Labels) Observer - WithLabelValues(...string) Observer - CurryWith(Labels) (ObserverVec, error) - MustCurryWith(Labels) ObserverVec - - Collector -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go deleted file mode 100644 index 32ac74a7f7..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import "github.com/prometheus/procfs" - -type processCollector struct { - pid int - collectFn func(chan<- Metric) - pidFn func() (int, error) - cpuTotal *Desc - openFDs, maxFDs *Desc - vsize, rss *Desc - startTime *Desc -} - -// NewProcessCollector returns a collector which exports the current state of -// process metrics including CPU, memory and file descriptor usage as well as -// the process start time for the given process ID under the given namespace. -// -// Currently, the collector depends on a Linux-style proc filesystem and -// therefore only exports metrics for Linux. -func NewProcessCollector(pid int, namespace string) Collector { - return NewProcessCollectorPIDFn( - func() (int, error) { return pid, nil }, - namespace, - ) -} - -// NewProcessCollectorPIDFn works like NewProcessCollector but the process ID is -// determined on each collect anew by calling the given pidFn function. -func NewProcessCollectorPIDFn( - pidFn func() (int, error), - namespace string, -) Collector { - ns := "" - if len(namespace) > 0 { - ns = namespace + "_" - } - - c := processCollector{ - pidFn: pidFn, - collectFn: func(chan<- Metric) {}, - - cpuTotal: NewDesc( - ns+"process_cpu_seconds_total", - "Total user and system CPU time spent in seconds.", - nil, nil, - ), - openFDs: NewDesc( - ns+"process_open_fds", - "Number of open file descriptors.", - nil, nil, - ), - maxFDs: NewDesc( - ns+"process_max_fds", - "Maximum number of open file descriptors.", - nil, nil, - ), - vsize: NewDesc( - ns+"process_virtual_memory_bytes", - "Virtual memory size in bytes.", - nil, nil, - ), - rss: NewDesc( - ns+"process_resident_memory_bytes", - "Resident memory size in bytes.", - nil, nil, - ), - startTime: NewDesc( - ns+"process_start_time_seconds", - "Start time of the process since unix epoch in seconds.", - nil, nil, - ), - } - - // Set up process metric collection if supported by the runtime. - if _, err := procfs.NewStat(); err == nil { - c.collectFn = c.processCollect - } - - return &c -} - -// Describe returns all descriptions of the collector. -func (c *processCollector) Describe(ch chan<- *Desc) { - ch <- c.cpuTotal - ch <- c.openFDs - ch <- c.maxFDs - ch <- c.vsize - ch <- c.rss - ch <- c.startTime -} - -// Collect returns the current state of all metrics of the collector. -func (c *processCollector) Collect(ch chan<- Metric) { - c.collectFn(ch) -} - -// TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the -// client allows users to configure the error behavior. -func (c *processCollector) processCollect(ch chan<- Metric) { - pid, err := c.pidFn() - if err != nil { - return - } - - p, err := procfs.NewProc(pid) - if err != nil { - return - } - - if stat, err := p.NewStat(); err == nil { - ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime()) - ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory())) - ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory())) - if startTime, err := stat.StartTime(); err == nil { - ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) - } - } - - if fds, err := p.FileDescriptorsLen(); err == nil { - ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds)) - } - - if limits, err := p.NewLimits(); err == nil { - ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles)) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go deleted file mode 100644 index 9c1c66dcc7..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promhttp - -import ( - "bufio" - "io" - "net" - "net/http" -) - -const ( - closeNotifier = 1 << iota - flusher - hijacker - readerFrom - pusher -) - -type delegator interface { - http.ResponseWriter - - Status() int - Written() int64 -} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool - observeWriteHeader func(int) -} - -func (r *responseWriterDelegator) Status() int { - return r.status -} - -func (r *responseWriterDelegator) Written() int64 { - return r.written -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) - if r.observeWriteHeader != nil { - r.observeWriteHeader(code) - } -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type closeNotifierDelegator struct{ *responseWriterDelegator } -type flusherDelegator struct{ *responseWriterDelegator } -type hijackerDelegator struct{ *responseWriterDelegator } -type readerFromDelegator struct{ *responseWriterDelegator } - -func (d *closeNotifierDelegator) CloseNotify() <-chan bool { - return d.ResponseWriter.(http.CloseNotifier).CloseNotify() -} -func (d *flusherDelegator) Flush() { - d.ResponseWriter.(http.Flusher).Flush() -} -func (d *hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return d.ResponseWriter.(http.Hijacker).Hijack() -} -func (d *readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { - if !d.wroteHeader { - d.WriteHeader(http.StatusOK) - } - n, err := d.ResponseWriter.(io.ReaderFrom).ReadFrom(re) - d.written += n - return n, err -} - -var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32) - -func init() { - // TODO(beorn7): Code generation would help here. - pickDelegator[0] = func(d *responseWriterDelegator) delegator { // 0 - return d - } - pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1 - return &closeNotifierDelegator{d} - } - pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2 - return &flusherDelegator{d} - } - pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3 - return struct { - *responseWriterDelegator - http.Flusher - http.CloseNotifier - }{d, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4 - return &hijackerDelegator{d} - } - pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5 - return struct { - *responseWriterDelegator - http.Hijacker - http.CloseNotifier - }{d, &hijackerDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6 - return struct { - *responseWriterDelegator - http.Hijacker - http.Flusher - }{d, &hijackerDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7 - return struct { - *responseWriterDelegator - http.Hijacker - http.Flusher - http.CloseNotifier - }{d, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8 - return readerFromDelegator{d} - } - pickDelegator[readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 9 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.CloseNotifier - }{d, &readerFromDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Flusher - }{d, &readerFromDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Flusher - http.CloseNotifier - }{d, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Hijacker - }{d, &readerFromDelegator{d}, &hijackerDelegator{d}} - } - pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Hijacker - http.CloseNotifier - }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Hijacker - http.Flusher - }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15 - return struct { - *responseWriterDelegator - io.ReaderFrom - http.Hijacker - http.Flusher - http.CloseNotifier - }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go deleted file mode 100644 index 75a905e2f4..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build go1.8 - -package promhttp - -import ( - "io" - "net/http" -) - -type pusherDelegator struct{ *responseWriterDelegator } - -func (d *pusherDelegator) Push(target string, opts *http.PushOptions) error { - return d.ResponseWriter.(http.Pusher).Push(target, opts) -} - -func init() { - pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16 - return &pusherDelegator{d} - } - pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17 - return struct { - *responseWriterDelegator - http.Pusher - http.CloseNotifier - }{d, &pusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18 - return struct { - *responseWriterDelegator - http.Pusher - http.Flusher - }{d, &pusherDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19 - return struct { - *responseWriterDelegator - http.Pusher - http.Flusher - http.CloseNotifier - }{d, &pusherDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20 - return struct { - *responseWriterDelegator - http.Pusher - http.Hijacker - }{d, &pusherDelegator{d}, &hijackerDelegator{d}} - } - pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21 - return struct { - *responseWriterDelegator - http.Pusher - http.Hijacker - http.CloseNotifier - }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22 - return struct { - *responseWriterDelegator - http.Pusher - http.Hijacker - http.Flusher - }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 - return struct { - *responseWriterDelegator - http.Pusher - http.Hijacker - http.Flusher - http.CloseNotifier - }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - }{d, &pusherDelegator{d}, &readerFromDelegator{d}} - } - pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.CloseNotifier - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Flusher - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Flusher - http.CloseNotifier - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Hijacker - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}} - } - pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Hijacker - http.CloseNotifier - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}} - } - pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Hijacker - http.Flusher - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}} - } - pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31 - return struct { - *responseWriterDelegator - http.Pusher - io.ReaderFrom - http.Hijacker - http.Flusher - http.CloseNotifier - }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}} - } -} - -func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { - d := &responseWriterDelegator{ - ResponseWriter: w, - observeWriteHeader: observeWriteHeaderFunc, - } - - id := 0 - if _, ok := w.(http.CloseNotifier); ok { - id += closeNotifier - } - if _, ok := w.(http.Flusher); ok { - id += flusher - } - if _, ok := w.(http.Hijacker); ok { - id += hijacker - } - if _, ok := w.(io.ReaderFrom); ok { - id += readerFrom - } - if _, ok := w.(http.Pusher); ok { - id += pusher - } - - return pickDelegator[id](d) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go deleted file mode 100644 index 8bb9b8b68f..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build !go1.8 - -package promhttp - -import ( - "io" - "net/http" -) - -func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { - d := &responseWriterDelegator{ - ResponseWriter: w, - observeWriteHeader: observeWriteHeaderFunc, - } - - id := 0 - if _, ok := w.(http.CloseNotifier); ok { - id += closeNotifier - } - if _, ok := w.(http.Flusher); ok { - id += flusher - } - if _, ok := w.(http.Hijacker); ok { - id += hijacker - } - if _, ok := w.(io.ReaderFrom); ok { - id += readerFrom - } - - return pickDelegator[id](d) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go deleted file mode 100644 index 714a7f98a7..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package promhttp provides tooling around HTTP servers and clients. -// -// First, the package allows the creation of http.Handler instances to expose -// Prometheus metrics via HTTP. promhttp.Handler acts on the -// prometheus.DefaultGatherer. With HandlerFor, you can create a handler for a -// custom registry or anything that implements the Gatherer interface. It also -// allows the creation of handlers that act differently on errors or allow to -// log errors. -// -// Second, the package provides tooling to instrument instances of http.Handler -// via middleware. Middleware wrappers follow the naming scheme -// InstrumentHandlerX, where X describes the intended use of the middleware. -// See each function's doc comment for specific details. -// -// Finally, the package allows for an http.RoundTripper to be instrumented via -// middleware. Middleware wrappers follow the naming scheme -// InstrumentRoundTripperX, where X describes the intended use of the -// middleware. See each function's doc comment for specific details. -package promhttp - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "net/http" - "strings" - "sync" - "time" - - "github.com/prometheus/common/expfmt" - - "github.com/prometheus/client_golang/prometheus" -) - -const ( - contentTypeHeader = "Content-Type" - contentLengthHeader = "Content-Length" - contentEncodingHeader = "Content-Encoding" - acceptEncodingHeader = "Accept-Encoding" -) - -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) -} - -// Handler returns an http.Handler for the prometheus.DefaultGatherer, using -// default HandlerOpts, i.e. it reports the first error as an HTTP error, it has -// no error logging, and it applies compression if requested by the client. -// -// The returned http.Handler is already instrumented using the -// InstrumentMetricHandler function and the prometheus.DefaultRegisterer. If you -// create multiple http.Handlers by separate calls of the Handler function, the -// metrics used for instrumentation will be shared between them, providing -// global scrape counts. -// -// This function is meant to cover the bulk of basic use cases. If you are doing -// anything that requires more customization (including using a non-default -// Gatherer, different instrumentation, and non-default HandlerOpts), use the -// HandlerFor function. See there for details. -func Handler() http.Handler { - return InstrumentMetricHandler( - prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}), - ) -} - -// HandlerFor returns an uninstrumented http.Handler for the provided -// Gatherer. The behavior of the Handler is defined by the provided -// HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom -// Gatherers, with non-default HandlerOpts, and/or with custom (or no) -// instrumentation. Use the InstrumentMetricHandler function to apply the same -// kind of instrumentation as it is used by the Handler function. -func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { - var inFlightSem chan struct{} - if opts.MaxRequestsInFlight > 0 { - inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight) - } - - h := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if inFlightSem != nil { - select { - case inFlightSem <- struct{}{}: // All good, carry on. - defer func() { <-inFlightSem }() - default: - http.Error(w, fmt.Sprintf( - "Limit of concurrent requests reached (%d), try again later.", opts.MaxRequestsInFlight, - ), http.StatusServiceUnavailable) - return - } - } - - mfs, err := reg.Gather() - if err != nil { - if opts.ErrorLog != nil { - opts.ErrorLog.Println("error gathering metrics:", err) - } - switch opts.ErrorHandling { - case PanicOnError: - panic(err) - case ContinueOnError: - if len(mfs) == 0 { - http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - } - - contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf, opts.DisableCompression) - enc := expfmt.NewEncoder(writer, contentType) - var lastErr error - for _, mf := range mfs { - if err := enc.Encode(mf); err != nil { - lastErr = err - if opts.ErrorLog != nil { - opts.ErrorLog.Println("error encoding metric family:", err) - } - switch opts.ErrorHandling { - case PanicOnError: - panic(err) - case ContinueOnError: - // Handled later. - case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - } - } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - if _, err := w.Write(buf.Bytes()); err != nil && opts.ErrorLog != nil { - opts.ErrorLog.Println("error while sending encoded metrics:", err) - } - // TODO(beorn7): Consider streaming serving of metrics. - }) - - if opts.Timeout <= 0 { - return h - } - return http.TimeoutHandler(h, opts.Timeout, fmt.Sprintf( - "Exceeded configured timeout of %v.\n", - opts.Timeout, - )) -} - -// InstrumentMetricHandler is usually used with an http.Handler returned by the -// HandlerFor function. It instruments the provided http.Handler with two -// metrics: A counter vector "promhttp_metric_handler_requests_total" to count -// scrapes partitioned by HTTP status code, and a gauge -// "promhttp_metric_handler_requests_in_flight" to track the number of -// simultaneous scrapes. This function idempotently registers collectors for -// both metrics with the provided Registerer. It panics if the registration -// fails. The provided metrics are useful to see how many scrapes hit the -// monitored target (which could be from different Prometheus servers or other -// scrapers), and how often they overlap (which would result in more than one -// scrape in flight at the same time). Note that the scrapes-in-flight gauge -// will contain the scrape by which it is exposed, while the scrape counter will -// only get incremented after the scrape is complete (as only then the status -// code is known). For tracking scrape durations, use the -// "scrape_duration_seconds" gauge created by the Prometheus server upon each -// scrape. -func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) http.Handler { - cnt := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "promhttp_metric_handler_requests_total", - Help: "Total number of scrapes by HTTP status code.", - }, - []string{"code"}, - ) - // Initialize the most likely HTTP status codes. - cnt.WithLabelValues("200") - cnt.WithLabelValues("500") - cnt.WithLabelValues("503") - if err := reg.Register(cnt); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - cnt = are.ExistingCollector.(*prometheus.CounterVec) - } else { - panic(err) - } - } - - gge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "promhttp_metric_handler_requests_in_flight", - Help: "Current number of scrapes being served.", - }) - if err := reg.Register(gge); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - gge = are.ExistingCollector.(prometheus.Gauge) - } else { - panic(err) - } - } - - return InstrumentHandlerCounter(cnt, InstrumentHandlerInFlight(gge, handler)) -} - -// HandlerErrorHandling defines how a Handler serving metrics will handle -// errors. -type HandlerErrorHandling int - -// These constants cause handlers serving metrics to behave as described if -// errors are encountered. -const ( - // Serve an HTTP status code 500 upon the first error - // encountered. Report the error message in the body. - HTTPErrorOnError HandlerErrorHandling = iota - // Ignore errors and try to serve as many metrics as possible. However, - // if no metrics can be served, serve an HTTP status code 500 and the - // last error message in the body. Only use this in deliberate "best - // effort" metrics collection scenarios. It is recommended to at least - // log errors (by providing an ErrorLog in HandlerOpts) to not mask - // errors completely. - ContinueOnError - // Panic upon the first error encountered (useful for "crash only" apps). - PanicOnError -) - -// Logger is the minimal interface HandlerOpts needs for logging. Note that -// log.Logger from the standard library implements this interface, and it is -// easy to implement by custom loggers, if they don't do so already anyway. -type Logger interface { - Println(v ...interface{}) -} - -// HandlerOpts specifies options how to serve metrics via an http.Handler. The -// zero value of HandlerOpts is a reasonable default. -type HandlerOpts struct { - // ErrorLog specifies an optional logger for errors collecting and - // serving metrics. If nil, errors are not logged at all. - ErrorLog Logger - // ErrorHandling defines how errors are handled. Note that errors are - // logged regardless of the configured ErrorHandling provided ErrorLog - // is not nil. - ErrorHandling HandlerErrorHandling - // If DisableCompression is true, the handler will never compress the - // response, even if requested by the client. - DisableCompression bool - // The number of concurrent HTTP requests is limited to - // MaxRequestsInFlight. Additional requests are responded to with 503 - // Service Unavailable and a suitable message in the body. If - // MaxRequestsInFlight is 0 or negative, no limit is applied. - MaxRequestsInFlight int - // If handling a request takes longer than Timeout, it is repsonded to - // with 503 ServiceUnavailable and a suitable Message. No timeout is - // applied if Timeout is 0 or negative. Note that with the current - // implementation, reaching the timeout simply ends the HTTP requests as - // described above (and even that only if sending of the body hasn't - // started yet), while the bulk work of gathering all the metrics keeps - // running in the background (with the eventual result to be thrown - // away). Until the implementation is improved, it is recommended to - // implement a separate timeout in potentially slow Collectors. - Timeout time.Duration -} - -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) { - if compressionDisabled { - return writer, "" - } - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") - for _, part := range parts { - part := strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" - } - } - return writer, "" -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go deleted file mode 100644 index 86fd564470..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promhttp - -import ( - "net/http" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -// The RoundTripperFunc type is an adapter to allow the use of ordinary -// functions as RoundTrippers. If f is a function with the appropriate -// signature, RountTripperFunc(f) is a RoundTripper that calls f. -type RoundTripperFunc func(req *http.Request) (*http.Response, error) - -// RoundTrip implements the RoundTripper interface. -func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { - return rt(r) -} - -// InstrumentRoundTripperInFlight is a middleware that wraps the provided -// http.RoundTripper. It sets the provided prometheus.Gauge to the number of -// requests currently handled by the wrapped http.RoundTripper. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - gauge.Inc() - defer gauge.Dec() - return next.RoundTrip(r) - }) -} - -// InstrumentRoundTripperCounter is a middleware that wraps the provided -// http.RoundTripper to observe the request result with the provided CounterVec. -// The CounterVec must have zero, one, or two non-const non-curried labels. For -// those, the only allowed label names are "code" and "method". The function -// panics otherwise. Partitioning of the CounterVec happens by HTTP status code -// and/or HTTP method if the respective instance label names are present in the -// CounterVec. For unpartitioned counting, use a CounterVec with zero labels. -// -// If the wrapped RoundTripper panics or returns a non-nil error, the Counter -// is not incremented. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { - code, method := checkLabels(counter) - - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - resp, err := next.RoundTrip(r) - if err == nil { - counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() - } - return resp, err - }) -} - -// InstrumentRoundTripperDuration is a middleware that wraps the provided -// http.RoundTripper to observe the request duration with the provided -// ObserverVec. The ObserverVec must have zero, one, or two non-const -// non-curried labels. For those, the only allowed label names are "code" and -// "method". The function panics otherwise. The Observe method of the Observer -// in the ObserverVec is called with the request duration in -// seconds. Partitioning happens by HTTP status code and/or HTTP method if the -// respective instance label names are present in the ObserverVec. For -// unpartitioned observations, use an ObserverVec with zero labels. Note that -// partitioning of Histograms is expensive and should be used judiciously. -// -// If the wrapped RoundTripper panics or returns a non-nil error, no values are -// reported. -// -// Note that this method is only guaranteed to never observe negative durations -// if used with Go1.9+. -func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { - code, method := checkLabels(obs) - - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - start := time.Now() - resp, err := next.RoundTrip(r) - if err == nil { - obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) - } - return resp, err - }) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go deleted file mode 100644 index 0bd80c3552..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build go1.8 - -package promhttp - -import ( - "context" - "crypto/tls" - "net/http" - "net/http/httptrace" - "time" -) - -// InstrumentTrace is used to offer flexibility in instrumenting the available -// httptrace.ClientTrace hook functions. Each function is passed a float64 -// representing the time in seconds since the start of the http request. A user -// may choose to use separately buckets Histograms, or implement custom -// instance labels on a per function basis. -type InstrumentTrace struct { - GotConn func(float64) - PutIdleConn func(float64) - GotFirstResponseByte func(float64) - Got100Continue func(float64) - DNSStart func(float64) - DNSDone func(float64) - ConnectStart func(float64) - ConnectDone func(float64) - TLSHandshakeStart func(float64) - TLSHandshakeDone func(float64) - WroteHeaders func(float64) - Wait100Continue func(float64) - WroteRequest func(float64) -} - -// InstrumentRoundTripperTrace is a middleware that wraps the provided -// RoundTripper and reports times to hook functions provided in the -// InstrumentTrace struct. Hook functions that are not present in the provided -// InstrumentTrace struct are ignored. Times reported to the hook functions are -// time since the start of the request. Only with Go1.9+, those times are -// guaranteed to never be negative. (Earlier Go versions are not using a -// monotonic clock.) Note that partitioning of Histograms is expensive and -// should be used judiciously. -// -// For hook functions that receive an error as an argument, no observations are -// made in the event of a non-nil error value. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - start := time.Now() - - trace := &httptrace.ClientTrace{ - GotConn: func(_ httptrace.GotConnInfo) { - if it.GotConn != nil { - it.GotConn(time.Since(start).Seconds()) - } - }, - PutIdleConn: func(err error) { - if err != nil { - return - } - if it.PutIdleConn != nil { - it.PutIdleConn(time.Since(start).Seconds()) - } - }, - DNSStart: func(_ httptrace.DNSStartInfo) { - if it.DNSStart != nil { - it.DNSStart(time.Since(start).Seconds()) - } - }, - DNSDone: func(_ httptrace.DNSDoneInfo) { - if it.DNSStart != nil { - it.DNSStart(time.Since(start).Seconds()) - } - }, - ConnectStart: func(_, _ string) { - if it.ConnectStart != nil { - it.ConnectStart(time.Since(start).Seconds()) - } - }, - ConnectDone: func(_, _ string, err error) { - if err != nil { - return - } - if it.ConnectDone != nil { - it.ConnectDone(time.Since(start).Seconds()) - } - }, - GotFirstResponseByte: func() { - if it.GotFirstResponseByte != nil { - it.GotFirstResponseByte(time.Since(start).Seconds()) - } - }, - Got100Continue: func() { - if it.Got100Continue != nil { - it.Got100Continue(time.Since(start).Seconds()) - } - }, - TLSHandshakeStart: func() { - if it.TLSHandshakeStart != nil { - it.TLSHandshakeStart(time.Since(start).Seconds()) - } - }, - TLSHandshakeDone: func(_ tls.ConnectionState, err error) { - if err != nil { - return - } - if it.TLSHandshakeDone != nil { - it.TLSHandshakeDone(time.Since(start).Seconds()) - } - }, - WroteHeaders: func() { - if it.WroteHeaders != nil { - it.WroteHeaders(time.Since(start).Seconds()) - } - }, - Wait100Continue: func() { - if it.Wait100Continue != nil { - it.Wait100Continue(time.Since(start).Seconds()) - } - }, - WroteRequest: func(_ httptrace.WroteRequestInfo) { - if it.WroteRequest != nil { - it.WroteRequest(time.Since(start).Seconds()) - } - }, - } - r = r.WithContext(httptrace.WithClientTrace(context.Background(), trace)) - - return next.RoundTrip(r) - }) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go deleted file mode 100644 index 9db2438053..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promhttp - -import ( - "errors" - "net/http" - "strconv" - "strings" - "time" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -// magicString is used for the hacky label test in checkLabels. Remove once fixed. -const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa" - -// InstrumentHandlerInFlight is a middleware that wraps the provided -// http.Handler. It sets the provided prometheus.Gauge to the number of -// requests currently handled by the wrapped http.Handler. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - g.Inc() - defer g.Dec() - next.ServeHTTP(w, r) - }) -} - -// InstrumentHandlerDuration is a middleware that wraps the provided -// http.Handler to observe the request duration with the provided ObserverVec. -// The ObserverVec must have zero, one, or two non-const non-curried labels. For -// those, the only allowed label names are "code" and "method". The function -// panics otherwise. The Observe method of the Observer in the ObserverVec is -// called with the request duration in seconds. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -// -// Note that this method is only guaranteed to never observe negative durations -// if used with Go1.9+. -func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(obs) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - d := newDelegator(w, nil) - next.ServeHTTP(d, r) - - obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds()) - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - next.ServeHTTP(w, r) - obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds()) - }) -} - -// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler -// to observe the request result with the provided CounterVec. The CounterVec -// must have zero, one, or two non-const non-curried labels. For those, the only -// allowed label names are "code" and "method". The function panics -// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or -// HTTP method if the respective instance label names are present in the -// CounterVec. For unpartitioned counting, use a CounterVec with zero labels. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, the Counter is not incremented. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(counter) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w, nil) - next.ServeHTTP(d, r) - counter.With(labels(code, method, r.Method, d.Status())).Inc() - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTP(w, r) - counter.With(labels(code, method, r.Method, 0)).Inc() - }) -} - -// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided -// http.Handler to observe with the provided ObserverVec the request duration -// until the response headers are written. The ObserverVec must have zero, one, -// or two non-const non-curried labels. For those, the only allowed label names -// are "code" and "method". The function panics otherwise. The Observe method of -// the Observer in the ObserverVec is called with the request duration in -// seconds. Partitioning happens by HTTP status code and/or HTTP method if the -// respective instance label names are present in the ObserverVec. For -// unpartitioned observations, use an ObserverVec with zero labels. Note that -// partitioning of Histograms is expensive and should be used judiciously. -// -// If the wrapped Handler panics before calling WriteHeader, no value is -// reported. -// -// Note that this method is only guaranteed to never observe negative durations -// if used with Go1.9+. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(obs) - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - d := newDelegator(w, func(status int) { - obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds()) - }) - next.ServeHTTP(d, r) - }) -} - -// InstrumentHandlerRequestSize is a middleware that wraps the provided -// http.Handler to observe the request size with the provided ObserverVec. The -// ObserverVec must have zero, one, or two non-const non-curried labels. For -// those, the only allowed label names are "code" and "method". The function -// panics otherwise. The Observe method of the Observer in the ObserverVec is -// called with the request size in bytes. Partitioning happens by HTTP status -// code and/or HTTP method if the respective instance label names are present in -// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero -// labels. Note that partitioning of Histograms is expensive and should be used -// judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(obs) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w, nil) - next.ServeHTTP(d, r) - size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size)) - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTP(w, r) - size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, 0)).Observe(float64(size)) - }) -} - -// InstrumentHandlerResponseSize is a middleware that wraps the provided -// http.Handler to observe the response size with the provided ObserverVec. The -// ObserverVec must have zero, one, or two non-const non-curried labels. For -// those, the only allowed label names are "code" and "method". The function -// panics otherwise. The Observe method of the Observer in the ObserverVec is -// called with the response size in bytes. Partitioning happens by HTTP status -// code and/or HTTP method if the respective instance label names are present in -// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero -// labels. Note that partitioning of Histograms is expensive and should be used -// judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler { - code, method := checkLabels(obs) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w, nil) - next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written())) - }) -} - -func checkLabels(c prometheus.Collector) (code bool, method bool) { - // TODO(beorn7): Remove this hacky way to check for instance labels - // once Descriptors can have their dimensionality queried. - var ( - desc *prometheus.Desc - m prometheus.Metric - pm dto.Metric - lvs []string - ) - - // Get the Desc from the Collector. - descc := make(chan *prometheus.Desc, 1) - c.Describe(descc) - - select { - case desc = <-descc: - default: - panic("no description provided by collector") - } - select { - case <-descc: - panic("more than one description provided by collector") - default: - } - - close(descc) - - // Create a ConstMetric with the Desc. Since we don't know how many - // variable labels there are, try for as long as it needs. - for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) { - m, err = prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, lvs...) - } - - // Write out the metric into a proto message and look at the labels. - // If the value is not the magicString, it is a constLabel, which doesn't interest us. - // If the label is curried, it doesn't interest us. - // In all other cases, only "code" or "method" is allowed. - if err := m.Write(&pm); err != nil { - panic("error checking metric for labels") - } - for _, label := range pm.Label { - name, value := label.GetName(), label.GetValue() - if value != magicString || isLabelCurried(c, name) { - continue - } - switch name { - case "code": - code = true - case "method": - method = true - default: - panic("metric partitioned with non-supported labels") - } - } - return -} - -func isLabelCurried(c prometheus.Collector, label string) bool { - // This is even hackier than the label test above. - // We essentially try to curry again and see if it works. - // But for that, we need to type-convert to the two - // types we use here, ObserverVec or *CounterVec. - switch v := c.(type) { - case *prometheus.CounterVec: - if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil { - return false - } - case prometheus.ObserverVec: - if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil { - return false - } - default: - panic("unsupported metric vec type") - } - return true -} - -// emptyLabels is a one-time allocation for non-partitioned metrics to avoid -// unnecessary allocations on each request. -var emptyLabels = prometheus.Labels{} - -func labels(code, method bool, reqMethod string, status int) prometheus.Labels { - if !(code || method) { - return emptyLabels - } - labels := prometheus.Labels{} - - if code { - labels["code"] = sanitizeCode(status) - } - if method { - labels["method"] = sanitizeMethod(reqMethod) - } - - return labels -} - -func computeApproximateRequestSize(r *http.Request) int { - s := 0 - if r.URL != nil { - s += len(r.URL.String()) - } - - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - return s -} - -func sanitizeMethod(m string) string { - switch m { - case "GET", "get": - return "get" - case "PUT", "put": - return "put" - case "HEAD", "head": - return "head" - case "POST", "post": - return "post" - case "DELETE", "delete": - return "delete" - case "CONNECT", "connect": - return "connect" - case "OPTIONS", "options": - return "options" - case "NOTIFY", "notify": - return "notify" - default: - return strings.ToLower(m) - } -} - -// If the wrapped http.Handler has not set a status code, i.e. the value is -// currently 0, santizeCode will return 200, for consistency with behavior in -// the stdlib. -func sanitizeCode(s int) string { - switch s { - case 100: - return "100" - case 101: - return "101" - - case 200, 0: - return "200" - case 201: - return "201" - case 202: - return "202" - case 203: - return "203" - case 204: - return "204" - case 205: - return "205" - case 206: - return "206" - - case 300: - return "300" - case 301: - return "301" - case 302: - return "302" - case 304: - return "304" - case 305: - return "305" - case 307: - return "307" - - case 400: - return "400" - case 401: - return "401" - case 402: - return "402" - case 403: - return "403" - case 404: - return "404" - case 405: - return "405" - case 406: - return "406" - case 407: - return "407" - case 408: - return "408" - case 409: - return "409" - case 410: - return "410" - case 411: - return "411" - case 412: - return "412" - case 413: - return "413" - case 414: - return "414" - case 415: - return "415" - case 416: - return "416" - case 417: - return "417" - case 418: - return "418" - - case 500: - return "500" - case 501: - return "501" - case 502: - return "502" - case 503: - return "503" - case 504: - return "504" - case 505: - return "505" - - case 428: - return "428" - case 429: - return "429" - case 431: - return "431" - case 511: - return "511" - - default: - return strconv.Itoa(s) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go deleted file mode 100644 index bee3703640..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ /dev/null @@ -1,807 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "bytes" - "errors" - "fmt" - "os" - "runtime" - "sort" - "sync" - "unicode/utf8" - - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -const ( - // Capacity for the channel to collect metrics and descriptors. - capMetricChan = 1000 - capDescChan = 10 -) - -// DefaultRegisterer and DefaultGatherer are the implementations of the -// Registerer and Gatherer interface a number of convenience functions in this -// package act on. Initially, both variables point to the same Registry, which -// has a process collector (currently on Linux only, see NewProcessCollector) -// and a Go collector (see NewGoCollector) already registered. This approach to -// keep default instances as global state mirrors the approach of other packages -// in the Go standard library. Note that there are caveats. Change the variables -// with caution and only if you understand the consequences. Users who want to -// avoid global state altogether should not use the convenience functions and -// act on custom instances instead. -var ( - defaultRegistry = NewRegistry() - DefaultRegisterer Registerer = defaultRegistry - DefaultGatherer Gatherer = defaultRegistry -) - -func init() { - MustRegister(NewProcessCollector(os.Getpid(), "")) - MustRegister(NewGoCollector()) -} - -// NewRegistry creates a new vanilla Registry without any Collectors -// pre-registered. -func NewRegistry() *Registry { - return &Registry{ - collectorsByID: map[uint64]Collector{}, - descIDs: map[uint64]struct{}{}, - dimHashesByName: map[string]uint64{}, - } -} - -// NewPedanticRegistry returns a registry that checks during collection if each -// collected Metric is consistent with its reported Desc, and if the Desc has -// actually been registered with the registry. -// -// Usually, a Registry will be happy as long as the union of all collected -// Metrics is consistent and valid even if some metrics are not consistent with -// their own Desc or a Desc provided by their registered Collector. Well-behaved -// Collectors and Metrics will only provide consistent Descs. This Registry is -// useful to test the implementation of Collectors and Metrics. -func NewPedanticRegistry() *Registry { - r := NewRegistry() - r.pedanticChecksEnabled = true - return r -} - -// Registerer is the interface for the part of a registry in charge of -// registering and unregistering. Users of custom registries should use -// Registerer as type for registration purposes (rather than the Registry type -// directly). In that way, they are free to use custom Registerer implementation -// (e.g. for testing purposes). -type Registerer interface { - // Register registers a new Collector to be included in metrics - // collection. It returns an error if the descriptors provided by the - // Collector are invalid or if they — in combination with descriptors of - // already registered Collectors — do not fulfill the consistency and - // uniqueness criteria described in the documentation of metric.Desc. - // - // If the provided Collector is equal to a Collector already registered - // (which includes the case of re-registering the same Collector), the - // returned error is an instance of AlreadyRegisteredError, which - // contains the previously registered Collector. - // - // It is in general not safe to register the same Collector multiple - // times concurrently. - Register(Collector) error - // MustRegister works like Register but registers any number of - // Collectors and panics upon the first registration that causes an - // error. - MustRegister(...Collector) - // Unregister unregisters the Collector that equals the Collector passed - // in as an argument. (Two Collectors are considered equal if their - // Describe method yields the same set of descriptors.) The function - // returns whether a Collector was unregistered. - // - // Note that even after unregistering, it will not be possible to - // register a new Collector that is inconsistent with the unregistered - // Collector, e.g. a Collector collecting metrics with the same name but - // a different help string. The rationale here is that the same registry - // instance must only collect consistent metrics throughout its - // lifetime. - Unregister(Collector) bool -} - -// Gatherer is the interface for the part of a registry in charge of gathering -// the collected metrics into a number of MetricFamilies. The Gatherer interface -// comes with the same general implication as described for the Registerer -// interface. -type Gatherer interface { - // Gather calls the Collect method of the registered Collectors and then - // gathers the collected metrics into a lexicographically sorted slice - // of MetricFamily protobufs. Even if an error occurs, Gather attempts - // to gather as many metrics as possible. Hence, if a non-nil error is - // returned, the returned MetricFamily slice could be nil (in case of a - // fatal error that prevented any meaningful metric collection) or - // contain a number of MetricFamily protobufs, some of which might be - // incomplete, and some might be missing altogether. The returned error - // (which might be a MultiError) explains the details. In scenarios - // where complete collection is critical, the returned MetricFamily - // protobufs should be disregarded if the returned error is non-nil. - Gather() ([]*dto.MetricFamily, error) -} - -// Register registers the provided Collector with the DefaultRegisterer. -// -// Register is a shortcut for DefaultRegisterer.Register(c). See there for more -// details. -func Register(c Collector) error { - return DefaultRegisterer.Register(c) -} - -// MustRegister registers the provided Collectors with the DefaultRegisterer and -// panics if any error occurs. -// -// MustRegister is a shortcut for DefaultRegisterer.MustRegister(cs...). See -// there for more details. -func MustRegister(cs ...Collector) { - DefaultRegisterer.MustRegister(cs...) -} - -// Unregister removes the registration of the provided Collector from the -// DefaultRegisterer. -// -// Unregister is a shortcut for DefaultRegisterer.Unregister(c). See there for -// more details. -func Unregister(c Collector) bool { - return DefaultRegisterer.Unregister(c) -} - -// GathererFunc turns a function into a Gatherer. -type GathererFunc func() ([]*dto.MetricFamily, error) - -// Gather implements Gatherer. -func (gf GathererFunc) Gather() ([]*dto.MetricFamily, error) { - return gf() -} - -// AlreadyRegisteredError is returned by the Register method if the Collector to -// be registered has already been registered before, or a different Collector -// that collects the same metrics has been registered before. Registration fails -// in that case, but you can detect from the kind of error what has -// happened. The error contains fields for the existing Collector and the -// (rejected) new Collector that equals the existing one. This can be used to -// find out if an equal Collector has been registered before and switch over to -// using the old one, as demonstrated in the example. -type AlreadyRegisteredError struct { - ExistingCollector, NewCollector Collector -} - -func (err AlreadyRegisteredError) Error() string { - return "duplicate metrics collector registration attempted" -} - -// MultiError is a slice of errors implementing the error interface. It is used -// by a Gatherer to report multiple errors during MetricFamily gathering. -type MultiError []error - -func (errs MultiError) Error() string { - if len(errs) == 0 { - return "" - } - buf := &bytes.Buffer{} - fmt.Fprintf(buf, "%d error(s) occurred:", len(errs)) - for _, err := range errs { - fmt.Fprintf(buf, "\n* %s", err) - } - return buf.String() -} - -// Append appends the provided error if it is not nil. -func (errs *MultiError) Append(err error) { - if err != nil { - *errs = append(*errs, err) - } -} - -// MaybeUnwrap returns nil if len(errs) is 0. It returns the first and only -// contained error as error if len(errs is 1). In all other cases, it returns -// the MultiError directly. This is helpful for returning a MultiError in a way -// that only uses the MultiError if needed. -func (errs MultiError) MaybeUnwrap() error { - switch len(errs) { - case 0: - return nil - case 1: - return errs[0] - default: - return errs - } -} - -// Registry registers Prometheus collectors, collects their metrics, and gathers -// them into MetricFamilies for exposition. It implements both Registerer and -// Gatherer. The zero value is not usable. Create instances with NewRegistry or -// NewPedanticRegistry. -type Registry struct { - mtx sync.RWMutex - collectorsByID map[uint64]Collector // ID is a hash of the descIDs. - descIDs map[uint64]struct{} - dimHashesByName map[string]uint64 - pedanticChecksEnabled bool -} - -// Register implements Registerer. -func (r *Registry) Register(c Collector) error { - var ( - descChan = make(chan *Desc, capDescChan) - newDescIDs = map[uint64]struct{}{} - newDimHashesByName = map[string]uint64{} - collectorID uint64 // Just a sum of all desc IDs. - duplicateDescErr error - ) - go func() { - c.Describe(descChan) - close(descChan) - }() - r.mtx.Lock() - defer r.mtx.Unlock() - // Conduct various tests... - for desc := range descChan { - - // Is the descriptor valid at all? - if desc.err != nil { - return fmt.Errorf("descriptor %s is invalid: %s", desc, desc.err) - } - - // Is the descID unique? - // (In other words: Is the fqName + constLabel combination unique?) - if _, exists := r.descIDs[desc.id]; exists { - duplicateDescErr = fmt.Errorf("descriptor %s already exists with the same fully-qualified name and const label values", desc) - } - // If it is not a duplicate desc in this collector, add it to - // the collectorID. (We allow duplicate descs within the same - // collector, but their existence must be a no-op.) - if _, exists := newDescIDs[desc.id]; !exists { - newDescIDs[desc.id] = struct{}{} - collectorID += desc.id - } - - // Are all the label names and the help string consistent with - // previous descriptors of the same name? - // First check existing descriptors... - if dimHash, exists := r.dimHashesByName[desc.fqName]; exists { - if dimHash != desc.dimHash { - return fmt.Errorf("a previously registered descriptor with the same fully-qualified name as %s has different label names or a different help string", desc) - } - } else { - // ...then check the new descriptors already seen. - if dimHash, exists := newDimHashesByName[desc.fqName]; exists { - if dimHash != desc.dimHash { - return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc) - } - } else { - newDimHashesByName[desc.fqName] = desc.dimHash - } - } - } - // Did anything happen at all? - if len(newDescIDs) == 0 { - return errors.New("collector has no descriptors") - } - if existing, exists := r.collectorsByID[collectorID]; exists { - return AlreadyRegisteredError{ - ExistingCollector: existing, - NewCollector: c, - } - } - // If the collectorID is new, but at least one of the descs existed - // before, we are in trouble. - if duplicateDescErr != nil { - return duplicateDescErr - } - - // Only after all tests have passed, actually register. - r.collectorsByID[collectorID] = c - for hash := range newDescIDs { - r.descIDs[hash] = struct{}{} - } - for name, dimHash := range newDimHashesByName { - r.dimHashesByName[name] = dimHash - } - return nil -} - -// Unregister implements Registerer. -func (r *Registry) Unregister(c Collector) bool { - var ( - descChan = make(chan *Desc, capDescChan) - descIDs = map[uint64]struct{}{} - collectorID uint64 // Just a sum of the desc IDs. - ) - go func() { - c.Describe(descChan) - close(descChan) - }() - for desc := range descChan { - if _, exists := descIDs[desc.id]; !exists { - collectorID += desc.id - descIDs[desc.id] = struct{}{} - } - } - - r.mtx.RLock() - if _, exists := r.collectorsByID[collectorID]; !exists { - r.mtx.RUnlock() - return false - } - r.mtx.RUnlock() - - r.mtx.Lock() - defer r.mtx.Unlock() - - delete(r.collectorsByID, collectorID) - for id := range descIDs { - delete(r.descIDs, id) - } - // dimHashesByName is left untouched as those must be consistent - // throughout the lifetime of a program. - return true -} - -// MustRegister implements Registerer. -func (r *Registry) MustRegister(cs ...Collector) { - for _, c := range cs { - if err := r.Register(c); err != nil { - panic(err) - } - } -} - -// Gather implements Gatherer. -func (r *Registry) Gather() ([]*dto.MetricFamily, error) { - var ( - metricChan = make(chan Metric, capMetricChan) - metricHashes = map[uint64]struct{}{} - dimHashes = map[string]uint64{} - wg sync.WaitGroup - errs MultiError // The collected errors to return in the end. - registeredDescIDs map[uint64]struct{} // Only used for pedantic checks - ) - - r.mtx.RLock() - goroutineBudget := len(r.collectorsByID) - metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName)) - collectors := make(chan Collector, len(r.collectorsByID)) - for _, collector := range r.collectorsByID { - collectors <- collector - } - // In case pedantic checks are enabled, we have to copy the map before - // giving up the RLock. - if r.pedanticChecksEnabled { - registeredDescIDs = make(map[uint64]struct{}, len(r.descIDs)) - for id := range r.descIDs { - registeredDescIDs[id] = struct{}{} - } - } - r.mtx.RUnlock() - - wg.Add(goroutineBudget) - - collectWorker := func() { - for { - select { - case collector := <-collectors: - collector.Collect(metricChan) - wg.Done() - default: - return - } - } - } - - // Start the first worker now to make sure at least one is running. - go collectWorker() - goroutineBudget-- - - // Close the metricChan once all collectors are collected. - go func() { - wg.Wait() - close(metricChan) - }() - - // Drain metricChan in case of premature return. - defer func() { - for range metricChan { - } - }() - -collectLoop: - for { - select { - case metric, ok := <-metricChan: - if !ok { - // metricChan is closed, we are done. - break collectLoop - } - errs.Append(processMetric( - metric, metricFamiliesByName, - metricHashes, dimHashes, - registeredDescIDs, - )) - default: - if goroutineBudget <= 0 || len(collectors) == 0 { - // All collectors are aleady being worked on or - // we have already as many goroutines started as - // there are collectors. Just process metrics - // from now on. - for metric := range metricChan { - errs.Append(processMetric( - metric, metricFamiliesByName, - metricHashes, dimHashes, - registeredDescIDs, - )) - } - break collectLoop - } - // Start more workers. - go collectWorker() - goroutineBudget-- - runtime.Gosched() - } - } - return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() -} - -// processMetric is an internal helper method only used by the Gather method. -func processMetric( - metric Metric, - metricFamiliesByName map[string]*dto.MetricFamily, - metricHashes map[uint64]struct{}, - dimHashes map[string]uint64, - registeredDescIDs map[uint64]struct{}, -) error { - desc := metric.Desc() - dtoMetric := &dto.Metric{} - if err := metric.Write(dtoMetric); err != nil { - return fmt.Errorf("error collecting metric %v: %s", desc, err) - } - metricFamily, ok := metricFamiliesByName[desc.fqName] - if ok { - if metricFamily.GetHelp() != desc.help { - return fmt.Errorf( - "collected metric %s %s has help %q but should have %q", - desc.fqName, dtoMetric, desc.help, metricFamily.GetHelp(), - ) - } - // TODO(beorn7): Simplify switch once Desc has type. - switch metricFamily.GetType() { - case dto.MetricType_COUNTER: - if dtoMetric.Counter == nil { - return fmt.Errorf( - "collected metric %s %s should be a Counter", - desc.fqName, dtoMetric, - ) - } - case dto.MetricType_GAUGE: - if dtoMetric.Gauge == nil { - return fmt.Errorf( - "collected metric %s %s should be a Gauge", - desc.fqName, dtoMetric, - ) - } - case dto.MetricType_SUMMARY: - if dtoMetric.Summary == nil { - return fmt.Errorf( - "collected metric %s %s should be a Summary", - desc.fqName, dtoMetric, - ) - } - case dto.MetricType_UNTYPED: - if dtoMetric.Untyped == nil { - return fmt.Errorf( - "collected metric %s %s should be Untyped", - desc.fqName, dtoMetric, - ) - } - case dto.MetricType_HISTOGRAM: - if dtoMetric.Histogram == nil { - return fmt.Errorf( - "collected metric %s %s should be a Histogram", - desc.fqName, dtoMetric, - ) - } - default: - panic("encountered MetricFamily with invalid type") - } - } else { - metricFamily = &dto.MetricFamily{} - metricFamily.Name = proto.String(desc.fqName) - metricFamily.Help = proto.String(desc.help) - // TODO(beorn7): Simplify switch once Desc has type. - switch { - case dtoMetric.Gauge != nil: - metricFamily.Type = dto.MetricType_GAUGE.Enum() - case dtoMetric.Counter != nil: - metricFamily.Type = dto.MetricType_COUNTER.Enum() - case dtoMetric.Summary != nil: - metricFamily.Type = dto.MetricType_SUMMARY.Enum() - case dtoMetric.Untyped != nil: - metricFamily.Type = dto.MetricType_UNTYPED.Enum() - case dtoMetric.Histogram != nil: - metricFamily.Type = dto.MetricType_HISTOGRAM.Enum() - default: - return fmt.Errorf("empty metric collected: %s", dtoMetric) - } - metricFamiliesByName[desc.fqName] = metricFamily - } - if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes, dimHashes); err != nil { - return err - } - if registeredDescIDs != nil { - // Is the desc registered at all? - if _, exist := registeredDescIDs[desc.id]; !exist { - return fmt.Errorf( - "collected metric %s %s with unregistered descriptor %s", - metricFamily.GetName(), dtoMetric, desc, - ) - } - if err := checkDescConsistency(metricFamily, dtoMetric, desc); err != nil { - return err - } - } - metricFamily.Metric = append(metricFamily.Metric, dtoMetric) - return nil -} - -// Gatherers is a slice of Gatherer instances that implements the Gatherer -// interface itself. Its Gather method calls Gather on all Gatherers in the -// slice in order and returns the merged results. Errors returned from the -// Gather calles are all returned in a flattened MultiError. Duplicate and -// inconsistent Metrics are skipped (first occurrence in slice order wins) and -// reported in the returned error. -// -// Gatherers can be used to merge the Gather results from multiple -// Registries. It also provides a way to directly inject existing MetricFamily -// protobufs into the gathering by creating a custom Gatherer with a Gather -// method that simply returns the existing MetricFamily protobufs. Note that no -// registration is involved (in contrast to Collector registration), so -// obviously registration-time checks cannot happen. Any inconsistencies between -// the gathered MetricFamilies are reported as errors by the Gather method, and -// inconsistent Metrics are dropped. Invalid parts of the MetricFamilies -// (e.g. syntactically invalid metric or label names) will go undetected. -type Gatherers []Gatherer - -// Gather implements Gatherer. -func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { - var ( - metricFamiliesByName = map[string]*dto.MetricFamily{} - metricHashes = map[uint64]struct{}{} - dimHashes = map[string]uint64{} - errs MultiError // The collected errors to return in the end. - ) - - for i, g := range gs { - mfs, err := g.Gather() - if err != nil { - if multiErr, ok := err.(MultiError); ok { - for _, err := range multiErr { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) - } - } else { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) - } - } - for _, mf := range mfs { - existingMF, exists := metricFamiliesByName[mf.GetName()] - if exists { - if existingMF.GetHelp() != mf.GetHelp() { - errs = append(errs, fmt.Errorf( - "gathered metric family %s has help %q but should have %q", - mf.GetName(), mf.GetHelp(), existingMF.GetHelp(), - )) - continue - } - if existingMF.GetType() != mf.GetType() { - errs = append(errs, fmt.Errorf( - "gathered metric family %s has type %s but should have %s", - mf.GetName(), mf.GetType(), existingMF.GetType(), - )) - continue - } - } else { - existingMF = &dto.MetricFamily{} - existingMF.Name = mf.Name - existingMF.Help = mf.Help - existingMF.Type = mf.Type - metricFamiliesByName[mf.GetName()] = existingMF - } - for _, m := range mf.Metric { - if err := checkMetricConsistency(existingMF, m, metricHashes, dimHashes); err != nil { - errs = append(errs, err) - continue - } - existingMF.Metric = append(existingMF.Metric, m) - } - } - } - return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() -} - -// metricSorter is a sortable slice of *dto.Metric. -type metricSorter []*dto.Metric - -func (s metricSorter) Len() int { - return len(s) -} - -func (s metricSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s metricSorter) Less(i, j int) bool { - if len(s[i].Label) != len(s[j].Label) { - // This should not happen. The metrics are - // inconsistent. However, we have to deal with the fact, as - // people might use custom collectors or metric family injection - // to create inconsistent metrics. So let's simply compare the - // number of labels in this case. That will still yield - // reproducible sorting. - return len(s[i].Label) < len(s[j].Label) - } - for n, lp := range s[i].Label { - vi := lp.GetValue() - vj := s[j].Label[n].GetValue() - if vi != vj { - return vi < vj - } - } - - // We should never arrive here. Multiple metrics with the same - // label set in the same scrape will lead to undefined ingestion - // behavior. However, as above, we have to provide stable sorting - // here, even for inconsistent metrics. So sort equal metrics - // by their timestamp, with missing timestamps (implying "now") - // coming last. - if s[i].TimestampMs == nil { - return false - } - if s[j].TimestampMs == nil { - return true - } - return s[i].GetTimestampMs() < s[j].GetTimestampMs() -} - -// normalizeMetricFamilies returns a MetricFamily slice with empty -// MetricFamilies pruned and the remaining MetricFamilies sorted by name within -// the slice, with the contained Metrics sorted within each MetricFamily. -func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { - for _, mf := range metricFamiliesByName { - sort.Sort(metricSorter(mf.Metric)) - } - names := make([]string, 0, len(metricFamiliesByName)) - for name, mf := range metricFamiliesByName { - if len(mf.Metric) > 0 { - names = append(names, name) - } - } - sort.Strings(names) - result := make([]*dto.MetricFamily, 0, len(names)) - for _, name := range names { - result = append(result, metricFamiliesByName[name]) - } - return result -} - -// checkMetricConsistency checks if the provided Metric is consistent with the -// provided MetricFamily. It also hashed the Metric labels and the MetricFamily -// name. If the resulting hash is already in the provided metricHashes, an error -// is returned. If not, it is added to metricHashes. The provided dimHashes maps -// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes -// doesn't yet contain a hash for the provided MetricFamily, it is -// added. Otherwise, an error is returned if the existing dimHashes in not equal -// the calculated dimHash. -func checkMetricConsistency( - metricFamily *dto.MetricFamily, - dtoMetric *dto.Metric, - metricHashes map[uint64]struct{}, - dimHashes map[string]uint64, -) error { - // Type consistency with metric family. - if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil || - metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil || - metricFamily.GetType() == dto.MetricType_SUMMARY && dtoMetric.Summary == nil || - metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil || - metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil { - return fmt.Errorf( - "collected metric %s %s is not a %s", - metricFamily.GetName(), dtoMetric, metricFamily.GetType(), - ) - } - - for _, labelPair := range dtoMetric.GetLabel() { - if !utf8.ValidString(*labelPair.Value) { - return fmt.Errorf("collected metric's label %s is not utf8: %#v", *labelPair.Name, *labelPair.Value) - } - } - - // Is the metric unique (i.e. no other metric with the same name and the same label values)? - h := hashNew() - h = hashAdd(h, metricFamily.GetName()) - h = hashAddByte(h, separatorByte) - dh := hashNew() - // Make sure label pairs are sorted. We depend on it for the consistency - // check. - sort.Sort(LabelPairSorter(dtoMetric.Label)) - for _, lp := range dtoMetric.Label { - h = hashAdd(h, lp.GetValue()) - h = hashAddByte(h, separatorByte) - dh = hashAdd(dh, lp.GetName()) - dh = hashAddByte(dh, separatorByte) - } - if _, exists := metricHashes[h]; exists { - return fmt.Errorf( - "collected metric %s %s was collected before with the same name and label values", - metricFamily.GetName(), dtoMetric, - ) - } - if dimHash, ok := dimHashes[metricFamily.GetName()]; ok { - if dimHash != dh { - return fmt.Errorf( - "collected metric %s %s has label dimensions inconsistent with previously collected metrics in the same metric family", - metricFamily.GetName(), dtoMetric, - ) - } - } else { - dimHashes[metricFamily.GetName()] = dh - } - metricHashes[h] = struct{}{} - return nil -} - -func checkDescConsistency( - metricFamily *dto.MetricFamily, - dtoMetric *dto.Metric, - desc *Desc, -) error { - // Desc help consistency with metric family help. - if metricFamily.GetHelp() != desc.help { - return fmt.Errorf( - "collected metric %s %s has help %q but should have %q", - metricFamily.GetName(), dtoMetric, metricFamily.GetHelp(), desc.help, - ) - } - - // Is the desc consistent with the content of the metric? - lpsFromDesc := make([]*dto.LabelPair, 0, len(dtoMetric.Label)) - lpsFromDesc = append(lpsFromDesc, desc.constLabelPairs...) - for _, l := range desc.variableLabels { - lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{ - Name: proto.String(l), - }) - } - if len(lpsFromDesc) != len(dtoMetric.Label) { - return fmt.Errorf( - "labels in collected metric %s %s are inconsistent with descriptor %s", - metricFamily.GetName(), dtoMetric, desc, - ) - } - sort.Sort(LabelPairSorter(lpsFromDesc)) - for i, lpFromDesc := range lpsFromDesc { - lpFromMetric := dtoMetric.Label[i] - if lpFromDesc.GetName() != lpFromMetric.GetName() || - lpFromDesc.Value != nil && lpFromDesc.GetValue() != lpFromMetric.GetValue() { - return fmt.Errorf( - "labels in collected metric %s %s are inconsistent with descriptor %s", - metricFamily.GetName(), dtoMetric, desc, - ) - } - } - return nil -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go deleted file mode 100644 index f7dc85b96d..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "math" - "sort" - "sync" - "time" - - "github.com/beorn7/perks/quantile" - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -// quantileLabel is used for the label that defines the quantile in a -// summary. -const quantileLabel = "quantile" - -// A Summary captures individual observations from an event or sample stream and -// summarizes them in a manner similar to traditional summary statistics: 1. sum -// of observations, 2. observation count, 3. rank estimations. -// -// A typical use-case is the observation of request latencies. By default, a -// Summary provides the median, the 90th and the 99th percentile of the latency -// as rank estimations. However, the default behavior will change in the -// upcoming v0.10 of the library. There will be no rank estiamtions at all by -// default. For a sane transition, it is recommended to set the desired rank -// estimations explicitly. -// -// Note that the rank estimations cannot be aggregated in a meaningful way with -// the Prometheus query language (i.e. you cannot average or add them). If you -// need aggregatable quantiles (e.g. you want the 99th percentile latency of all -// queries served across all instances of a service), consider the Histogram -// metric type. See the Prometheus documentation for more details. -// -// To create Summary instances, use NewSummary. -type Summary interface { - Metric - Collector - - // Observe adds a single observation to the summary. - Observe(float64) -} - -// DefObjectives are the default Summary quantile values. -// -// Deprecated: DefObjectives will not be used as the default objectives in -// v0.10 of the library. The default Summary will have no quantiles then. -var ( - DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001} - - errQuantileLabelNotAllowed = fmt.Errorf( - "%q is not allowed as label name in summaries", quantileLabel, - ) -) - -// Default values for SummaryOpts. -const ( - // DefMaxAge is the default duration for which observations stay - // relevant. - DefMaxAge time.Duration = 10 * time.Minute - // DefAgeBuckets is the default number of buckets used to calculate the - // age of observations. - DefAgeBuckets = 5 - // DefBufCap is the standard buffer size for collecting Summary observations. - DefBufCap = 500 -) - -// SummaryOpts bundles the options for creating a Summary metric. It is -// mandatory to set Name and Help to a non-empty string. While all other fields -// are optional and can safely be left at their zero value, it is recommended to -// explicitly set the Objectives field to the desired value as the default value -// will change in the upcoming v0.10 of the library. -type SummaryOpts struct { - // Namespace, Subsystem, and Name are components of the fully-qualified - // name of the Summary (created by joining these components with - // "_"). Only Name is mandatory, the others merely help structuring the - // name. Note that the fully-qualified name of the Summary must be a - // valid Prometheus metric name. - Namespace string - Subsystem string - Name string - - // Help provides information about this Summary. Mandatory! - // - // Metrics with the same fully-qualified name must have the same Help - // string. - Help string - - // ConstLabels are used to attach fixed labels to this metric. Metrics - // with the same fully-qualified name must have the same label names in - // their ConstLabels. - // - // ConstLabels are only used rarely. In particular, do not use them to - // attach the same labels to all your metrics. Those use cases are - // better covered by target labels set by the scraping Prometheus - // server, or by one specific metric (e.g. a build_info or a - // machine_role metric). See also - // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels - ConstLabels Labels - - // Objectives defines the quantile rank estimates with their respective - // absolute error. If Objectives[q] = e, then the value reported for q - // will be the φ-quantile value for some φ between q-e and q+e. The - // default value is DefObjectives. It is used if Objectives is left at - // its zero value (i.e. nil). To create a Summary without Objectives, - // set it to an empty map (i.e. map[float64]float64{}). - // - // Deprecated: Note that the current value of DefObjectives is - // deprecated. It will be replaced by an empty map in v0.10 of the - // library. Please explicitly set Objectives to the desired value. - Objectives map[float64]float64 - - // MaxAge defines the duration for which an observation stays relevant - // for the summary. Must be positive. The default value is DefMaxAge. - MaxAge time.Duration - - // AgeBuckets is the number of buckets used to exclude observations that - // are older than MaxAge from the summary. A higher number has a - // resource penalty, so only increase it if the higher resolution is - // really required. For very high observation rates, you might want to - // reduce the number of age buckets. With only one age bucket, you will - // effectively see a complete reset of the summary each time MaxAge has - // passed. The default value is DefAgeBuckets. - AgeBuckets uint32 - - // BufCap defines the default sample stream buffer size. The default - // value of DefBufCap should suffice for most uses. If there is a need - // to increase the value, a multiple of 500 is recommended (because that - // is the internal buffer size of the underlying package - // "github.com/bmizerany/perks/quantile"). - BufCap uint32 -} - -// Great fuck-up with the sliding-window decay algorithm... The Merge method of -// perk/quantile is actually not working as advertised - and it might be -// unfixable, as the underlying algorithm is apparently not capable of merging -// summaries in the first place. To avoid using Merge, we are currently adding -// observations to _each_ age bucket, i.e. the effort to add a sample is -// essentially multiplied by the number of age buckets. When rotating age -// buckets, we empty the previous head stream. On scrape time, we simply take -// the quantiles from the head stream (no merging required). Result: More effort -// on observation time, less effort on scrape time, which is exactly the -// opposite of what we try to accomplish, but at least the results are correct. -// -// The quite elegant previous contraption to merge the age buckets efficiently -// on scrape time (see code up commit 6b9530d72ea715f0ba612c0120e6e09fbf1d49d0) -// can't be used anymore. - -// NewSummary creates a new Summary based on the provided SummaryOpts. -func NewSummary(opts SummaryOpts) Summary { - return newSummary( - NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), - opts, - ) -} - -func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { - if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) - } - - for _, n := range desc.variableLabels { - if n == quantileLabel { - panic(errQuantileLabelNotAllowed) - } - } - for _, lp := range desc.constLabelPairs { - if lp.GetName() == quantileLabel { - panic(errQuantileLabelNotAllowed) - } - } - - if opts.Objectives == nil { - opts.Objectives = DefObjectives - } - - if opts.MaxAge < 0 { - panic(fmt.Errorf("illegal max age MaxAge=%v", opts.MaxAge)) - } - if opts.MaxAge == 0 { - opts.MaxAge = DefMaxAge - } - - if opts.AgeBuckets == 0 { - opts.AgeBuckets = DefAgeBuckets - } - - if opts.BufCap == 0 { - opts.BufCap = DefBufCap - } - - s := &summary{ - desc: desc, - - objectives: opts.Objectives, - sortedObjectives: make([]float64, 0, len(opts.Objectives)), - - labelPairs: makeLabelPairs(desc, labelValues), - - hotBuf: make([]float64, 0, opts.BufCap), - coldBuf: make([]float64, 0, opts.BufCap), - streamDuration: opts.MaxAge / time.Duration(opts.AgeBuckets), - } - s.headStreamExpTime = time.Now().Add(s.streamDuration) - s.hotBufExpTime = s.headStreamExpTime - - for i := uint32(0); i < opts.AgeBuckets; i++ { - s.streams = append(s.streams, s.newStream()) - } - s.headStream = s.streams[0] - - for qu := range s.objectives { - s.sortedObjectives = append(s.sortedObjectives, qu) - } - sort.Float64s(s.sortedObjectives) - - s.init(s) // Init self-collection. - return s -} - -type summary struct { - selfCollector - - bufMtx sync.Mutex // Protects hotBuf and hotBufExpTime. - mtx sync.Mutex // Protects every other moving part. - // Lock bufMtx before mtx if both are needed. - - desc *Desc - - objectives map[float64]float64 - sortedObjectives []float64 - - labelPairs []*dto.LabelPair - - sum float64 - cnt uint64 - - hotBuf, coldBuf []float64 - - streams []*quantile.Stream - streamDuration time.Duration - headStream *quantile.Stream - headStreamIdx int - headStreamExpTime, hotBufExpTime time.Time -} - -func (s *summary) Desc() *Desc { - return s.desc -} - -func (s *summary) Observe(v float64) { - s.bufMtx.Lock() - defer s.bufMtx.Unlock() - - now := time.Now() - if now.After(s.hotBufExpTime) { - s.asyncFlush(now) - } - s.hotBuf = append(s.hotBuf, v) - if len(s.hotBuf) == cap(s.hotBuf) { - s.asyncFlush(now) - } -} - -func (s *summary) Write(out *dto.Metric) error { - sum := &dto.Summary{} - qs := make([]*dto.Quantile, 0, len(s.objectives)) - - s.bufMtx.Lock() - s.mtx.Lock() - // Swap bufs even if hotBuf is empty to set new hotBufExpTime. - s.swapBufs(time.Now()) - s.bufMtx.Unlock() - - s.flushColdBuf() - sum.SampleCount = proto.Uint64(s.cnt) - sum.SampleSum = proto.Float64(s.sum) - - for _, rank := range s.sortedObjectives { - var q float64 - if s.headStream.Count() == 0 { - q = math.NaN() - } else { - q = s.headStream.Query(rank) - } - qs = append(qs, &dto.Quantile{ - Quantile: proto.Float64(rank), - Value: proto.Float64(q), - }) - } - - s.mtx.Unlock() - - if len(qs) > 0 { - sort.Sort(quantSort(qs)) - } - sum.Quantile = qs - - out.Summary = sum - out.Label = s.labelPairs - return nil -} - -func (s *summary) newStream() *quantile.Stream { - return quantile.NewTargeted(s.objectives) -} - -// asyncFlush needs bufMtx locked. -func (s *summary) asyncFlush(now time.Time) { - s.mtx.Lock() - s.swapBufs(now) - - // Unblock the original goroutine that was responsible for the mutation - // that triggered the compaction. But hold onto the global non-buffer - // state mutex until the operation finishes. - go func() { - s.flushColdBuf() - s.mtx.Unlock() - }() -} - -// rotateStreams needs mtx AND bufMtx locked. -func (s *summary) maybeRotateStreams() { - for !s.hotBufExpTime.Equal(s.headStreamExpTime) { - s.headStream.Reset() - s.headStreamIdx++ - if s.headStreamIdx >= len(s.streams) { - s.headStreamIdx = 0 - } - s.headStream = s.streams[s.headStreamIdx] - s.headStreamExpTime = s.headStreamExpTime.Add(s.streamDuration) - } -} - -// flushColdBuf needs mtx locked. -func (s *summary) flushColdBuf() { - for _, v := range s.coldBuf { - for _, stream := range s.streams { - stream.Insert(v) - } - s.cnt++ - s.sum += v - } - s.coldBuf = s.coldBuf[0:0] - s.maybeRotateStreams() -} - -// swapBufs needs mtx AND bufMtx locked, coldBuf must be empty. -func (s *summary) swapBufs(now time.Time) { - if len(s.coldBuf) != 0 { - panic("coldBuf is not empty") - } - s.hotBuf, s.coldBuf = s.coldBuf, s.hotBuf - // hotBuf is now empty and gets new expiration set. - for now.After(s.hotBufExpTime) { - s.hotBufExpTime = s.hotBufExpTime.Add(s.streamDuration) - } -} - -type quantSort []*dto.Quantile - -func (s quantSort) Len() int { - return len(s) -} - -func (s quantSort) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s quantSort) Less(i, j int) bool { - return s[i].GetQuantile() < s[j].GetQuantile() -} - -// SummaryVec is a Collector that bundles a set of Summaries that all share the -// same Desc, but have different values for their variable labels. This is used -// if you want to count the same thing partitioned by various dimensions -// (e.g. HTTP request latencies, partitioned by status code and method). Create -// instances with NewSummaryVec. -type SummaryVec struct { - *metricVec -} - -// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and -// partitioned by the given label names. -func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - labelNames, - opts.ConstLabels, - ) - return &SummaryVec{ - metricVec: newMetricVec(desc, func(lvs ...string) Metric { - return newSummary(desc, opts, lvs...) - }), - } -} - -// GetMetricWithLabelValues returns the Summary for the given slice of label -// values (same order as the VariableLabels in Desc). If that combination of -// label values is accessed for the first time, a new Summary is created. -// -// It is possible to call this method without using the returned Summary to only -// create the new Summary but leave it at its starting value, a Summary without -// any observations. -// -// Keeping the Summary for later use is possible (and should be considered if -// performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Summary from the SummaryVec. In that case, -// the Summary will still exist, but it will not be exported anymore, even if a -// Summary with the same label values is created later. See also the CounterVec -// example. -// -// An error is returned if the number of label values is not the same as the -// number of VariableLabels in Desc (minus any curried labels). -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as -// an alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the GaugeVec example. -func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { - metric, err := v.metricVec.getMetricWithLabelValues(lvs...) - if metric != nil { - return metric.(Observer), err - } - return nil, err -} - -// GetMetricWith returns the Summary for the given Labels map (the label names -// must match those of the VariableLabels in Desc). If that label map is -// accessed for the first time, a new Summary is created. Implications of -// creating a Summary without using it and keeping the Summary for later use are -// the same as for GetMetricWithLabelValues. -// -// An error is returned if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc (minus any curried labels). -// -// This method is used for the same purpose as -// GetMetricWithLabelValues(...string). See there for pros and cons of the two -// methods. -func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { - metric, err := v.metricVec.getMetricWith(labels) - if metric != nil { - return metric.(Observer), err - } - return nil, err -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. Not returning an -// error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) -func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { - s, err := v.GetMetricWithLabelValues(lvs...) - if err != nil { - panic(err) - } - return s -} - -// With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) -func (v *SummaryVec) With(labels Labels) Observer { - s, err := v.GetMetricWith(labels) - if err != nil { - panic(err) - } - return s -} - -// CurryWith returns a vector curried with the provided labels, i.e. the -// returned vector has those labels pre-set for all labeled operations performed -// on it. The cardinality of the curried vector is reduced accordingly. The -// order of the remaining labels stays the same (just with the curried labels -// taken out of the sequence – which is relevant for the -// (GetMetric)WithLabelValues methods). It is possible to curry a curried -// vector, but only with labels not yet used for currying before. -// -// The metrics contained in the SummaryVec are shared between the curried and -// uncurried vectors. They are just accessed differently. Curried and uncurried -// vectors behave identically in terms of collection. Only one must be -// registered with a given registry (usually the uncurried version). The Reset -// method deletes all metrics, even if called on a curried vector. -func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) { - vec, err := v.curryWith(labels) - if vec != nil { - return &SummaryVec{vec}, err - } - return nil, err -} - -// MustCurryWith works as CurryWith but panics where CurryWith would have -// returned an error. -func (v *SummaryVec) MustCurryWith(labels Labels) ObserverVec { - vec, err := v.CurryWith(labels) - if err != nil { - panic(err) - } - return vec -} - -type constSummary struct { - desc *Desc - count uint64 - sum float64 - quantiles map[float64]float64 - labelPairs []*dto.LabelPair -} - -func (s *constSummary) Desc() *Desc { - return s.desc -} - -func (s *constSummary) Write(out *dto.Metric) error { - sum := &dto.Summary{} - qs := make([]*dto.Quantile, 0, len(s.quantiles)) - - sum.SampleCount = proto.Uint64(s.count) - sum.SampleSum = proto.Float64(s.sum) - - for rank, q := range s.quantiles { - qs = append(qs, &dto.Quantile{ - Quantile: proto.Float64(rank), - Value: proto.Float64(q), - }) - } - - if len(qs) > 0 { - sort.Sort(quantSort(qs)) - } - sum.Quantile = qs - - out.Summary = sum - out.Label = s.labelPairs - - return nil -} - -// NewConstSummary returns a metric representing a Prometheus summary with fixed -// values for the count, sum, and quantiles. As those parameters cannot be -// changed, the returned value does not implement the Summary interface (but -// only the Metric interface). Users of this package will not have much use for -// it in regular operations. However, when implementing custom Collectors, it is -// useful as a throw-away metric that is generated on the fly to send it to -// Prometheus in the Collect method. -// -// quantiles maps ranks to quantile values. For example, a median latency of -// 0.23s and a 99th percentile latency of 0.56s would be expressed as: -// map[float64]float64{0.5: 0.23, 0.99: 0.56} -// -// NewConstSummary returns an error if the length of labelValues is not -// consistent with the variable labels in Desc. -func NewConstSummary( - desc *Desc, - count uint64, - sum float64, - quantiles map[float64]float64, - labelValues ...string, -) (Metric, error) { - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { - return nil, err - } - return &constSummary{ - desc: desc, - count: count, - sum: sum, - quantiles: quantiles, - labelPairs: makeLabelPairs(desc, labelValues), - }, nil -} - -// MustNewConstSummary is a version of NewConstSummary that panics where -// NewConstMetric would have returned an error. -func MustNewConstSummary( - desc *Desc, - count uint64, - sum float64, - quantiles map[float64]float64, - labelValues ...string, -) Metric { - m, err := NewConstSummary(desc, count, sum, quantiles, labelValues...) - if err != nil { - panic(err) - } - return m -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer.go b/vendor/github.com/prometheus/client_golang/prometheus/timer.go deleted file mode 100644 index b8fc5f18c8..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import "time" - -// Timer is a helper type to time functions. Use NewTimer to create new -// instances. -type Timer struct { - begin time.Time - observer Observer -} - -// NewTimer creates a new Timer. The provided Observer is used to observe a -// duration in seconds. Timer is usually used to time a function call in the -// following way: -// func TimeMe() { -// timer := NewTimer(myHistogram) -// defer timer.ObserveDuration() -// // Do actual work. -// } -func NewTimer(o Observer) *Timer { - return &Timer{ - begin: time.Now(), - observer: o, - } -} - -// ObserveDuration records the duration passed since the Timer was created with -// NewTimer. It calls the Observe method of the Observer provided during -// construction with the duration in seconds as an argument. ObserveDuration is -// usually called with a defer statement. -// -// Note that this method is only guaranteed to never observe negative durations -// if used with Go1.9+. -func (t *Timer) ObserveDuration() { - if t.observer != nil { - t.observer.Observe(time.Since(t.begin).Seconds()) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/untyped.go b/vendor/github.com/prometheus/client_golang/prometheus/untyped.go deleted file mode 100644 index 0f9ce63f40..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/untyped.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -// UntypedOpts is an alias for Opts. See there for doc comments. -type UntypedOpts Opts - -// UntypedFunc works like GaugeFunc but the collected metric is of type -// "Untyped". UntypedFunc is useful to mirror an external metric of unknown -// type. -// -// To create UntypedFunc instances, use NewUntypedFunc. -type UntypedFunc interface { - Metric - Collector -} - -// NewUntypedFunc creates a new UntypedFunc based on the provided -// UntypedOpts. The value reported is determined by calling the given function -// from within the Write method. Take into account that metric collection may -// happen concurrently. If that results in concurrent calls to Write, like in -// the case where an UntypedFunc is directly registered with Prometheus, the -// provided function must be concurrency-safe. -func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc { - return newValueFunc(NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), UntypedValue, function) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go deleted file mode 100644 index 543b57c27e..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/value.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "sort" - - dto "github.com/prometheus/client_model/go" - - "github.com/golang/protobuf/proto" -) - -// ValueType is an enumeration of metric types that represent a simple value. -type ValueType int - -// Possible values for the ValueType enum. -const ( - _ ValueType = iota - CounterValue - GaugeValue - UntypedValue -) - -// valueFunc is a generic metric for simple values retrieved on collect time -// from a function. It implements Metric and Collector. Its effective type is -// determined by ValueType. This is a low-level building block used by the -// library to back the implementations of CounterFunc, GaugeFunc, and -// UntypedFunc. -type valueFunc struct { - selfCollector - - desc *Desc - valType ValueType - function func() float64 - labelPairs []*dto.LabelPair -} - -// newValueFunc returns a newly allocated valueFunc with the given Desc and -// ValueType. The value reported is determined by calling the given function -// from within the Write method. Take into account that metric collection may -// happen concurrently. If that results in concurrent calls to Write, like in -// the case where a valueFunc is directly registered with Prometheus, the -// provided function must be concurrency-safe. -func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc { - result := &valueFunc{ - desc: desc, - valType: valueType, - function: function, - labelPairs: makeLabelPairs(desc, nil), - } - result.init(result) - return result -} - -func (v *valueFunc) Desc() *Desc { - return v.desc -} - -func (v *valueFunc) Write(out *dto.Metric) error { - return populateMetric(v.valType, v.function(), v.labelPairs, out) -} - -// NewConstMetric returns a metric with one fixed value that cannot be -// changed. Users of this package will not have much use for it in regular -// operations. However, when implementing custom Collectors, it is useful as a -// throw-away metric that is generated on the fly to send it to Prometheus in -// the Collect method. NewConstMetric returns an error if the length of -// labelValues is not consistent with the variable labels in Desc. -func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) { - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { - return nil, err - } - return &constMetric{ - desc: desc, - valType: valueType, - val: value, - labelPairs: makeLabelPairs(desc, labelValues), - }, nil -} - -// MustNewConstMetric is a version of NewConstMetric that panics where -// NewConstMetric would have returned an error. -func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric { - m, err := NewConstMetric(desc, valueType, value, labelValues...) - if err != nil { - panic(err) - } - return m -} - -type constMetric struct { - desc *Desc - valType ValueType - val float64 - labelPairs []*dto.LabelPair -} - -func (m *constMetric) Desc() *Desc { - return m.desc -} - -func (m *constMetric) Write(out *dto.Metric) error { - return populateMetric(m.valType, m.val, m.labelPairs, out) -} - -func populateMetric( - t ValueType, - v float64, - labelPairs []*dto.LabelPair, - m *dto.Metric, -) error { - m.Label = labelPairs - switch t { - case CounterValue: - m.Counter = &dto.Counter{Value: proto.Float64(v)} - case GaugeValue: - m.Gauge = &dto.Gauge{Value: proto.Float64(v)} - case UntypedValue: - m.Untyped = &dto.Untyped{Value: proto.Float64(v)} - default: - return fmt.Errorf("encountered unknown type %v", t) - } - return nil -} - -func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair { - totalLen := len(desc.variableLabels) + len(desc.constLabelPairs) - if totalLen == 0 { - // Super fast path. - return nil - } - if len(desc.variableLabels) == 0 { - // Moderately fast path. - return desc.constLabelPairs - } - labelPairs := make([]*dto.LabelPair, 0, totalLen) - for i, n := range desc.variableLabels { - labelPairs = append(labelPairs, &dto.LabelPair{ - Name: proto.String(n), - Value: proto.String(labelValues[i]), - }) - } - for _, lp := range desc.constLabelPairs { - labelPairs = append(labelPairs, lp) - } - sort.Sort(LabelPairSorter(labelPairs)) - return labelPairs -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go deleted file mode 100644 index cea1582499..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ /dev/null @@ -1,469 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "sync" - - "github.com/prometheus/common/model" -) - -// metricVec is a Collector to bundle metrics of the same name that differ in -// their label values. metricVec is not used directly (and therefore -// unexported). It is used as a building block for implementations of vectors of -// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec. -// It also handles label currying. It uses basicMetricVec internally. -type metricVec struct { - *metricMap - - curry []curriedLabelValue - - // hashAdd and hashAddByte can be replaced for testing collision handling. - hashAdd func(h uint64, s string) uint64 - hashAddByte func(h uint64, b byte) uint64 -} - -// newMetricVec returns an initialized metricVec. -func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec { - return &metricVec{ - metricMap: &metricMap{ - metrics: map[uint64][]metricWithLabelValues{}, - desc: desc, - newMetric: newMetric, - }, - hashAdd: hashAdd, - hashAddByte: hashAddByte, - } -} - -// DeleteLabelValues removes the metric where the variable labels are the same -// as those passed in as labels (same order as the VariableLabels in Desc). It -// returns true if a metric was deleted. -// -// It is not an error if the number of label values is not the same as the -// number of VariableLabels in Desc. However, such inconsistent label count can -// never match an actual metric, so the method will always return false in that -// case. -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider Delete(Labels) as an -// alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the CounterVec example. -func (m *metricVec) DeleteLabelValues(lvs ...string) bool { - h, err := m.hashLabelValues(lvs) - if err != nil { - return false - } - - return m.metricMap.deleteByHashWithLabelValues(h, lvs, m.curry) -} - -// Delete deletes the metric where the variable labels are the same as those -// passed in as labels. It returns true if a metric was deleted. -// -// It is not an error if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc. However, such inconsistent Labels -// can never match an actual metric, so the method will always return false in -// that case. -// -// This method is used for the same purpose as DeleteLabelValues(...string). See -// there for pros and cons of the two methods. -func (m *metricVec) Delete(labels Labels) bool { - h, err := m.hashLabels(labels) - if err != nil { - return false - } - - return m.metricMap.deleteByHashWithLabels(h, labels, m.curry) -} - -func (m *metricVec) curryWith(labels Labels) (*metricVec, error) { - var ( - newCurry []curriedLabelValue - oldCurry = m.curry - iCurry int - ) - for i, label := range m.desc.variableLabels { - val, ok := labels[label] - if iCurry < len(oldCurry) && oldCurry[iCurry].index == i { - if ok { - return nil, fmt.Errorf("label name %q is already curried", label) - } - newCurry = append(newCurry, oldCurry[iCurry]) - iCurry++ - } else { - if !ok { - continue // Label stays uncurried. - } - newCurry = append(newCurry, curriedLabelValue{i, val}) - } - } - if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 { - return nil, fmt.Errorf("%d unknown label(s) found during currying", l) - } - - return &metricVec{ - metricMap: m.metricMap, - curry: newCurry, - hashAdd: m.hashAdd, - hashAddByte: m.hashAddByte, - }, nil -} - -func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) { - h, err := m.hashLabelValues(lvs) - if err != nil { - return nil, err - } - - return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil -} - -func (m *metricVec) getMetricWith(labels Labels) (Metric, error) { - h, err := m.hashLabels(labels) - if err != nil { - return nil, err - } - - return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil -} - -func (m *metricVec) hashLabelValues(vals []string) (uint64, error) { - if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil { - return 0, err - } - - var ( - h = hashNew() - curry = m.curry - iVals, iCurry int - ) - for i := 0; i < len(m.desc.variableLabels); i++ { - if iCurry < len(curry) && curry[iCurry].index == i { - h = m.hashAdd(h, curry[iCurry].value) - iCurry++ - } else { - h = m.hashAdd(h, vals[iVals]) - iVals++ - } - h = m.hashAddByte(h, model.SeparatorByte) - } - return h, nil -} - -func (m *metricVec) hashLabels(labels Labels) (uint64, error) { - if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil { - return 0, err - } - - var ( - h = hashNew() - curry = m.curry - iCurry int - ) - for i, label := range m.desc.variableLabels { - val, ok := labels[label] - if iCurry < len(curry) && curry[iCurry].index == i { - if ok { - return 0, fmt.Errorf("label name %q is already curried", label) - } - h = m.hashAdd(h, curry[iCurry].value) - iCurry++ - } else { - if !ok { - return 0, fmt.Errorf("label name %q missing in label map", label) - } - h = m.hashAdd(h, val) - } - h = m.hashAddByte(h, model.SeparatorByte) - } - return h, nil -} - -// metricWithLabelValues provides the metric and its label values for -// disambiguation on hash collision. -type metricWithLabelValues struct { - values []string - metric Metric -} - -// curriedLabelValue sets the curried value for a label at the given index. -type curriedLabelValue struct { - index int - value string -} - -// metricMap is a helper for metricVec and shared between differently curried -// metricVecs. -type metricMap struct { - mtx sync.RWMutex // Protects metrics. - metrics map[uint64][]metricWithLabelValues - desc *Desc - newMetric func(labelValues ...string) Metric -} - -// Describe implements Collector. It will send exactly one Desc to the provided -// channel. -func (m *metricMap) Describe(ch chan<- *Desc) { - ch <- m.desc -} - -// Collect implements Collector. -func (m *metricMap) Collect(ch chan<- Metric) { - m.mtx.RLock() - defer m.mtx.RUnlock() - - for _, metrics := range m.metrics { - for _, metric := range metrics { - ch <- metric.metric - } - } -} - -// Reset deletes all metrics in this vector. -func (m *metricMap) Reset() { - m.mtx.Lock() - defer m.mtx.Unlock() - - for h := range m.metrics { - delete(m.metrics, h) - } -} - -// deleteByHashWithLabelValues removes the metric from the hash bucket h. If -// there are multiple matches in the bucket, use lvs to select a metric and -// remove only that metric. -func (m *metricMap) deleteByHashWithLabelValues( - h uint64, lvs []string, curry []curriedLabelValue, -) bool { - m.mtx.Lock() - defer m.mtx.Unlock() - - metrics, ok := m.metrics[h] - if !ok { - return false - } - - i := findMetricWithLabelValues(metrics, lvs, curry) - if i >= len(metrics) { - return false - } - - if len(metrics) > 1 { - m.metrics[h] = append(metrics[:i], metrics[i+1:]...) - } else { - delete(m.metrics, h) - } - return true -} - -// deleteByHashWithLabels removes the metric from the hash bucket h. If there -// are multiple matches in the bucket, use lvs to select a metric and remove -// only that metric. -func (m *metricMap) deleteByHashWithLabels( - h uint64, labels Labels, curry []curriedLabelValue, -) bool { - metrics, ok := m.metrics[h] - if !ok { - return false - } - i := findMetricWithLabels(m.desc, metrics, labels, curry) - if i >= len(metrics) { - return false - } - - if len(metrics) > 1 { - m.metrics[h] = append(metrics[:i], metrics[i+1:]...) - } else { - delete(m.metrics, h) - } - return true -} - -// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value -// or creates it and returns the new one. -// -// This function holds the mutex. -func (m *metricMap) getOrCreateMetricWithLabelValues( - hash uint64, lvs []string, curry []curriedLabelValue, -) Metric { - m.mtx.RLock() - metric, ok := m.getMetricWithHashAndLabelValues(hash, lvs, curry) - m.mtx.RUnlock() - if ok { - return metric - } - - m.mtx.Lock() - defer m.mtx.Unlock() - metric, ok = m.getMetricWithHashAndLabelValues(hash, lvs, curry) - if !ok { - inlinedLVs := inlineLabelValues(lvs, curry) - metric = m.newMetric(inlinedLVs...) - m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: inlinedLVs, metric: metric}) - } - return metric -} - -// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value -// or creates it and returns the new one. -// -// This function holds the mutex. -func (m *metricMap) getOrCreateMetricWithLabels( - hash uint64, labels Labels, curry []curriedLabelValue, -) Metric { - m.mtx.RLock() - metric, ok := m.getMetricWithHashAndLabels(hash, labels, curry) - m.mtx.RUnlock() - if ok { - return metric - } - - m.mtx.Lock() - defer m.mtx.Unlock() - metric, ok = m.getMetricWithHashAndLabels(hash, labels, curry) - if !ok { - lvs := extractLabelValues(m.desc, labels, curry) - metric = m.newMetric(lvs...) - m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: lvs, metric: metric}) - } - return metric -} - -// getMetricWithHashAndLabelValues gets a metric while handling possible -// collisions in the hash space. Must be called while holding the read mutex. -func (m *metricMap) getMetricWithHashAndLabelValues( - h uint64, lvs []string, curry []curriedLabelValue, -) (Metric, bool) { - metrics, ok := m.metrics[h] - if ok { - if i := findMetricWithLabelValues(metrics, lvs, curry); i < len(metrics) { - return metrics[i].metric, true - } - } - return nil, false -} - -// getMetricWithHashAndLabels gets a metric while handling possible collisions in -// the hash space. Must be called while holding read mutex. -func (m *metricMap) getMetricWithHashAndLabels( - h uint64, labels Labels, curry []curriedLabelValue, -) (Metric, bool) { - metrics, ok := m.metrics[h] - if ok { - if i := findMetricWithLabels(m.desc, metrics, labels, curry); i < len(metrics) { - return metrics[i].metric, true - } - } - return nil, false -} - -// findMetricWithLabelValues returns the index of the matching metric or -// len(metrics) if not found. -func findMetricWithLabelValues( - metrics []metricWithLabelValues, lvs []string, curry []curriedLabelValue, -) int { - for i, metric := range metrics { - if matchLabelValues(metric.values, lvs, curry) { - return i - } - } - return len(metrics) -} - -// findMetricWithLabels returns the index of the matching metric or len(metrics) -// if not found. -func findMetricWithLabels( - desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue, -) int { - for i, metric := range metrics { - if matchLabels(desc, metric.values, labels, curry) { - return i - } - } - return len(metrics) -} - -func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool { - if len(values) != len(lvs)+len(curry) { - return false - } - var iLVs, iCurry int - for i, v := range values { - if iCurry < len(curry) && curry[iCurry].index == i { - if v != curry[iCurry].value { - return false - } - iCurry++ - continue - } - if v != lvs[iLVs] { - return false - } - iLVs++ - } - return true -} - -func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool { - if len(values) != len(labels)+len(curry) { - return false - } - iCurry := 0 - for i, k := range desc.variableLabels { - if iCurry < len(curry) && curry[iCurry].index == i { - if values[i] != curry[iCurry].value { - return false - } - iCurry++ - continue - } - if values[i] != labels[k] { - return false - } - } - return true -} - -func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string { - labelValues := make([]string, len(labels)+len(curry)) - iCurry := 0 - for i, k := range desc.variableLabels { - if iCurry < len(curry) && curry[iCurry].index == i { - labelValues[i] = curry[iCurry].value - iCurry++ - continue - } - labelValues[i] = labels[k] - } - return labelValues -} - -func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string { - labelValues := make([]string, len(lvs)+len(curry)) - var iCurry, iLVs int - for i := range labelValues { - if iCurry < len(curry) && curry[iCurry].index == i { - labelValues[i] = curry[iCurry].value - iCurry++ - continue - } - labelValues[i] = lvs[iLVs] - iLVs++ - } - return labelValues -} diff --git a/vendor/github.com/prometheus/client_model/LICENSE b/vendor/github.com/prometheus/client_model/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/prometheus/client_model/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/prometheus/client_model/NOTICE b/vendor/github.com/prometheus/client_model/NOTICE deleted file mode 100644 index 20110e410e..0000000000 --- a/vendor/github.com/prometheus/client_model/NOTICE +++ /dev/null @@ -1,5 +0,0 @@ -Data model artifacts for Prometheus. -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). diff --git a/vendor/github.com/prometheus/client_model/go/metrics.pb.go b/vendor/github.com/prometheus/client_model/go/metrics.pb.go deleted file mode 100644 index b065f8683f..0000000000 --- a/vendor/github.com/prometheus/client_model/go/metrics.pb.go +++ /dev/null @@ -1,364 +0,0 @@ -// Code generated by protoc-gen-go. -// source: metrics.proto -// DO NOT EDIT! - -/* -Package io_prometheus_client is a generated protocol buffer package. - -It is generated from these files: - metrics.proto - -It has these top-level messages: - LabelPair - Gauge - Counter - Quantile - Summary - Untyped - Histogram - Bucket - Metric - MetricFamily -*/ -package io_prometheus_client - -import proto "github.com/golang/protobuf/proto" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = math.Inf - -type MetricType int32 - -const ( - MetricType_COUNTER MetricType = 0 - MetricType_GAUGE MetricType = 1 - MetricType_SUMMARY MetricType = 2 - MetricType_UNTYPED MetricType = 3 - MetricType_HISTOGRAM MetricType = 4 -) - -var MetricType_name = map[int32]string{ - 0: "COUNTER", - 1: "GAUGE", - 2: "SUMMARY", - 3: "UNTYPED", - 4: "HISTOGRAM", -} -var MetricType_value = map[string]int32{ - "COUNTER": 0, - "GAUGE": 1, - "SUMMARY": 2, - "UNTYPED": 3, - "HISTOGRAM": 4, -} - -func (x MetricType) Enum() *MetricType { - p := new(MetricType) - *p = x - return p -} -func (x MetricType) String() string { - return proto.EnumName(MetricType_name, int32(x)) -} -func (x *MetricType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType") - if err != nil { - return err - } - *x = MetricType(value) - return nil -} - -type LabelPair struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LabelPair) Reset() { *m = LabelPair{} } -func (m *LabelPair) String() string { return proto.CompactTextString(m) } -func (*LabelPair) ProtoMessage() {} - -func (m *LabelPair) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *LabelPair) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value - } - return "" -} - -type Gauge struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Gauge) Reset() { *m = Gauge{} } -func (m *Gauge) String() string { return proto.CompactTextString(m) } -func (*Gauge) ProtoMessage() {} - -func (m *Gauge) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type Counter struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Counter) Reset() { *m = Counter{} } -func (m *Counter) String() string { return proto.CompactTextString(m) } -func (*Counter) ProtoMessage() {} - -func (m *Counter) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type Quantile struct { - Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` - Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Quantile) Reset() { *m = Quantile{} } -func (m *Quantile) String() string { return proto.CompactTextString(m) } -func (*Quantile) ProtoMessage() {} - -func (m *Quantile) GetQuantile() float64 { - if m != nil && m.Quantile != nil { - return *m.Quantile - } - return 0 -} - -func (m *Quantile) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type Summary struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"` - Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Summary) Reset() { *m = Summary{} } -func (m *Summary) String() string { return proto.CompactTextString(m) } -func (*Summary) ProtoMessage() {} - -func (m *Summary) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount - } - return 0 -} - -func (m *Summary) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum - } - return 0 -} - -func (m *Summary) GetQuantile() []*Quantile { - if m != nil { - return m.Quantile - } - return nil -} - -type Untyped struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Untyped) Reset() { *m = Untyped{} } -func (m *Untyped) String() string { return proto.CompactTextString(m) } -func (*Untyped) ProtoMessage() {} - -func (m *Untyped) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type Histogram struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"` - Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Histogram) Reset() { *m = Histogram{} } -func (m *Histogram) String() string { return proto.CompactTextString(m) } -func (*Histogram) ProtoMessage() {} - -func (m *Histogram) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount - } - return 0 -} - -func (m *Histogram) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum - } - return 0 -} - -func (m *Histogram) GetBucket() []*Bucket { - if m != nil { - return m.Bucket - } - return nil -} - -type Bucket struct { - CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count" json:"cumulative_count,omitempty"` - UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound" json:"upper_bound,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Bucket) Reset() { *m = Bucket{} } -func (m *Bucket) String() string { return proto.CompactTextString(m) } -func (*Bucket) ProtoMessage() {} - -func (m *Bucket) GetCumulativeCount() uint64 { - if m != nil && m.CumulativeCount != nil { - return *m.CumulativeCount - } - return 0 -} - -func (m *Bucket) GetUpperBound() float64 { - if m != nil && m.UpperBound != nil { - return *m.UpperBound - } - return 0 -} - -type Metric struct { - Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` - Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` - Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` - Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` - Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` - Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` - TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms" json:"timestamp_ms,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Metric) Reset() { *m = Metric{} } -func (m *Metric) String() string { return proto.CompactTextString(m) } -func (*Metric) ProtoMessage() {} - -func (m *Metric) GetLabel() []*LabelPair { - if m != nil { - return m.Label - } - return nil -} - -func (m *Metric) GetGauge() *Gauge { - if m != nil { - return m.Gauge - } - return nil -} - -func (m *Metric) GetCounter() *Counter { - if m != nil { - return m.Counter - } - return nil -} - -func (m *Metric) GetSummary() *Summary { - if m != nil { - return m.Summary - } - return nil -} - -func (m *Metric) GetUntyped() *Untyped { - if m != nil { - return m.Untyped - } - return nil -} - -func (m *Metric) GetHistogram() *Histogram { - if m != nil { - return m.Histogram - } - return nil -} - -func (m *Metric) GetTimestampMs() int64 { - if m != nil && m.TimestampMs != nil { - return *m.TimestampMs - } - return 0 -} - -type MetricFamily struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` - Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` - Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MetricFamily) Reset() { *m = MetricFamily{} } -func (m *MetricFamily) String() string { return proto.CompactTextString(m) } -func (*MetricFamily) ProtoMessage() {} - -func (m *MetricFamily) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MetricFamily) GetHelp() string { - if m != nil && m.Help != nil { - return *m.Help - } - return "" -} - -func (m *MetricFamily) GetType() MetricType { - if m != nil && m.Type != nil { - return *m.Type - } - return MetricType_COUNTER -} - -func (m *MetricFamily) GetMetric() []*Metric { - if m != nil { - return m.Metric - } - return nil -} - -func init() { - proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value) -} diff --git a/vendor/github.com/prometheus/client_model/ruby/LICENSE b/vendor/github.com/prometheus/client_model/ruby/LICENSE deleted file mode 100644 index 11069edd79..0000000000 --- a/vendor/github.com/prometheus/client_model/ruby/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/github.com/prometheus/common/LICENSE b/vendor/github.com/prometheus/common/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/prometheus/common/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/prometheus/common/NOTICE b/vendor/github.com/prometheus/common/NOTICE deleted file mode 100644 index 636a2c1a5e..0000000000 --- a/vendor/github.com/prometheus/common/NOTICE +++ /dev/null @@ -1,5 +0,0 @@ -Common libraries shared by Prometheus Go components. -Copyright 2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go deleted file mode 100644 index c092723e84..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "fmt" - "io" - "math" - "mime" - "net/http" - - dto "github.com/prometheus/client_model/go" - - "github.com/matttproud/golang_protobuf_extensions/pbutil" - "github.com/prometheus/common/model" -) - -// Decoder types decode an input stream into metric families. -type Decoder interface { - Decode(*dto.MetricFamily) error -} - -// DecodeOptions contains options used by the Decoder and in sample extraction. -type DecodeOptions struct { - // Timestamp is added to each value from the stream that has no explicit timestamp set. - Timestamp model.Time -} - -// ResponseFormat extracts the correct format from a HTTP response header. -// If no matching format can be found FormatUnknown is returned. -func ResponseFormat(h http.Header) Format { - ct := h.Get(hdrContentType) - - mediatype, params, err := mime.ParseMediaType(ct) - if err != nil { - return FmtUnknown - } - - const textType = "text/plain" - - switch mediatype { - case ProtoType: - if p, ok := params["proto"]; ok && p != ProtoProtocol { - return FmtUnknown - } - if e, ok := params["encoding"]; ok && e != "delimited" { - return FmtUnknown - } - return FmtProtoDelim - - case textType: - if v, ok := params["version"]; ok && v != TextVersion { - return FmtUnknown - } - return FmtText - } - - return FmtUnknown -} - -// NewDecoder returns a new decoder based on the given input format. -// If the input format does not imply otherwise, a text format decoder is returned. -func NewDecoder(r io.Reader, format Format) Decoder { - switch format { - case FmtProtoDelim: - return &protoDecoder{r: r} - } - return &textDecoder{r: r} -} - -// protoDecoder implements the Decoder interface for protocol buffers. -type protoDecoder struct { - r io.Reader -} - -// Decode implements the Decoder interface. -func (d *protoDecoder) Decode(v *dto.MetricFamily) error { - _, err := pbutil.ReadDelimited(d.r, v) - if err != nil { - return err - } - if !model.IsValidMetricName(model.LabelValue(v.GetName())) { - return fmt.Errorf("invalid metric name %q", v.GetName()) - } - for _, m := range v.GetMetric() { - if m == nil { - continue - } - for _, l := range m.GetLabel() { - if l == nil { - continue - } - if !model.LabelValue(l.GetValue()).IsValid() { - return fmt.Errorf("invalid label value %q", l.GetValue()) - } - if !model.LabelName(l.GetName()).IsValid() { - return fmt.Errorf("invalid label name %q", l.GetName()) - } - } - } - return nil -} - -// textDecoder implements the Decoder interface for the text protocol. -type textDecoder struct { - r io.Reader - p TextParser - fams []*dto.MetricFamily -} - -// Decode implements the Decoder interface. -func (d *textDecoder) Decode(v *dto.MetricFamily) error { - // TODO(fabxc): Wrap this as a line reader to make streaming safer. - if len(d.fams) == 0 { - // No cached metric families, read everything and parse metrics. - fams, err := d.p.TextToMetricFamilies(d.r) - if err != nil { - return err - } - if len(fams) == 0 { - return io.EOF - } - d.fams = make([]*dto.MetricFamily, 0, len(fams)) - for _, f := range fams { - d.fams = append(d.fams, f) - } - } - - *v = *d.fams[0] - d.fams = d.fams[1:] - - return nil -} - -// SampleDecoder wraps a Decoder to extract samples from the metric families -// decoded by the wrapped Decoder. -type SampleDecoder struct { - Dec Decoder - Opts *DecodeOptions - - f dto.MetricFamily -} - -// Decode calls the Decode method of the wrapped Decoder and then extracts the -// samples from the decoded MetricFamily into the provided model.Vector. -func (sd *SampleDecoder) Decode(s *model.Vector) error { - err := sd.Dec.Decode(&sd.f) - if err != nil { - return err - } - *s, err = extractSamples(&sd.f, sd.Opts) - return err -} - -// ExtractSamples builds a slice of samples from the provided metric -// families. If an error occurrs during sample extraction, it continues to -// extract from the remaining metric families. The returned error is the last -// error that has occurred. -func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) { - var ( - all model.Vector - lastErr error - ) - for _, f := range fams { - some, err := extractSamples(f, o) - if err != nil { - lastErr = err - continue - } - all = append(all, some...) - } - return all, lastErr -} - -func extractSamples(f *dto.MetricFamily, o *DecodeOptions) (model.Vector, error) { - switch f.GetType() { - case dto.MetricType_COUNTER: - return extractCounter(o, f), nil - case dto.MetricType_GAUGE: - return extractGauge(o, f), nil - case dto.MetricType_SUMMARY: - return extractSummary(o, f), nil - case dto.MetricType_UNTYPED: - return extractUntyped(o, f), nil - case dto.MetricType_HISTOGRAM: - return extractHistogram(o, f), nil - } - return nil, fmt.Errorf("expfmt.extractSamples: unknown metric family type %v", f.GetType()) -} - -func extractCounter(o *DecodeOptions, f *dto.MetricFamily) model.Vector { - samples := make(model.Vector, 0, len(f.Metric)) - - for _, m := range f.Metric { - if m.Counter == nil { - continue - } - - lset := make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName()) - - smpl := &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Counter.GetValue()), - } - - if m.TimestampMs != nil { - smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000) - } else { - smpl.Timestamp = o.Timestamp - } - - samples = append(samples, smpl) - } - - return samples -} - -func extractGauge(o *DecodeOptions, f *dto.MetricFamily) model.Vector { - samples := make(model.Vector, 0, len(f.Metric)) - - for _, m := range f.Metric { - if m.Gauge == nil { - continue - } - - lset := make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName()) - - smpl := &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Gauge.GetValue()), - } - - if m.TimestampMs != nil { - smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000) - } else { - smpl.Timestamp = o.Timestamp - } - - samples = append(samples, smpl) - } - - return samples -} - -func extractUntyped(o *DecodeOptions, f *dto.MetricFamily) model.Vector { - samples := make(model.Vector, 0, len(f.Metric)) - - for _, m := range f.Metric { - if m.Untyped == nil { - continue - } - - lset := make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName()) - - smpl := &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Untyped.GetValue()), - } - - if m.TimestampMs != nil { - smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000) - } else { - smpl.Timestamp = o.Timestamp - } - - samples = append(samples, smpl) - } - - return samples -} - -func extractSummary(o *DecodeOptions, f *dto.MetricFamily) model.Vector { - samples := make(model.Vector, 0, len(f.Metric)) - - for _, m := range f.Metric { - if m.Summary == nil { - continue - } - - timestamp := o.Timestamp - if m.TimestampMs != nil { - timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000) - } - - for _, q := range m.Summary.Quantile { - lset := make(model.LabelSet, len(m.Label)+2) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - // BUG(matt): Update other names to "quantile". - lset[model.LabelName(model.QuantileLabel)] = model.LabelValue(fmt.Sprint(q.GetQuantile())) - lset[model.MetricNameLabel] = model.LabelValue(f.GetName()) - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(q.GetValue()), - Timestamp: timestamp, - }) - } - - lset := make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum") - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Summary.GetSampleSum()), - Timestamp: timestamp, - }) - - lset = make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count") - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Summary.GetSampleCount()), - Timestamp: timestamp, - }) - } - - return samples -} - -func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector { - samples := make(model.Vector, 0, len(f.Metric)) - - for _, m := range f.Metric { - if m.Histogram == nil { - continue - } - - timestamp := o.Timestamp - if m.TimestampMs != nil { - timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000) - } - - infSeen := false - - for _, q := range m.Histogram.Bucket { - lset := make(model.LabelSet, len(m.Label)+2) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.LabelName(model.BucketLabel)] = model.LabelValue(fmt.Sprint(q.GetUpperBound())) - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket") - - if math.IsInf(q.GetUpperBound(), +1) { - infSeen = true - } - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(q.GetCumulativeCount()), - Timestamp: timestamp, - }) - } - - lset := make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum") - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Histogram.GetSampleSum()), - Timestamp: timestamp, - }) - - lset = make(model.LabelSet, len(m.Label)+1) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count") - - count := &model.Sample{ - Metric: model.Metric(lset), - Value: model.SampleValue(m.Histogram.GetSampleCount()), - Timestamp: timestamp, - } - samples = append(samples, count) - - if !infSeen { - // Append an infinity bucket sample. - lset := make(model.LabelSet, len(m.Label)+2) - for _, p := range m.Label { - lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue()) - } - lset[model.LabelName(model.BucketLabel)] = model.LabelValue("+Inf") - lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket") - - samples = append(samples, &model.Sample{ - Metric: model.Metric(lset), - Value: count.Value, - Timestamp: timestamp, - }) - } - } - - return samples -} diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go deleted file mode 100644 index 11839ed65c..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "fmt" - "io" - "net/http" - - "github.com/golang/protobuf/proto" - "github.com/matttproud/golang_protobuf_extensions/pbutil" - "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" - - dto "github.com/prometheus/client_model/go" -) - -// Encoder types encode metric families into an underlying wire protocol. -type Encoder interface { - Encode(*dto.MetricFamily) error -} - -type encoder func(*dto.MetricFamily) error - -func (e encoder) Encode(v *dto.MetricFamily) error { - return e(v) -} - -// Negotiate returns the Content-Type based on the given Accept header. -// If no appropriate accepted type is found, FmtText is returned. -func Negotiate(h http.Header) Format { - for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { - // Check for protocol buffer - if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { - switch ac.Params["encoding"] { - case "delimited": - return FmtProtoDelim - case "text": - return FmtProtoText - case "compact-text": - return FmtProtoCompact - } - } - // Check for text format. - ver := ac.Params["version"] - if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText - } - } - return FmtText -} - -// NewEncoder returns a new encoder based on content type negotiation. -func NewEncoder(w io.Writer, format Format) Encoder { - switch format { - case FmtProtoDelim: - return encoder(func(v *dto.MetricFamily) error { - _, err := pbutil.WriteDelimited(w, v) - return err - }) - case FmtProtoCompact: - return encoder(func(v *dto.MetricFamily) error { - _, err := fmt.Fprintln(w, v.String()) - return err - }) - case FmtProtoText: - return encoder(func(v *dto.MetricFamily) error { - _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) - return err - }) - case FmtText: - return encoder(func(v *dto.MetricFamily) error { - _, err := MetricFamilyToText(w, v) - return err - }) - } - panic("expfmt.NewEncoder: unknown format") -} diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go deleted file mode 100644 index c71bcb9816..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package expfmt contains tools for reading and writing Prometheus metrics. -package expfmt - -// Format specifies the HTTP content type of the different wire protocols. -type Format string - -// Constants to assemble the Content-Type values for the different wire protocols. -const ( - TextVersion = "0.0.4" - ProtoType = `application/vnd.google.protobuf` - ProtoProtocol = `io.prometheus.client.MetricFamily` - ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" - - // The Content-Type values for the different wire protocols. - FmtUnknown Format = `` - FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` - FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` - FmtProtoText Format = ProtoFmt + ` encoding=text` - FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` -) - -const ( - hdrContentType = "Content-Type" - hdrAccept = "Accept" -) diff --git a/vendor/github.com/prometheus/common/expfmt/fuzz.go b/vendor/github.com/prometheus/common/expfmt/fuzz.go deleted file mode 100644 index dc2eedeefc..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/fuzz.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Build only when actually fuzzing -// +build gofuzz - -package expfmt - -import "bytes" - -// Fuzz text metric parser with with github.com/dvyukov/go-fuzz: -// -// go-fuzz-build github.com/prometheus/common/expfmt -// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz -// -// Further input samples should go in the folder fuzz/corpus. -func Fuzz(in []byte) int { - parser := TextParser{} - _, err := parser.TextToMetricFamilies(bytes.NewReader(in)) - - if err != nil { - return 0 - } - - return 1 -} diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go deleted file mode 100644 index f11321cd0c..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/text_create.go +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "fmt" - "io" - "math" - "strings" - - dto "github.com/prometheus/client_model/go" - "github.com/prometheus/common/model" -) - -// MetricFamilyToText converts a MetricFamily proto message into text format and -// writes the resulting lines to 'out'. It returns the number of bytes written -// and any error encountered. The output will have the same order as the input, -// no further sorting is performed. Furthermore, this function assumes the input -// is already sanitized and does not perform any sanity checks. If the input -// contains duplicate metrics or invalid metric or label names, the conversion -// will result in invalid text format output. -// -// This method fulfills the type 'prometheus.encoder'. -func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) { - var written int - - // Fail-fast checks. - if len(in.Metric) == 0 { - return written, fmt.Errorf("MetricFamily has no metrics: %s", in) - } - name := in.GetName() - if name == "" { - return written, fmt.Errorf("MetricFamily has no name: %s", in) - } - - // Comments, first HELP, then TYPE. - if in.Help != nil { - n, err := fmt.Fprintf( - out, "# HELP %s %s\n", - name, escapeString(*in.Help, false), - ) - written += n - if err != nil { - return written, err - } - } - metricType := in.GetType() - n, err := fmt.Fprintf( - out, "# TYPE %s %s\n", - name, strings.ToLower(metricType.String()), - ) - written += n - if err != nil { - return written, err - } - - // Finally the samples, one line for each. - for _, metric := range in.Metric { - switch metricType { - case dto.MetricType_COUNTER: - if metric.Counter == nil { - return written, fmt.Errorf( - "expected counter in metric %s %s", name, metric, - ) - } - n, err = writeSample( - name, metric, "", "", - metric.Counter.GetValue(), - out, - ) - case dto.MetricType_GAUGE: - if metric.Gauge == nil { - return written, fmt.Errorf( - "expected gauge in metric %s %s", name, metric, - ) - } - n, err = writeSample( - name, metric, "", "", - metric.Gauge.GetValue(), - out, - ) - case dto.MetricType_UNTYPED: - if metric.Untyped == nil { - return written, fmt.Errorf( - "expected untyped in metric %s %s", name, metric, - ) - } - n, err = writeSample( - name, metric, "", "", - metric.Untyped.GetValue(), - out, - ) - case dto.MetricType_SUMMARY: - if metric.Summary == nil { - return written, fmt.Errorf( - "expected summary in metric %s %s", name, metric, - ) - } - for _, q := range metric.Summary.Quantile { - n, err = writeSample( - name, metric, - model.QuantileLabel, fmt.Sprint(q.GetQuantile()), - q.GetValue(), - out, - ) - written += n - if err != nil { - return written, err - } - } - n, err = writeSample( - name+"_sum", metric, "", "", - metric.Summary.GetSampleSum(), - out, - ) - if err != nil { - return written, err - } - written += n - n, err = writeSample( - name+"_count", metric, "", "", - float64(metric.Summary.GetSampleCount()), - out, - ) - case dto.MetricType_HISTOGRAM: - if metric.Histogram == nil { - return written, fmt.Errorf( - "expected histogram in metric %s %s", name, metric, - ) - } - infSeen := false - for _, q := range metric.Histogram.Bucket { - n, err = writeSample( - name+"_bucket", metric, - model.BucketLabel, fmt.Sprint(q.GetUpperBound()), - float64(q.GetCumulativeCount()), - out, - ) - written += n - if err != nil { - return written, err - } - if math.IsInf(q.GetUpperBound(), +1) { - infSeen = true - } - } - if !infSeen { - n, err = writeSample( - name+"_bucket", metric, - model.BucketLabel, "+Inf", - float64(metric.Histogram.GetSampleCount()), - out, - ) - if err != nil { - return written, err - } - written += n - } - n, err = writeSample( - name+"_sum", metric, "", "", - metric.Histogram.GetSampleSum(), - out, - ) - if err != nil { - return written, err - } - written += n - n, err = writeSample( - name+"_count", metric, "", "", - float64(metric.Histogram.GetSampleCount()), - out, - ) - default: - return written, fmt.Errorf( - "unexpected type in metric %s %s", name, metric, - ) - } - written += n - if err != nil { - return written, err - } - } - return written, nil -} - -// writeSample writes a single sample in text format to out, given the metric -// name, the metric proto message itself, optionally an additional label name -// and value (use empty strings if not required), and the value. The function -// returns the number of bytes written and any error encountered. -func writeSample( - name string, - metric *dto.Metric, - additionalLabelName, additionalLabelValue string, - value float64, - out io.Writer, -) (int, error) { - var written int - n, err := fmt.Fprint(out, name) - written += n - if err != nil { - return written, err - } - n, err = labelPairsToText( - metric.Label, - additionalLabelName, additionalLabelValue, - out, - ) - written += n - if err != nil { - return written, err - } - n, err = fmt.Fprintf(out, " %v", value) - written += n - if err != nil { - return written, err - } - if metric.TimestampMs != nil { - n, err = fmt.Fprintf(out, " %v", *metric.TimestampMs) - written += n - if err != nil { - return written, err - } - } - n, err = out.Write([]byte{'\n'}) - written += n - if err != nil { - return written, err - } - return written, nil -} - -// labelPairsToText converts a slice of LabelPair proto messages plus the -// explicitly given additional label pair into text formatted as required by the -// text format and writes it to 'out'. An empty slice in combination with an -// empty string 'additionalLabelName' results in nothing being -// written. Otherwise, the label pairs are written, escaped as required by the -// text format, and enclosed in '{...}'. The function returns the number of -// bytes written and any error encountered. -func labelPairsToText( - in []*dto.LabelPair, - additionalLabelName, additionalLabelValue string, - out io.Writer, -) (int, error) { - if len(in) == 0 && additionalLabelName == "" { - return 0, nil - } - var written int - separator := '{' - for _, lp := range in { - n, err := fmt.Fprintf( - out, `%c%s="%s"`, - separator, lp.GetName(), escapeString(lp.GetValue(), true), - ) - written += n - if err != nil { - return written, err - } - separator = ',' - } - if additionalLabelName != "" { - n, err := fmt.Fprintf( - out, `%c%s="%s"`, - separator, additionalLabelName, - escapeString(additionalLabelValue, true), - ) - written += n - if err != nil { - return written, err - } - } - n, err := out.Write([]byte{'}'}) - written += n - if err != nil { - return written, err - } - return written, nil -} - -var ( - escape = strings.NewReplacer("\\", `\\`, "\n", `\n`) - escapeWithDoubleQuote = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`) -) - -// escapeString replaces '\' by '\\', new line character by '\n', and - if -// includeDoubleQuote is true - '"' by '\"'. -func escapeString(v string, includeDoubleQuote bool) string { - if includeDoubleQuote { - return escapeWithDoubleQuote.Replace(v) - } - - return escape.Replace(v) -} diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go deleted file mode 100644 index b86290afa3..0000000000 --- a/vendor/github.com/prometheus/common/expfmt/text_parse.go +++ /dev/null @@ -1,757 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "bufio" - "bytes" - "fmt" - "io" - "math" - "strconv" - "strings" - - dto "github.com/prometheus/client_model/go" - - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/model" -) - -// A stateFn is a function that represents a state in a state machine. By -// executing it, the state is progressed to the next state. The stateFn returns -// another stateFn, which represents the new state. The end state is represented -// by nil. -type stateFn func() stateFn - -// ParseError signals errors while parsing the simple and flat text-based -// exchange format. -type ParseError struct { - Line int - Msg string -} - -// Error implements the error interface. -func (e ParseError) Error() string { - return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg) -} - -// TextParser is used to parse the simple and flat text-based exchange format. Its -// zero value is ready to use. -type TextParser struct { - metricFamiliesByName map[string]*dto.MetricFamily - buf *bufio.Reader // Where the parsed input is read through. - err error // Most recent error. - lineCount int // Tracks the line count for error messages. - currentByte byte // The most recent byte read. - currentToken bytes.Buffer // Re-used each time a token has to be gathered from multiple bytes. - currentMF *dto.MetricFamily - currentMetric *dto.Metric - currentLabelPair *dto.LabelPair - - // The remaining member variables are only used for summaries/histograms. - currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le' - // Summary specific. - summaries map[uint64]*dto.Metric // Key is created with LabelsToSignature. - currentQuantile float64 - // Histogram specific. - histograms map[uint64]*dto.Metric // Key is created with LabelsToSignature. - currentBucket float64 - // These tell us if the currently processed line ends on '_count' or - // '_sum' respectively and belong to a summary/histogram, representing the sample - // count and sum of that summary/histogram. - currentIsSummaryCount, currentIsSummarySum bool - currentIsHistogramCount, currentIsHistogramSum bool -} - -// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange -// format and creates MetricFamily proto messages. It returns the MetricFamily -// proto messages in a map where the metric names are the keys, along with any -// error encountered. -// -// If the input contains duplicate metrics (i.e. lines with the same metric name -// and exactly the same label set), the resulting MetricFamily will contain -// duplicate Metric proto messages. Similar is true for duplicate label -// names. Checks for duplicates have to be performed separately, if required. -// Also note that neither the metrics within each MetricFamily are sorted nor -// the label pairs within each Metric. Sorting is not required for the most -// frequent use of this method, which is sample ingestion in the Prometheus -// server. However, for presentation purposes, you might want to sort the -// metrics, and in some cases, you must sort the labels, e.g. for consumption by -// the metric family injection hook of the Prometheus registry. -// -// Summaries and histograms are rather special beasts. You would probably not -// use them in the simple text format anyway. This method can deal with -// summaries and histograms if they are presented in exactly the way the -// text.Create function creates them. -// -// This method must not be called concurrently. If you want to parse different -// input concurrently, instantiate a separate Parser for each goroutine. -func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) { - p.reset(in) - for nextState := p.startOfLine; nextState != nil; nextState = nextState() { - // Magic happens here... - } - // Get rid of empty metric families. - for k, mf := range p.metricFamiliesByName { - if len(mf.GetMetric()) == 0 { - delete(p.metricFamiliesByName, k) - } - } - // If p.err is io.EOF now, we have run into a premature end of the input - // stream. Turn this error into something nicer and more - // meaningful. (io.EOF is often used as a signal for the legitimate end - // of an input stream.) - if p.err == io.EOF { - p.parseError("unexpected end of input stream") - } - return p.metricFamiliesByName, p.err -} - -func (p *TextParser) reset(in io.Reader) { - p.metricFamiliesByName = map[string]*dto.MetricFamily{} - if p.buf == nil { - p.buf = bufio.NewReader(in) - } else { - p.buf.Reset(in) - } - p.err = nil - p.lineCount = 0 - if p.summaries == nil || len(p.summaries) > 0 { - p.summaries = map[uint64]*dto.Metric{} - } - if p.histograms == nil || len(p.histograms) > 0 { - p.histograms = map[uint64]*dto.Metric{} - } - p.currentQuantile = math.NaN() - p.currentBucket = math.NaN() -} - -// startOfLine represents the state where the next byte read from p.buf is the -// start of a line (or whitespace leading up to it). -func (p *TextParser) startOfLine() stateFn { - p.lineCount++ - if p.skipBlankTab(); p.err != nil { - // End of input reached. This is the only case where - // that is not an error but a signal that we are done. - p.err = nil - return nil - } - switch p.currentByte { - case '#': - return p.startComment - case '\n': - return p.startOfLine // Empty line, start the next one. - } - return p.readingMetricName -} - -// startComment represents the state where the next byte read from p.buf is the -// start of a comment (or whitespace leading up to it). -func (p *TextParser) startComment() stateFn { - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte == '\n' { - return p.startOfLine - } - if p.readTokenUntilWhitespace(); p.err != nil { - return nil // Unexpected end of input. - } - // If we have hit the end of line already, there is nothing left - // to do. This is not considered a syntax error. - if p.currentByte == '\n' { - return p.startOfLine - } - keyword := p.currentToken.String() - if keyword != "HELP" && keyword != "TYPE" { - // Generic comment, ignore by fast forwarding to end of line. - for p.currentByte != '\n' { - if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil { - return nil // Unexpected end of input. - } - } - return p.startOfLine - } - // There is something. Next has to be a metric name. - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.readTokenAsMetricName(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte == '\n' { - // At the end of the line already. - // Again, this is not considered a syntax error. - return p.startOfLine - } - if !isBlankOrTab(p.currentByte) { - p.parseError("invalid metric name in comment") - return nil - } - p.setOrCreateCurrentMF() - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte == '\n' { - // At the end of the line already. - // Again, this is not considered a syntax error. - return p.startOfLine - } - switch keyword { - case "HELP": - return p.readingHelp - case "TYPE": - return p.readingType - } - panic(fmt.Sprintf("code error: unexpected keyword %q", keyword)) -} - -// readingMetricName represents the state where the last byte read (now in -// p.currentByte) is the first byte of a metric name. -func (p *TextParser) readingMetricName() stateFn { - if p.readTokenAsMetricName(); p.err != nil { - return nil - } - if p.currentToken.Len() == 0 { - p.parseError("invalid metric name") - return nil - } - p.setOrCreateCurrentMF() - // Now is the time to fix the type if it hasn't happened yet. - if p.currentMF.Type == nil { - p.currentMF.Type = dto.MetricType_UNTYPED.Enum() - } - p.currentMetric = &dto.Metric{} - // Do not append the newly created currentMetric to - // currentMF.Metric right now. First wait if this is a summary, - // and the metric exists already, which we can only know after - // having read all the labels. - if p.skipBlankTabIfCurrentBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - return p.readingLabels -} - -// readingLabels represents the state where the last byte read (now in -// p.currentByte) is either the first byte of the label set (i.e. a '{'), or the -// first byte of the value (otherwise). -func (p *TextParser) readingLabels() stateFn { - // Summaries/histograms are special. We have to reset the - // currentLabels map, currentQuantile and currentBucket before starting to - // read labels. - if p.currentMF.GetType() == dto.MetricType_SUMMARY || p.currentMF.GetType() == dto.MetricType_HISTOGRAM { - p.currentLabels = map[string]string{} - p.currentLabels[string(model.MetricNameLabel)] = p.currentMF.GetName() - p.currentQuantile = math.NaN() - p.currentBucket = math.NaN() - } - if p.currentByte != '{' { - return p.readingValue - } - return p.startLabelName -} - -// startLabelName represents the state where the next byte read from p.buf is -// the start of a label name (or whitespace leading up to it). -func (p *TextParser) startLabelName() stateFn { - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte == '}' { - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - return p.readingValue - } - if p.readTokenAsLabelName(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentToken.Len() == 0 { - p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName())) - return nil - } - p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())} - if p.currentLabelPair.GetName() == string(model.MetricNameLabel) { - p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel)) - return nil - } - // Special summary/histogram treatment. Don't add 'quantile' and 'le' - // labels to 'real' labels. - if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) && - !(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) { - p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair) - } - if p.skipBlankTabIfCurrentBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte != '=' { - p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte)) - return nil - } - return p.startLabelValue -} - -// startLabelValue represents the state where the next byte read from p.buf is -// the start of a (quoted) label value (or whitespace leading up to it). -func (p *TextParser) startLabelValue() stateFn { - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte != '"' { - p.parseError(fmt.Sprintf("expected '\"' at start of label value, found %q", p.currentByte)) - return nil - } - if p.readTokenAsLabelValue(); p.err != nil { - return nil - } - if !model.LabelValue(p.currentToken.String()).IsValid() { - p.parseError(fmt.Sprintf("invalid label value %q", p.currentToken.String())) - return nil - } - p.currentLabelPair.Value = proto.String(p.currentToken.String()) - // Special treatment of summaries: - // - Quantile labels are special, will result in dto.Quantile later. - // - Other labels have to be added to currentLabels for signature calculation. - if p.currentMF.GetType() == dto.MetricType_SUMMARY { - if p.currentLabelPair.GetName() == model.QuantileLabel { - if p.currentQuantile, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil { - // Create a more helpful error message. - p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue())) - return nil - } - } else { - p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue() - } - } - // Similar special treatment of histograms. - if p.currentMF.GetType() == dto.MetricType_HISTOGRAM { - if p.currentLabelPair.GetName() == model.BucketLabel { - if p.currentBucket, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil { - // Create a more helpful error message. - p.parseError(fmt.Sprintf("expected float as value for 'le' label, got %q", p.currentLabelPair.GetValue())) - return nil - } - } else { - p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue() - } - } - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - switch p.currentByte { - case ',': - return p.startLabelName - - case '}': - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - return p.readingValue - default: - p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.Value)) - return nil - } -} - -// readingValue represents the state where the last byte read (now in -// p.currentByte) is the first byte of the sample value (i.e. a float). -func (p *TextParser) readingValue() stateFn { - // When we are here, we have read all the labels, so for the - // special case of a summary/histogram, we can finally find out - // if the metric already exists. - if p.currentMF.GetType() == dto.MetricType_SUMMARY { - signature := model.LabelsToSignature(p.currentLabels) - if summary := p.summaries[signature]; summary != nil { - p.currentMetric = summary - } else { - p.summaries[signature] = p.currentMetric - p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric) - } - } else if p.currentMF.GetType() == dto.MetricType_HISTOGRAM { - signature := model.LabelsToSignature(p.currentLabels) - if histogram := p.histograms[signature]; histogram != nil { - p.currentMetric = histogram - } else { - p.histograms[signature] = p.currentMetric - p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric) - } - } else { - p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric) - } - if p.readTokenUntilWhitespace(); p.err != nil { - return nil // Unexpected end of input. - } - value, err := strconv.ParseFloat(p.currentToken.String(), 64) - if err != nil { - // Create a more helpful error message. - p.parseError(fmt.Sprintf("expected float as value, got %q", p.currentToken.String())) - return nil - } - switch p.currentMF.GetType() { - case dto.MetricType_COUNTER: - p.currentMetric.Counter = &dto.Counter{Value: proto.Float64(value)} - case dto.MetricType_GAUGE: - p.currentMetric.Gauge = &dto.Gauge{Value: proto.Float64(value)} - case dto.MetricType_UNTYPED: - p.currentMetric.Untyped = &dto.Untyped{Value: proto.Float64(value)} - case dto.MetricType_SUMMARY: - // *sigh* - if p.currentMetric.Summary == nil { - p.currentMetric.Summary = &dto.Summary{} - } - switch { - case p.currentIsSummaryCount: - p.currentMetric.Summary.SampleCount = proto.Uint64(uint64(value)) - case p.currentIsSummarySum: - p.currentMetric.Summary.SampleSum = proto.Float64(value) - case !math.IsNaN(p.currentQuantile): - p.currentMetric.Summary.Quantile = append( - p.currentMetric.Summary.Quantile, - &dto.Quantile{ - Quantile: proto.Float64(p.currentQuantile), - Value: proto.Float64(value), - }, - ) - } - case dto.MetricType_HISTOGRAM: - // *sigh* - if p.currentMetric.Histogram == nil { - p.currentMetric.Histogram = &dto.Histogram{} - } - switch { - case p.currentIsHistogramCount: - p.currentMetric.Histogram.SampleCount = proto.Uint64(uint64(value)) - case p.currentIsHistogramSum: - p.currentMetric.Histogram.SampleSum = proto.Float64(value) - case !math.IsNaN(p.currentBucket): - p.currentMetric.Histogram.Bucket = append( - p.currentMetric.Histogram.Bucket, - &dto.Bucket{ - UpperBound: proto.Float64(p.currentBucket), - CumulativeCount: proto.Uint64(uint64(value)), - }, - ) - } - default: - p.err = fmt.Errorf("unexpected type for metric name %q", p.currentMF.GetName()) - } - if p.currentByte == '\n' { - return p.startOfLine - } - return p.startTimestamp -} - -// startTimestamp represents the state where the next byte read from p.buf is -// the start of the timestamp (or whitespace leading up to it). -func (p *TextParser) startTimestamp() stateFn { - if p.skipBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.readTokenUntilWhitespace(); p.err != nil { - return nil // Unexpected end of input. - } - timestamp, err := strconv.ParseInt(p.currentToken.String(), 10, 64) - if err != nil { - // Create a more helpful error message. - p.parseError(fmt.Sprintf("expected integer as timestamp, got %q", p.currentToken.String())) - return nil - } - p.currentMetric.TimestampMs = proto.Int64(timestamp) - if p.readTokenUntilNewline(false); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentToken.Len() > 0 { - p.parseError(fmt.Sprintf("spurious string after timestamp: %q", p.currentToken.String())) - return nil - } - return p.startOfLine -} - -// readingHelp represents the state where the last byte read (now in -// p.currentByte) is the first byte of the docstring after 'HELP'. -func (p *TextParser) readingHelp() stateFn { - if p.currentMF.Help != nil { - p.parseError(fmt.Sprintf("second HELP line for metric name %q", p.currentMF.GetName())) - return nil - } - // Rest of line is the docstring. - if p.readTokenUntilNewline(true); p.err != nil { - return nil // Unexpected end of input. - } - p.currentMF.Help = proto.String(p.currentToken.String()) - return p.startOfLine -} - -// readingType represents the state where the last byte read (now in -// p.currentByte) is the first byte of the type hint after 'HELP'. -func (p *TextParser) readingType() stateFn { - if p.currentMF.Type != nil { - p.parseError(fmt.Sprintf("second TYPE line for metric name %q, or TYPE reported after samples", p.currentMF.GetName())) - return nil - } - // Rest of line is the type. - if p.readTokenUntilNewline(false); p.err != nil { - return nil // Unexpected end of input. - } - metricType, ok := dto.MetricType_value[strings.ToUpper(p.currentToken.String())] - if !ok { - p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String())) - return nil - } - p.currentMF.Type = dto.MetricType(metricType).Enum() - return p.startOfLine -} - -// parseError sets p.err to a ParseError at the current line with the given -// message. -func (p *TextParser) parseError(msg string) { - p.err = ParseError{ - Line: p.lineCount, - Msg: msg, - } -} - -// skipBlankTab reads (and discards) bytes from p.buf until it encounters a byte -// that is neither ' ' nor '\t'. That byte is left in p.currentByte. -func (p *TextParser) skipBlankTab() { - for { - if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil || !isBlankOrTab(p.currentByte) { - return - } - } -} - -// skipBlankTabIfCurrentBlankTab works exactly as skipBlankTab but doesn't do -// anything if p.currentByte is neither ' ' nor '\t'. -func (p *TextParser) skipBlankTabIfCurrentBlankTab() { - if isBlankOrTab(p.currentByte) { - p.skipBlankTab() - } -} - -// readTokenUntilWhitespace copies bytes from p.buf into p.currentToken. The -// first byte considered is the byte already read (now in p.currentByte). The -// first whitespace byte encountered is still copied into p.currentByte, but not -// into p.currentToken. -func (p *TextParser) readTokenUntilWhitespace() { - p.currentToken.Reset() - for p.err == nil && !isBlankOrTab(p.currentByte) && p.currentByte != '\n' { - p.currentToken.WriteByte(p.currentByte) - p.currentByte, p.err = p.buf.ReadByte() - } -} - -// readTokenUntilNewline copies bytes from p.buf into p.currentToken. The first -// byte considered is the byte already read (now in p.currentByte). The first -// newline byte encountered is still copied into p.currentByte, but not into -// p.currentToken. If recognizeEscapeSequence is true, two escape sequences are -// recognized: '\\' translates into '\', and '\n' into a line-feed character. -// All other escape sequences are invalid and cause an error. -func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) { - p.currentToken.Reset() - escaped := false - for p.err == nil { - if recognizeEscapeSequence && escaped { - switch p.currentByte { - case '\\': - p.currentToken.WriteByte(p.currentByte) - case 'n': - p.currentToken.WriteByte('\n') - default: - p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) - return - } - escaped = false - } else { - switch p.currentByte { - case '\n': - return - case '\\': - escaped = true - default: - p.currentToken.WriteByte(p.currentByte) - } - } - p.currentByte, p.err = p.buf.ReadByte() - } -} - -// readTokenAsMetricName copies a metric name from p.buf into p.currentToken. -// The first byte considered is the byte already read (now in p.currentByte). -// The first byte not part of a metric name is still copied into p.currentByte, -// but not into p.currentToken. -func (p *TextParser) readTokenAsMetricName() { - p.currentToken.Reset() - if !isValidMetricNameStart(p.currentByte) { - return - } - for { - p.currentToken.WriteByte(p.currentByte) - p.currentByte, p.err = p.buf.ReadByte() - if p.err != nil || !isValidMetricNameContinuation(p.currentByte) { - return - } - } -} - -// readTokenAsLabelName copies a label name from p.buf into p.currentToken. -// The first byte considered is the byte already read (now in p.currentByte). -// The first byte not part of a label name is still copied into p.currentByte, -// but not into p.currentToken. -func (p *TextParser) readTokenAsLabelName() { - p.currentToken.Reset() - if !isValidLabelNameStart(p.currentByte) { - return - } - for { - p.currentToken.WriteByte(p.currentByte) - p.currentByte, p.err = p.buf.ReadByte() - if p.err != nil || !isValidLabelNameContinuation(p.currentByte) { - return - } - } -} - -// readTokenAsLabelValue copies a label value from p.buf into p.currentToken. -// In contrast to the other 'readTokenAs...' functions, which start with the -// last read byte in p.currentByte, this method ignores p.currentByte and starts -// with reading a new byte from p.buf. The first byte not part of a label value -// is still copied into p.currentByte, but not into p.currentToken. -func (p *TextParser) readTokenAsLabelValue() { - p.currentToken.Reset() - escaped := false - for { - if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil { - return - } - if escaped { - switch p.currentByte { - case '"', '\\': - p.currentToken.WriteByte(p.currentByte) - case 'n': - p.currentToken.WriteByte('\n') - default: - p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) - return - } - escaped = false - continue - } - switch p.currentByte { - case '"': - return - case '\n': - p.parseError(fmt.Sprintf("label value %q contains unescaped new-line", p.currentToken.String())) - return - case '\\': - escaped = true - default: - p.currentToken.WriteByte(p.currentByte) - } - } -} - -func (p *TextParser) setOrCreateCurrentMF() { - p.currentIsSummaryCount = false - p.currentIsSummarySum = false - p.currentIsHistogramCount = false - p.currentIsHistogramSum = false - name := p.currentToken.String() - if p.currentMF = p.metricFamiliesByName[name]; p.currentMF != nil { - return - } - // Try out if this is a _sum or _count for a summary/histogram. - summaryName := summaryMetricName(name) - if p.currentMF = p.metricFamiliesByName[summaryName]; p.currentMF != nil { - if p.currentMF.GetType() == dto.MetricType_SUMMARY { - if isCount(name) { - p.currentIsSummaryCount = true - } - if isSum(name) { - p.currentIsSummarySum = true - } - return - } - } - histogramName := histogramMetricName(name) - if p.currentMF = p.metricFamiliesByName[histogramName]; p.currentMF != nil { - if p.currentMF.GetType() == dto.MetricType_HISTOGRAM { - if isCount(name) { - p.currentIsHistogramCount = true - } - if isSum(name) { - p.currentIsHistogramSum = true - } - return - } - } - p.currentMF = &dto.MetricFamily{Name: proto.String(name)} - p.metricFamiliesByName[name] = p.currentMF -} - -func isValidLabelNameStart(b byte) bool { - return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' -} - -func isValidLabelNameContinuation(b byte) bool { - return isValidLabelNameStart(b) || (b >= '0' && b <= '9') -} - -func isValidMetricNameStart(b byte) bool { - return isValidLabelNameStart(b) || b == ':' -} - -func isValidMetricNameContinuation(b byte) bool { - return isValidLabelNameContinuation(b) || b == ':' -} - -func isBlankOrTab(b byte) bool { - return b == ' ' || b == '\t' -} - -func isCount(name string) bool { - return len(name) > 6 && name[len(name)-6:] == "_count" -} - -func isSum(name string) bool { - return len(name) > 4 && name[len(name)-4:] == "_sum" -} - -func isBucket(name string) bool { - return len(name) > 7 && name[len(name)-7:] == "_bucket" -} - -func summaryMetricName(name string) string { - switch { - case isCount(name): - return name[:len(name)-6] - case isSum(name): - return name[:len(name)-4] - default: - return name - } -} - -func histogramMetricName(name string) string { - switch { - case isCount(name): - return name[:len(name)-6] - case isSum(name): - return name[:len(name)-4] - case isBucket(name): - return name[:len(name)-7] - default: - return name - } -} diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go deleted file mode 100644 index 648b38cb65..0000000000 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go +++ /dev/null @@ -1,162 +0,0 @@ -/* -HTTP Content-Type Autonegotiation. - -The functions in this package implement the behaviour specified in -http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - -Copyright (c) 2011, Open Knowledge Foundation Ltd. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - Neither the name of the Open Knowledge Foundation Ltd. nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -*/ -package goautoneg - -import ( - "sort" - "strconv" - "strings" -) - -// Structure to represent a clause in an HTTP Accept Header -type Accept struct { - Type, SubType string - Q float64 - Params map[string]string -} - -// For internal use, so that we can use the sort interface -type accept_slice []Accept - -func (accept accept_slice) Len() int { - slice := []Accept(accept) - return len(slice) -} - -func (accept accept_slice) Less(i, j int) bool { - slice := []Accept(accept) - ai, aj := slice[i], slice[j] - if ai.Q > aj.Q { - return true - } - if ai.Type != "*" && aj.Type == "*" { - return true - } - if ai.SubType != "*" && aj.SubType == "*" { - return true - } - return false -} - -func (accept accept_slice) Swap(i, j int) { - slice := []Accept(accept) - slice[i], slice[j] = slice[j], slice[i] -} - -// Parse an Accept Header string returning a sorted list -// of clauses -func ParseAccept(header string) (accept []Accept) { - parts := strings.Split(header, ",") - accept = make([]Accept, 0, len(parts)) - for _, part := range parts { - part := strings.Trim(part, " ") - - a := Accept{} - a.Params = make(map[string]string) - a.Q = 1.0 - - mrp := strings.Split(part, ";") - - media_range := mrp[0] - sp := strings.Split(media_range, "/") - a.Type = strings.Trim(sp[0], " ") - - switch { - case len(sp) == 1 && a.Type == "*": - a.SubType = "*" - case len(sp) == 2: - a.SubType = strings.Trim(sp[1], " ") - default: - continue - } - - if len(mrp) == 1 { - accept = append(accept, a) - continue - } - - for _, param := range mrp[1:] { - sp := strings.SplitN(param, "=", 2) - if len(sp) != 2 { - continue - } - token := strings.Trim(sp[0], " ") - if token == "q" { - a.Q, _ = strconv.ParseFloat(sp[1], 32) - } else { - a.Params[token] = strings.Trim(sp[1], " ") - } - } - - accept = append(accept, a) - } - - slice := accept_slice(accept) - sort.Sort(slice) - - return -} - -// Negotiate the most appropriate content_type given the accept header -// and a list of alternatives. -func Negotiate(header string, alternatives []string) (content_type string) { - asp := make([][]string, 0, len(alternatives)) - for _, ctype := range alternatives { - asp = append(asp, strings.SplitN(ctype, "/", 2)) - } - for _, clause := range ParseAccept(header) { - for i, ctsp := range asp { - if clause.Type == ctsp[0] && clause.SubType == ctsp[1] { - content_type = alternatives[i] - return - } - if clause.Type == ctsp[0] && clause.SubType == "*" { - content_type = alternatives[i] - return - } - if clause.Type == "*" && clause.SubType == "*" { - content_type = alternatives[i] - return - } - } - } - return -} diff --git a/vendor/github.com/prometheus/common/model/alert.go b/vendor/github.com/prometheus/common/model/alert.go deleted file mode 100644 index 35e739c7ad..0000000000 --- a/vendor/github.com/prometheus/common/model/alert.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "time" -) - -type AlertStatus string - -const ( - AlertFiring AlertStatus = "firing" - AlertResolved AlertStatus = "resolved" -) - -// Alert is a generic representation of an alert in the Prometheus eco-system. -type Alert struct { - // Label value pairs for purpose of aggregation, matching, and disposition - // dispatching. This must minimally include an "alertname" label. - Labels LabelSet `json:"labels"` - - // Extra key/value information which does not define alert identity. - Annotations LabelSet `json:"annotations"` - - // The known time range for this alert. Both ends are optional. - StartsAt time.Time `json:"startsAt,omitempty"` - EndsAt time.Time `json:"endsAt,omitempty"` - GeneratorURL string `json:"generatorURL"` -} - -// Name returns the name of the alert. It is equivalent to the "alertname" label. -func (a *Alert) Name() string { - return string(a.Labels[AlertNameLabel]) -} - -// Fingerprint returns a unique hash for the alert. It is equivalent to -// the fingerprint of the alert's label set. -func (a *Alert) Fingerprint() Fingerprint { - return a.Labels.Fingerprint() -} - -func (a *Alert) String() string { - s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) - if a.Resolved() { - return s + "[resolved]" - } - return s + "[active]" -} - -// Resolved returns true iff the activity interval ended in the past. -func (a *Alert) Resolved() bool { - return a.ResolvedAt(time.Now()) -} - -// ResolvedAt returns true off the activity interval ended before -// the given timestamp. -func (a *Alert) ResolvedAt(ts time.Time) bool { - if a.EndsAt.IsZero() { - return false - } - return !a.EndsAt.After(ts) -} - -// Status returns the status of the alert. -func (a *Alert) Status() AlertStatus { - if a.Resolved() { - return AlertResolved - } - return AlertFiring -} - -// Validate checks whether the alert data is inconsistent. -func (a *Alert) Validate() error { - if a.StartsAt.IsZero() { - return fmt.Errorf("start time missing") - } - if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { - return fmt.Errorf("start time must be before end time") - } - if err := a.Labels.Validate(); err != nil { - return fmt.Errorf("invalid label set: %s", err) - } - if len(a.Labels) == 0 { - return fmt.Errorf("at least one label pair required") - } - if err := a.Annotations.Validate(); err != nil { - return fmt.Errorf("invalid annotations: %s", err) - } - return nil -} - -// Alert is a list of alerts that can be sorted in chronological order. -type Alerts []*Alert - -func (as Alerts) Len() int { return len(as) } -func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } - -func (as Alerts) Less(i, j int) bool { - if as[i].StartsAt.Before(as[j].StartsAt) { - return true - } - if as[i].EndsAt.Before(as[j].EndsAt) { - return true - } - return as[i].Fingerprint() < as[j].Fingerprint() -} - -// HasFiring returns true iff one of the alerts is not resolved. -func (as Alerts) HasFiring() bool { - for _, a := range as { - if !a.Resolved() { - return true - } - } - return false -} - -// Status returns StatusFiring iff at least one of the alerts is firing. -func (as Alerts) Status() AlertStatus { - if as.HasFiring() { - return AlertFiring - } - return AlertResolved -} diff --git a/vendor/github.com/prometheus/common/model/fingerprinting.go b/vendor/github.com/prometheus/common/model/fingerprinting.go deleted file mode 100644 index fc4de4106e..0000000000 --- a/vendor/github.com/prometheus/common/model/fingerprinting.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "strconv" -) - -// Fingerprint provides a hash-capable representation of a Metric. -// For our purposes, FNV-1A 64-bit is used. -type Fingerprint uint64 - -// FingerprintFromString transforms a string representation into a Fingerprint. -func FingerprintFromString(s string) (Fingerprint, error) { - num, err := strconv.ParseUint(s, 16, 64) - return Fingerprint(num), err -} - -// ParseFingerprint parses the input string into a fingerprint. -func ParseFingerprint(s string) (Fingerprint, error) { - num, err := strconv.ParseUint(s, 16, 64) - if err != nil { - return 0, err - } - return Fingerprint(num), nil -} - -func (f Fingerprint) String() string { - return fmt.Sprintf("%016x", uint64(f)) -} - -// Fingerprints represents a collection of Fingerprint subject to a given -// natural sorting scheme. It implements sort.Interface. -type Fingerprints []Fingerprint - -// Len implements sort.Interface. -func (f Fingerprints) Len() int { - return len(f) -} - -// Less implements sort.Interface. -func (f Fingerprints) Less(i, j int) bool { - return f[i] < f[j] -} - -// Swap implements sort.Interface. -func (f Fingerprints) Swap(i, j int) { - f[i], f[j] = f[j], f[i] -} - -// FingerprintSet is a set of Fingerprints. -type FingerprintSet map[Fingerprint]struct{} - -// Equal returns true if both sets contain the same elements (and not more). -func (s FingerprintSet) Equal(o FingerprintSet) bool { - if len(s) != len(o) { - return false - } - - for k := range s { - if _, ok := o[k]; !ok { - return false - } - } - - return true -} - -// Intersection returns the elements contained in both sets. -func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { - myLength, otherLength := len(s), len(o) - if myLength == 0 || otherLength == 0 { - return FingerprintSet{} - } - - subSet := s - superSet := o - - if otherLength < myLength { - subSet = o - superSet = s - } - - out := FingerprintSet{} - - for k := range subSet { - if _, ok := superSet[k]; ok { - out[k] = struct{}{} - } - } - - return out -} diff --git a/vendor/github.com/prometheus/common/model/fnv.go b/vendor/github.com/prometheus/common/model/fnv.go deleted file mode 100644 index 038fc1c900..0000000000 --- a/vendor/github.com/prometheus/common/model/fnv.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -// Inline and byte-free variant of hash/fnv's fnv64a. - -const ( - offset64 = 14695981039346656037 - prime64 = 1099511628211 -) - -// hashNew initializies a new fnv64a hash value. -func hashNew() uint64 { - return offset64 -} - -// hashAdd adds a string to a fnv64a hash value, returning the updated hash. -func hashAdd(h uint64, s string) uint64 { - for i := 0; i < len(s); i++ { - h ^= uint64(s[i]) - h *= prime64 - } - return h -} - -// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. -func hashAddByte(h uint64, b byte) uint64 { - h ^= uint64(b) - h *= prime64 - return h -} diff --git a/vendor/github.com/prometheus/common/model/labels.go b/vendor/github.com/prometheus/common/model/labels.go deleted file mode 100644 index 41051a01a3..0000000000 --- a/vendor/github.com/prometheus/common/model/labels.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "fmt" - "regexp" - "strings" - "unicode/utf8" -) - -const ( - // AlertNameLabel is the name of the label containing the an alert's name. - AlertNameLabel = "alertname" - - // ExportedLabelPrefix is the prefix to prepend to the label names present in - // exported metrics if a label of the same name is added by the server. - ExportedLabelPrefix = "exported_" - - // MetricNameLabel is the label name indicating the metric name of a - // timeseries. - MetricNameLabel = "__name__" - - // SchemeLabel is the name of the label that holds the scheme on which to - // scrape a target. - SchemeLabel = "__scheme__" - - // AddressLabel is the name of the label that holds the address of - // a scrape target. - AddressLabel = "__address__" - - // MetricsPathLabel is the name of the label that holds the path on which to - // scrape a target. - MetricsPathLabel = "__metrics_path__" - - // ReservedLabelPrefix is a prefix which is not legal in user-supplied - // label names. - ReservedLabelPrefix = "__" - - // MetaLabelPrefix is a prefix for labels that provide meta information. - // Labels with this prefix are used for intermediate label processing and - // will not be attached to time series. - MetaLabelPrefix = "__meta_" - - // TmpLabelPrefix is a prefix for temporary labels as part of relabelling. - // Labels with this prefix are used for intermediate label processing and - // will not be attached to time series. This is reserved for use in - // Prometheus configuration files by users. - TmpLabelPrefix = "__tmp_" - - // ParamLabelPrefix is a prefix for labels that provide URL parameters - // used to scrape a target. - ParamLabelPrefix = "__param_" - - // JobLabel is the label name indicating the job from which a timeseries - // was scraped. - JobLabel = "job" - - // InstanceLabel is the label name used for the instance label. - InstanceLabel = "instance" - - // BucketLabel is used for the label that defines the upper bound of a - // bucket of a histogram ("le" -> "less or equal"). - BucketLabel = "le" - - // QuantileLabel is used for the label that defines the quantile in a - // summary. - QuantileLabel = "quantile" -) - -// LabelNameRE is a regular expression matching valid label names. Note that the -// IsValid method of LabelName performs the same check but faster than a match -// with this regular expression. -var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") - -// A LabelName is a key for a LabelSet or Metric. It has a value associated -// therewith. -type LabelName string - -// IsValid is true iff the label name matches the pattern of LabelNameRE. This -// method, however, does not use LabelNameRE for the check but a much faster -// hardcoded implementation. -func (ln LabelName) IsValid() bool { - if len(ln) == 0 { - return false - } - for i, b := range ln { - if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { - return false - } - } - return true -} - -// UnmarshalYAML implements the yaml.Unmarshaler interface. -func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - if err := unmarshal(&s); err != nil { - return err - } - if !LabelName(s).IsValid() { - return fmt.Errorf("%q is not a valid label name", s) - } - *ln = LabelName(s) - return nil -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (ln *LabelName) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - if !LabelName(s).IsValid() { - return fmt.Errorf("%q is not a valid label name", s) - } - *ln = LabelName(s) - return nil -} - -// LabelNames is a sortable LabelName slice. In implements sort.Interface. -type LabelNames []LabelName - -func (l LabelNames) Len() int { - return len(l) -} - -func (l LabelNames) Less(i, j int) bool { - return l[i] < l[j] -} - -func (l LabelNames) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} - -func (l LabelNames) String() string { - labelStrings := make([]string, 0, len(l)) - for _, label := range l { - labelStrings = append(labelStrings, string(label)) - } - return strings.Join(labelStrings, ", ") -} - -// A LabelValue is an associated value for a LabelName. -type LabelValue string - -// IsValid returns true iff the string is a valid UTF8. -func (lv LabelValue) IsValid() bool { - return utf8.ValidString(string(lv)) -} - -// LabelValues is a sortable LabelValue slice. It implements sort.Interface. -type LabelValues []LabelValue - -func (l LabelValues) Len() int { - return len(l) -} - -func (l LabelValues) Less(i, j int) bool { - return string(l[i]) < string(l[j]) -} - -func (l LabelValues) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} - -// LabelPair pairs a name with a value. -type LabelPair struct { - Name LabelName - Value LabelValue -} - -// LabelPairs is a sortable slice of LabelPair pointers. It implements -// sort.Interface. -type LabelPairs []*LabelPair - -func (l LabelPairs) Len() int { - return len(l) -} - -func (l LabelPairs) Less(i, j int) bool { - switch { - case l[i].Name > l[j].Name: - return false - case l[i].Name < l[j].Name: - return true - case l[i].Value > l[j].Value: - return false - case l[i].Value < l[j].Value: - return true - default: - return false - } -} - -func (l LabelPairs) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} diff --git a/vendor/github.com/prometheus/common/model/labelset.go b/vendor/github.com/prometheus/common/model/labelset.go deleted file mode 100644 index 6eda08a739..0000000000 --- a/vendor/github.com/prometheus/common/model/labelset.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "fmt" - "sort" - "strings" -) - -// A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet -// may be fully-qualified down to the point where it may resolve to a single -// Metric in the data store or not. All operations that occur within the realm -// of a LabelSet can emit a vector of Metric entities to which the LabelSet may -// match. -type LabelSet map[LabelName]LabelValue - -// Validate checks whether all names and values in the label set -// are valid. -func (ls LabelSet) Validate() error { - for ln, lv := range ls { - if !ln.IsValid() { - return fmt.Errorf("invalid name %q", ln) - } - if !lv.IsValid() { - return fmt.Errorf("invalid value %q", lv) - } - } - return nil -} - -// Equal returns true iff both label sets have exactly the same key/value pairs. -func (ls LabelSet) Equal(o LabelSet) bool { - if len(ls) != len(o) { - return false - } - for ln, lv := range ls { - olv, ok := o[ln] - if !ok { - return false - } - if olv != lv { - return false - } - } - return true -} - -// Before compares the metrics, using the following criteria: -// -// If m has fewer labels than o, it is before o. If it has more, it is not. -// -// If the number of labels is the same, the superset of all label names is -// sorted alphanumerically. The first differing label pair found in that order -// determines the outcome: If the label does not exist at all in m, then m is -// before o, and vice versa. Otherwise the label value is compared -// alphanumerically. -// -// If m and o are equal, the method returns false. -func (ls LabelSet) Before(o LabelSet) bool { - if len(ls) < len(o) { - return true - } - if len(ls) > len(o) { - return false - } - - lns := make(LabelNames, 0, len(ls)+len(o)) - for ln := range ls { - lns = append(lns, ln) - } - for ln := range o { - lns = append(lns, ln) - } - // It's probably not worth it to de-dup lns. - sort.Sort(lns) - for _, ln := range lns { - mlv, ok := ls[ln] - if !ok { - return true - } - olv, ok := o[ln] - if !ok { - return false - } - if mlv < olv { - return true - } - if mlv > olv { - return false - } - } - return false -} - -// Clone returns a copy of the label set. -func (ls LabelSet) Clone() LabelSet { - lsn := make(LabelSet, len(ls)) - for ln, lv := range ls { - lsn[ln] = lv - } - return lsn -} - -// Merge is a helper function to non-destructively merge two label sets. -func (l LabelSet) Merge(other LabelSet) LabelSet { - result := make(LabelSet, len(l)) - - for k, v := range l { - result[k] = v - } - - for k, v := range other { - result[k] = v - } - - return result -} - -func (l LabelSet) String() string { - lstrs := make([]string, 0, len(l)) - for l, v := range l { - lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v)) - } - - sort.Strings(lstrs) - return fmt.Sprintf("{%s}", strings.Join(lstrs, ", ")) -} - -// Fingerprint returns the LabelSet's fingerprint. -func (ls LabelSet) Fingerprint() Fingerprint { - return labelSetToFingerprint(ls) -} - -// FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing -// algorithm, which is, however, more susceptible to hash collisions. -func (ls LabelSet) FastFingerprint() Fingerprint { - return labelSetToFastFingerprint(ls) -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (l *LabelSet) UnmarshalJSON(b []byte) error { - var m map[LabelName]LabelValue - if err := json.Unmarshal(b, &m); err != nil { - return err - } - // encoding/json only unmarshals maps of the form map[string]T. It treats - // LabelName as a string and does not call its UnmarshalJSON method. - // Thus, we have to replicate the behavior here. - for ln := range m { - if !ln.IsValid() { - return fmt.Errorf("%q is not a valid label name", ln) - } - } - *l = LabelSet(m) - return nil -} diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go deleted file mode 100644 index f7250909b9..0000000000 --- a/vendor/github.com/prometheus/common/model/metric.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "regexp" - "sort" - "strings" -) - -var ( - separator = []byte{0} - // MetricNameRE is a regular expression matching valid metric - // names. Note that the IsValidMetricName function performs the same - // check but faster than a match with this regular expression. - MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) -) - -// A Metric is similar to a LabelSet, but the key difference is that a Metric is -// a singleton and refers to one and only one stream of samples. -type Metric LabelSet - -// Equal compares the metrics. -func (m Metric) Equal(o Metric) bool { - return LabelSet(m).Equal(LabelSet(o)) -} - -// Before compares the metrics' underlying label sets. -func (m Metric) Before(o Metric) bool { - return LabelSet(m).Before(LabelSet(o)) -} - -// Clone returns a copy of the Metric. -func (m Metric) Clone() Metric { - clone := make(Metric, len(m)) - for k, v := range m { - clone[k] = v - } - return clone -} - -func (m Metric) String() string { - metricName, hasName := m[MetricNameLabel] - numLabels := len(m) - 1 - if !hasName { - numLabels = len(m) - } - labelStrings := make([]string, 0, numLabels) - for label, value := range m { - if label != MetricNameLabel { - labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value)) - } - } - - switch numLabels { - case 0: - if hasName { - return string(metricName) - } - return "{}" - default: - sort.Strings(labelStrings) - return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", ")) - } -} - -// Fingerprint returns a Metric's Fingerprint. -func (m Metric) Fingerprint() Fingerprint { - return LabelSet(m).Fingerprint() -} - -// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing -// algorithm, which is, however, more susceptible to hash collisions. -func (m Metric) FastFingerprint() Fingerprint { - return LabelSet(m).FastFingerprint() -} - -// IsValidMetricName returns true iff name matches the pattern of MetricNameRE. -// This function, however, does not use MetricNameRE for the check but a much -// faster hardcoded implementation. -func IsValidMetricName(n LabelValue) bool { - if len(n) == 0 { - return false - } - for i, b := range n { - if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { - return false - } - } - return true -} diff --git a/vendor/github.com/prometheus/common/model/signature.go b/vendor/github.com/prometheus/common/model/signature.go deleted file mode 100644 index 8762b13c63..0000000000 --- a/vendor/github.com/prometheus/common/model/signature.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "sort" -) - -// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is -// used to separate label names, label values, and other strings from each other -// when calculating their combined hash value (aka signature aka fingerprint). -const SeparatorByte byte = 255 - -var ( - // cache the signature of an empty label set. - emptyLabelSignature = hashNew() -) - -// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a -// given label set. (Collisions are possible but unlikely if the number of label -// sets the function is applied to is small.) -func LabelsToSignature(labels map[string]string) uint64 { - if len(labels) == 0 { - return emptyLabelSignature - } - - labelNames := make([]string, 0, len(labels)) - for labelName := range labels { - labelNames = append(labelNames, labelName) - } - sort.Strings(labelNames) - - sum := hashNew() - for _, labelName := range labelNames { - sum = hashAdd(sum, labelName) - sum = hashAddByte(sum, SeparatorByte) - sum = hashAdd(sum, labels[labelName]) - sum = hashAddByte(sum, SeparatorByte) - } - return sum -} - -// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as -// parameter (rather than a label map) and returns a Fingerprint. -func labelSetToFingerprint(ls LabelSet) Fingerprint { - if len(ls) == 0 { - return Fingerprint(emptyLabelSignature) - } - - labelNames := make(LabelNames, 0, len(ls)) - for labelName := range ls { - labelNames = append(labelNames, labelName) - } - sort.Sort(labelNames) - - sum := hashNew() - for _, labelName := range labelNames { - sum = hashAdd(sum, string(labelName)) - sum = hashAddByte(sum, SeparatorByte) - sum = hashAdd(sum, string(ls[labelName])) - sum = hashAddByte(sum, SeparatorByte) - } - return Fingerprint(sum) -} - -// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a -// faster and less allocation-heavy hash function, which is more susceptible to -// create hash collisions. Therefore, collision detection should be applied. -func labelSetToFastFingerprint(ls LabelSet) Fingerprint { - if len(ls) == 0 { - return Fingerprint(emptyLabelSignature) - } - - var result uint64 - for labelName, labelValue := range ls { - sum := hashNew() - sum = hashAdd(sum, string(labelName)) - sum = hashAddByte(sum, SeparatorByte) - sum = hashAdd(sum, string(labelValue)) - result ^= sum - } - return Fingerprint(result) -} - -// SignatureForLabels works like LabelsToSignature but takes a Metric as -// parameter (rather than a label map) and only includes the labels with the -// specified LabelNames into the signature calculation. The labels passed in -// will be sorted by this function. -func SignatureForLabels(m Metric, labels ...LabelName) uint64 { - if len(labels) == 0 { - return emptyLabelSignature - } - - sort.Sort(LabelNames(labels)) - - sum := hashNew() - for _, label := range labels { - sum = hashAdd(sum, string(label)) - sum = hashAddByte(sum, SeparatorByte) - sum = hashAdd(sum, string(m[label])) - sum = hashAddByte(sum, SeparatorByte) - } - return sum -} - -// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as -// parameter (rather than a label map) and excludes the labels with any of the -// specified LabelNames from the signature calculation. -func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 { - if len(m) == 0 { - return emptyLabelSignature - } - - labelNames := make(LabelNames, 0, len(m)) - for labelName := range m { - if _, exclude := labels[labelName]; !exclude { - labelNames = append(labelNames, labelName) - } - } - if len(labelNames) == 0 { - return emptyLabelSignature - } - sort.Sort(labelNames) - - sum := hashNew() - for _, labelName := range labelNames { - sum = hashAdd(sum, string(labelName)) - sum = hashAddByte(sum, SeparatorByte) - sum = hashAdd(sum, string(m[labelName])) - sum = hashAddByte(sum, SeparatorByte) - } - return sum -} diff --git a/vendor/github.com/prometheus/common/model/silence.go b/vendor/github.com/prometheus/common/model/silence.go deleted file mode 100644 index bb99889d2c..0000000000 --- a/vendor/github.com/prometheus/common/model/silence.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "fmt" - "regexp" - "time" -) - -// Matcher describes a matches the value of a given label. -type Matcher struct { - Name LabelName `json:"name"` - Value string `json:"value"` - IsRegex bool `json:"isRegex"` -} - -func (m *Matcher) UnmarshalJSON(b []byte) error { - type plain Matcher - if err := json.Unmarshal(b, (*plain)(m)); err != nil { - return err - } - - if len(m.Name) == 0 { - return fmt.Errorf("label name in matcher must not be empty") - } - if m.IsRegex { - if _, err := regexp.Compile(m.Value); err != nil { - return err - } - } - return nil -} - -// Validate returns true iff all fields of the matcher have valid values. -func (m *Matcher) Validate() error { - if !m.Name.IsValid() { - return fmt.Errorf("invalid name %q", m.Name) - } - if m.IsRegex { - if _, err := regexp.Compile(m.Value); err != nil { - return fmt.Errorf("invalid regular expression %q", m.Value) - } - } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 { - return fmt.Errorf("invalid value %q", m.Value) - } - return nil -} - -// Silence defines the representation of a silence definition in the Prometheus -// eco-system. -type Silence struct { - ID uint64 `json:"id,omitempty"` - - Matchers []*Matcher `json:"matchers"` - - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` - - CreatedAt time.Time `json:"createdAt,omitempty"` - CreatedBy string `json:"createdBy"` - Comment string `json:"comment,omitempty"` -} - -// Validate returns true iff all fields of the silence have valid values. -func (s *Silence) Validate() error { - if len(s.Matchers) == 0 { - return fmt.Errorf("at least one matcher required") - } - for _, m := range s.Matchers { - if err := m.Validate(); err != nil { - return fmt.Errorf("invalid matcher: %s", err) - } - } - if s.StartsAt.IsZero() { - return fmt.Errorf("start time missing") - } - if s.EndsAt.IsZero() { - return fmt.Errorf("end time missing") - } - if s.EndsAt.Before(s.StartsAt) { - return fmt.Errorf("start time must be before end time") - } - if s.CreatedBy == "" { - return fmt.Errorf("creator information missing") - } - if s.Comment == "" { - return fmt.Errorf("comment missing") - } - if s.CreatedAt.IsZero() { - return fmt.Errorf("creation timestamp missing") - } - return nil -} diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go deleted file mode 100644 index 74ed5a9f7e..0000000000 --- a/vendor/github.com/prometheus/common/model/time.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "math" - "regexp" - "strconv" - "strings" - "time" -) - -const ( - // MinimumTick is the minimum supported time resolution. This has to be - // at least time.Second in order for the code below to work. - minimumTick = time.Millisecond - // second is the Time duration equivalent to one second. - second = int64(time.Second / minimumTick) - // The number of nanoseconds per minimum tick. - nanosPerTick = int64(minimumTick / time.Nanosecond) - - // Earliest is the earliest Time representable. Handy for - // initializing a high watermark. - Earliest = Time(math.MinInt64) - // Latest is the latest Time representable. Handy for initializing - // a low watermark. - Latest = Time(math.MaxInt64) -) - -// Time is the number of milliseconds since the epoch -// (1970-01-01 00:00 UTC) excluding leap seconds. -type Time int64 - -// Interval describes and interval between two timestamps. -type Interval struct { - Start, End Time -} - -// Now returns the current time as a Time. -func Now() Time { - return TimeFromUnixNano(time.Now().UnixNano()) -} - -// TimeFromUnix returns the Time equivalent to the Unix Time t -// provided in seconds. -func TimeFromUnix(t int64) Time { - return Time(t * second) -} - -// TimeFromUnixNano returns the Time equivalent to the Unix Time -// t provided in nanoseconds. -func TimeFromUnixNano(t int64) Time { - return Time(t / nanosPerTick) -} - -// Equal reports whether two Times represent the same instant. -func (t Time) Equal(o Time) bool { - return t == o -} - -// Before reports whether the Time t is before o. -func (t Time) Before(o Time) bool { - return t < o -} - -// After reports whether the Time t is after o. -func (t Time) After(o Time) bool { - return t > o -} - -// Add returns the Time t + d. -func (t Time) Add(d time.Duration) Time { - return t + Time(d/minimumTick) -} - -// Sub returns the Duration t - o. -func (t Time) Sub(o Time) time.Duration { - return time.Duration(t-o) * minimumTick -} - -// Time returns the time.Time representation of t. -func (t Time) Time() time.Time { - return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick) -} - -// Unix returns t as a Unix time, the number of seconds elapsed -// since January 1, 1970 UTC. -func (t Time) Unix() int64 { - return int64(t) / second -} - -// UnixNano returns t as a Unix time, the number of nanoseconds elapsed -// since January 1, 1970 UTC. -func (t Time) UnixNano() int64 { - return int64(t) * nanosPerTick -} - -// The number of digits after the dot. -var dotPrecision = int(math.Log10(float64(second))) - -// String returns a string representation of the Time. -func (t Time) String() string { - return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64) -} - -// MarshalJSON implements the json.Marshaler interface. -func (t Time) MarshalJSON() ([]byte, error) { - return []byte(t.String()), nil -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (t *Time) UnmarshalJSON(b []byte) error { - p := strings.Split(string(b), ".") - switch len(p) { - case 1: - v, err := strconv.ParseInt(string(p[0]), 10, 64) - if err != nil { - return err - } - *t = Time(v * second) - - case 2: - v, err := strconv.ParseInt(string(p[0]), 10, 64) - if err != nil { - return err - } - v *= second - - prec := dotPrecision - len(p[1]) - if prec < 0 { - p[1] = p[1][:dotPrecision] - } else if prec > 0 { - p[1] = p[1] + strings.Repeat("0", prec) - } - - va, err := strconv.ParseInt(p[1], 10, 32) - if err != nil { - return err - } - - *t = Time(v + va) - - default: - return fmt.Errorf("invalid time %q", string(b)) - } - return nil -} - -// Duration wraps time.Duration. It is used to parse the custom duration format -// from YAML. -// This type should not propagate beyond the scope of input/output processing. -type Duration time.Duration - -// Set implements pflag/flag.Value -func (d *Duration) Set(s string) error { - var err error - *d, err = ParseDuration(s) - return err -} - -// Type implements pflag.Value -func (d *Duration) Type() string { - return "duration" -} - -var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$") - -// ParseDuration parses a string into a time.Duration, assuming that a year -// always has 365d, a week always has 7d, and a day always has 24h. -func ParseDuration(durationStr string) (Duration, error) { - matches := durationRE.FindStringSubmatch(durationStr) - if len(matches) != 3 { - return 0, fmt.Errorf("not a valid duration string: %q", durationStr) - } - var ( - n, _ = strconv.Atoi(matches[1]) - dur = time.Duration(n) * time.Millisecond - ) - switch unit := matches[2]; unit { - case "y": - dur *= 1000 * 60 * 60 * 24 * 365 - case "w": - dur *= 1000 * 60 * 60 * 24 * 7 - case "d": - dur *= 1000 * 60 * 60 * 24 - case "h": - dur *= 1000 * 60 * 60 - case "m": - dur *= 1000 * 60 - case "s": - dur *= 1000 - case "ms": - // Value already correct - default: - return 0, fmt.Errorf("invalid time unit in duration string: %q", unit) - } - return Duration(dur), nil -} - -func (d Duration) String() string { - var ( - ms = int64(time.Duration(d) / time.Millisecond) - unit = "ms" - ) - if ms == 0 { - return "0s" - } - factors := map[string]int64{ - "y": 1000 * 60 * 60 * 24 * 365, - "w": 1000 * 60 * 60 * 24 * 7, - "d": 1000 * 60 * 60 * 24, - "h": 1000 * 60 * 60, - "m": 1000 * 60, - "s": 1000, - "ms": 1, - } - - switch int64(0) { - case ms % factors["y"]: - unit = "y" - case ms % factors["w"]: - unit = "w" - case ms % factors["d"]: - unit = "d" - case ms % factors["h"]: - unit = "h" - case ms % factors["m"]: - unit = "m" - case ms % factors["s"]: - unit = "s" - } - return fmt.Sprintf("%v%v", ms/factors[unit], unit) -} - -// MarshalYAML implements the yaml.Marshaler interface. -func (d Duration) MarshalYAML() (interface{}, error) { - return d.String(), nil -} - -// UnmarshalYAML implements the yaml.Unmarshaler interface. -func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - if err := unmarshal(&s); err != nil { - return err - } - dur, err := ParseDuration(s) - if err != nil { - return err - } - *d = dur - return nil -} diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go deleted file mode 100644 index c9d8fb1a28..0000000000 --- a/vendor/github.com/prometheus/common/model/value.go +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "fmt" - "math" - "sort" - "strconv" - "strings" -) - -var ( - // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a - // non-existing sample pair. It is a SamplePair with timestamp Earliest and - // value 0.0. Note that the natural zero value of SamplePair has a timestamp - // of 0, which is possible to appear in a real SamplePair and thus not - // suitable to signal a non-existing SamplePair. - ZeroSamplePair = SamplePair{Timestamp: Earliest} - - // ZeroSample is the pseudo zero-value of Sample used to signal a - // non-existing sample. It is a Sample with timestamp Earliest, value 0.0, - // and metric nil. Note that the natural zero value of Sample has a timestamp - // of 0, which is possible to appear in a real Sample and thus not suitable - // to signal a non-existing Sample. - ZeroSample = Sample{Timestamp: Earliest} -) - -// A SampleValue is a representation of a value for a given sample at a given -// time. -type SampleValue float64 - -// MarshalJSON implements json.Marshaler. -func (v SampleValue) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (v *SampleValue) UnmarshalJSON(b []byte) error { - if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { - return fmt.Errorf("sample value must be a quoted string") - } - f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) - if err != nil { - return err - } - *v = SampleValue(f) - return nil -} - -// Equal returns true if the value of v and o is equal or if both are NaN. Note -// that v==o is false if both are NaN. If you want the conventional float -// behavior, use == to compare two SampleValues. -func (v SampleValue) Equal(o SampleValue) bool { - if v == o { - return true - } - return math.IsNaN(float64(v)) && math.IsNaN(float64(o)) -} - -func (v SampleValue) String() string { - return strconv.FormatFloat(float64(v), 'f', -1, 64) -} - -// SamplePair pairs a SampleValue with a Timestamp. -type SamplePair struct { - Timestamp Time - Value SampleValue -} - -// MarshalJSON implements json.Marshaler. -func (s SamplePair) MarshalJSON() ([]byte, error) { - t, err := json.Marshal(s.Timestamp) - if err != nil { - return nil, err - } - v, err := json.Marshal(s.Value) - if err != nil { - return nil, err - } - return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *SamplePair) UnmarshalJSON(b []byte) error { - v := [...]json.Unmarshaler{&s.Timestamp, &s.Value} - return json.Unmarshal(b, &v) -} - -// Equal returns true if this SamplePair and o have equal Values and equal -// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. -func (s *SamplePair) Equal(o *SamplePair) bool { - return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) -} - -func (s SamplePair) String() string { - return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp) -} - -// Sample is a sample pair associated with a metric. -type Sample struct { - Metric Metric `json:"metric"` - Value SampleValue `json:"value"` - Timestamp Time `json:"timestamp"` -} - -// Equal compares first the metrics, then the timestamp, then the value. The -// semantics of value equality is defined by SampleValue.Equal. -func (s *Sample) Equal(o *Sample) bool { - if s == o { - return true - } - - if !s.Metric.Equal(o.Metric) { - return false - } - if !s.Timestamp.Equal(o.Timestamp) { - return false - } - - return s.Value.Equal(o.Value) -} - -func (s Sample) String() string { - return fmt.Sprintf("%s => %s", s.Metric, SamplePair{ - Timestamp: s.Timestamp, - Value: s.Value, - }) -} - -// MarshalJSON implements json.Marshaler. -func (s Sample) MarshalJSON() ([]byte, error) { - v := struct { - Metric Metric `json:"metric"` - Value SamplePair `json:"value"` - }{ - Metric: s.Metric, - Value: SamplePair{ - Timestamp: s.Timestamp, - Value: s.Value, - }, - } - - return json.Marshal(&v) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *Sample) UnmarshalJSON(b []byte) error { - v := struct { - Metric Metric `json:"metric"` - Value SamplePair `json:"value"` - }{ - Metric: s.Metric, - Value: SamplePair{ - Timestamp: s.Timestamp, - Value: s.Value, - }, - } - - if err := json.Unmarshal(b, &v); err != nil { - return err - } - - s.Metric = v.Metric - s.Timestamp = v.Value.Timestamp - s.Value = v.Value.Value - - return nil -} - -// Samples is a sortable Sample slice. It implements sort.Interface. -type Samples []*Sample - -func (s Samples) Len() int { - return len(s) -} - -// Less compares first the metrics, then the timestamp. -func (s Samples) Less(i, j int) bool { - switch { - case s[i].Metric.Before(s[j].Metric): - return true - case s[j].Metric.Before(s[i].Metric): - return false - case s[i].Timestamp.Before(s[j].Timestamp): - return true - default: - return false - } -} - -func (s Samples) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Equal compares two sets of samples and returns true if they are equal. -func (s Samples) Equal(o Samples) bool { - if len(s) != len(o) { - return false - } - - for i, sample := range s { - if !sample.Equal(o[i]) { - return false - } - } - return true -} - -// SampleStream is a stream of Values belonging to an attached COWMetric. -type SampleStream struct { - Metric Metric `json:"metric"` - Values []SamplePair `json:"values"` -} - -func (ss SampleStream) String() string { - vals := make([]string, len(ss.Values)) - for i, v := range ss.Values { - vals[i] = v.String() - } - return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n")) -} - -// Value is a generic interface for values resulting from a query evaluation. -type Value interface { - Type() ValueType - String() string -} - -func (Matrix) Type() ValueType { return ValMatrix } -func (Vector) Type() ValueType { return ValVector } -func (*Scalar) Type() ValueType { return ValScalar } -func (*String) Type() ValueType { return ValString } - -type ValueType int - -const ( - ValNone ValueType = iota - ValScalar - ValVector - ValMatrix - ValString -) - -// MarshalJSON implements json.Marshaler. -func (et ValueType) MarshalJSON() ([]byte, error) { - return json.Marshal(et.String()) -} - -func (et *ValueType) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - switch s { - case "": - *et = ValNone - case "scalar": - *et = ValScalar - case "vector": - *et = ValVector - case "matrix": - *et = ValMatrix - case "string": - *et = ValString - default: - return fmt.Errorf("unknown value type %q", s) - } - return nil -} - -func (e ValueType) String() string { - switch e { - case ValNone: - return "" - case ValScalar: - return "scalar" - case ValVector: - return "vector" - case ValMatrix: - return "matrix" - case ValString: - return "string" - } - panic("ValueType.String: unhandled value type") -} - -// Scalar is a scalar value evaluated at the set timestamp. -type Scalar struct { - Value SampleValue `json:"value"` - Timestamp Time `json:"timestamp"` -} - -func (s Scalar) String() string { - return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp) -} - -// MarshalJSON implements json.Marshaler. -func (s Scalar) MarshalJSON() ([]byte, error) { - v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64) - return json.Marshal([...]interface{}{s.Timestamp, string(v)}) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *Scalar) UnmarshalJSON(b []byte) error { - var f string - v := [...]interface{}{&s.Timestamp, &f} - - if err := json.Unmarshal(b, &v); err != nil { - return err - } - - value, err := strconv.ParseFloat(f, 64) - if err != nil { - return fmt.Errorf("error parsing sample value: %s", err) - } - s.Value = SampleValue(value) - return nil -} - -// String is a string value evaluated at the set timestamp. -type String struct { - Value string `json:"value"` - Timestamp Time `json:"timestamp"` -} - -func (s *String) String() string { - return s.Value -} - -// MarshalJSON implements json.Marshaler. -func (s String) MarshalJSON() ([]byte, error) { - return json.Marshal([]interface{}{s.Timestamp, s.Value}) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *String) UnmarshalJSON(b []byte) error { - v := [...]interface{}{&s.Timestamp, &s.Value} - return json.Unmarshal(b, &v) -} - -// Vector is basically only an alias for Samples, but the -// contract is that in a Vector, all Samples have the same timestamp. -type Vector []*Sample - -func (vec Vector) String() string { - entries := make([]string, len(vec)) - for i, s := range vec { - entries[i] = s.String() - } - return strings.Join(entries, "\n") -} - -func (vec Vector) Len() int { return len(vec) } -func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] } - -// Less compares first the metrics, then the timestamp. -func (vec Vector) Less(i, j int) bool { - switch { - case vec[i].Metric.Before(vec[j].Metric): - return true - case vec[j].Metric.Before(vec[i].Metric): - return false - case vec[i].Timestamp.Before(vec[j].Timestamp): - return true - default: - return false - } -} - -// Equal compares two sets of samples and returns true if they are equal. -func (vec Vector) Equal(o Vector) bool { - if len(vec) != len(o) { - return false - } - - for i, sample := range vec { - if !sample.Equal(o[i]) { - return false - } - } - return true -} - -// Matrix is a list of time series. -type Matrix []*SampleStream - -func (m Matrix) Len() int { return len(m) } -func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) } -func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] } - -func (mat Matrix) String() string { - matCp := make(Matrix, len(mat)) - copy(matCp, mat) - sort.Sort(matCp) - - strs := make([]string, len(matCp)) - - for i, ss := range matCp { - strs[i] = ss.String() - } - - return strings.Join(strs, "\n") -} diff --git a/vendor/github.com/prometheus/procfs/LICENSE b/vendor/github.com/prometheus/procfs/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/prometheus/procfs/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/prometheus/procfs/NOTICE b/vendor/github.com/prometheus/procfs/NOTICE deleted file mode 100644 index 53c5e9aa11..0000000000 --- a/vendor/github.com/prometheus/procfs/NOTICE +++ /dev/null @@ -1,7 +0,0 @@ -procfs provides functions to retrieve system, kernel and process -metrics from the pseudo-filesystem proc. - -Copyright 2014-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go deleted file mode 100644 index d3a8268078..0000000000 --- a/vendor/github.com/prometheus/procfs/buddyinfo.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "fmt" - "io" - "os" - "strconv" - "strings" -) - -// A BuddyInfo is the details parsed from /proc/buddyinfo. -// The data is comprised of an array of free fragments of each size. -// The sizes are 2^n*PAGE_SIZE, where n is the array index. -type BuddyInfo struct { - Node string - Zone string - Sizes []float64 -} - -// NewBuddyInfo reads the buddyinfo statistics. -func NewBuddyInfo() ([]BuddyInfo, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return nil, err - } - - return fs.NewBuddyInfo() -} - -// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. -func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) { - file, err := os.Open(fs.Path("buddyinfo")) - if err != nil { - return nil, err - } - defer file.Close() - - return parseBuddyInfo(file) -} - -func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { - var ( - buddyInfo = []BuddyInfo{} - scanner = bufio.NewScanner(r) - bucketCount = -1 - ) - - for scanner.Scan() { - var err error - line := scanner.Text() - parts := strings.Fields(line) - - if len(parts) < 4 { - return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") - } - - node := strings.TrimRight(parts[1], ",") - zone := strings.TrimRight(parts[3], ",") - arraySize := len(parts[4:]) - - if bucketCount == -1 { - bucketCount = arraySize - } else { - if bucketCount != arraySize { - return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize) - } - } - - sizes := make([]float64, arraySize) - for i := 0; i < arraySize; i++ { - sizes[i], err = strconv.ParseFloat(parts[i+4], 64) - if err != nil { - return nil, fmt.Errorf("invalid value in buddyinfo: %s", err) - } - } - - buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes}) - } - - return buddyInfo, scanner.Err() -} diff --git a/vendor/github.com/prometheus/procfs/doc.go b/vendor/github.com/prometheus/procfs/doc.go deleted file mode 100644 index e2acd6d40a..0000000000 --- a/vendor/github.com/prometheus/procfs/doc.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package procfs provides functions to retrieve system, kernel and process -// metrics from the pseudo-filesystem proc. -// -// Example: -// -// package main -// -// import ( -// "fmt" -// "log" -// -// "github.com/prometheus/procfs" -// ) -// -// func main() { -// p, err := procfs.Self() -// if err != nil { -// log.Fatalf("could not get process: %s", err) -// } -// -// stat, err := p.NewStat() -// if err != nil { -// log.Fatalf("could not get process stat: %s", err) -// } -// -// fmt.Printf("command: %s\n", stat.Comm) -// fmt.Printf("cpu time: %fs\n", stat.CPUTime()) -// fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) -// fmt.Printf("rss: %dB\n", stat.ResidentMemory()) -// } -// -package procfs diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go deleted file mode 100644 index b6c6b2ce1f..0000000000 --- a/vendor/github.com/prometheus/procfs/fs.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "fmt" - "os" - "path" - - "github.com/prometheus/procfs/nfs" - "github.com/prometheus/procfs/xfs" -) - -// FS represents the pseudo-filesystem proc, which provides an interface to -// kernel data structures. -type FS string - -// DefaultMountPoint is the common mount point of the proc filesystem. -const DefaultMountPoint = "/proc" - -// NewFS returns a new FS mounted under the given mountPoint. It will error -// if the mount point can't be read. -func NewFS(mountPoint string) (FS, error) { - info, err := os.Stat(mountPoint) - if err != nil { - return "", fmt.Errorf("could not read %s: %s", mountPoint, err) - } - if !info.IsDir() { - return "", fmt.Errorf("mount point %s is not a directory", mountPoint) - } - - return FS(mountPoint), nil -} - -// Path returns the path of the given subsystem relative to the procfs root. -func (fs FS) Path(p ...string) string { - return path.Join(append([]string{string(fs)}, p...)...) -} - -// XFSStats retrieves XFS filesystem runtime statistics. -func (fs FS) XFSStats() (*xfs.Stats, error) { - f, err := os.Open(fs.Path("fs/xfs/stat")) - if err != nil { - return nil, err - } - defer f.Close() - - return xfs.ParseStats(f) -} - -// NFSClientRPCStats retrieves NFS client RPC statistics. -func (fs FS) NFSClientRPCStats() (*nfs.ClientRPCStats, error) { - f, err := os.Open(fs.Path("net/rpc/nfs")) - if err != nil { - return nil, err - } - defer f.Close() - - return nfs.ParseClientRPCStats(f) -} - -// NFSdServerRPCStats retrieves NFS daemon RPC statistics. -func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) { - f, err := os.Open(fs.Path("net/rpc/nfsd")) - if err != nil { - return nil, err - } - defer f.Close() - - return nfs.ParseServerRPCStats(f) -} diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go deleted file mode 100644 index 1ad21c91a3..0000000000 --- a/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package util - -import "strconv" - -// ParseUint32s parses a slice of strings into a slice of uint32s. -func ParseUint32s(ss []string) ([]uint32, error) { - us := make([]uint32, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 32) - if err != nil { - return nil, err - } - - us = append(us, uint32(u)) - } - - return us, nil -} - -// ParseUint64s parses a slice of strings into a slice of uint64s. -func ParseUint64s(ss []string) ([]uint64, error) { - us := make([]uint64, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - us = append(us, u) - } - - return us, nil -} diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go deleted file mode 100644 index e36d4a3bd0..0000000000 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "encoding/hex" - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "os" - "strconv" - "strings" -) - -// IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`. -type IPVSStats struct { - // Total count of connections. - Connections uint64 - // Total incoming packages processed. - IncomingPackets uint64 - // Total outgoing packages processed. - OutgoingPackets uint64 - // Total incoming traffic. - IncomingBytes uint64 - // Total outgoing traffic. - OutgoingBytes uint64 -} - -// IPVSBackendStatus holds current metrics of one virtual / real address pair. -type IPVSBackendStatus struct { - // The local (virtual) IP address. - LocalAddress net.IP - // The remote (real) IP address. - RemoteAddress net.IP - // The local (virtual) port. - LocalPort uint16 - // The remote (real) port. - RemotePort uint16 - // The local firewall mark - LocalMark string - // The transport protocol (TCP, UDP). - Proto string - // The current number of active connections for this virtual/real address pair. - ActiveConn uint64 - // The current number of inactive connections for this virtual/real address pair. - InactConn uint64 - // The current weight of this virtual/real address pair. - Weight uint64 -} - -// NewIPVSStats reads the IPVS statistics. -func NewIPVSStats() (IPVSStats, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return IPVSStats{}, err - } - - return fs.NewIPVSStats() -} - -// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem. -func (fs FS) NewIPVSStats() (IPVSStats, error) { - file, err := os.Open(fs.Path("net/ip_vs_stats")) - if err != nil { - return IPVSStats{}, err - } - defer file.Close() - - return parseIPVSStats(file) -} - -// parseIPVSStats performs the actual parsing of `ip_vs_stats`. -func parseIPVSStats(file io.Reader) (IPVSStats, error) { - var ( - statContent []byte - statLines []string - statFields []string - stats IPVSStats - ) - - statContent, err := ioutil.ReadAll(file) - if err != nil { - return IPVSStats{}, err - } - - statLines = strings.SplitN(string(statContent), "\n", 4) - if len(statLines) != 4 { - return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short") - } - - statFields = strings.Fields(statLines[2]) - if len(statFields) != 5 { - return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields") - } - - stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64) - if err != nil { - return IPVSStats{}, err - } - stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64) - if err != nil { - return IPVSStats{}, err - } - stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64) - if err != nil { - return IPVSStats{}, err - } - stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64) - if err != nil { - return IPVSStats{}, err - } - stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64) - if err != nil { - return IPVSStats{}, err - } - - return stats, nil -} - -// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs. -func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return []IPVSBackendStatus{}, err - } - - return fs.NewIPVSBackendStatus() -} - -// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem. -func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) { - file, err := os.Open(fs.Path("net/ip_vs")) - if err != nil { - return nil, err - } - defer file.Close() - - return parseIPVSBackendStatus(file) -} - -func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) { - var ( - status []IPVSBackendStatus - scanner = bufio.NewScanner(file) - proto string - localMark string - localAddress net.IP - localPort uint16 - err error - ) - - for scanner.Scan() { - fields := strings.Fields(scanner.Text()) - if len(fields) == 0 { - continue - } - switch { - case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port": - continue - case fields[0] == "TCP" || fields[0] == "UDP": - if len(fields) < 2 { - continue - } - proto = fields[0] - localMark = "" - localAddress, localPort, err = parseIPPort(fields[1]) - if err != nil { - return nil, err - } - case fields[0] == "FWM": - if len(fields) < 2 { - continue - } - proto = fields[0] - localMark = fields[1] - localAddress = nil - localPort = 0 - case fields[0] == "->": - if len(fields) < 6 { - continue - } - remoteAddress, remotePort, err := parseIPPort(fields[1]) - if err != nil { - return nil, err - } - weight, err := strconv.ParseUint(fields[3], 10, 64) - if err != nil { - return nil, err - } - activeConn, err := strconv.ParseUint(fields[4], 10, 64) - if err != nil { - return nil, err - } - inactConn, err := strconv.ParseUint(fields[5], 10, 64) - if err != nil { - return nil, err - } - status = append(status, IPVSBackendStatus{ - LocalAddress: localAddress, - LocalPort: localPort, - LocalMark: localMark, - RemoteAddress: remoteAddress, - RemotePort: remotePort, - Proto: proto, - Weight: weight, - ActiveConn: activeConn, - InactConn: inactConn, - }) - } - } - return status, nil -} - -func parseIPPort(s string) (net.IP, uint16, error) { - var ( - ip net.IP - err error - ) - - switch len(s) { - case 13: - ip, err = hex.DecodeString(s[0:8]) - if err != nil { - return nil, 0, err - } - case 46: - ip = net.ParseIP(s[1:40]) - if ip == nil { - return nil, 0, fmt.Errorf("invalid IPv6 address: %s", s[1:40]) - } - default: - return nil, 0, fmt.Errorf("unexpected IP:Port: %s", s) - } - - portString := s[len(s)-4:] - if len(portString) != 4 { - return nil, 0, fmt.Errorf("unexpected port string format: %s", portString) - } - port, err := strconv.ParseUint(portString, 16, 16) - if err != nil { - return nil, 0, err - } - - return ip, uint16(port), nil -} diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go deleted file mode 100644 index 9dc19583d8..0000000000 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "fmt" - "io/ioutil" - "regexp" - "strconv" - "strings" -) - -var ( - statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) - buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) -) - -// MDStat holds info parsed from /proc/mdstat. -type MDStat struct { - // Name of the device. - Name string - // activity-state of the device. - ActivityState string - // Number of active disks. - DisksActive int64 - // Total number of disks the device consists of. - DisksTotal int64 - // Number of blocks the device holds. - BlocksTotal int64 - // Number of blocks on the device that are in sync. - BlocksSynced int64 -} - -// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos. -func (fs FS) ParseMDStat() (mdstates []MDStat, err error) { - mdStatusFilePath := fs.Path("mdstat") - content, err := ioutil.ReadFile(mdStatusFilePath) - if err != nil { - return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) - } - - mdStates := []MDStat{} - lines := strings.Split(string(content), "\n") - for i, l := range lines { - if l == "" { - continue - } - if l[0] == ' ' { - continue - } - if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") { - continue - } - - mainLine := strings.Split(l, " ") - if len(mainLine) < 3 { - return mdStates, fmt.Errorf("error parsing mdline: %s", l) - } - mdName := mainLine[0] - activityState := mainLine[2] - - if len(lines) <= i+3 { - return mdStates, fmt.Errorf( - "error parsing %s: too few lines for md device %s", - mdStatusFilePath, - mdName, - ) - } - - active, total, size, err := evalStatusline(lines[i+1]) - if err != nil { - return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) - } - - // j is the line number of the syncing-line. - j := i + 2 - if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line - j = i + 3 - } - - // If device is syncing at the moment, get the number of currently - // synced bytes, otherwise that number equals the size of the device. - syncedBlocks := size - if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { - syncedBlocks, err = evalBuildline(lines[j]) - if err != nil { - return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) - } - } - - mdStates = append(mdStates, MDStat{ - Name: mdName, - ActivityState: activityState, - DisksActive: active, - DisksTotal: total, - BlocksTotal: size, - BlocksSynced: syncedBlocks, - }) - } - - return mdStates, nil -} - -func evalStatusline(statusline string) (active, total, size int64, err error) { - matches := statuslineRE.FindStringSubmatch(statusline) - if len(matches) != 4 { - return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline) - } - - size, err = strconv.ParseInt(matches[1], 10, 64) - if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) - } - - total, err = strconv.ParseInt(matches[2], 10, 64) - if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) - } - - active, err = strconv.ParseInt(matches[3], 10, 64) - if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) - } - - return active, total, size, nil -} - -func evalBuildline(buildline string) (syncedBlocks int64, err error) { - matches := buildlineRE.FindStringSubmatch(buildline) - if len(matches) != 2 { - return 0, fmt.Errorf("unexpected buildline: %s", buildline) - } - - syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) - if err != nil { - return 0, fmt.Errorf("%s in buildline: %s", err, buildline) - } - - return syncedBlocks, nil -} diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go deleted file mode 100644 index e95ddbc67c..0000000000 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ /dev/null @@ -1,569 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -// While implementing parsing of /proc/[pid]/mountstats, this blog was used -// heavily as a reference: -// https://utcc.utoronto.ca/~cks/space/blog/linux/NFSMountstatsIndex -// -// Special thanks to Chris Siebenmann for all of his posts explaining the -// various statistics available for NFS. - -import ( - "bufio" - "fmt" - "io" - "strconv" - "strings" - "time" -) - -// Constants shared between multiple functions. -const ( - deviceEntryLen = 8 - - fieldBytesLen = 8 - fieldEventsLen = 27 - - statVersion10 = "1.0" - statVersion11 = "1.1" - - fieldTransport10Len = 10 - fieldTransport11Len = 13 -) - -// A Mount is a device mount parsed from /proc/[pid]/mountstats. -type Mount struct { - // Name of the device. - Device string - // The mount point of the device. - Mount string - // The filesystem type used by the device. - Type string - // If available additional statistics related to this Mount. - // Use a type assertion to determine if additional statistics are available. - Stats MountStats -} - -// A MountStats is a type which contains detailed statistics for a specific -// type of Mount. -type MountStats interface { - mountStats() -} - -// A MountStatsNFS is a MountStats implementation for NFSv3 and v4 mounts. -type MountStatsNFS struct { - // The version of statistics provided. - StatVersion string - // The age of the NFS mount. - Age time.Duration - // Statistics related to byte counters for various operations. - Bytes NFSBytesStats - // Statistics related to various NFS event occurrences. - Events NFSEventsStats - // Statistics broken down by filesystem operation. - Operations []NFSOperationStats - // Statistics about the NFS RPC transport. - Transport NFSTransportStats -} - -// mountStats implements MountStats. -func (m MountStatsNFS) mountStats() {} - -// A NFSBytesStats contains statistics about the number of bytes read and written -// by an NFS client to and from an NFS server. -type NFSBytesStats struct { - // Number of bytes read using the read() syscall. - Read uint64 - // Number of bytes written using the write() syscall. - Write uint64 - // Number of bytes read using the read() syscall in O_DIRECT mode. - DirectRead uint64 - // Number of bytes written using the write() syscall in O_DIRECT mode. - DirectWrite uint64 - // Number of bytes read from the NFS server, in total. - ReadTotal uint64 - // Number of bytes written to the NFS server, in total. - WriteTotal uint64 - // Number of pages read directly via mmap()'d files. - ReadPages uint64 - // Number of pages written directly via mmap()'d files. - WritePages uint64 -} - -// A NFSEventsStats contains statistics about NFS event occurrences. -type NFSEventsStats struct { - // Number of times cached inode attributes are re-validated from the server. - InodeRevalidate uint64 - // Number of times cached dentry nodes are re-validated from the server. - DnodeRevalidate uint64 - // Number of times an inode cache is cleared. - DataInvalidate uint64 - // Number of times cached inode attributes are invalidated. - AttributeInvalidate uint64 - // Number of times files or directories have been open()'d. - VFSOpen uint64 - // Number of times a directory lookup has occurred. - VFSLookup uint64 - // Number of times permissions have been checked. - VFSAccess uint64 - // Number of updates (and potential writes) to pages. - VFSUpdatePage uint64 - // Number of pages read directly via mmap()'d files. - VFSReadPage uint64 - // Number of times a group of pages have been read. - VFSReadPages uint64 - // Number of pages written directly via mmap()'d files. - VFSWritePage uint64 - // Number of times a group of pages have been written. - VFSWritePages uint64 - // Number of times directory entries have been read with getdents(). - VFSGetdents uint64 - // Number of times attributes have been set on inodes. - VFSSetattr uint64 - // Number of pending writes that have been forcefully flushed to the server. - VFSFlush uint64 - // Number of times fsync() has been called on directories and files. - VFSFsync uint64 - // Number of times locking has been attempted on a file. - VFSLock uint64 - // Number of times files have been closed and released. - VFSFileRelease uint64 - // Unknown. Possibly unused. - CongestionWait uint64 - // Number of times files have been truncated. - Truncation uint64 - // Number of times a file has been grown due to writes beyond its existing end. - WriteExtension uint64 - // Number of times a file was removed while still open by another process. - SillyRename uint64 - // Number of times the NFS server gave less data than expected while reading. - ShortRead uint64 - // Number of times the NFS server wrote less data than expected while writing. - ShortWrite uint64 - // Number of times the NFS server indicated EJUKEBOX; retrieving data from - // offline storage. - JukeboxDelay uint64 - // Number of NFS v4.1+ pNFS reads. - PNFSRead uint64 - // Number of NFS v4.1+ pNFS writes. - PNFSWrite uint64 -} - -// A NFSOperationStats contains statistics for a single operation. -type NFSOperationStats struct { - // The name of the operation. - Operation string - // Number of requests performed for this operation. - Requests uint64 - // Number of times an actual RPC request has been transmitted for this operation. - Transmissions uint64 - // Number of times a request has had a major timeout. - MajorTimeouts uint64 - // Number of bytes sent for this operation, including RPC headers and payload. - BytesSent uint64 - // Number of bytes received for this operation, including RPC headers and payload. - BytesReceived uint64 - // Duration all requests spent queued for transmission before they were sent. - CumulativeQueueTime time.Duration - // Duration it took to get a reply back after the request was transmitted. - CumulativeTotalResponseTime time.Duration - // Duration from when a request was enqueued to when it was completely handled. - CumulativeTotalRequestTime time.Duration -} - -// A NFSTransportStats contains statistics for the NFS mount RPC requests and -// responses. -type NFSTransportStats struct { - // The local port used for the NFS mount. - Port uint64 - // Number of times the client has had to establish a connection from scratch - // to the NFS server. - Bind uint64 - // Number of times the client has made a TCP connection to the NFS server. - Connect uint64 - // Duration (in jiffies, a kernel internal unit of time) the NFS mount has - // spent waiting for connections to the server to be established. - ConnectIdleTime uint64 - // Duration since the NFS mount last saw any RPC traffic. - IdleTime time.Duration - // Number of RPC requests for this mount sent to the NFS server. - Sends uint64 - // Number of RPC responses for this mount received from the NFS server. - Receives uint64 - // Number of times the NFS server sent a response with a transaction ID - // unknown to this client. - BadTransactionIDs uint64 - // A running counter, incremented on each request as the current difference - // ebetween sends and receives. - CumulativeActiveRequests uint64 - // A running counter, incremented on each request by the current backlog - // queue size. - CumulativeBacklog uint64 - - // Stats below only available with stat version 1.1. - - // Maximum number of simultaneously active RPC requests ever used. - MaximumRPCSlotsUsed uint64 - // A running counter, incremented on each request as the current size of the - // sending queue. - CumulativeSendingQueue uint64 - // A running counter, incremented on each request as the current size of the - // pending queue. - CumulativePendingQueue uint64 -} - -// parseMountStats parses a /proc/[pid]/mountstats file and returns a slice -// of Mount structures containing detailed information about each mount. -// If available, statistics for each mount are parsed as well. -func parseMountStats(r io.Reader) ([]*Mount, error) { - const ( - device = "device" - statVersionPrefix = "statvers=" - - nfs3Type = "nfs" - nfs4Type = "nfs4" - ) - - var mounts []*Mount - - s := bufio.NewScanner(r) - for s.Scan() { - // Only look for device entries in this function - ss := strings.Fields(string(s.Bytes())) - if len(ss) == 0 || ss[0] != device { - continue - } - - m, err := parseMount(ss) - if err != nil { - return nil, err - } - - // Does this mount also possess statistics information? - if len(ss) > deviceEntryLen { - // Only NFSv3 and v4 are supported for parsing statistics - if m.Type != nfs3Type && m.Type != nfs4Type { - return nil, fmt.Errorf("cannot parse MountStats for fstype %q", m.Type) - } - - statVersion := strings.TrimPrefix(ss[8], statVersionPrefix) - - stats, err := parseMountStatsNFS(s, statVersion) - if err != nil { - return nil, err - } - - m.Stats = stats - } - - mounts = append(mounts, m) - } - - return mounts, s.Err() -} - -// parseMount parses an entry in /proc/[pid]/mountstats in the format: -// device [device] mounted on [mount] with fstype [type] -func parseMount(ss []string) (*Mount, error) { - if len(ss) < deviceEntryLen { - return nil, fmt.Errorf("invalid device entry: %v", ss) - } - - // Check for specific words appearing at specific indices to ensure - // the format is consistent with what we expect - format := []struct { - i int - s string - }{ - {i: 0, s: "device"}, - {i: 2, s: "mounted"}, - {i: 3, s: "on"}, - {i: 5, s: "with"}, - {i: 6, s: "fstype"}, - } - - for _, f := range format { - if ss[f.i] != f.s { - return nil, fmt.Errorf("invalid device entry: %v", ss) - } - } - - return &Mount{ - Device: ss[1], - Mount: ss[4], - Type: ss[7], - }, nil -} - -// parseMountStatsNFS parses a MountStatsNFS by scanning additional information -// related to NFS statistics. -func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, error) { - // Field indicators for parsing specific types of data - const ( - fieldAge = "age:" - fieldBytes = "bytes:" - fieldEvents = "events:" - fieldPerOpStats = "per-op" - fieldTransport = "xprt:" - ) - - stats := &MountStatsNFS{ - StatVersion: statVersion, - } - - for s.Scan() { - ss := strings.Fields(string(s.Bytes())) - if len(ss) == 0 { - break - } - if len(ss) < 2 { - return nil, fmt.Errorf("not enough information for NFS stats: %v", ss) - } - - switch ss[0] { - case fieldAge: - // Age integer is in seconds - d, err := time.ParseDuration(ss[1] + "s") - if err != nil { - return nil, err - } - - stats.Age = d - case fieldBytes: - bstats, err := parseNFSBytesStats(ss[1:]) - if err != nil { - return nil, err - } - - stats.Bytes = *bstats - case fieldEvents: - estats, err := parseNFSEventsStats(ss[1:]) - if err != nil { - return nil, err - } - - stats.Events = *estats - case fieldTransport: - if len(ss) < 3 { - return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss) - } - - tstats, err := parseNFSTransportStats(ss[2:], statVersion) - if err != nil { - return nil, err - } - - stats.Transport = *tstats - } - - // When encountering "per-operation statistics", we must break this - // loop and parse them separately to ensure we can terminate parsing - // before reaching another device entry; hence why this 'if' statement - // is not just another switch case - if ss[0] == fieldPerOpStats { - break - } - } - - if err := s.Err(); err != nil { - return nil, err - } - - // NFS per-operation stats appear last before the next device entry - perOpStats, err := parseNFSOperationStats(s) - if err != nil { - return nil, err - } - - stats.Operations = perOpStats - - return stats, nil -} - -// parseNFSBytesStats parses a NFSBytesStats line using an input set of -// integer fields. -func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) { - if len(ss) != fieldBytesLen { - return nil, fmt.Errorf("invalid NFS bytes stats: %v", ss) - } - - ns := make([]uint64, 0, fieldBytesLen) - for _, s := range ss { - n, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - ns = append(ns, n) - } - - return &NFSBytesStats{ - Read: ns[0], - Write: ns[1], - DirectRead: ns[2], - DirectWrite: ns[3], - ReadTotal: ns[4], - WriteTotal: ns[5], - ReadPages: ns[6], - WritePages: ns[7], - }, nil -} - -// parseNFSEventsStats parses a NFSEventsStats line using an input set of -// integer fields. -func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) { - if len(ss) != fieldEventsLen { - return nil, fmt.Errorf("invalid NFS events stats: %v", ss) - } - - ns := make([]uint64, 0, fieldEventsLen) - for _, s := range ss { - n, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - ns = append(ns, n) - } - - return &NFSEventsStats{ - InodeRevalidate: ns[0], - DnodeRevalidate: ns[1], - DataInvalidate: ns[2], - AttributeInvalidate: ns[3], - VFSOpen: ns[4], - VFSLookup: ns[5], - VFSAccess: ns[6], - VFSUpdatePage: ns[7], - VFSReadPage: ns[8], - VFSReadPages: ns[9], - VFSWritePage: ns[10], - VFSWritePages: ns[11], - VFSGetdents: ns[12], - VFSSetattr: ns[13], - VFSFlush: ns[14], - VFSFsync: ns[15], - VFSLock: ns[16], - VFSFileRelease: ns[17], - CongestionWait: ns[18], - Truncation: ns[19], - WriteExtension: ns[20], - SillyRename: ns[21], - ShortRead: ns[22], - ShortWrite: ns[23], - JukeboxDelay: ns[24], - PNFSRead: ns[25], - PNFSWrite: ns[26], - }, nil -} - -// parseNFSOperationStats parses a slice of NFSOperationStats by scanning -// additional information about per-operation statistics until an empty -// line is reached. -func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { - const ( - // Number of expected fields in each per-operation statistics set - numFields = 9 - ) - - var ops []NFSOperationStats - - for s.Scan() { - ss := strings.Fields(string(s.Bytes())) - if len(ss) == 0 { - // Must break when reading a blank line after per-operation stats to - // enable top-level function to parse the next device entry - break - } - - if len(ss) != numFields { - return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss) - } - - // Skip string operation name for integers - ns := make([]uint64, 0, numFields-1) - for _, st := range ss[1:] { - n, err := strconv.ParseUint(st, 10, 64) - if err != nil { - return nil, err - } - - ns = append(ns, n) - } - - ops = append(ops, NFSOperationStats{ - Operation: strings.TrimSuffix(ss[0], ":"), - Requests: ns[0], - Transmissions: ns[1], - MajorTimeouts: ns[2], - BytesSent: ns[3], - BytesReceived: ns[4], - CumulativeQueueTime: time.Duration(ns[5]) * time.Millisecond, - CumulativeTotalResponseTime: time.Duration(ns[6]) * time.Millisecond, - CumulativeTotalRequestTime: time.Duration(ns[7]) * time.Millisecond, - }) - } - - return ops, s.Err() -} - -// parseNFSTransportStats parses a NFSTransportStats line using an input set of -// integer fields matched to a specific stats version. -func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) { - switch statVersion { - case statVersion10: - if len(ss) != fieldTransport10Len { - return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss) - } - case statVersion11: - if len(ss) != fieldTransport11Len { - return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss) - } - default: - return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion) - } - - // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay - // in a v1.0 response. - // - // Note: slice length must be set to length of v1.1 stats to avoid a panic when - // only v1.0 stats are present. - // See: https://github.com/prometheus/node_exporter/issues/571. - ns := make([]uint64, fieldTransport11Len) - for i, s := range ss { - n, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - ns[i] = n - } - - return &NFSTransportStats{ - Port: ns[0], - Bind: ns[1], - Connect: ns[2], - ConnectIdleTime: ns[3], - IdleTime: time.Duration(ns[4]) * time.Second, - Sends: ns[5], - Receives: ns[6], - BadTransactionIDs: ns[7], - CumulativeActiveRequests: ns[8], - CumulativeBacklog: ns[9], - MaximumRPCSlotsUsed: ns[10], - CumulativeSendingQueue: ns[11], - CumulativePendingQueue: ns[12], - }, nil -} diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go deleted file mode 100644 index 3f2523371a..0000000000 --- a/vendor/github.com/prometheus/procfs/net_dev.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "errors" - "os" - "sort" - "strconv" - "strings" -) - -// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev. -type NetDevLine struct { - Name string `json:"name"` // The name of the interface. - RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received. - RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received. - RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered. - RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving. - RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors. - RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors. - RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver. - RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver. - TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted. - TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted. - TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered. - TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting. - TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors. - TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface. - TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver. - TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver. -} - -// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys -// are interface names. -type NetDev map[string]NetDevLine - -// NewNetDev returns kernel/system statistics read from /proc/net/dev. -func NewNetDev() (NetDev, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return nil, err - } - - return fs.NewNetDev() -} - -// NewNetDev returns kernel/system statistics read from /proc/net/dev. -func (fs FS) NewNetDev() (NetDev, error) { - return newNetDev(fs.Path("net/dev")) -} - -// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev. -func (p Proc) NewNetDev() (NetDev, error) { - return newNetDev(p.path("net/dev")) -} - -// newNetDev creates a new NetDev from the contents of the given file. -func newNetDev(file string) (NetDev, error) { - f, err := os.Open(file) - if err != nil { - return NetDev{}, err - } - defer f.Close() - - nd := NetDev{} - s := bufio.NewScanner(f) - for n := 0; s.Scan(); n++ { - // Skip the 2 header lines. - if n < 2 { - continue - } - - line, err := nd.parseLine(s.Text()) - if err != nil { - return nd, err - } - - nd[line.Name] = *line - } - - return nd, s.Err() -} - -// parseLine parses a single line from the /proc/net/dev file. Header lines -// must be filtered prior to calling this method. -func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) { - parts := strings.SplitN(rawLine, ":", 2) - if len(parts) != 2 { - return nil, errors.New("invalid net/dev line, missing colon") - } - fields := strings.Fields(strings.TrimSpace(parts[1])) - - var err error - line := &NetDevLine{} - - // Interface Name - line.Name = strings.TrimSpace(parts[0]) - if line.Name == "" { - return nil, errors.New("invalid net/dev line, empty interface name") - } - - // RX - line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64) - if err != nil { - return nil, err - } - line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64) - if err != nil { - return nil, err - } - line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64) - if err != nil { - return nil, err - } - line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64) - if err != nil { - return nil, err - } - line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64) - if err != nil { - return nil, err - } - line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64) - if err != nil { - return nil, err - } - line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64) - if err != nil { - return nil, err - } - line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64) - if err != nil { - return nil, err - } - - // TX - line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64) - if err != nil { - return nil, err - } - line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64) - if err != nil { - return nil, err - } - line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64) - if err != nil { - return nil, err - } - line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64) - if err != nil { - return nil, err - } - line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64) - if err != nil { - return nil, err - } - line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64) - if err != nil { - return nil, err - } - line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64) - if err != nil { - return nil, err - } - line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64) - if err != nil { - return nil, err - } - - return line, nil -} - -// Total aggregates the values across interfaces and returns a new NetDevLine. -// The Name field will be a sorted comma separated list of interface names. -func (nd NetDev) Total() NetDevLine { - total := NetDevLine{} - - names := make([]string, 0, len(nd)) - for _, ifc := range nd { - names = append(names, ifc.Name) - total.RxBytes += ifc.RxBytes - total.RxPackets += ifc.RxPackets - total.RxPackets += ifc.RxPackets - total.RxErrors += ifc.RxErrors - total.RxDropped += ifc.RxDropped - total.RxFIFO += ifc.RxFIFO - total.RxFrame += ifc.RxFrame - total.RxCompressed += ifc.RxCompressed - total.RxMulticast += ifc.RxMulticast - total.TxBytes += ifc.TxBytes - total.TxPackets += ifc.TxPackets - total.TxErrors += ifc.TxErrors - total.TxDropped += ifc.TxDropped - total.TxFIFO += ifc.TxFIFO - total.TxCollisions += ifc.TxCollisions - total.TxCarrier += ifc.TxCarrier - total.TxCompressed += ifc.TxCompressed - } - sort.Strings(names) - total.Name = strings.Join(names, ", ") - - return total -} diff --git a/vendor/github.com/prometheus/procfs/nfs/nfs.go b/vendor/github.com/prometheus/procfs/nfs/nfs.go deleted file mode 100644 index 651bf68195..0000000000 --- a/vendor/github.com/prometheus/procfs/nfs/nfs.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package nfs implements parsing of /proc/net/rpc/nfsd. -// Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/ -package nfs - -// ReplyCache models the "rc" line. -type ReplyCache struct { - Hits uint64 - Misses uint64 - NoCache uint64 -} - -// FileHandles models the "fh" line. -type FileHandles struct { - Stale uint64 - TotalLookups uint64 - AnonLookups uint64 - DirNoCache uint64 - NoDirNoCache uint64 -} - -// InputOutput models the "io" line. -type InputOutput struct { - Read uint64 - Write uint64 -} - -// Threads models the "th" line. -type Threads struct { - Threads uint64 - FullCnt uint64 -} - -// ReadAheadCache models the "ra" line. -type ReadAheadCache struct { - CacheSize uint64 - CacheHistogram []uint64 - NotFound uint64 -} - -// Network models the "net" line. -type Network struct { - NetCount uint64 - UDPCount uint64 - TCPCount uint64 - TCPConnect uint64 -} - -// ClientRPC models the nfs "rpc" line. -type ClientRPC struct { - RPCCount uint64 - Retransmissions uint64 - AuthRefreshes uint64 -} - -// ServerRPC models the nfsd "rpc" line. -type ServerRPC struct { - RPCCount uint64 - BadCnt uint64 - BadFmt uint64 - BadAuth uint64 - BadcInt uint64 -} - -// V2Stats models the "proc2" line. -type V2Stats struct { - Null uint64 - GetAttr uint64 - SetAttr uint64 - Root uint64 - Lookup uint64 - ReadLink uint64 - Read uint64 - WrCache uint64 - Write uint64 - Create uint64 - Remove uint64 - Rename uint64 - Link uint64 - SymLink uint64 - MkDir uint64 - RmDir uint64 - ReadDir uint64 - FsStat uint64 -} - -// V3Stats models the "proc3" line. -type V3Stats struct { - Null uint64 - GetAttr uint64 - SetAttr uint64 - Lookup uint64 - Access uint64 - ReadLink uint64 - Read uint64 - Write uint64 - Create uint64 - MkDir uint64 - SymLink uint64 - MkNod uint64 - Remove uint64 - RmDir uint64 - Rename uint64 - Link uint64 - ReadDir uint64 - ReadDirPlus uint64 - FsStat uint64 - FsInfo uint64 - PathConf uint64 - Commit uint64 -} - -// ClientV4Stats models the nfs "proc4" line. -type ClientV4Stats struct { - Null uint64 - Read uint64 - Write uint64 - Commit uint64 - Open uint64 - OpenConfirm uint64 - OpenNoattr uint64 - OpenDowngrade uint64 - Close uint64 - Setattr uint64 - FsInfo uint64 - Renew uint64 - SetClientID uint64 - SetClientIDConfirm uint64 - Lock uint64 - Lockt uint64 - Locku uint64 - Access uint64 - Getattr uint64 - Lookup uint64 - LookupRoot uint64 - Remove uint64 - Rename uint64 - Link uint64 - Symlink uint64 - Create uint64 - Pathconf uint64 - StatFs uint64 - ReadLink uint64 - ReadDir uint64 - ServerCaps uint64 - DelegReturn uint64 - GetACL uint64 - SetACL uint64 - FsLocations uint64 - ReleaseLockowner uint64 - Secinfo uint64 - FsidPresent uint64 - ExchangeID uint64 - CreateSession uint64 - DestroySession uint64 - Sequence uint64 - GetLeaseTime uint64 - ReclaimComplete uint64 - LayoutGet uint64 - GetDeviceInfo uint64 - LayoutCommit uint64 - LayoutReturn uint64 - SecinfoNoName uint64 - TestStateID uint64 - FreeStateID uint64 - GetDeviceList uint64 - BindConnToSession uint64 - DestroyClientID uint64 - Seek uint64 - Allocate uint64 - DeAllocate uint64 - LayoutStats uint64 - Clone uint64 -} - -// ServerV4Stats models the nfsd "proc4" line. -type ServerV4Stats struct { - Null uint64 - Compound uint64 -} - -// V4Ops models the "proc4ops" line: NFSv4 operations -// Variable list, see: -// v4.0 https://tools.ietf.org/html/rfc3010 (38 operations) -// v4.1 https://tools.ietf.org/html/rfc5661 (58 operations) -// v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations) -type V4Ops struct { - //Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct? - Op0Unused uint64 - Op1Unused uint64 - Op2Future uint64 - Access uint64 - Close uint64 - Commit uint64 - Create uint64 - DelegPurge uint64 - DelegReturn uint64 - GetAttr uint64 - GetFH uint64 - Link uint64 - Lock uint64 - Lockt uint64 - Locku uint64 - Lookup uint64 - LookupRoot uint64 - Nverify uint64 - Open uint64 - OpenAttr uint64 - OpenConfirm uint64 - OpenDgrd uint64 - PutFH uint64 - PutPubFH uint64 - PutRootFH uint64 - Read uint64 - ReadDir uint64 - ReadLink uint64 - Remove uint64 - Rename uint64 - Renew uint64 - RestoreFH uint64 - SaveFH uint64 - SecInfo uint64 - SetAttr uint64 - Verify uint64 - Write uint64 - RelLockOwner uint64 -} - -// ClientRPCStats models all stats from /proc/net/rpc/nfs. -type ClientRPCStats struct { - Network Network - ClientRPC ClientRPC - V2Stats V2Stats - V3Stats V3Stats - ClientV4Stats ClientV4Stats -} - -// ServerRPCStats models all stats from /proc/net/rpc/nfsd. -type ServerRPCStats struct { - ReplyCache ReplyCache - FileHandles FileHandles - InputOutput InputOutput - Threads Threads - ReadAheadCache ReadAheadCache - Network Network - ServerRPC ServerRPC - V2Stats V2Stats - V3Stats V3Stats - ServerV4Stats ServerV4Stats - V4Ops V4Ops -} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse.go b/vendor/github.com/prometheus/procfs/nfs/parse.go deleted file mode 100644 index 95a83cc5bc..0000000000 --- a/vendor/github.com/prometheus/procfs/nfs/parse.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package nfs - -import ( - "fmt" -) - -func parseReplyCache(v []uint64) (ReplyCache, error) { - if len(v) != 3 { - return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v) - } - - return ReplyCache{ - Hits: v[0], - Misses: v[1], - NoCache: v[2], - }, nil -} - -func parseFileHandles(v []uint64) (FileHandles, error) { - if len(v) != 5 { - return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v) - } - - return FileHandles{ - Stale: v[0], - TotalLookups: v[1], - AnonLookups: v[2], - DirNoCache: v[3], - NoDirNoCache: v[4], - }, nil -} - -func parseInputOutput(v []uint64) (InputOutput, error) { - if len(v) != 2 { - return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v) - } - - return InputOutput{ - Read: v[0], - Write: v[1], - }, nil -} - -func parseThreads(v []uint64) (Threads, error) { - if len(v) != 2 { - return Threads{}, fmt.Errorf("invalid Threads line %q", v) - } - - return Threads{ - Threads: v[0], - FullCnt: v[1], - }, nil -} - -func parseReadAheadCache(v []uint64) (ReadAheadCache, error) { - if len(v) != 12 { - return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v) - } - - return ReadAheadCache{ - CacheSize: v[0], - CacheHistogram: v[1:11], - NotFound: v[11], - }, nil -} - -func parseNetwork(v []uint64) (Network, error) { - if len(v) != 4 { - return Network{}, fmt.Errorf("invalid Network line %q", v) - } - - return Network{ - NetCount: v[0], - UDPCount: v[1], - TCPCount: v[2], - TCPConnect: v[3], - }, nil -} - -func parseServerRPC(v []uint64) (ServerRPC, error) { - if len(v) != 5 { - return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v) - } - - return ServerRPC{ - RPCCount: v[0], - BadCnt: v[1], - BadFmt: v[2], - BadAuth: v[3], - BadcInt: v[4], - }, nil -} - -func parseClientRPC(v []uint64) (ClientRPC, error) { - if len(v) != 3 { - return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v) - } - - return ClientRPC{ - RPCCount: v[0], - Retransmissions: v[1], - AuthRefreshes: v[2], - }, nil -} - -func parseV2Stats(v []uint64) (V2Stats, error) { - values := int(v[0]) - if len(v[1:]) != values || values != 18 { - return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v) - } - - return V2Stats{ - Null: v[1], - GetAttr: v[2], - SetAttr: v[3], - Root: v[4], - Lookup: v[5], - ReadLink: v[6], - Read: v[7], - WrCache: v[8], - Write: v[9], - Create: v[10], - Remove: v[11], - Rename: v[12], - Link: v[13], - SymLink: v[14], - MkDir: v[15], - RmDir: v[16], - ReadDir: v[17], - FsStat: v[18], - }, nil -} - -func parseV3Stats(v []uint64) (V3Stats, error) { - values := int(v[0]) - if len(v[1:]) != values || values != 22 { - return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v) - } - - return V3Stats{ - Null: v[1], - GetAttr: v[2], - SetAttr: v[3], - Lookup: v[4], - Access: v[5], - ReadLink: v[6], - Read: v[7], - Write: v[8], - Create: v[9], - MkDir: v[10], - SymLink: v[11], - MkNod: v[12], - Remove: v[13], - RmDir: v[14], - Rename: v[15], - Link: v[16], - ReadDir: v[17], - ReadDirPlus: v[18], - FsStat: v[19], - FsInfo: v[20], - PathConf: v[21], - Commit: v[22], - }, nil -} - -func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { - values := int(v[0]) - if len(v[1:]) != values { - return ClientV4Stats{}, fmt.Errorf("invalid ClientV4Stats line %q", v) - } - - // This function currently supports mapping 59 NFS v4 client stats. Older - // kernels may emit fewer stats, so we must detect this and pad out the - // values to match the expected slice size. - if values < 59 { - newValues := make([]uint64, 60) - copy(newValues, v) - v = newValues - } - - return ClientV4Stats{ - Null: v[1], - Read: v[2], - Write: v[3], - Commit: v[4], - Open: v[5], - OpenConfirm: v[6], - OpenNoattr: v[7], - OpenDowngrade: v[8], - Close: v[9], - Setattr: v[10], - FsInfo: v[11], - Renew: v[12], - SetClientID: v[13], - SetClientIDConfirm: v[14], - Lock: v[15], - Lockt: v[16], - Locku: v[17], - Access: v[18], - Getattr: v[19], - Lookup: v[20], - LookupRoot: v[21], - Remove: v[22], - Rename: v[23], - Link: v[24], - Symlink: v[25], - Create: v[26], - Pathconf: v[27], - StatFs: v[28], - ReadLink: v[29], - ReadDir: v[30], - ServerCaps: v[31], - DelegReturn: v[32], - GetACL: v[33], - SetACL: v[34], - FsLocations: v[35], - ReleaseLockowner: v[36], - Secinfo: v[37], - FsidPresent: v[38], - ExchangeID: v[39], - CreateSession: v[40], - DestroySession: v[41], - Sequence: v[42], - GetLeaseTime: v[43], - ReclaimComplete: v[44], - LayoutGet: v[45], - GetDeviceInfo: v[46], - LayoutCommit: v[47], - LayoutReturn: v[48], - SecinfoNoName: v[49], - TestStateID: v[50], - FreeStateID: v[51], - GetDeviceList: v[52], - BindConnToSession: v[53], - DestroyClientID: v[54], - Seek: v[55], - Allocate: v[56], - DeAllocate: v[57], - LayoutStats: v[58], - Clone: v[59], - }, nil -} - -func parseServerV4Stats(v []uint64) (ServerV4Stats, error) { - values := int(v[0]) - if len(v[1:]) != values || values != 2 { - return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v) - } - - return ServerV4Stats{ - Null: v[1], - Compound: v[2], - }, nil -} - -func parseV4Ops(v []uint64) (V4Ops, error) { - values := int(v[0]) - if len(v[1:]) != values || values < 39 { - return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v) - } - - stats := V4Ops{ - Op0Unused: v[1], - Op1Unused: v[2], - Op2Future: v[3], - Access: v[4], - Close: v[5], - Commit: v[6], - Create: v[7], - DelegPurge: v[8], - DelegReturn: v[9], - GetAttr: v[10], - GetFH: v[11], - Link: v[12], - Lock: v[13], - Lockt: v[14], - Locku: v[15], - Lookup: v[16], - LookupRoot: v[17], - Nverify: v[18], - Open: v[19], - OpenAttr: v[20], - OpenConfirm: v[21], - OpenDgrd: v[22], - PutFH: v[23], - PutPubFH: v[24], - PutRootFH: v[25], - Read: v[26], - ReadDir: v[27], - ReadLink: v[28], - Remove: v[29], - Rename: v[30], - Renew: v[31], - RestoreFH: v[32], - SaveFH: v[33], - SecInfo: v[34], - SetAttr: v[35], - Verify: v[36], - Write: v[37], - RelLockOwner: v[38], - } - - return stats, nil -} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go deleted file mode 100644 index c0d3a5ad9b..0000000000 --- a/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package nfs - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/prometheus/procfs/internal/util" -) - -// ParseClientRPCStats returns stats read from /proc/net/rpc/nfs -func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) { - stats := &ClientRPCStats{} - - scanner := bufio.NewScanner(r) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(scanner.Text()) - // require at least - if len(parts) < 2 { - return nil, fmt.Errorf("invalid NFS metric line %q", line) - } - - values, err := util.ParseUint64s(parts[1:]) - if err != nil { - return nil, fmt.Errorf("error parsing NFS metric line: %s", err) - } - - switch metricLine := parts[0]; metricLine { - case "net": - stats.Network, err = parseNetwork(values) - case "rpc": - stats.ClientRPC, err = parseClientRPC(values) - case "proc2": - stats.V2Stats, err = parseV2Stats(values) - case "proc3": - stats.V3Stats, err = parseV3Stats(values) - case "proc4": - stats.ClientV4Stats, err = parseClientV4Stats(values) - default: - return nil, fmt.Errorf("unknown NFS metric line %q", metricLine) - } - if err != nil { - return nil, fmt.Errorf("errors parsing NFS metric line: %s", err) - } - } - - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning NFS file: %s", err) - } - - return stats, nil -} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go deleted file mode 100644 index 57bb4a3585..0000000000 --- a/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package nfs - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/prometheus/procfs/internal/util" -) - -// ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd -func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { - stats := &ServerRPCStats{} - - scanner := bufio.NewScanner(r) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(scanner.Text()) - // require at least - if len(parts) < 2 { - return nil, fmt.Errorf("invalid NFSd metric line %q", line) - } - label := parts[0] - - var values []uint64 - var err error - if label == "th" { - if len(parts) < 3 { - return nil, fmt.Errorf("invalid NFSd th metric line %q", line) - } - values, err = util.ParseUint64s(parts[1:3]) - } else { - values, err = util.ParseUint64s(parts[1:]) - } - if err != nil { - return nil, fmt.Errorf("error parsing NFSd metric line: %s", err) - } - - switch metricLine := parts[0]; metricLine { - case "rc": - stats.ReplyCache, err = parseReplyCache(values) - case "fh": - stats.FileHandles, err = parseFileHandles(values) - case "io": - stats.InputOutput, err = parseInputOutput(values) - case "th": - stats.Threads, err = parseThreads(values) - case "ra": - stats.ReadAheadCache, err = parseReadAheadCache(values) - case "net": - stats.Network, err = parseNetwork(values) - case "rpc": - stats.ServerRPC, err = parseServerRPC(values) - case "proc2": - stats.V2Stats, err = parseV2Stats(values) - case "proc3": - stats.V3Stats, err = parseV3Stats(values) - case "proc4": - stats.ServerV4Stats, err = parseServerV4Stats(values) - case "proc4ops": - stats.V4Ops, err = parseV4Ops(values) - default: - return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) - } - if err != nil { - return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err) - } - } - - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning NFSd file: %s", err) - } - - return stats, nil -} diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go deleted file mode 100644 index 7cf5b8acf9..0000000000 --- a/vendor/github.com/prometheus/procfs/proc.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "strconv" - "strings" -) - -// Proc provides information about a running process. -type Proc struct { - // The process ID. - PID int - - fs FS -} - -// Procs represents a list of Proc structs. -type Procs []Proc - -func (p Procs) Len() int { return len(p) } -func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } -func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } - -// Self returns a process for the current process read via /proc/self. -func Self() (Proc, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return Proc{}, err - } - return fs.Self() -} - -// NewProc returns a process for the given pid under /proc. -func NewProc(pid int) (Proc, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return Proc{}, err - } - return fs.NewProc(pid) -} - -// AllProcs returns a list of all currently available processes under /proc. -func AllProcs() (Procs, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return Procs{}, err - } - return fs.AllProcs() -} - -// Self returns a process for the current process. -func (fs FS) Self() (Proc, error) { - p, err := os.Readlink(fs.Path("self")) - if err != nil { - return Proc{}, err - } - pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1)) - if err != nil { - return Proc{}, err - } - return fs.NewProc(pid) -} - -// NewProc returns a process for the given pid. -func (fs FS) NewProc(pid int) (Proc, error) { - if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil { - return Proc{}, err - } - return Proc{PID: pid, fs: fs}, nil -} - -// AllProcs returns a list of all currently available processes. -func (fs FS) AllProcs() (Procs, error) { - d, err := os.Open(fs.Path()) - if err != nil { - return Procs{}, err - } - defer d.Close() - - names, err := d.Readdirnames(-1) - if err != nil { - return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err) - } - - p := Procs{} - for _, n := range names { - pid, err := strconv.ParseInt(n, 10, 64) - if err != nil { - continue - } - p = append(p, Proc{PID: int(pid), fs: fs}) - } - - return p, nil -} - -// CmdLine returns the command line of a process. -func (p Proc) CmdLine() ([]string, error) { - f, err := os.Open(p.path("cmdline")) - if err != nil { - return nil, err - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return nil, err - } - - if len(data) < 1 { - return []string{}, nil - } - - return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil -} - -// Comm returns the command name of a process. -func (p Proc) Comm() (string, error) { - f, err := os.Open(p.path("comm")) - if err != nil { - return "", err - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return "", err - } - - return strings.TrimSpace(string(data)), nil -} - -// Executable returns the absolute path of the executable command of a process. -func (p Proc) Executable() (string, error) { - exe, err := os.Readlink(p.path("exe")) - if os.IsNotExist(err) { - return "", nil - } - - return exe, err -} - -// FileDescriptors returns the currently open file descriptors of a process. -func (p Proc) FileDescriptors() ([]uintptr, error) { - names, err := p.fileDescriptors() - if err != nil { - return nil, err - } - - fds := make([]uintptr, len(names)) - for i, n := range names { - fd, err := strconv.ParseInt(n, 10, 32) - if err != nil { - return nil, fmt.Errorf("could not parse fd %s: %s", n, err) - } - fds[i] = uintptr(fd) - } - - return fds, nil -} - -// FileDescriptorTargets returns the targets of all file descriptors of a process. -// If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string. -func (p Proc) FileDescriptorTargets() ([]string, error) { - names, err := p.fileDescriptors() - if err != nil { - return nil, err - } - - targets := make([]string, len(names)) - - for i, name := range names { - target, err := os.Readlink(p.path("fd", name)) - if err == nil { - targets[i] = target - } - } - - return targets, nil -} - -// FileDescriptorsLen returns the number of currently open file descriptors of -// a process. -func (p Proc) FileDescriptorsLen() (int, error) { - fds, err := p.fileDescriptors() - if err != nil { - return 0, err - } - - return len(fds), nil -} - -// MountStats retrieves statistics and configuration for mount points in a -// process's namespace. -func (p Proc) MountStats() ([]*Mount, error) { - f, err := os.Open(p.path("mountstats")) - if err != nil { - return nil, err - } - defer f.Close() - - return parseMountStats(f) -} - -func (p Proc) fileDescriptors() ([]string, error) { - d, err := os.Open(p.path("fd")) - if err != nil { - return nil, err - } - defer d.Close() - - names, err := d.Readdirnames(-1) - if err != nil { - return nil, fmt.Errorf("could not read %s: %s", d.Name(), err) - } - - return names, nil -} - -func (p Proc) path(pa ...string) string { - return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) -} diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go deleted file mode 100644 index 0251c83bfe..0000000000 --- a/vendor/github.com/prometheus/procfs/proc_io.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "fmt" - "io/ioutil" - "os" -) - -// ProcIO models the content of /proc//io. -type ProcIO struct { - // Chars read. - RChar uint64 - // Chars written. - WChar uint64 - // Read syscalls. - SyscR uint64 - // Write syscalls. - SyscW uint64 - // Bytes read. - ReadBytes uint64 - // Bytes written. - WriteBytes uint64 - // Bytes written, but taking into account truncation. See - // Documentation/filesystems/proc.txt in the kernel sources for - // detailed explanation. - CancelledWriteBytes int64 -} - -// NewIO creates a new ProcIO instance from a given Proc instance. -func (p Proc) NewIO() (ProcIO, error) { - pio := ProcIO{} - - f, err := os.Open(p.path("io")) - if err != nil { - return pio, err - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return pio, err - } - - ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + - "read_bytes: %d\nwrite_bytes: %d\n" + - "cancelled_write_bytes: %d\n" - - _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, - &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) - - return pio, err -} diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go deleted file mode 100644 index f04ba6fda8..0000000000 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "fmt" - "os" - "regexp" - "strconv" -) - -// ProcLimits represents the soft limits for each of the process's resource -// limits. For more information see getrlimit(2): -// http://man7.org/linux/man-pages/man2/getrlimit.2.html. -type ProcLimits struct { - // CPU time limit in seconds. - CPUTime int64 - // Maximum size of files that the process may create. - FileSize int64 - // Maximum size of the process's data segment (initialized data, - // uninitialized data, and heap). - DataSize int64 - // Maximum size of the process stack in bytes. - StackSize int64 - // Maximum size of a core file. - CoreFileSize int64 - // Limit of the process's resident set in pages. - ResidentSet int64 - // Maximum number of processes that can be created for the real user ID of - // the calling process. - Processes int64 - // Value one greater than the maximum file descriptor number that can be - // opened by this process. - OpenFiles int64 - // Maximum number of bytes of memory that may be locked into RAM. - LockedMemory int64 - // Maximum size of the process's virtual memory address space in bytes. - AddressSpace int64 - // Limit on the combined number of flock(2) locks and fcntl(2) leases that - // this process may establish. - FileLocks int64 - // Limit of signals that may be queued for the real user ID of the calling - // process. - PendingSignals int64 - // Limit on the number of bytes that can be allocated for POSIX message - // queues for the real user ID of the calling process. - MsqqueueSize int64 - // Limit of the nice priority set using setpriority(2) or nice(2). - NicePriority int64 - // Limit of the real-time priority set using sched_setscheduler(2) or - // sched_setparam(2). - RealtimePriority int64 - // Limit (in microseconds) on the amount of CPU time that a process - // scheduled under a real-time scheduling policy may consume without making - // a blocking system call. - RealtimeTimeout int64 -} - -const ( - limitsFields = 3 - limitsUnlimited = "unlimited" -) - -var ( - limitsDelimiter = regexp.MustCompile(" +") -) - -// NewLimits returns the current soft limits of the process. -func (p Proc) NewLimits() (ProcLimits, error) { - f, err := os.Open(p.path("limits")) - if err != nil { - return ProcLimits{}, err - } - defer f.Close() - - var ( - l = ProcLimits{} - s = bufio.NewScanner(f) - ) - for s.Scan() { - fields := limitsDelimiter.Split(s.Text(), limitsFields) - if len(fields) != limitsFields { - return ProcLimits{}, fmt.Errorf( - "couldn't parse %s line %s", f.Name(), s.Text()) - } - - switch fields[0] { - case "Max cpu time": - l.CPUTime, err = parseInt(fields[1]) - case "Max file size": - l.FileSize, err = parseInt(fields[1]) - case "Max data size": - l.DataSize, err = parseInt(fields[1]) - case "Max stack size": - l.StackSize, err = parseInt(fields[1]) - case "Max core file size": - l.CoreFileSize, err = parseInt(fields[1]) - case "Max resident set": - l.ResidentSet, err = parseInt(fields[1]) - case "Max processes": - l.Processes, err = parseInt(fields[1]) - case "Max open files": - l.OpenFiles, err = parseInt(fields[1]) - case "Max locked memory": - l.LockedMemory, err = parseInt(fields[1]) - case "Max address space": - l.AddressSpace, err = parseInt(fields[1]) - case "Max file locks": - l.FileLocks, err = parseInt(fields[1]) - case "Max pending signals": - l.PendingSignals, err = parseInt(fields[1]) - case "Max msgqueue size": - l.MsqqueueSize, err = parseInt(fields[1]) - case "Max nice priority": - l.NicePriority, err = parseInt(fields[1]) - case "Max realtime priority": - l.RealtimePriority, err = parseInt(fields[1]) - case "Max realtime timeout": - l.RealtimeTimeout, err = parseInt(fields[1]) - } - if err != nil { - return ProcLimits{}, err - } - } - - return l, s.Err() -} - -func parseInt(s string) (int64, error) { - if s == limitsUnlimited { - return -1, nil - } - i, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) - } - return i, nil -} diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go deleted file mode 100644 index d06c26ebad..0000000000 --- a/vendor/github.com/prometheus/procfs/proc_ns.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "fmt" - "os" - "strconv" - "strings" -) - -// Namespace represents a single namespace of a process. -type Namespace struct { - Type string // Namespace type. - Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match. -} - -// Namespaces contains all of the namespaces that the process is contained in. -type Namespaces map[string]Namespace - -// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the -// process is a member. -func (p Proc) NewNamespaces() (Namespaces, error) { - d, err := os.Open(p.path("ns")) - if err != nil { - return nil, err - } - defer d.Close() - - names, err := d.Readdirnames(-1) - if err != nil { - return nil, fmt.Errorf("failed to read contents of ns dir: %v", err) - } - - ns := make(Namespaces, len(names)) - for _, name := range names { - target, err := os.Readlink(p.path("ns", name)) - if err != nil { - return nil, err - } - - fields := strings.SplitN(target, ":", 2) - if len(fields) != 2 { - return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target) - } - - typ := fields[0] - inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) - if err != nil { - return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err) - } - - ns[name] = Namespace{typ, uint32(inode)} - } - - return ns, nil -} diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go deleted file mode 100644 index 3cf2a9f18f..0000000000 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" -) - -// Originally, this USER_HZ value was dynamically retrieved via a sysconf call -// which required cgo. However, that caused a lot of problems regarding -// cross-compilation. Alternatives such as running a binary to determine the -// value, or trying to derive it in some other way were all problematic. After -// much research it was determined that USER_HZ is actually hardcoded to 100 on -// all Go-supported platforms as of the time of this writing. This is why we -// decided to hardcode it here as well. It is not impossible that there could -// be systems with exceptions, but they should be very exotic edge cases, and -// in that case, the worst outcome will be two misreported metrics. -// -// See also the following discussions: -// -// - https://github.com/prometheus/node_exporter/issues/52 -// - https://github.com/prometheus/procfs/pull/2 -// - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue -const userHZ = 100 - -// ProcStat provides status information about the process, -// read from /proc/[pid]/stat. -type ProcStat struct { - // The process ID. - PID int - // The filename of the executable. - Comm string - // The process state. - State string - // The PID of the parent of this process. - PPID int - // The process group ID of the process. - PGRP int - // The session ID of the process. - Session int - // The controlling terminal of the process. - TTY int - // The ID of the foreground process group of the controlling terminal of - // the process. - TPGID int - // The kernel flags word of the process. - Flags uint - // The number of minor faults the process has made which have not required - // loading a memory page from disk. - MinFlt uint - // The number of minor faults that the process's waited-for children have - // made. - CMinFlt uint - // The number of major faults the process has made which have required - // loading a memory page from disk. - MajFlt uint - // The number of major faults that the process's waited-for children have - // made. - CMajFlt uint - // Amount of time that this process has been scheduled in user mode, - // measured in clock ticks. - UTime uint - // Amount of time that this process has been scheduled in kernel mode, - // measured in clock ticks. - STime uint - // Amount of time that this process's waited-for children have been - // scheduled in user mode, measured in clock ticks. - CUTime uint - // Amount of time that this process's waited-for children have been - // scheduled in kernel mode, measured in clock ticks. - CSTime uint - // For processes running a real-time scheduling policy, this is the negated - // scheduling priority, minus one. - Priority int - // The nice value, a value in the range 19 (low priority) to -20 (high - // priority). - Nice int - // Number of threads in this process. - NumThreads int - // The time the process started after system boot, the value is expressed - // in clock ticks. - Starttime uint64 - // Virtual memory size in bytes. - VSize int - // Resident set size in pages. - RSS int - - fs FS -} - -// NewStat returns the current status information of the process. -func (p Proc) NewStat() (ProcStat, error) { - f, err := os.Open(p.path("stat")) - if err != nil { - return ProcStat{}, err - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return ProcStat{}, err - } - - var ( - ignore int - - s = ProcStat{PID: p.PID, fs: p.fs} - l = bytes.Index(data, []byte("(")) - r = bytes.LastIndex(data, []byte(")")) - ) - - if l < 0 || r < 0 { - return ProcStat{}, fmt.Errorf( - "unexpected format, couldn't extract comm: %s", - data, - ) - } - - s.Comm = string(data[l+1 : r]) - _, err = fmt.Fscan( - bytes.NewBuffer(data[r+2:]), - &s.State, - &s.PPID, - &s.PGRP, - &s.Session, - &s.TTY, - &s.TPGID, - &s.Flags, - &s.MinFlt, - &s.CMinFlt, - &s.MajFlt, - &s.CMajFlt, - &s.UTime, - &s.STime, - &s.CUTime, - &s.CSTime, - &s.Priority, - &s.Nice, - &s.NumThreads, - &ignore, - &s.Starttime, - &s.VSize, - &s.RSS, - ) - if err != nil { - return ProcStat{}, err - } - - return s, nil -} - -// VirtualMemory returns the virtual memory size in bytes. -func (s ProcStat) VirtualMemory() int { - return s.VSize -} - -// ResidentMemory returns the resident memory size in bytes. -func (s ProcStat) ResidentMemory() int { - return s.RSS * os.Getpagesize() -} - -// StartTime returns the unix timestamp of the process in seconds. -func (s ProcStat) StartTime() (float64, error) { - stat, err := s.fs.NewStat() - if err != nil { - return 0, err - } - return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil -} - -// CPUTime returns the total CPU user and system time in seconds. -func (s ProcStat) CPUTime() float64 { - return float64(s.UTime+s.STime) / userHZ -} diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go deleted file mode 100644 index 61eb6b0e3c..0000000000 --- a/vendor/github.com/prometheus/procfs/stat.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "fmt" - "io" - "os" - "strconv" - "strings" -) - -// CPUStat shows how much time the cpu spend in various stages. -type CPUStat struct { - User float64 - Nice float64 - System float64 - Idle float64 - Iowait float64 - IRQ float64 - SoftIRQ float64 - Steal float64 - Guest float64 - GuestNice float64 -} - -// SoftIRQStat represent the softirq statistics as exported in the procfs stat file. -// A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html -// It is possible to get per-cpu stats by reading /proc/softirqs -type SoftIRQStat struct { - Hi uint64 - Timer uint64 - NetTx uint64 - NetRx uint64 - Block uint64 - BlockIoPoll uint64 - Tasklet uint64 - Sched uint64 - Hrtimer uint64 - Rcu uint64 -} - -// Stat represents kernel/system statistics. -type Stat struct { - // Boot time in seconds since the Epoch. - BootTime uint64 - // Summed up cpu statistics. - CPUTotal CPUStat - // Per-CPU statistics. - CPU []CPUStat - // Number of times interrupts were handled, which contains numbered and unnumbered IRQs. - IRQTotal uint64 - // Number of times a numbered IRQ was triggered. - IRQ []uint64 - // Number of times a context switch happened. - ContextSwitches uint64 - // Number of times a process was created. - ProcessCreated uint64 - // Number of processes currently running. - ProcessesRunning uint64 - // Number of processes currently blocked (waiting for IO). - ProcessesBlocked uint64 - // Number of times a softirq was scheduled. - SoftIRQTotal uint64 - // Detailed softirq statistics. - SoftIRQ SoftIRQStat -} - -// NewStat returns kernel/system statistics read from /proc/stat. -func NewStat() (Stat, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return Stat{}, err - } - - return fs.NewStat() -} - -// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum). -func parseCPUStat(line string) (CPUStat, int64, error) { - cpuStat := CPUStat{} - var cpu string - - count, err := fmt.Sscanf(line, "%s %f %f %f %f %f %f %f %f %f %f", - &cpu, - &cpuStat.User, &cpuStat.Nice, &cpuStat.System, &cpuStat.Idle, - &cpuStat.Iowait, &cpuStat.IRQ, &cpuStat.SoftIRQ, &cpuStat.Steal, - &cpuStat.Guest, &cpuStat.GuestNice) - - if err != nil && err != io.EOF { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): %s", line, err) - } - if count == 0 { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): 0 elements parsed", line) - } - - cpuStat.User /= userHZ - cpuStat.Nice /= userHZ - cpuStat.System /= userHZ - cpuStat.Idle /= userHZ - cpuStat.Iowait /= userHZ - cpuStat.IRQ /= userHZ - cpuStat.SoftIRQ /= userHZ - cpuStat.Steal /= userHZ - cpuStat.Guest /= userHZ - cpuStat.GuestNice /= userHZ - - if cpu == "cpu" { - return cpuStat, -1, nil - } - - cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) - if err != nil { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu/cpuid): %s", line, err) - } - - return cpuStat, cpuID, nil -} - -// Parse a softirq line. -func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { - softIRQStat := SoftIRQStat{} - var total uint64 - var prefix string - - _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d", - &prefix, &total, - &softIRQStat.Hi, &softIRQStat.Timer, &softIRQStat.NetTx, &softIRQStat.NetRx, - &softIRQStat.Block, &softIRQStat.BlockIoPoll, - &softIRQStat.Tasklet, &softIRQStat.Sched, - &softIRQStat.Hrtimer, &softIRQStat.Rcu) - - if err != nil { - return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %s (softirq): %s", line, err) - } - - return softIRQStat, total, nil -} - -// NewStat returns an information about current kernel/system statistics. -func (fs FS) NewStat() (Stat, error) { - // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt - - f, err := os.Open(fs.Path("stat")) - if err != nil { - return Stat{}, err - } - defer f.Close() - - stat := Stat{} - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(scanner.Text()) - // require at least - if len(parts) < 2 { - continue - } - switch { - case parts[0] == "btime": - if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (btime): %s", parts[1], err) - } - case parts[0] == "intr": - if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (intr): %s", parts[1], err) - } - numberedIRQs := parts[2:] - stat.IRQ = make([]uint64, len(numberedIRQs)) - for i, count := range numberedIRQs { - if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (intr%d): %s", count, i, err) - } - } - case parts[0] == "ctxt": - if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (ctxt): %s", parts[1], err) - } - case parts[0] == "processes": - if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (processes): %s", parts[1], err) - } - case parts[0] == "procs_running": - if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (procs_running): %s", parts[1], err) - } - case parts[0] == "procs_blocked": - if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s (procs_blocked): %s", parts[1], err) - } - case parts[0] == "softirq": - softIRQStats, total, err := parseSoftIRQStat(line) - if err != nil { - return Stat{}, err - } - stat.SoftIRQTotal = total - stat.SoftIRQ = softIRQStats - case strings.HasPrefix(parts[0], "cpu"): - cpuStat, cpuID, err := parseCPUStat(line) - if err != nil { - return Stat{}, err - } - if cpuID == -1 { - stat.CPUTotal = cpuStat - } else { - for int64(len(stat.CPU)) <= cpuID { - stat.CPU = append(stat.CPU, CPUStat{}) - } - stat.CPU[cpuID] = cpuStat - } - } - } - - if err := scanner.Err(); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err) - } - - return stat, nil -} diff --git a/vendor/github.com/prometheus/procfs/xfrm.go b/vendor/github.com/prometheus/procfs/xfrm.go deleted file mode 100644 index ffe9df50d6..0000000000 --- a/vendor/github.com/prometheus/procfs/xfrm.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2017 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "fmt" - "os" - "strconv" - "strings" -) - -// XfrmStat models the contents of /proc/net/xfrm_stat. -type XfrmStat struct { - // All errors which are not matched by other - XfrmInError int - // No buffer is left - XfrmInBufferError int - // Header Error - XfrmInHdrError int - // No state found - // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong - XfrmInNoStates int - // Transformation protocol specific error - // e.g. SA Key is wrong - XfrmInStateProtoError int - // Transformation mode specific error - XfrmInStateModeError int - // Sequence error - // e.g. sequence number is out of window - XfrmInStateSeqError int - // State is expired - XfrmInStateExpired int - // State has mismatch option - // e.g. UDP encapsulation type is mismatched - XfrmInStateMismatch int - // State is invalid - XfrmInStateInvalid int - // No matching template for states - // e.g. Inbound SAs are correct but SP rule is wrong - XfrmInTmplMismatch int - // No policy is found for states - // e.g. Inbound SAs are correct but no SP is found - XfrmInNoPols int - // Policy discards - XfrmInPolBlock int - // Policy error - XfrmInPolError int - // All errors which are not matched by others - XfrmOutError int - // Bundle generation error - XfrmOutBundleGenError int - // Bundle check error - XfrmOutBundleCheckError int - // No state was found - XfrmOutNoStates int - // Transformation protocol specific error - XfrmOutStateProtoError int - // Transportation mode specific error - XfrmOutStateModeError int - // Sequence error - // i.e sequence number overflow - XfrmOutStateSeqError int - // State is expired - XfrmOutStateExpired int - // Policy discads - XfrmOutPolBlock int - // Policy is dead - XfrmOutPolDead int - // Policy Error - XfrmOutPolError int - XfrmFwdHdrError int - XfrmOutStateInvalid int - XfrmAcquireError int -} - -// NewXfrmStat reads the xfrm_stat statistics. -func NewXfrmStat() (XfrmStat, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return XfrmStat{}, err - } - - return fs.NewXfrmStat() -} - -// NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem. -func (fs FS) NewXfrmStat() (XfrmStat, error) { - file, err := os.Open(fs.Path("net/xfrm_stat")) - if err != nil { - return XfrmStat{}, err - } - defer file.Close() - - var ( - x = XfrmStat{} - s = bufio.NewScanner(file) - ) - - for s.Scan() { - fields := strings.Fields(s.Text()) - - if len(fields) != 2 { - return XfrmStat{}, fmt.Errorf( - "couldnt parse %s line %s", file.Name(), s.Text()) - } - - name := fields[0] - value, err := strconv.Atoi(fields[1]) - if err != nil { - return XfrmStat{}, err - } - - switch name { - case "XfrmInError": - x.XfrmInError = value - case "XfrmInBufferError": - x.XfrmInBufferError = value - case "XfrmInHdrError": - x.XfrmInHdrError = value - case "XfrmInNoStates": - x.XfrmInNoStates = value - case "XfrmInStateProtoError": - x.XfrmInStateProtoError = value - case "XfrmInStateModeError": - x.XfrmInStateModeError = value - case "XfrmInStateSeqError": - x.XfrmInStateSeqError = value - case "XfrmInStateExpired": - x.XfrmInStateExpired = value - case "XfrmInStateInvalid": - x.XfrmInStateInvalid = value - case "XfrmInTmplMismatch": - x.XfrmInTmplMismatch = value - case "XfrmInNoPols": - x.XfrmInNoPols = value - case "XfrmInPolBlock": - x.XfrmInPolBlock = value - case "XfrmInPolError": - x.XfrmInPolError = value - case "XfrmOutError": - x.XfrmOutError = value - case "XfrmInStateMismatch": - x.XfrmInStateMismatch = value - case "XfrmOutBundleGenError": - x.XfrmOutBundleGenError = value - case "XfrmOutBundleCheckError": - x.XfrmOutBundleCheckError = value - case "XfrmOutNoStates": - x.XfrmOutNoStates = value - case "XfrmOutStateProtoError": - x.XfrmOutStateProtoError = value - case "XfrmOutStateModeError": - x.XfrmOutStateModeError = value - case "XfrmOutStateSeqError": - x.XfrmOutStateSeqError = value - case "XfrmOutStateExpired": - x.XfrmOutStateExpired = value - case "XfrmOutPolBlock": - x.XfrmOutPolBlock = value - case "XfrmOutPolDead": - x.XfrmOutPolDead = value - case "XfrmOutPolError": - x.XfrmOutPolError = value - case "XfrmFwdHdrError": - x.XfrmFwdHdrError = value - case "XfrmOutStateInvalid": - x.XfrmOutStateInvalid = value - case "XfrmAcquireError": - x.XfrmAcquireError = value - } - - } - - return x, s.Err() -} diff --git a/vendor/github.com/prometheus/procfs/xfs/parse.go b/vendor/github.com/prometheus/procfs/xfs/parse.go deleted file mode 100644 index 2bc0ef3427..0000000000 --- a/vendor/github.com/prometheus/procfs/xfs/parse.go +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package xfs - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/prometheus/procfs/internal/util" -) - -// ParseStats parses a Stats from an input io.Reader, using the format -// found in /proc/fs/xfs/stat. -func ParseStats(r io.Reader) (*Stats, error) { - const ( - // Fields parsed into stats structures. - fieldExtentAlloc = "extent_alloc" - fieldAbt = "abt" - fieldBlkMap = "blk_map" - fieldBmbt = "bmbt" - fieldDir = "dir" - fieldTrans = "trans" - fieldIg = "ig" - fieldLog = "log" - fieldRw = "rw" - fieldAttr = "attr" - fieldIcluster = "icluster" - fieldVnodes = "vnodes" - fieldBuf = "buf" - fieldXpc = "xpc" - - // Unimplemented at this time due to lack of documentation. - fieldPushAil = "push_ail" - fieldXstrat = "xstrat" - fieldAbtb2 = "abtb2" - fieldAbtc2 = "abtc2" - fieldBmbt2 = "bmbt2" - fieldIbt2 = "ibt2" - fieldFibt2 = "fibt2" - fieldQm = "qm" - fieldDebug = "debug" - ) - - var xfss Stats - - s := bufio.NewScanner(r) - for s.Scan() { - // Expect at least a string label and a single integer value, ex: - // - abt 0 - // - rw 1 2 - ss := strings.Fields(string(s.Bytes())) - if len(ss) < 2 { - continue - } - label := ss[0] - - // Extended precision counters are uint64 values. - if label == fieldXpc { - us, err := util.ParseUint64s(ss[1:]) - if err != nil { - return nil, err - } - - xfss.ExtendedPrecision, err = extendedPrecisionStats(us) - if err != nil { - return nil, err - } - - continue - } - - // All other counters are uint32 values. - us, err := util.ParseUint32s(ss[1:]) - if err != nil { - return nil, err - } - - switch label { - case fieldExtentAlloc: - xfss.ExtentAllocation, err = extentAllocationStats(us) - case fieldAbt: - xfss.AllocationBTree, err = btreeStats(us) - case fieldBlkMap: - xfss.BlockMapping, err = blockMappingStats(us) - case fieldBmbt: - xfss.BlockMapBTree, err = btreeStats(us) - case fieldDir: - xfss.DirectoryOperation, err = directoryOperationStats(us) - case fieldTrans: - xfss.Transaction, err = transactionStats(us) - case fieldIg: - xfss.InodeOperation, err = inodeOperationStats(us) - case fieldLog: - xfss.LogOperation, err = logOperationStats(us) - case fieldRw: - xfss.ReadWrite, err = readWriteStats(us) - case fieldAttr: - xfss.AttributeOperation, err = attributeOperationStats(us) - case fieldIcluster: - xfss.InodeClustering, err = inodeClusteringStats(us) - case fieldVnodes: - xfss.Vnode, err = vnodeStats(us) - case fieldBuf: - xfss.Buffer, err = bufferStats(us) - } - if err != nil { - return nil, err - } - } - - return &xfss, s.Err() -} - -// extentAllocationStats builds an ExtentAllocationStats from a slice of uint32s. -func extentAllocationStats(us []uint32) (ExtentAllocationStats, error) { - if l := len(us); l != 4 { - return ExtentAllocationStats{}, fmt.Errorf("incorrect number of values for XFS extent allocation stats: %d", l) - } - - return ExtentAllocationStats{ - ExtentsAllocated: us[0], - BlocksAllocated: us[1], - ExtentsFreed: us[2], - BlocksFreed: us[3], - }, nil -} - -// btreeStats builds a BTreeStats from a slice of uint32s. -func btreeStats(us []uint32) (BTreeStats, error) { - if l := len(us); l != 4 { - return BTreeStats{}, fmt.Errorf("incorrect number of values for XFS btree stats: %d", l) - } - - return BTreeStats{ - Lookups: us[0], - Compares: us[1], - RecordsInserted: us[2], - RecordsDeleted: us[3], - }, nil -} - -// BlockMappingStat builds a BlockMappingStats from a slice of uint32s. -func blockMappingStats(us []uint32) (BlockMappingStats, error) { - if l := len(us); l != 7 { - return BlockMappingStats{}, fmt.Errorf("incorrect number of values for XFS block mapping stats: %d", l) - } - - return BlockMappingStats{ - Reads: us[0], - Writes: us[1], - Unmaps: us[2], - ExtentListInsertions: us[3], - ExtentListDeletions: us[4], - ExtentListLookups: us[5], - ExtentListCompares: us[6], - }, nil -} - -// DirectoryOperationStats builds a DirectoryOperationStats from a slice of uint32s. -func directoryOperationStats(us []uint32) (DirectoryOperationStats, error) { - if l := len(us); l != 4 { - return DirectoryOperationStats{}, fmt.Errorf("incorrect number of values for XFS directory operation stats: %d", l) - } - - return DirectoryOperationStats{ - Lookups: us[0], - Creates: us[1], - Removes: us[2], - Getdents: us[3], - }, nil -} - -// TransactionStats builds a TransactionStats from a slice of uint32s. -func transactionStats(us []uint32) (TransactionStats, error) { - if l := len(us); l != 3 { - return TransactionStats{}, fmt.Errorf("incorrect number of values for XFS transaction stats: %d", l) - } - - return TransactionStats{ - Sync: us[0], - Async: us[1], - Empty: us[2], - }, nil -} - -// InodeOperationStats builds an InodeOperationStats from a slice of uint32s. -func inodeOperationStats(us []uint32) (InodeOperationStats, error) { - if l := len(us); l != 7 { - return InodeOperationStats{}, fmt.Errorf("incorrect number of values for XFS inode operation stats: %d", l) - } - - return InodeOperationStats{ - Attempts: us[0], - Found: us[1], - Recycle: us[2], - Missed: us[3], - Duplicate: us[4], - Reclaims: us[5], - AttributeChange: us[6], - }, nil -} - -// LogOperationStats builds a LogOperationStats from a slice of uint32s. -func logOperationStats(us []uint32) (LogOperationStats, error) { - if l := len(us); l != 5 { - return LogOperationStats{}, fmt.Errorf("incorrect number of values for XFS log operation stats: %d", l) - } - - return LogOperationStats{ - Writes: us[0], - Blocks: us[1], - NoInternalBuffers: us[2], - Force: us[3], - ForceSleep: us[4], - }, nil -} - -// ReadWriteStats builds a ReadWriteStats from a slice of uint32s. -func readWriteStats(us []uint32) (ReadWriteStats, error) { - if l := len(us); l != 2 { - return ReadWriteStats{}, fmt.Errorf("incorrect number of values for XFS read write stats: %d", l) - } - - return ReadWriteStats{ - Read: us[0], - Write: us[1], - }, nil -} - -// AttributeOperationStats builds an AttributeOperationStats from a slice of uint32s. -func attributeOperationStats(us []uint32) (AttributeOperationStats, error) { - if l := len(us); l != 4 { - return AttributeOperationStats{}, fmt.Errorf("incorrect number of values for XFS attribute operation stats: %d", l) - } - - return AttributeOperationStats{ - Get: us[0], - Set: us[1], - Remove: us[2], - List: us[3], - }, nil -} - -// InodeClusteringStats builds an InodeClusteringStats from a slice of uint32s. -func inodeClusteringStats(us []uint32) (InodeClusteringStats, error) { - if l := len(us); l != 3 { - return InodeClusteringStats{}, fmt.Errorf("incorrect number of values for XFS inode clustering stats: %d", l) - } - - return InodeClusteringStats{ - Iflush: us[0], - Flush: us[1], - FlushInode: us[2], - }, nil -} - -// VnodeStats builds a VnodeStats from a slice of uint32s. -func vnodeStats(us []uint32) (VnodeStats, error) { - // The attribute "Free" appears to not be available on older XFS - // stats versions. Therefore, 7 or 8 elements may appear in - // this slice. - l := len(us) - if l != 7 && l != 8 { - return VnodeStats{}, fmt.Errorf("incorrect number of values for XFS vnode stats: %d", l) - } - - s := VnodeStats{ - Active: us[0], - Allocate: us[1], - Get: us[2], - Hold: us[3], - Release: us[4], - Reclaim: us[5], - Remove: us[6], - } - - // Skip adding free, unless it is present. The zero value will - // be used in place of an actual count. - if l == 7 { - return s, nil - } - - s.Free = us[7] - return s, nil -} - -// BufferStats builds a BufferStats from a slice of uint32s. -func bufferStats(us []uint32) (BufferStats, error) { - if l := len(us); l != 9 { - return BufferStats{}, fmt.Errorf("incorrect number of values for XFS buffer stats: %d", l) - } - - return BufferStats{ - Get: us[0], - Create: us[1], - GetLocked: us[2], - GetLockedWaited: us[3], - BusyLocked: us[4], - MissLocked: us[5], - PageRetries: us[6], - PageFound: us[7], - GetRead: us[8], - }, nil -} - -// ExtendedPrecisionStats builds an ExtendedPrecisionStats from a slice of uint32s. -func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) { - if l := len(us); l != 3 { - return ExtendedPrecisionStats{}, fmt.Errorf("incorrect number of values for XFS extended precision stats: %d", l) - } - - return ExtendedPrecisionStats{ - FlushBytes: us[0], - WriteBytes: us[1], - ReadBytes: us[2], - }, nil -} diff --git a/vendor/github.com/prometheus/procfs/xfs/xfs.go b/vendor/github.com/prometheus/procfs/xfs/xfs.go deleted file mode 100644 index d86794b7ca..0000000000 --- a/vendor/github.com/prometheus/procfs/xfs/xfs.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package xfs provides access to statistics exposed by the XFS filesystem. -package xfs - -// Stats contains XFS filesystem runtime statistics, parsed from -// /proc/fs/xfs/stat. -// -// The names and meanings of each statistic were taken from -// http://xfs.org/index.php/Runtime_Stats and xfs_stats.h in the Linux -// kernel source. Most counters are uint32s (same data types used in -// xfs_stats.h), but some of the "extended precision stats" are uint64s. -type Stats struct { - // The name of the filesystem used to source these statistics. - // If empty, this indicates aggregated statistics for all XFS - // filesystems on the host. - Name string - - ExtentAllocation ExtentAllocationStats - AllocationBTree BTreeStats - BlockMapping BlockMappingStats - BlockMapBTree BTreeStats - DirectoryOperation DirectoryOperationStats - Transaction TransactionStats - InodeOperation InodeOperationStats - LogOperation LogOperationStats - ReadWrite ReadWriteStats - AttributeOperation AttributeOperationStats - InodeClustering InodeClusteringStats - Vnode VnodeStats - Buffer BufferStats - ExtendedPrecision ExtendedPrecisionStats -} - -// ExtentAllocationStats contains statistics regarding XFS extent allocations. -type ExtentAllocationStats struct { - ExtentsAllocated uint32 - BlocksAllocated uint32 - ExtentsFreed uint32 - BlocksFreed uint32 -} - -// BTreeStats contains statistics regarding an XFS internal B-tree. -type BTreeStats struct { - Lookups uint32 - Compares uint32 - RecordsInserted uint32 - RecordsDeleted uint32 -} - -// BlockMappingStats contains statistics regarding XFS block maps. -type BlockMappingStats struct { - Reads uint32 - Writes uint32 - Unmaps uint32 - ExtentListInsertions uint32 - ExtentListDeletions uint32 - ExtentListLookups uint32 - ExtentListCompares uint32 -} - -// DirectoryOperationStats contains statistics regarding XFS directory entries. -type DirectoryOperationStats struct { - Lookups uint32 - Creates uint32 - Removes uint32 - Getdents uint32 -} - -// TransactionStats contains statistics regarding XFS metadata transactions. -type TransactionStats struct { - Sync uint32 - Async uint32 - Empty uint32 -} - -// InodeOperationStats contains statistics regarding XFS inode operations. -type InodeOperationStats struct { - Attempts uint32 - Found uint32 - Recycle uint32 - Missed uint32 - Duplicate uint32 - Reclaims uint32 - AttributeChange uint32 -} - -// LogOperationStats contains statistics regarding the XFS log buffer. -type LogOperationStats struct { - Writes uint32 - Blocks uint32 - NoInternalBuffers uint32 - Force uint32 - ForceSleep uint32 -} - -// ReadWriteStats contains statistics regarding the number of read and write -// system calls for XFS filesystems. -type ReadWriteStats struct { - Read uint32 - Write uint32 -} - -// AttributeOperationStats contains statistics regarding manipulation of -// XFS extended file attributes. -type AttributeOperationStats struct { - Get uint32 - Set uint32 - Remove uint32 - List uint32 -} - -// InodeClusteringStats contains statistics regarding XFS inode clustering -// operations. -type InodeClusteringStats struct { - Iflush uint32 - Flush uint32 - FlushInode uint32 -} - -// VnodeStats contains statistics regarding XFS vnode operations. -type VnodeStats struct { - Active uint32 - Allocate uint32 - Get uint32 - Hold uint32 - Release uint32 - Reclaim uint32 - Remove uint32 - Free uint32 -} - -// BufferStats contains statistics regarding XFS read/write I/O buffers. -type BufferStats struct { - Get uint32 - Create uint32 - GetLocked uint32 - GetLockedWaited uint32 - BusyLocked uint32 - MissLocked uint32 - PageRetries uint32 - PageFound uint32 - GetRead uint32 -} - -// ExtendedPrecisionStats contains high precision counters used to track the -// total number of bytes read, written, or flushed, during XFS operations. -type ExtendedPrecisionStats struct { - FlushBytes uint64 - WriteBytes uint64 - ReadBytes uint64 -} diff --git a/vendor/github.com/tchap/go-patricia/AUTHORS b/vendor/github.com/tchap/go-patricia/AUTHORS deleted file mode 100644 index e640b0bf51..0000000000 --- a/vendor/github.com/tchap/go-patricia/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -This is the complete list of go-patricia copyright holders: - -Ondřej Kupka diff --git a/vendor/github.com/tchap/go-patricia/LICENSE b/vendor/github.com/tchap/go-patricia/LICENSE deleted file mode 100644 index e50d398e98..0000000000 --- a/vendor/github.com/tchap/go-patricia/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 The AUTHORS - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/tchap/go-patricia/patricia/children.go b/vendor/github.com/tchap/go-patricia/patricia/children.go deleted file mode 100644 index a5677c3352..0000000000 --- a/vendor/github.com/tchap/go-patricia/patricia/children.go +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2014 The go-patricia AUTHORS -// -// Use of this source code is governed by The MIT License -// that can be found in the LICENSE file. - -package patricia - -import ( - "fmt" - "io" - "sort" -) - -type childList interface { - length() int - head() *Trie - add(child *Trie) childList - remove(b byte) - replace(b byte, child *Trie) - next(b byte) *Trie - walk(prefix *Prefix, visitor VisitorFunc) error - print(w io.Writer, indent int) - total() int -} - -type tries []*Trie - -func (t tries) Len() int { - return len(t) -} - -func (t tries) Less(i, j int) bool { - strings := sort.StringSlice{string(t[i].prefix), string(t[j].prefix)} - return strings.Less(0, 1) -} - -func (t tries) Swap(i, j int) { - t[i], t[j] = t[j], t[i] -} - -type sparseChildList struct { - children tries -} - -func newSparseChildList(maxChildrenPerSparseNode int) childList { - return &sparseChildList{ - children: make(tries, 0, maxChildrenPerSparseNode), - } -} - -func (list *sparseChildList) length() int { - return len(list.children) -} - -func (list *sparseChildList) head() *Trie { - return list.children[0] -} - -func (list *sparseChildList) add(child *Trie) childList { - // Search for an empty spot and insert the child if possible. - if len(list.children) != cap(list.children) { - list.children = append(list.children, child) - return list - } - - // Otherwise we have to transform to the dense list type. - return newDenseChildList(list, child) -} - -func (list *sparseChildList) remove(b byte) { - for i, node := range list.children { - if node.prefix[0] == b { - list.children[i] = list.children[len(list.children)-1] - list.children[len(list.children)-1] = nil - list.children = list.children[:len(list.children)-1] - return - } - } - - // This is not supposed to be reached. - panic("removing non-existent child") -} - -func (list *sparseChildList) replace(b byte, child *Trie) { - // Make a consistency check. - if p0 := child.prefix[0]; p0 != b { - panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b)) - } - - // Seek the child and replace it. - for i, node := range list.children { - if node.prefix[0] == b { - list.children[i] = child - return - } - } -} - -func (list *sparseChildList) next(b byte) *Trie { - for _, child := range list.children { - if child.prefix[0] == b { - return child - } - } - return nil -} - -func (list *sparseChildList) walk(prefix *Prefix, visitor VisitorFunc) error { - - sort.Sort(list.children) - - for _, child := range list.children { - *prefix = append(*prefix, child.prefix...) - if child.item != nil { - err := visitor(*prefix, child.item) - if err != nil { - if err == SkipSubtree { - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - continue - } - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - return err - } - } - - err := child.children.walk(prefix, visitor) - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - if err != nil { - return err - } - } - - return nil -} - -func (list *sparseChildList) total() int { - tot := 0 - for _, child := range list.children { - if child != nil { - tot = tot + child.total() - } - } - return tot -} - -func (list *sparseChildList) print(w io.Writer, indent int) { - for _, child := range list.children { - if child != nil { - child.print(w, indent) - } - } -} - -type denseChildList struct { - min int - max int - numChildren int - headIndex int - children []*Trie -} - -func newDenseChildList(list *sparseChildList, child *Trie) childList { - var ( - min int = 255 - max int = 0 - ) - for _, child := range list.children { - b := int(child.prefix[0]) - if b < min { - min = b - } - if b > max { - max = b - } - } - - b := int(child.prefix[0]) - if b < min { - min = b - } - if b > max { - max = b - } - - children := make([]*Trie, max-min+1) - for _, child := range list.children { - children[int(child.prefix[0])-min] = child - } - children[int(child.prefix[0])-min] = child - - return &denseChildList{ - min: min, - max: max, - numChildren: list.length() + 1, - headIndex: 0, - children: children, - } -} - -func (list *denseChildList) length() int { - return list.numChildren -} - -func (list *denseChildList) head() *Trie { - return list.children[list.headIndex] -} - -func (list *denseChildList) add(child *Trie) childList { - b := int(child.prefix[0]) - var i int - - switch { - case list.min <= b && b <= list.max: - if list.children[b-list.min] != nil { - panic("dense child list collision detected") - } - i = b - list.min - list.children[i] = child - - case b < list.min: - children := make([]*Trie, list.max-b+1) - i = 0 - children[i] = child - copy(children[list.min-b:], list.children) - list.children = children - list.min = b - - default: // b > list.max - children := make([]*Trie, b-list.min+1) - i = b - list.min - children[i] = child - copy(children, list.children) - list.children = children - list.max = b - } - - list.numChildren++ - if i < list.headIndex { - list.headIndex = i - } - return list -} - -func (list *denseChildList) remove(b byte) { - i := int(b) - list.min - if list.children[i] == nil { - // This is not supposed to be reached. - panic("removing non-existent child") - } - list.numChildren-- - list.children[i] = nil - - // Update head index. - if i == list.headIndex { - for ; i < len(list.children); i++ { - if list.children[i] != nil { - list.headIndex = i - return - } - } - } -} - -func (list *denseChildList) replace(b byte, child *Trie) { - // Make a consistency check. - if p0 := child.prefix[0]; p0 != b { - panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b)) - } - - // Replace the child. - list.children[int(b)-list.min] = child -} - -func (list *denseChildList) next(b byte) *Trie { - i := int(b) - if i < list.min || list.max < i { - return nil - } - return list.children[i-list.min] -} - -func (list *denseChildList) walk(prefix *Prefix, visitor VisitorFunc) error { - for _, child := range list.children { - if child == nil { - continue - } - *prefix = append(*prefix, child.prefix...) - if child.item != nil { - if err := visitor(*prefix, child.item); err != nil { - if err == SkipSubtree { - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - continue - } - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - return err - } - } - - err := child.children.walk(prefix, visitor) - *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] - if err != nil { - return err - } - } - - return nil -} - -func (list *denseChildList) print(w io.Writer, indent int) { - for _, child := range list.children { - if child != nil { - child.print(w, indent) - } - } -} - -func (list *denseChildList) total() int { - tot := 0 - for _, child := range list.children { - if child != nil { - tot = tot + child.total() - } - } - return tot -} diff --git a/vendor/github.com/tchap/go-patricia/patricia/patricia.go b/vendor/github.com/tchap/go-patricia/patricia/patricia.go deleted file mode 100644 index a1fc53d5db..0000000000 --- a/vendor/github.com/tchap/go-patricia/patricia/patricia.go +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright (c) 2014 The go-patricia AUTHORS -// -// Use of this source code is governed by The MIT License -// that can be found in the LICENSE file. - -package patricia - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" -) - -//------------------------------------------------------------------------------ -// Trie -//------------------------------------------------------------------------------ - -const ( - DefaultMaxPrefixPerNode = 10 - DefaultMaxChildrenPerSparseNode = 8 -) - -type ( - Prefix []byte - Item interface{} - VisitorFunc func(prefix Prefix, item Item) error -) - -// Trie is a generic patricia trie that allows fast retrieval of items by prefix. -// and other funky stuff. -// -// Trie is not thread-safe. -type Trie struct { - prefix Prefix - item Item - - maxPrefixPerNode int - maxChildrenPerSparseNode int - - children childList -} - -// Public API ------------------------------------------------------------------ - -type Option func(*Trie) - -// Trie constructor. -func NewTrie(options ...Option) *Trie { - trie := &Trie{} - - for _, opt := range options { - opt(trie) - } - - if trie.maxPrefixPerNode <= 0 { - trie.maxPrefixPerNode = DefaultMaxPrefixPerNode - } - if trie.maxChildrenPerSparseNode <= 0 { - trie.maxChildrenPerSparseNode = DefaultMaxChildrenPerSparseNode - } - - trie.children = newSparseChildList(trie.maxChildrenPerSparseNode) - return trie -} - -func MaxPrefixPerNode(value int) Option { - return func(trie *Trie) { - trie.maxPrefixPerNode = value - } -} - -func MaxChildrenPerSparseNode(value int) Option { - return func(trie *Trie) { - trie.maxChildrenPerSparseNode = value - } -} - -// Item returns the item stored in the root of this trie. -func (trie *Trie) Item() Item { - return trie.item -} - -// Insert inserts a new item into the trie using the given prefix. Insert does -// not replace existing items. It returns false if an item was already in place. -func (trie *Trie) Insert(key Prefix, item Item) (inserted bool) { - return trie.put(key, item, false) -} - -// Set works much like Insert, but it always sets the item, possibly replacing -// the item previously inserted. -func (trie *Trie) Set(key Prefix, item Item) { - trie.put(key, item, true) -} - -// Get returns the item located at key. -// -// This method is a bit dangerous, because Get can as well end up in an internal -// node that is not really representing any user-defined value. So when nil is -// a valid value being used, it is not possible to tell if the value was inserted -// into the tree by the user or not. A possible workaround for this is not to use -// nil interface as a valid value, even using zero value of any type is enough -// to prevent this bad behaviour. -func (trie *Trie) Get(key Prefix) (item Item) { - _, node, found, leftover := trie.findSubtree(key) - if !found || len(leftover) != 0 { - return nil - } - return node.item -} - -// Match returns what Get(prefix) != nil would return. The same warning as for -// Get applies here as well. -func (trie *Trie) Match(prefix Prefix) (matchedExactly bool) { - return trie.Get(prefix) != nil -} - -// MatchSubtree returns true when there is a subtree representing extensions -// to key, that is if there are any keys in the tree which have key as prefix. -func (trie *Trie) MatchSubtree(key Prefix) (matched bool) { - _, _, matched, _ = trie.findSubtree(key) - return -} - -// Visit calls visitor on every node containing a non-nil item -// in alphabetical order. -// -// If an error is returned from visitor, the function stops visiting the tree -// and returns that error, unless it is a special error - SkipSubtree. In that -// case Visit skips the subtree represented by the current node and continues -// elsewhere. -func (trie *Trie) Visit(visitor VisitorFunc) error { - return trie.walk(nil, visitor) -} - -func (trie *Trie) size() int { - n := 0 - - trie.walk(nil, func(prefix Prefix, item Item) error { - n++ - return nil - }) - - return n -} - -func (trie *Trie) total() int { - return 1 + trie.children.total() -} - -// VisitSubtree works much like Visit, but it only visits nodes matching prefix. -func (trie *Trie) VisitSubtree(prefix Prefix, visitor VisitorFunc) error { - // Nil prefix not allowed. - if prefix == nil { - panic(ErrNilPrefix) - } - - // Empty trie must be handled explicitly. - if trie.prefix == nil { - return nil - } - - // Locate the relevant subtree. - _, root, found, leftover := trie.findSubtree(prefix) - if !found { - return nil - } - prefix = append(prefix, leftover...) - - // Visit it. - return root.walk(prefix, visitor) -} - -// VisitPrefixes visits only nodes that represent prefixes of key. -// To say the obvious, returning SkipSubtree from visitor makes no sense here. -func (trie *Trie) VisitPrefixes(key Prefix, visitor VisitorFunc) error { - // Nil key not allowed. - if key == nil { - panic(ErrNilPrefix) - } - - // Empty trie must be handled explicitly. - if trie.prefix == nil { - return nil - } - - // Walk the path matching key prefixes. - node := trie - prefix := key - offset := 0 - for { - // Compute what part of prefix matches. - common := node.longestCommonPrefixLength(key) - key = key[common:] - offset += common - - // Partial match means that there is no subtree matching prefix. - if common < len(node.prefix) { - return nil - } - - // Call the visitor. - if item := node.item; item != nil { - if err := visitor(prefix[:offset], item); err != nil { - return err - } - } - - if len(key) == 0 { - // This node represents key, we are finished. - return nil - } - - // There is some key suffix left, move to the children. - child := node.children.next(key[0]) - if child == nil { - // There is nowhere to continue, return. - return nil - } - - node = child - } -} - -// Delete deletes the item represented by the given prefix. -// -// True is returned if the matching node was found and deleted. -func (trie *Trie) Delete(key Prefix) (deleted bool) { - // Nil prefix not allowed. - if key == nil { - panic(ErrNilPrefix) - } - - // Empty trie must be handled explicitly. - if trie.prefix == nil { - return false - } - - // Find the relevant node. - path, found, _ := trie.findSubtreePath(key) - if !found { - return false - } - - node := path[len(path)-1] - var parent *Trie - if len(path) != 1 { - parent = path[len(path)-2] - } - - // If the item is already set to nil, there is nothing to do. - if node.item == nil { - return false - } - - // Delete the item. - node.item = nil - - // Initialise i before goto. - // Will be used later in a loop. - i := len(path) - 1 - - // In case there are some child nodes, we cannot drop the whole subtree. - // We can try to compact nodes, though. - if node.children.length() != 0 { - goto Compact - } - - // In case we are at the root, just reset it and we are done. - if parent == nil { - node.reset() - return true - } - - // We can drop a subtree. - // Find the first ancestor that has its value set or it has 2 or more child nodes. - // That will be the node where to drop the subtree at. - for ; i >= 0; i-- { - if current := path[i]; current.item != nil || current.children.length() >= 2 { - break - } - } - - // Handle the case when there is no such node. - // In other words, we can reset the whole tree. - if i == -1 { - path[0].reset() - return true - } - - // We can just remove the subtree here. - node = path[i] - if i == 0 { - parent = nil - } else { - parent = path[i-1] - } - // i+1 is always a valid index since i is never pointing to the last node. - // The loop above skips at least the last node since we are sure that the item - // is set to nil and it has no children, othewise we would be compacting instead. - node.children.remove(path[i+1].prefix[0]) - -Compact: - // The node is set to the first non-empty ancestor, - // so try to compact since that might be possible now. - if compacted := node.compact(); compacted != node { - if parent == nil { - *node = *compacted - } else { - parent.children.replace(node.prefix[0], compacted) - *parent = *parent.compact() - } - } - - return true -} - -// DeleteSubtree finds the subtree exactly matching prefix and deletes it. -// -// True is returned if the subtree was found and deleted. -func (trie *Trie) DeleteSubtree(prefix Prefix) (deleted bool) { - // Nil prefix not allowed. - if prefix == nil { - panic(ErrNilPrefix) - } - - // Empty trie must be handled explicitly. - if trie.prefix == nil { - return false - } - - // Locate the relevant subtree. - parent, root, found, _ := trie.findSubtree(prefix) - if !found { - return false - } - - // If we are in the root of the trie, reset the trie. - if parent == nil { - root.reset() - return true - } - - // Otherwise remove the root node from its parent. - parent.children.remove(root.prefix[0]) - return true -} - -// Internal helper methods ----------------------------------------------------- - -func (trie *Trie) empty() bool { - return trie.item == nil && trie.children.length() == 0 -} - -func (trie *Trie) reset() { - trie.prefix = nil - trie.children = newSparseChildList(trie.maxPrefixPerNode) -} - -func (trie *Trie) put(key Prefix, item Item, replace bool) (inserted bool) { - // Nil prefix not allowed. - if key == nil { - panic(ErrNilPrefix) - } - - var ( - common int - node *Trie = trie - child *Trie - ) - - if node.prefix == nil { - if len(key) <= trie.maxPrefixPerNode { - node.prefix = key - goto InsertItem - } - node.prefix = key[:trie.maxPrefixPerNode] - key = key[trie.maxPrefixPerNode:] - goto AppendChild - } - - for { - // Compute the longest common prefix length. - common = node.longestCommonPrefixLength(key) - key = key[common:] - - // Only a part matches, split. - if common < len(node.prefix) { - goto SplitPrefix - } - - // common == len(node.prefix) since never (common > len(node.prefix)) - // common == len(former key) <-> 0 == len(key) - // -> former key == node.prefix - if len(key) == 0 { - goto InsertItem - } - - // Check children for matching prefix. - child = node.children.next(key[0]) - if child == nil { - goto AppendChild - } - node = child - } - -SplitPrefix: - // Split the prefix if necessary. - child = new(Trie) - *child = *node - *node = *NewTrie() - node.prefix = child.prefix[:common] - child.prefix = child.prefix[common:] - child = child.compact() - node.children = node.children.add(child) - -AppendChild: - // Keep appending children until whole prefix is inserted. - // This loop starts with empty node.prefix that needs to be filled. - for len(key) != 0 { - child := NewTrie() - if len(key) <= trie.maxPrefixPerNode { - child.prefix = key - node.children = node.children.add(child) - node = child - goto InsertItem - } else { - child.prefix = key[:trie.maxPrefixPerNode] - key = key[trie.maxPrefixPerNode:] - node.children = node.children.add(child) - node = child - } - } - -InsertItem: - // Try to insert the item if possible. - if replace || node.item == nil { - node.item = item - return true - } - return false -} - -func (trie *Trie) compact() *Trie { - // Only a node with a single child can be compacted. - if trie.children.length() != 1 { - return trie - } - - child := trie.children.head() - - // If any item is set, we cannot compact since we want to retain - // the ability to do searching by key. This makes compaction less usable, - // but that simply cannot be avoided. - if trie.item != nil || child.item != nil { - return trie - } - - // Make sure the combined prefixes fit into a single node. - if len(trie.prefix)+len(child.prefix) > trie.maxPrefixPerNode { - return trie - } - - // Concatenate the prefixes, move the items. - child.prefix = append(trie.prefix, child.prefix...) - if trie.item != nil { - child.item = trie.item - } - - return child -} - -func (trie *Trie) findSubtree(prefix Prefix) (parent *Trie, root *Trie, found bool, leftover Prefix) { - // Find the subtree matching prefix. - root = trie - for { - // Compute what part of prefix matches. - common := root.longestCommonPrefixLength(prefix) - prefix = prefix[common:] - - // We used up the whole prefix, subtree found. - if len(prefix) == 0 { - found = true - leftover = root.prefix[common:] - return - } - - // Partial match means that there is no subtree matching prefix. - if common < len(root.prefix) { - leftover = root.prefix[common:] - return - } - - // There is some prefix left, move to the children. - child := root.children.next(prefix[0]) - if child == nil { - // There is nowhere to continue, there is no subtree matching prefix. - return - } - - parent = root - root = child - } -} - -func (trie *Trie) findSubtreePath(prefix Prefix) (path []*Trie, found bool, leftover Prefix) { - // Find the subtree matching prefix. - root := trie - var subtreePath []*Trie - for { - // Append the current root to the path. - subtreePath = append(subtreePath, root) - - // Compute what part of prefix matches. - common := root.longestCommonPrefixLength(prefix) - prefix = prefix[common:] - - // We used up the whole prefix, subtree found. - if len(prefix) == 0 { - path = subtreePath - found = true - leftover = root.prefix[common:] - return - } - - // Partial match means that there is no subtree matching prefix. - if common < len(root.prefix) { - leftover = root.prefix[common:] - return - } - - // There is some prefix left, move to the children. - child := root.children.next(prefix[0]) - if child == nil { - // There is nowhere to continue, there is no subtree matching prefix. - return - } - - root = child - } -} - -func (trie *Trie) walk(actualRootPrefix Prefix, visitor VisitorFunc) error { - var prefix Prefix - // Allocate a bit more space for prefix at the beginning. - if actualRootPrefix == nil { - prefix = make(Prefix, 32+len(trie.prefix)) - copy(prefix, trie.prefix) - prefix = prefix[:len(trie.prefix)] - } else { - prefix = make(Prefix, 32+len(actualRootPrefix)) - copy(prefix, actualRootPrefix) - prefix = prefix[:len(actualRootPrefix)] - } - - // Visit the root first. Not that this works for empty trie as well since - // in that case item == nil && len(children) == 0. - if trie.item != nil { - if err := visitor(prefix, trie.item); err != nil { - if err == SkipSubtree { - return nil - } - return err - } - } - - // Then continue to the children. - return trie.children.walk(&prefix, visitor) -} - -func (trie *Trie) longestCommonPrefixLength(prefix Prefix) (i int) { - for ; i < len(prefix) && i < len(trie.prefix) && prefix[i] == trie.prefix[i]; i++ { - } - return -} - -func (trie *Trie) dump() string { - writer := &bytes.Buffer{} - trie.print(writer, 0) - return writer.String() -} - -func (trie *Trie) print(writer io.Writer, indent int) { - fmt.Fprintf(writer, "%s%s %v\n", strings.Repeat(" ", indent), string(trie.prefix), trie.item) - trie.children.print(writer, indent+2) -} - -// Errors ---------------------------------------------------------------------- - -var ( - SkipSubtree = errors.New("Skip this subtree") - ErrNilPrefix = errors.New("Nil prefix passed into a method call") -) diff --git a/vendor/github.com/vbatts/tar-split/LICENSE b/vendor/github.com/vbatts/tar-split/LICENSE deleted file mode 100644 index ca03685b15..0000000000 --- a/vendor/github.com/vbatts/tar-split/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2015 Vincent Batts, Raleigh, NC, USA - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors -may be used to endorse or promote products derived from this software without -specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/common.go b/vendor/github.com/vbatts/tar-split/archive/tar/common.go deleted file mode 100644 index 36f4e23980..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/common.go +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tar implements access to tar archives. -// It aims to cover most of the variations, including those produced -// by GNU and BSD tars. -// -// References: -// http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 -// http://www.gnu.org/software/tar/manual/html_node/Standard.html -// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html -package tar - -import ( - "bytes" - "errors" - "fmt" - "os" - "path" - "time" -) - -const ( - blockSize = 512 - - // Types - TypeReg = '0' // regular file - TypeRegA = '\x00' // regular file - TypeLink = '1' // hard link - TypeSymlink = '2' // symbolic link - TypeChar = '3' // character device node - TypeBlock = '4' // block device node - TypeDir = '5' // directory - TypeFifo = '6' // fifo node - TypeCont = '7' // reserved - TypeXHeader = 'x' // extended header - TypeXGlobalHeader = 'g' // global extended header - TypeGNULongName = 'L' // Next file has a long name - TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name - TypeGNUSparse = 'S' // sparse file -) - -// A Header represents a single header in a tar archive. -// Some fields may not be populated. -type Header struct { - Name string // name of header file entry - Mode int64 // permission and mode bits - Uid int // user id of owner - Gid int // group id of owner - Size int64 // length in bytes - ModTime time.Time // modified time - Typeflag byte // type of header entry - Linkname string // target name of link - Uname string // user name of owner - Gname string // group name of owner - Devmajor int64 // major number of character or block device - Devminor int64 // minor number of character or block device - AccessTime time.Time // access time - ChangeTime time.Time // status change time - Xattrs map[string]string -} - -// File name constants from the tar spec. -const ( - fileNameSize = 100 // Maximum number of bytes in a standard tar name. - fileNamePrefixSize = 155 // Maximum number of ustar extension bytes. -) - -// FileInfo returns an os.FileInfo for the Header. -func (h *Header) FileInfo() os.FileInfo { - return headerFileInfo{h} -} - -// headerFileInfo implements os.FileInfo. -type headerFileInfo struct { - h *Header -} - -func (fi headerFileInfo) Size() int64 { return fi.h.Size } -func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } -func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } -func (fi headerFileInfo) Sys() interface{} { return fi.h } - -// Name returns the base name of the file. -func (fi headerFileInfo) Name() string { - if fi.IsDir() { - return path.Base(path.Clean(fi.h.Name)) - } - return path.Base(fi.h.Name) -} - -// Mode returns the permission and mode bits for the headerFileInfo. -func (fi headerFileInfo) Mode() (mode os.FileMode) { - // Set file permission bits. - mode = os.FileMode(fi.h.Mode).Perm() - - // Set setuid, setgid and sticky bits. - if fi.h.Mode&c_ISUID != 0 { - // setuid - mode |= os.ModeSetuid - } - if fi.h.Mode&c_ISGID != 0 { - // setgid - mode |= os.ModeSetgid - } - if fi.h.Mode&c_ISVTX != 0 { - // sticky - mode |= os.ModeSticky - } - - // Set file mode bits. - // clear perm, setuid, setgid and sticky bits. - m := os.FileMode(fi.h.Mode) &^ 07777 - if m == c_ISDIR { - // directory - mode |= os.ModeDir - } - if m == c_ISFIFO { - // named pipe (FIFO) - mode |= os.ModeNamedPipe - } - if m == c_ISLNK { - // symbolic link - mode |= os.ModeSymlink - } - if m == c_ISBLK { - // device file - mode |= os.ModeDevice - } - if m == c_ISCHR { - // Unix character device - mode |= os.ModeDevice - mode |= os.ModeCharDevice - } - if m == c_ISSOCK { - // Unix domain socket - mode |= os.ModeSocket - } - - switch fi.h.Typeflag { - case TypeSymlink: - // symbolic link - mode |= os.ModeSymlink - case TypeChar: - // character device node - mode |= os.ModeDevice - mode |= os.ModeCharDevice - case TypeBlock: - // block device node - mode |= os.ModeDevice - case TypeDir: - // directory - mode |= os.ModeDir - case TypeFifo: - // fifo node - mode |= os.ModeNamedPipe - } - - return mode -} - -// sysStat, if non-nil, populates h from system-dependent fields of fi. -var sysStat func(fi os.FileInfo, h *Header) error - -// Mode constants from the tar spec. -const ( - c_ISUID = 04000 // Set uid - c_ISGID = 02000 // Set gid - c_ISVTX = 01000 // Save text (sticky bit) - c_ISDIR = 040000 // Directory - c_ISFIFO = 010000 // FIFO - c_ISREG = 0100000 // Regular file - c_ISLNK = 0120000 // Symbolic link - c_ISBLK = 060000 // Block special file - c_ISCHR = 020000 // Character special file - c_ISSOCK = 0140000 // Socket -) - -// Keywords for the PAX Extended Header -const ( - paxAtime = "atime" - paxCharset = "charset" - paxComment = "comment" - paxCtime = "ctime" // please note that ctime is not a valid pax header. - paxGid = "gid" - paxGname = "gname" - paxLinkpath = "linkpath" - paxMtime = "mtime" - paxPath = "path" - paxSize = "size" - paxUid = "uid" - paxUname = "uname" - paxXattr = "SCHILY.xattr." - paxNone = "" -) - -// FileInfoHeader creates a partially-populated Header from fi. -// If fi describes a symlink, FileInfoHeader records link as the link target. -// If fi describes a directory, a slash is appended to the name. -// Because os.FileInfo's Name method returns only the base name of -// the file it describes, it may be necessary to modify the Name field -// of the returned header to provide the full path name of the file. -func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { - if fi == nil { - return nil, errors.New("tar: FileInfo is nil") - } - fm := fi.Mode() - h := &Header{ - Name: fi.Name(), - ModTime: fi.ModTime(), - Mode: int64(fm.Perm()), // or'd with c_IS* constants later - } - switch { - case fm.IsRegular(): - h.Mode |= c_ISREG - h.Typeflag = TypeReg - h.Size = fi.Size() - case fi.IsDir(): - h.Typeflag = TypeDir - h.Mode |= c_ISDIR - h.Name += "/" - case fm&os.ModeSymlink != 0: - h.Typeflag = TypeSymlink - h.Mode |= c_ISLNK - h.Linkname = link - case fm&os.ModeDevice != 0: - if fm&os.ModeCharDevice != 0 { - h.Mode |= c_ISCHR - h.Typeflag = TypeChar - } else { - h.Mode |= c_ISBLK - h.Typeflag = TypeBlock - } - case fm&os.ModeNamedPipe != 0: - h.Typeflag = TypeFifo - h.Mode |= c_ISFIFO - case fm&os.ModeSocket != 0: - h.Mode |= c_ISSOCK - default: - return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) - } - if fm&os.ModeSetuid != 0 { - h.Mode |= c_ISUID - } - if fm&os.ModeSetgid != 0 { - h.Mode |= c_ISGID - } - if fm&os.ModeSticky != 0 { - h.Mode |= c_ISVTX - } - // If possible, populate additional fields from OS-specific - // FileInfo fields. - if sys, ok := fi.Sys().(*Header); ok { - // This FileInfo came from a Header (not the OS). Use the - // original Header to populate all remaining fields. - h.Uid = sys.Uid - h.Gid = sys.Gid - h.Uname = sys.Uname - h.Gname = sys.Gname - h.AccessTime = sys.AccessTime - h.ChangeTime = sys.ChangeTime - if sys.Xattrs != nil { - h.Xattrs = make(map[string]string) - for k, v := range sys.Xattrs { - h.Xattrs[k] = v - } - } - if sys.Typeflag == TypeLink { - // hard link - h.Typeflag = TypeLink - h.Size = 0 - h.Linkname = sys.Linkname - } - } - if sysStat != nil { - return h, sysStat(fi, h) - } - return h, nil -} - -var zeroBlock = make([]byte, blockSize) - -// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values. -// We compute and return both. -func checksum(header []byte) (unsigned int64, signed int64) { - for i := 0; i < len(header); i++ { - if i == 148 { - // The chksum field (header[148:156]) is special: it should be treated as space bytes. - unsigned += ' ' * 8 - signed += ' ' * 8 - i += 7 - continue - } - unsigned += int64(header[i]) - signed += int64(int8(header[i])) - } - return -} - -type slicer []byte - -func (sp *slicer) next(n int) (b []byte) { - s := *sp - b, *sp = s[0:n], s[n:] - return -} - -func isASCII(s string) bool { - for _, c := range s { - if c >= 0x80 { - return false - } - } - return true -} - -func toASCII(s string) string { - if isASCII(s) { - return s - } - var buf bytes.Buffer - for _, c := range s { - if c < 0x80 { - buf.WriteByte(byte(c)) - } - } - return buf.String() -} - -// isHeaderOnlyType checks if the given type flag is of the type that has no -// data section even if a size is specified. -func isHeaderOnlyType(flag byte) bool { - switch flag { - case TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, TypeFifo: - return true - default: - return false - } -} diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go deleted file mode 100644 index adf32122e1..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go +++ /dev/null @@ -1,1064 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tar - -// TODO(dsymonds): -// - pax extensions - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "math" - "os" - "strconv" - "strings" - "time" -) - -var ( - ErrHeader = errors.New("archive/tar: invalid tar header") -) - -const maxNanoSecondIntSize = 9 - -// A Reader provides sequential access to the contents of a tar archive. -// A tar archive consists of a sequence of files. -// The Next method advances to the next file in the archive (including the first), -// and then it can be treated as an io.Reader to access the file's data. -type Reader struct { - r io.Reader - err error - pad int64 // amount of padding (ignored) after current file entry - curr numBytesReader // reader for current file entry - hdrBuff [blockSize]byte // buffer to use in readHeader - - RawAccounting bool // Whether to enable the access needed to reassemble the tar from raw bytes. Some performance/memory hit for this. - rawBytes *bytes.Buffer // last raw bits -} - -type parser struct { - err error // Last error seen -} - -// RawBytes accesses the raw bytes of the archive, apart from the file payload itself. -// This includes the header and padding. -// -// This call resets the current rawbytes buffer -// -// Only when RawAccounting is enabled, otherwise this returns nil -func (tr *Reader) RawBytes() []byte { - if !tr.RawAccounting { - return nil - } - if tr.rawBytes == nil { - tr.rawBytes = bytes.NewBuffer(nil) - } - // if we've read them, then flush them. - defer tr.rawBytes.Reset() - return tr.rawBytes.Bytes() -} - -// A numBytesReader is an io.Reader with a numBytes method, returning the number -// of bytes remaining in the underlying encoded data. -type numBytesReader interface { - io.Reader - numBytes() int64 -} - -// A regFileReader is a numBytesReader for reading file data from a tar archive. -type regFileReader struct { - r io.Reader // underlying reader - nb int64 // number of unread bytes for current file entry -} - -// A sparseFileReader is a numBytesReader for reading sparse file data from a -// tar archive. -type sparseFileReader struct { - rfr numBytesReader // Reads the sparse-encoded file data - sp []sparseEntry // The sparse map for the file - pos int64 // Keeps track of file position - total int64 // Total size of the file -} - -// A sparseEntry holds a single entry in a sparse file's sparse map. -// -// Sparse files are represented using a series of sparseEntrys. -// Despite the name, a sparseEntry represents an actual data fragment that -// references data found in the underlying archive stream. All regions not -// covered by a sparseEntry are logically filled with zeros. -// -// For example, if the underlying raw file contains the 10-byte data: -// var compactData = "abcdefgh" -// -// And the sparse map has the following entries: -// var sp = []sparseEntry{ -// {offset: 2, numBytes: 5} // Data fragment for [2..7] -// {offset: 18, numBytes: 3} // Data fragment for [18..21] -// } -// -// Then the content of the resulting sparse file with a "real" size of 25 is: -// var sparseData = "\x00"*2 + "abcde" + "\x00"*11 + "fgh" + "\x00"*4 -type sparseEntry struct { - offset int64 // Starting position of the fragment - numBytes int64 // Length of the fragment -} - -// Keywords for GNU sparse files in a PAX extended header -const ( - paxGNUSparseNumBlocks = "GNU.sparse.numblocks" - paxGNUSparseOffset = "GNU.sparse.offset" - paxGNUSparseNumBytes = "GNU.sparse.numbytes" - paxGNUSparseMap = "GNU.sparse.map" - paxGNUSparseName = "GNU.sparse.name" - paxGNUSparseMajor = "GNU.sparse.major" - paxGNUSparseMinor = "GNU.sparse.minor" - paxGNUSparseSize = "GNU.sparse.size" - paxGNUSparseRealSize = "GNU.sparse.realsize" -) - -// Keywords for old GNU sparse headers -const ( - oldGNUSparseMainHeaderOffset = 386 - oldGNUSparseMainHeaderIsExtendedOffset = 482 - oldGNUSparseMainHeaderNumEntries = 4 - oldGNUSparseExtendedHeaderIsExtendedOffset = 504 - oldGNUSparseExtendedHeaderNumEntries = 21 - oldGNUSparseOffsetSize = 12 - oldGNUSparseNumBytesSize = 12 -) - -// NewReader creates a new Reader reading from r. -func NewReader(r io.Reader) *Reader { return &Reader{r: r} } - -// Next advances to the next entry in the tar archive. -// -// io.EOF is returned at the end of the input. -func (tr *Reader) Next() (*Header, error) { - if tr.RawAccounting { - if tr.rawBytes == nil { - tr.rawBytes = bytes.NewBuffer(nil) - } else { - tr.rawBytes.Reset() - } - } - - if tr.err != nil { - return nil, tr.err - } - - var hdr *Header - var extHdrs map[string]string - - // Externally, Next iterates through the tar archive as if it is a series of - // files. Internally, the tar format often uses fake "files" to add meta - // data that describes the next file. These meta data "files" should not - // normally be visible to the outside. As such, this loop iterates through - // one or more "header files" until it finds a "normal file". -loop: - for { - tr.err = tr.skipUnread() - if tr.err != nil { - return nil, tr.err - } - - hdr = tr.readHeader() - if tr.err != nil { - return nil, tr.err - } - // Check for PAX/GNU special headers and files. - switch hdr.Typeflag { - case TypeXHeader: - extHdrs, tr.err = parsePAX(tr) - if tr.err != nil { - return nil, tr.err - } - continue loop // This is a meta header affecting the next header - case TypeGNULongName, TypeGNULongLink: - var realname []byte - realname, tr.err = ioutil.ReadAll(tr) - if tr.err != nil { - return nil, tr.err - } - - if tr.RawAccounting { - if _, tr.err = tr.rawBytes.Write(realname); tr.err != nil { - return nil, tr.err - } - } - - // Convert GNU extensions to use PAX headers. - if extHdrs == nil { - extHdrs = make(map[string]string) - } - var p parser - switch hdr.Typeflag { - case TypeGNULongName: - extHdrs[paxPath] = p.parseString(realname) - case TypeGNULongLink: - extHdrs[paxLinkpath] = p.parseString(realname) - } - if p.err != nil { - tr.err = p.err - return nil, tr.err - } - continue loop // This is a meta header affecting the next header - default: - mergePAX(hdr, extHdrs) - - // Check for a PAX format sparse file - sp, err := tr.checkForGNUSparsePAXHeaders(hdr, extHdrs) - if err != nil { - tr.err = err - return nil, err - } - if sp != nil { - // Current file is a PAX format GNU sparse file. - // Set the current file reader to a sparse file reader. - tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size) - if tr.err != nil { - return nil, tr.err - } - } - break loop // This is a file, so stop - } - } - return hdr, nil -} - -// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then -// this function reads the sparse map and returns it. Unknown sparse formats are ignored, causing the file to -// be treated as a regular file. -func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]string) ([]sparseEntry, error) { - var sparseFormat string - - // Check for sparse format indicators - major, majorOk := headers[paxGNUSparseMajor] - minor, minorOk := headers[paxGNUSparseMinor] - sparseName, sparseNameOk := headers[paxGNUSparseName] - _, sparseMapOk := headers[paxGNUSparseMap] - sparseSize, sparseSizeOk := headers[paxGNUSparseSize] - sparseRealSize, sparseRealSizeOk := headers[paxGNUSparseRealSize] - - // Identify which, if any, sparse format applies from which PAX headers are set - if majorOk && minorOk { - sparseFormat = major + "." + minor - } else if sparseNameOk && sparseMapOk { - sparseFormat = "0.1" - } else if sparseSizeOk { - sparseFormat = "0.0" - } else { - // Not a PAX format GNU sparse file. - return nil, nil - } - - // Check for unknown sparse format - if sparseFormat != "0.0" && sparseFormat != "0.1" && sparseFormat != "1.0" { - return nil, nil - } - - // Update hdr from GNU sparse PAX headers - if sparseNameOk { - hdr.Name = sparseName - } - if sparseSizeOk { - realSize, err := strconv.ParseInt(sparseSize, 10, 0) - if err != nil { - return nil, ErrHeader - } - hdr.Size = realSize - } else if sparseRealSizeOk { - realSize, err := strconv.ParseInt(sparseRealSize, 10, 0) - if err != nil { - return nil, ErrHeader - } - hdr.Size = realSize - } - - // Set up the sparse map, according to the particular sparse format in use - var sp []sparseEntry - var err error - switch sparseFormat { - case "0.0", "0.1": - sp, err = readGNUSparseMap0x1(headers) - case "1.0": - sp, err = readGNUSparseMap1x0(tr.curr) - } - return sp, err -} - -// mergePAX merges well known headers according to PAX standard. -// In general headers with the same name as those found -// in the header struct overwrite those found in the header -// struct with higher precision or longer values. Esp. useful -// for name and linkname fields. -func mergePAX(hdr *Header, headers map[string]string) error { - for k, v := range headers { - switch k { - case paxPath: - hdr.Name = v - case paxLinkpath: - hdr.Linkname = v - case paxGname: - hdr.Gname = v - case paxUname: - hdr.Uname = v - case paxUid: - uid, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Uid = int(uid) - case paxGid: - gid, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Gid = int(gid) - case paxAtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.AccessTime = t - case paxMtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.ModTime = t - case paxCtime: - t, err := parsePAXTime(v) - if err != nil { - return err - } - hdr.ChangeTime = t - case paxSize: - size, err := strconv.ParseInt(v, 10, 0) - if err != nil { - return err - } - hdr.Size = int64(size) - default: - if strings.HasPrefix(k, paxXattr) { - if hdr.Xattrs == nil { - hdr.Xattrs = make(map[string]string) - } - hdr.Xattrs[k[len(paxXattr):]] = v - } - } - } - return nil -} - -// parsePAXTime takes a string of the form %d.%d as described in -// the PAX specification. -func parsePAXTime(t string) (time.Time, error) { - buf := []byte(t) - pos := bytes.IndexByte(buf, '.') - var seconds, nanoseconds int64 - var err error - if pos == -1 { - seconds, err = strconv.ParseInt(t, 10, 0) - if err != nil { - return time.Time{}, err - } - } else { - seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0) - if err != nil { - return time.Time{}, err - } - nano_buf := string(buf[pos+1:]) - // Pad as needed before converting to a decimal. - // For example .030 -> .030000000 -> 30000000 nanoseconds - if len(nano_buf) < maxNanoSecondIntSize { - // Right pad - nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf)) - } else if len(nano_buf) > maxNanoSecondIntSize { - // Right truncate - nano_buf = nano_buf[:maxNanoSecondIntSize] - } - nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0) - if err != nil { - return time.Time{}, err - } - } - ts := time.Unix(seconds, nanoseconds) - return ts, nil -} - -// parsePAX parses PAX headers. -// If an extended header (type 'x') is invalid, ErrHeader is returned -func parsePAX(r io.Reader) (map[string]string, error) { - buf, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - // leaving this function for io.Reader makes it more testable - if tr, ok := r.(*Reader); ok && tr.RawAccounting { - if _, err = tr.rawBytes.Write(buf); err != nil { - return nil, err - } - } - sbuf := string(buf) - - // For GNU PAX sparse format 0.0 support. - // This function transforms the sparse format 0.0 headers into sparse format 0.1 headers. - var sparseMap bytes.Buffer - - headers := make(map[string]string) - // Each record is constructed as - // "%d %s=%s\n", length, keyword, value - for len(sbuf) > 0 { - key, value, residual, err := parsePAXRecord(sbuf) - if err != nil { - return nil, ErrHeader - } - sbuf = residual - - keyStr := string(key) - if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes { - // GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map. - sparseMap.WriteString(value) - sparseMap.Write([]byte{','}) - } else { - // Normal key. Set the value in the headers map. - headers[keyStr] = string(value) - } - } - if sparseMap.Len() != 0 { - // Add sparse info to headers, chopping off the extra comma - sparseMap.Truncate(sparseMap.Len() - 1) - headers[paxGNUSparseMap] = sparseMap.String() - } - return headers, nil -} - -// parsePAXRecord parses the input PAX record string into a key-value pair. -// If parsing is successful, it will slice off the currently read record and -// return the remainder as r. -// -// A PAX record is of the following form: -// "%d %s=%s\n" % (size, key, value) -func parsePAXRecord(s string) (k, v, r string, err error) { - // The size field ends at the first space. - sp := strings.IndexByte(s, ' ') - if sp == -1 { - return "", "", s, ErrHeader - } - - // Parse the first token as a decimal integer. - n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int - if perr != nil || n < 5 || int64(len(s)) < n { - return "", "", s, ErrHeader - } - - // Extract everything between the space and the final newline. - rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:] - if nl != "\n" { - return "", "", s, ErrHeader - } - - // The first equals separates the key from the value. - eq := strings.IndexByte(rec, '=') - if eq == -1 { - return "", "", s, ErrHeader - } - return rec[:eq], rec[eq+1:], rem, nil -} - -// parseString parses bytes as a NUL-terminated C-style string. -// If a NUL byte is not found then the whole slice is returned as a string. -func (*parser) parseString(b []byte) string { - n := 0 - for n < len(b) && b[n] != 0 { - n++ - } - return string(b[0:n]) -} - -// parseNumeric parses the input as being encoded in either base-256 or octal. -// This function may return negative numbers. -// If parsing fails or an integer overflow occurs, err will be set. -func (p *parser) parseNumeric(b []byte) int64 { - // Check for base-256 (binary) format first. - // If the first bit is set, then all following bits constitute a two's - // complement encoded number in big-endian byte order. - if len(b) > 0 && b[0]&0x80 != 0 { - // Handling negative numbers relies on the following identity: - // -a-1 == ^a - // - // If the number is negative, we use an inversion mask to invert the - // data bytes and treat the value as an unsigned number. - var inv byte // 0x00 if positive or zero, 0xff if negative - if b[0]&0x40 != 0 { - inv = 0xff - } - - var x uint64 - for i, c := range b { - c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing - if i == 0 { - c &= 0x7f // Ignore signal bit in first byte - } - if (x >> 56) > 0 { - p.err = ErrHeader // Integer overflow - return 0 - } - x = x<<8 | uint64(c) - } - if (x >> 63) > 0 { - p.err = ErrHeader // Integer overflow - return 0 - } - if inv == 0xff { - return ^int64(x) - } - return int64(x) - } - - // Normal case is base-8 (octal) format. - return p.parseOctal(b) -} - -func (p *parser) parseOctal(b []byte) int64 { - // Because unused fields are filled with NULs, we need - // to skip leading NULs. Fields may also be padded with - // spaces or NULs. - // So we remove leading and trailing NULs and spaces to - // be sure. - b = bytes.Trim(b, " \x00") - - if len(b) == 0 { - return 0 - } - x, perr := strconv.ParseUint(p.parseString(b), 8, 64) - if perr != nil { - p.err = ErrHeader - } - return int64(x) -} - -// skipUnread skips any unread bytes in the existing file entry, as well as any -// alignment padding. It returns io.ErrUnexpectedEOF if any io.EOF is -// encountered in the data portion; it is okay to hit io.EOF in the padding. -// -// Note that this function still works properly even when sparse files are being -// used since numBytes returns the bytes remaining in the underlying io.Reader. -func (tr *Reader) skipUnread() error { - dataSkip := tr.numBytes() // Number of data bytes to skip - totalSkip := dataSkip + tr.pad // Total number of bytes to skip - tr.curr, tr.pad = nil, 0 - if tr.RawAccounting { - _, tr.err = io.CopyN(tr.rawBytes, tr.r, totalSkip) - return tr.err - } - // If possible, Seek to the last byte before the end of the data section. - // Do this because Seek is often lazy about reporting errors; this will mask - // the fact that the tar stream may be truncated. We can rely on the - // io.CopyN done shortly afterwards to trigger any IO errors. - var seekSkipped int64 // Number of bytes skipped via Seek - if sr, ok := tr.r.(io.Seeker); ok && dataSkip > 1 { - // Not all io.Seeker can actually Seek. For example, os.Stdin implements - // io.Seeker, but calling Seek always returns an error and performs - // no action. Thus, we try an innocent seek to the current position - // to see if Seek is really supported. - pos1, err := sr.Seek(0, os.SEEK_CUR) - if err == nil { - // Seek seems supported, so perform the real Seek. - pos2, err := sr.Seek(dataSkip-1, os.SEEK_CUR) - if err != nil { - tr.err = err - return tr.err - } - seekSkipped = pos2 - pos1 - } - } - - var copySkipped int64 // Number of bytes skipped via CopyN - copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped) - if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip { - tr.err = io.ErrUnexpectedEOF - } - return tr.err -} - -func (tr *Reader) verifyChecksum(header []byte) bool { - if tr.err != nil { - return false - } - - var p parser - given := p.parseOctal(header[148:156]) - unsigned, signed := checksum(header) - return p.err == nil && (given == unsigned || given == signed) -} - -// readHeader reads the next block header and assumes that the underlying reader -// is already aligned to a block boundary. -// -// The err will be set to io.EOF only when one of the following occurs: -// * Exactly 0 bytes are read and EOF is hit. -// * Exactly 1 block of zeros is read and EOF is hit. -// * At least 2 blocks of zeros are read. -func (tr *Reader) readHeader() *Header { - header := tr.hdrBuff[:] - copy(header, zeroBlock) - - if n, err := io.ReadFull(tr.r, header); err != nil { - tr.err = err - // because it could read some of the block, but reach EOF first - if tr.err == io.EOF && tr.RawAccounting { - if _, err := tr.rawBytes.Write(header[:n]); err != nil { - tr.err = err - } - } - return nil // io.EOF is okay here - } - if tr.RawAccounting { - if _, tr.err = tr.rawBytes.Write(header); tr.err != nil { - return nil - } - } - - // Two blocks of zero bytes marks the end of the archive. - if bytes.Equal(header, zeroBlock[0:blockSize]) { - if n, err := io.ReadFull(tr.r, header); err != nil { - tr.err = err - // because it could read some of the block, but reach EOF first - if tr.err == io.EOF && tr.RawAccounting { - if _, err := tr.rawBytes.Write(header[:n]); err != nil { - tr.err = err - } - } - return nil // io.EOF is okay here - } - if tr.RawAccounting { - if _, tr.err = tr.rawBytes.Write(header); tr.err != nil { - return nil - } - } - if bytes.Equal(header, zeroBlock[0:blockSize]) { - tr.err = io.EOF - } else { - tr.err = ErrHeader // zero block and then non-zero block - } - return nil - } - - if !tr.verifyChecksum(header) { - tr.err = ErrHeader - return nil - } - - // Unpack - var p parser - hdr := new(Header) - s := slicer(header) - - hdr.Name = p.parseString(s.next(100)) - hdr.Mode = p.parseNumeric(s.next(8)) - hdr.Uid = int(p.parseNumeric(s.next(8))) - hdr.Gid = int(p.parseNumeric(s.next(8))) - hdr.Size = p.parseNumeric(s.next(12)) - hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0) - s.next(8) // chksum - hdr.Typeflag = s.next(1)[0] - hdr.Linkname = p.parseString(s.next(100)) - - // The remainder of the header depends on the value of magic. - // The original (v7) version of tar had no explicit magic field, - // so its magic bytes, like the rest of the block, are NULs. - magic := string(s.next(8)) // contains version field as well. - var format string - switch { - case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988) - if string(header[508:512]) == "tar\x00" { - format = "star" - } else { - format = "posix" - } - case magic == "ustar \x00": // old GNU tar - format = "gnu" - } - - switch format { - case "posix", "gnu", "star": - hdr.Uname = p.parseString(s.next(32)) - hdr.Gname = p.parseString(s.next(32)) - devmajor := s.next(8) - devminor := s.next(8) - if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock { - hdr.Devmajor = p.parseNumeric(devmajor) - hdr.Devminor = p.parseNumeric(devminor) - } - var prefix string - switch format { - case "posix", "gnu": - prefix = p.parseString(s.next(155)) - case "star": - prefix = p.parseString(s.next(131)) - hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0) - hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0) - } - if len(prefix) > 0 { - hdr.Name = prefix + "/" + hdr.Name - } - } - - if p.err != nil { - tr.err = p.err - return nil - } - - nb := hdr.Size - if isHeaderOnlyType(hdr.Typeflag) { - nb = 0 - } - if nb < 0 { - tr.err = ErrHeader - return nil - } - - // Set the current file reader. - tr.pad = -nb & (blockSize - 1) // blockSize is a power of two - tr.curr = ®FileReader{r: tr.r, nb: nb} - - // Check for old GNU sparse format entry. - if hdr.Typeflag == TypeGNUSparse { - // Get the real size of the file. - hdr.Size = p.parseNumeric(header[483:495]) - if p.err != nil { - tr.err = p.err - return nil - } - - // Read the sparse map. - sp := tr.readOldGNUSparseMap(header) - if tr.err != nil { - return nil - } - - // Current file is a GNU sparse file. Update the current file reader. - tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size) - if tr.err != nil { - return nil - } - } - - return hdr -} - -// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format. -// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries, -// then one or more extension headers are used to store the rest of the sparse map. -func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry { - var p parser - isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0 - spCap := oldGNUSparseMainHeaderNumEntries - if isExtended { - spCap += oldGNUSparseExtendedHeaderNumEntries - } - sp := make([]sparseEntry, 0, spCap) - s := slicer(header[oldGNUSparseMainHeaderOffset:]) - - // Read the four entries from the main tar header - for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ { - offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize)) - numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize)) - if p.err != nil { - tr.err = p.err - return nil - } - if offset == 0 && numBytes == 0 { - break - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - - for isExtended { - // There are more entries. Read an extension header and parse its entries. - sparseHeader := make([]byte, blockSize) - if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil { - return nil - } - if tr.RawAccounting { - if _, tr.err = tr.rawBytes.Write(sparseHeader); tr.err != nil { - return nil - } - } - - isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0 - s = slicer(sparseHeader) - for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ { - offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize)) - numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize)) - if p.err != nil { - tr.err = p.err - return nil - } - if offset == 0 && numBytes == 0 { - break - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - } - return sp -} - -// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format -// version 1.0. The format of the sparse map consists of a series of -// newline-terminated numeric fields. The first field is the number of entries -// and is always present. Following this are the entries, consisting of two -// fields (offset, numBytes). This function must stop reading at the end -// boundary of the block containing the last newline. -// -// Note that the GNU manual says that numeric values should be encoded in octal -// format. However, the GNU tar utility itself outputs these values in decimal. -// As such, this library treats values as being encoded in decimal. -func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) { - var cntNewline int64 - var buf bytes.Buffer - var blk = make([]byte, blockSize) - - // feedTokens copies data in numBlock chunks from r into buf until there are - // at least cnt newlines in buf. It will not read more blocks than needed. - var feedTokens = func(cnt int64) error { - for cntNewline < cnt { - if _, err := io.ReadFull(r, blk); err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return err - } - buf.Write(blk) - for _, c := range blk { - if c == '\n' { - cntNewline++ - } - } - } - return nil - } - - // nextToken gets the next token delimited by a newline. This assumes that - // at least one newline exists in the buffer. - var nextToken = func() string { - cntNewline-- - tok, _ := buf.ReadString('\n') - return tok[:len(tok)-1] // Cut off newline - } - - // Parse for the number of entries. - // Use integer overflow resistant math to check this. - if err := feedTokens(1); err != nil { - return nil, err - } - numEntries, err := strconv.ParseInt(nextToken(), 10, 0) // Intentionally parse as native int - if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) { - return nil, ErrHeader - } - - // Parse for all member entries. - // numEntries is trusted after this since a potential attacker must have - // committed resources proportional to what this library used. - if err := feedTokens(2 * numEntries); err != nil { - return nil, err - } - sp := make([]sparseEntry, 0, numEntries) - for i := int64(0); i < numEntries; i++ { - offset, err := strconv.ParseInt(nextToken(), 10, 64) - if err != nil { - return nil, ErrHeader - } - numBytes, err := strconv.ParseInt(nextToken(), 10, 64) - if err != nil { - return nil, ErrHeader - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - return sp, nil -} - -// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format -// version 0.1. The sparse map is stored in the PAX headers. -func readGNUSparseMap0x1(extHdrs map[string]string) ([]sparseEntry, error) { - // Get number of entries. - // Use integer overflow resistant math to check this. - numEntriesStr := extHdrs[paxGNUSparseNumBlocks] - numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0) // Intentionally parse as native int - if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) { - return nil, ErrHeader - } - - // There should be two numbers in sparseMap for each entry. - sparseMap := strings.Split(extHdrs[paxGNUSparseMap], ",") - if int64(len(sparseMap)) != 2*numEntries { - return nil, ErrHeader - } - - // Loop through the entries in the sparse map. - // numEntries is trusted now. - sp := make([]sparseEntry, 0, numEntries) - for i := int64(0); i < numEntries; i++ { - offset, err := strconv.ParseInt(sparseMap[2*i], 10, 64) - if err != nil { - return nil, ErrHeader - } - numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 64) - if err != nil { - return nil, ErrHeader - } - sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) - } - return sp, nil -} - -// numBytes returns the number of bytes left to read in the current file's entry -// in the tar archive, or 0 if there is no current file. -func (tr *Reader) numBytes() int64 { - if tr.curr == nil { - // No current file, so no bytes - return 0 - } - return tr.curr.numBytes() -} - -// Read reads from the current entry in the tar archive. -// It returns 0, io.EOF when it reaches the end of that entry, -// until Next is called to advance to the next entry. -// -// Calling Read on special types like TypeLink, TypeSymLink, TypeChar, -// TypeBlock, TypeDir, and TypeFifo returns 0, io.EOF regardless of what -// the Header.Size claims. -func (tr *Reader) Read(b []byte) (n int, err error) { - if tr.err != nil { - return 0, tr.err - } - if tr.curr == nil { - return 0, io.EOF - } - - n, err = tr.curr.Read(b) - if err != nil && err != io.EOF { - tr.err = err - } - return -} - -func (rfr *regFileReader) Read(b []byte) (n int, err error) { - if rfr.nb == 0 { - // file consumed - return 0, io.EOF - } - if int64(len(b)) > rfr.nb { - b = b[0:rfr.nb] - } - n, err = rfr.r.Read(b) - rfr.nb -= int64(n) - - if err == io.EOF && rfr.nb > 0 { - err = io.ErrUnexpectedEOF - } - return -} - -// numBytes returns the number of bytes left to read in the file's data in the tar archive. -func (rfr *regFileReader) numBytes() int64 { - return rfr.nb -} - -// newSparseFileReader creates a new sparseFileReader, but validates all of the -// sparse entries before doing so. -func newSparseFileReader(rfr numBytesReader, sp []sparseEntry, total int64) (*sparseFileReader, error) { - if total < 0 { - return nil, ErrHeader // Total size cannot be negative - } - - // Validate all sparse entries. These are the same checks as performed by - // the BSD tar utility. - for i, s := range sp { - switch { - case s.offset < 0 || s.numBytes < 0: - return nil, ErrHeader // Negative values are never okay - case s.offset > math.MaxInt64-s.numBytes: - return nil, ErrHeader // Integer overflow with large length - case s.offset+s.numBytes > total: - return nil, ErrHeader // Region extends beyond the "real" size - case i > 0 && sp[i-1].offset+sp[i-1].numBytes > s.offset: - return nil, ErrHeader // Regions can't overlap and must be in order - } - } - return &sparseFileReader{rfr: rfr, sp: sp, total: total}, nil -} - -// readHole reads a sparse hole ending at endOffset. -func (sfr *sparseFileReader) readHole(b []byte, endOffset int64) int { - n64 := endOffset - sfr.pos - if n64 > int64(len(b)) { - n64 = int64(len(b)) - } - n := int(n64) - for i := 0; i < n; i++ { - b[i] = 0 - } - sfr.pos += n64 - return n -} - -// Read reads the sparse file data in expanded form. -func (sfr *sparseFileReader) Read(b []byte) (n int, err error) { - // Skip past all empty fragments. - for len(sfr.sp) > 0 && sfr.sp[0].numBytes == 0 { - sfr.sp = sfr.sp[1:] - } - - // If there are no more fragments, then it is possible that there - // is one last sparse hole. - if len(sfr.sp) == 0 { - // This behavior matches the BSD tar utility. - // However, GNU tar stops returning data even if sfr.total is unmet. - if sfr.pos < sfr.total { - return sfr.readHole(b, sfr.total), nil - } - return 0, io.EOF - } - - // In front of a data fragment, so read a hole. - if sfr.pos < sfr.sp[0].offset { - return sfr.readHole(b, sfr.sp[0].offset), nil - } - - // In a data fragment, so read from it. - // This math is overflow free since we verify that offset and numBytes can - // be safely added when creating the sparseFileReader. - endPos := sfr.sp[0].offset + sfr.sp[0].numBytes // End offset of fragment - bytesLeft := endPos - sfr.pos // Bytes left in fragment - if int64(len(b)) > bytesLeft { - b = b[:bytesLeft] - } - - n, err = sfr.rfr.Read(b) - sfr.pos += int64(n) - if err == io.EOF { - if sfr.pos < endPos { - err = io.ErrUnexpectedEOF // There was supposed to be more data - } else if sfr.pos < sfr.total { - err = nil // There is still an implicit sparse hole at the end - } - } - - if sfr.pos == endPos { - sfr.sp = sfr.sp[1:] // We are done with this fragment, so pop it - } - return n, err -} - -// numBytes returns the number of bytes left to read in the sparse file's -// sparse-encoded data in the tar archive. -func (sfr *sparseFileReader) numBytes() int64 { - return sfr.rfr.numBytes() -} diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/stat_atim.go b/vendor/github.com/vbatts/tar-split/archive/tar/stat_atim.go deleted file mode 100644 index cf9cc79c59..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/stat_atim.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux dragonfly openbsd solaris - -package tar - -import ( - "syscall" - "time" -) - -func statAtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Atim.Unix()) -} - -func statCtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Ctim.Unix()) -} diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/stat_atimespec.go b/vendor/github.com/vbatts/tar-split/archive/tar/stat_atimespec.go deleted file mode 100644 index 6f17dbe307..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/stat_atimespec.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin freebsd netbsd - -package tar - -import ( - "syscall" - "time" -) - -func statAtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Atimespec.Unix()) -} - -func statCtime(st *syscall.Stat_t) time.Time { - return time.Unix(st.Ctimespec.Unix()) -} diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/stat_unix.go b/vendor/github.com/vbatts/tar-split/archive/tar/stat_unix.go deleted file mode 100644 index cb843db4cf..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/stat_unix.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux darwin dragonfly freebsd openbsd netbsd solaris - -package tar - -import ( - "os" - "syscall" -) - -func init() { - sysStat = statUnix -} - -func statUnix(fi os.FileInfo, h *Header) error { - sys, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return nil - } - h.Uid = int(sys.Uid) - h.Gid = int(sys.Gid) - // TODO(bradfitz): populate username & group. os/user - // doesn't cache LookupId lookups, and lacks group - // lookup functions. - h.AccessTime = statAtime(sys) - h.ChangeTime = statCtime(sys) - // TODO(bradfitz): major/minor device numbers? - return nil -} diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/writer.go b/vendor/github.com/vbatts/tar-split/archive/tar/writer.go deleted file mode 100644 index 042638175c..0000000000 --- a/vendor/github.com/vbatts/tar-split/archive/tar/writer.go +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tar - -// TODO(dsymonds): -// - catch more errors (no first header, etc.) - -import ( - "bytes" - "errors" - "fmt" - "io" - "path" - "sort" - "strconv" - "strings" - "time" -) - -var ( - ErrWriteTooLong = errors.New("archive/tar: write too long") - ErrFieldTooLong = errors.New("archive/tar: header field too long") - ErrWriteAfterClose = errors.New("archive/tar: write after close") - errInvalidHeader = errors.New("archive/tar: header field too long or contains invalid values") -) - -// A Writer provides sequential writing of a tar archive in POSIX.1 format. -// A tar archive consists of a sequence of files. -// Call WriteHeader to begin a new file, and then call Write to supply that file's data, -// writing at most hdr.Size bytes in total. -type Writer struct { - w io.Writer - err error - nb int64 // number of unwritten bytes for current file entry - pad int64 // amount of padding to write after current file entry - closed bool - usedBinary bool // whether the binary numeric field extension was used - preferPax bool // use pax header instead of binary numeric header - hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header - paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header -} - -type formatter struct { - err error // Last error seen -} - -// NewWriter creates a new Writer writing to w. -func NewWriter(w io.Writer) *Writer { return &Writer{w: w} } - -// Flush finishes writing the current file (optional). -func (tw *Writer) Flush() error { - if tw.nb > 0 { - tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb) - return tw.err - } - - n := tw.nb + tw.pad - for n > 0 && tw.err == nil { - nr := n - if nr > blockSize { - nr = blockSize - } - var nw int - nw, tw.err = tw.w.Write(zeroBlock[0:nr]) - n -= int64(nw) - } - tw.nb = 0 - tw.pad = 0 - return tw.err -} - -// Write s into b, terminating it with a NUL if there is room. -func (f *formatter) formatString(b []byte, s string) { - if len(s) > len(b) { - f.err = ErrFieldTooLong - return - } - ascii := toASCII(s) - copy(b, ascii) - if len(ascii) < len(b) { - b[len(ascii)] = 0 - } -} - -// Encode x as an octal ASCII string and write it into b with leading zeros. -func (f *formatter) formatOctal(b []byte, x int64) { - s := strconv.FormatInt(x, 8) - // leading zeros, but leave room for a NUL. - for len(s)+1 < len(b) { - s = "0" + s - } - f.formatString(b, s) -} - -// fitsInBase256 reports whether x can be encoded into n bytes using base-256 -// encoding. Unlike octal encoding, base-256 encoding does not require that the -// string ends with a NUL character. Thus, all n bytes are available for output. -// -// If operating in binary mode, this assumes strict GNU binary mode; which means -// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is -// equivalent to the sign bit in two's complement form. -func fitsInBase256(n int, x int64) bool { - var binBits = uint(n-1) * 8 - return n >= 9 || (x >= -1<= 0; i-- { - b[i] = byte(x) - x >>= 8 - } - b[0] |= 0x80 // Highest bit indicates binary format - return - } - - f.formatOctal(b, 0) // Last resort, just write zero - f.err = ErrFieldTooLong -} - -var ( - minTime = time.Unix(0, 0) - // There is room for 11 octal digits (33 bits) of mtime. - maxTime = minTime.Add((1<<33 - 1) * time.Second) -) - -// WriteHeader writes hdr and prepares to accept the file's contents. -// WriteHeader calls Flush if it is not the first header. -// Calling after a Close will return ErrWriteAfterClose. -func (tw *Writer) WriteHeader(hdr *Header) error { - return tw.writeHeader(hdr, true) -} - -// WriteHeader writes hdr and prepares to accept the file's contents. -// WriteHeader calls Flush if it is not the first header. -// Calling after a Close will return ErrWriteAfterClose. -// As this method is called internally by writePax header to allow it to -// suppress writing the pax header. -func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { - if tw.closed { - return ErrWriteAfterClose - } - if tw.err == nil { - tw.Flush() - } - if tw.err != nil { - return tw.err - } - - // a map to hold pax header records, if any are needed - paxHeaders := make(map[string]string) - - // TODO(shanemhansen): we might want to use PAX headers for - // subsecond time resolution, but for now let's just capture - // too long fields or non ascii characters - - var f formatter - var header []byte - - // We need to select which scratch buffer to use carefully, - // since this method is called recursively to write PAX headers. - // If allowPax is true, this is the non-recursive call, and we will use hdrBuff. - // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is - // already being used by the non-recursive call, so we must use paxHdrBuff. - header = tw.hdrBuff[:] - if !allowPax { - header = tw.paxHdrBuff[:] - } - copy(header, zeroBlock) - s := slicer(header) - - // Wrappers around formatter that automatically sets paxHeaders if the - // argument extends beyond the capacity of the input byte slice. - var formatString = func(b []byte, s string, paxKeyword string) { - needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s) - if needsPaxHeader { - paxHeaders[paxKeyword] = s - return - } - f.formatString(b, s) - } - var formatNumeric = func(b []byte, x int64, paxKeyword string) { - // Try octal first. - s := strconv.FormatInt(x, 8) - if len(s) < len(b) { - f.formatOctal(b, x) - return - } - - // If it is too long for octal, and PAX is preferred, use a PAX header. - if paxKeyword != paxNone && tw.preferPax { - f.formatOctal(b, 0) - s := strconv.FormatInt(x, 10) - paxHeaders[paxKeyword] = s - return - } - - tw.usedBinary = true - f.formatNumeric(b, x) - } - - // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax - pathHeaderBytes := s.next(fileNameSize) - - formatString(pathHeaderBytes, hdr.Name, paxPath) - - // Handle out of range ModTime carefully. - var modTime int64 - if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) { - modTime = hdr.ModTime.Unix() - } - - f.formatOctal(s.next(8), hdr.Mode) // 100:108 - formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116 - formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124 - formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136 - formatNumeric(s.next(12), modTime, paxNone) // 136:148 --- consider using pax for finer granularity - s.next(8) // chksum (148:156) - s.next(1)[0] = hdr.Typeflag // 156:157 - - formatString(s.next(100), hdr.Linkname, paxLinkpath) - - copy(s.next(8), []byte("ustar\x0000")) // 257:265 - formatString(s.next(32), hdr.Uname, paxUname) // 265:297 - formatString(s.next(32), hdr.Gname, paxGname) // 297:329 - formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337 - formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345 - - // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax - prefixHeaderBytes := s.next(155) - formatString(prefixHeaderBytes, "", paxNone) // 345:500 prefix - - // Use the GNU magic instead of POSIX magic if we used any GNU extensions. - if tw.usedBinary { - copy(header[257:265], []byte("ustar \x00")) - } - - _, paxPathUsed := paxHeaders[paxPath] - // try to use a ustar header when only the name is too long - if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed { - prefix, suffix, ok := splitUSTARPath(hdr.Name) - if ok { - // Since we can encode in USTAR format, disable PAX header. - delete(paxHeaders, paxPath) - - // Update the path fields - formatString(pathHeaderBytes, suffix, paxNone) - formatString(prefixHeaderBytes, prefix, paxNone) - } - } - - // The chksum field is terminated by a NUL and a space. - // This is different from the other octal fields. - chksum, _ := checksum(header) - f.formatOctal(header[148:155], chksum) // Never fails - header[155] = ' ' - - // Check if there were any formatting errors. - if f.err != nil { - tw.err = f.err - return tw.err - } - - if allowPax { - for k, v := range hdr.Xattrs { - paxHeaders[paxXattr+k] = v - } - } - - if len(paxHeaders) > 0 { - if !allowPax { - return errInvalidHeader - } - if err := tw.writePAXHeader(hdr, paxHeaders); err != nil { - return err - } - } - tw.nb = int64(hdr.Size) - tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize - - _, tw.err = tw.w.Write(header) - return tw.err -} - -// splitUSTARPath splits a path according to USTAR prefix and suffix rules. -// If the path is not splittable, then it will return ("", "", false). -func splitUSTARPath(name string) (prefix, suffix string, ok bool) { - length := len(name) - if length <= fileNameSize || !isASCII(name) { - return "", "", false - } else if length > fileNamePrefixSize+1 { - length = fileNamePrefixSize + 1 - } else if name[length-1] == '/' { - length-- - } - - i := strings.LastIndex(name[:length], "/") - nlen := len(name) - i - 1 // nlen is length of suffix - plen := i // plen is length of prefix - if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize { - return "", "", false - } - return name[:i], name[i+1:], true -} - -// writePaxHeader writes an extended pax header to the -// archive. -func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error { - // Prepare extended header - ext := new(Header) - ext.Typeflag = TypeXHeader - // Setting ModTime is required for reader parsing to - // succeed, and seems harmless enough. - ext.ModTime = hdr.ModTime - // The spec asks that we namespace our pseudo files - // with the current pid. However, this results in differing outputs - // for identical inputs. As such, the constant 0 is now used instead. - // golang.org/issue/12358 - dir, file := path.Split(hdr.Name) - fullName := path.Join(dir, "PaxHeaders.0", file) - - ascii := toASCII(fullName) - if len(ascii) > 100 { - ascii = ascii[:100] - } - ext.Name = ascii - // Construct the body - var buf bytes.Buffer - - // Keys are sorted before writing to body to allow deterministic output. - var keys []string - for k := range paxHeaders { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - fmt.Fprint(&buf, formatPAXRecord(k, paxHeaders[k])) - } - - ext.Size = int64(len(buf.Bytes())) - if err := tw.writeHeader(ext, false); err != nil { - return err - } - if _, err := tw.Write(buf.Bytes()); err != nil { - return err - } - if err := tw.Flush(); err != nil { - return err - } - return nil -} - -// formatPAXRecord formats a single PAX record, prefixing it with the -// appropriate length. -func formatPAXRecord(k, v string) string { - const padding = 3 // Extra padding for ' ', '=', and '\n' - size := len(k) + len(v) + padding - size += len(strconv.Itoa(size)) - record := fmt.Sprintf("%d %s=%s\n", size, k, v) - - // Final adjustment if adding size field increased the record size. - if len(record) != size { - size = len(record) - record = fmt.Sprintf("%d %s=%s\n", size, k, v) - } - return record -} - -// Write writes to the current entry in the tar archive. -// Write returns the error ErrWriteTooLong if more than -// hdr.Size bytes are written after WriteHeader. -func (tw *Writer) Write(b []byte) (n int, err error) { - if tw.closed { - err = ErrWriteAfterClose - return - } - overwrite := false - if int64(len(b)) > tw.nb { - b = b[0:tw.nb] - overwrite = true - } - n, err = tw.w.Write(b) - tw.nb -= int64(n) - if err == nil && overwrite { - err = ErrWriteTooLong - return - } - tw.err = err - return -} - -// Close closes the tar archive, flushing any unwritten -// data to the underlying writer. -func (tw *Writer) Close() error { - if tw.err != nil || tw.closed { - return tw.err - } - tw.Flush() - tw.closed = true - if tw.err != nil { - return tw.err - } - - // trailer: two zero blocks - for i := 0; i < 2; i++ { - _, tw.err = tw.w.Write(zeroBlock) - if tw.err != nil { - break - } - } - return tw.err -} diff --git a/vendor/github.com/vbatts/tar-split/tar/asm/assemble.go b/vendor/github.com/vbatts/tar-split/tar/asm/assemble.go deleted file mode 100644 index d624450ab7..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/asm/assemble.go +++ /dev/null @@ -1,130 +0,0 @@ -package asm - -import ( - "bytes" - "fmt" - "hash" - "hash/crc64" - "io" - "sync" - - "github.com/vbatts/tar-split/tar/storage" -) - -// NewOutputTarStream returns an io.ReadCloser that is an assembled tar archive -// stream. -// -// It takes a storage.FileGetter, for mapping the file payloads that are to be read in, -// and a storage.Unpacker, which has access to the rawbytes and file order -// metadata. With the combination of these two items, a precise assembled Tar -// archive is possible. -func NewOutputTarStream(fg storage.FileGetter, up storage.Unpacker) io.ReadCloser { - // ... Since these are interfaces, this is possible, so let's not have a nil pointer - if fg == nil || up == nil { - return nil - } - pr, pw := io.Pipe() - go func() { - err := WriteOutputTarStream(fg, up, pw) - if err != nil { - pw.CloseWithError(err) - } else { - pw.Close() - } - }() - return pr -} - -// WriteOutputTarStream writes assembled tar archive to a writer. -func WriteOutputTarStream(fg storage.FileGetter, up storage.Unpacker, w io.Writer) error { - // ... Since these are interfaces, this is possible, so let's not have a nil pointer - if fg == nil || up == nil { - return nil - } - var copyBuffer []byte - var crcHash hash.Hash - var crcSum []byte - var multiWriter io.Writer - for { - entry, err := up.Next() - if err != nil { - if err == io.EOF { - return nil - } - return err - } - switch entry.Type { - case storage.SegmentType: - if _, err := w.Write(entry.Payload); err != nil { - return err - } - case storage.FileType: - if entry.Size == 0 { - continue - } - fh, err := fg.Get(entry.GetName()) - if err != nil { - return err - } - if crcHash == nil { - crcHash = crc64.New(storage.CRCTable) - crcSum = make([]byte, 8) - multiWriter = io.MultiWriter(w, crcHash) - copyBuffer = byteBufferPool.Get().([]byte) - defer byteBufferPool.Put(copyBuffer) - } else { - crcHash.Reset() - } - - if _, err := copyWithBuffer(multiWriter, fh, copyBuffer); err != nil { - fh.Close() - return err - } - - if !bytes.Equal(crcHash.Sum(crcSum[:0]), entry.Payload) { - // I would rather this be a comparable ErrInvalidChecksum or such, - // but since it's coming through the PipeReader, the context of - // _which_ file would be lost... - fh.Close() - return fmt.Errorf("file integrity checksum failed for %q", entry.GetName()) - } - fh.Close() - } - } -} - -var byteBufferPool = &sync.Pool{ - New: func() interface{} { - return make([]byte, 32*1024) - }, -} - -// copyWithBuffer is taken from stdlib io.Copy implementation -// https://github.com/golang/go/blob/go1.5.1/src/io/io.go#L367 -func copyWithBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err error) { - for { - nr, er := src.Read(buf) - if nr > 0 { - nw, ew := dst.Write(buf[0:nr]) - if nw > 0 { - written += int64(nw) - } - if ew != nil { - err = ew - break - } - if nr != nw { - err = io.ErrShortWrite - break - } - } - if er == io.EOF { - break - } - if er != nil { - err = er - break - } - } - return written, err -} diff --git a/vendor/github.com/vbatts/tar-split/tar/asm/disassemble.go b/vendor/github.com/vbatts/tar-split/tar/asm/disassemble.go deleted file mode 100644 index 009b3f5d81..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/asm/disassemble.go +++ /dev/null @@ -1,154 +0,0 @@ -package asm - -import ( - "io" - - "github.com/vbatts/tar-split/archive/tar" - "github.com/vbatts/tar-split/tar/storage" -) - -// NewInputTarStream wraps the Reader stream of a tar archive and provides a -// Reader stream of the same. -// -// In the middle it will pack the segments and file metadata to storage.Packer -// `p`. -// -// The the storage.FilePutter is where payload of files in the stream are -// stashed. If this stashing is not needed, you can provide a nil -// storage.FilePutter. Since the checksumming is still needed, then a default -// of NewDiscardFilePutter will be used internally -func NewInputTarStream(r io.Reader, p storage.Packer, fp storage.FilePutter) (io.Reader, error) { - // What to do here... folks will want their own access to the Reader that is - // their tar archive stream, but we'll need that same stream to use our - // forked 'archive/tar'. - // Perhaps do an io.TeeReader that hands back an io.Reader for them to read - // from, and we'll MITM the stream to store metadata. - // We'll need a storage.FilePutter too ... - - // Another concern, whether to do any storage.FilePutter operations, such that we - // don't extract any amount of the archive. But then again, we're not making - // files/directories, hardlinks, etc. Just writing the io to the storage.FilePutter. - // Perhaps we have a DiscardFilePutter that is a bit bucket. - - // we'll return the pipe reader, since TeeReader does not buffer and will - // only read what the outputRdr Read's. Since Tar archives have padding on - // the end, we want to be the one reading the padding, even if the user's - // `archive/tar` doesn't care. - pR, pW := io.Pipe() - outputRdr := io.TeeReader(r, pW) - - // we need a putter that will generate the crc64 sums of file payloads - if fp == nil { - fp = storage.NewDiscardFilePutter() - } - - go func() { - tr := tar.NewReader(outputRdr) - tr.RawAccounting = true - for { - hdr, err := tr.Next() - if err != nil { - if err != io.EOF { - pW.CloseWithError(err) - return - } - // even when an EOF is reached, there is often 1024 null bytes on - // the end of an archive. Collect them too. - if b := tr.RawBytes(); len(b) > 0 { - _, err := p.AddEntry(storage.Entry{ - Type: storage.SegmentType, - Payload: b, - }) - if err != nil { - pW.CloseWithError(err) - return - } - } - break // not return. We need the end of the reader. - } - if hdr == nil { - break // not return. We need the end of the reader. - } - - if b := tr.RawBytes(); len(b) > 0 { - _, err := p.AddEntry(storage.Entry{ - Type: storage.SegmentType, - Payload: b, - }) - if err != nil { - pW.CloseWithError(err) - return - } - } - - var csum []byte - if hdr.Size > 0 { - var err error - _, csum, err = fp.Put(hdr.Name, tr) - if err != nil { - pW.CloseWithError(err) - return - } - } - - entry := storage.Entry{ - Type: storage.FileType, - Size: hdr.Size, - Payload: csum, - } - // For proper marshalling of non-utf8 characters - entry.SetName(hdr.Name) - - // File entries added, regardless of size - _, err = p.AddEntry(entry) - if err != nil { - pW.CloseWithError(err) - return - } - - if b := tr.RawBytes(); len(b) > 0 { - _, err = p.AddEntry(storage.Entry{ - Type: storage.SegmentType, - Payload: b, - }) - if err != nil { - pW.CloseWithError(err) - return - } - } - } - - // It is allowable, and not uncommon that there is further padding on - // the end of an archive, apart from the expected 1024 null bytes. We - // do this in chunks rather than in one go to avoid cases where a - // maliciously crafted tar file tries to trick us into reading many GBs - // into memory. - const paddingChunkSize = 1024 * 1024 - var paddingChunk [paddingChunkSize]byte - for { - var isEOF bool - n, err := outputRdr.Read(paddingChunk[:]) - if err != nil { - if err != io.EOF { - pW.CloseWithError(err) - return - } - isEOF = true - } - _, err = p.AddEntry(storage.Entry{ - Type: storage.SegmentType, - Payload: paddingChunk[:n], - }) - if err != nil { - pW.CloseWithError(err) - return - } - if isEOF { - break - } - } - pW.Close() - }() - - return pR, nil -} diff --git a/vendor/github.com/vbatts/tar-split/tar/asm/doc.go b/vendor/github.com/vbatts/tar-split/tar/asm/doc.go deleted file mode 100644 index 4367b90220..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/asm/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -/* -Package asm provides the API for streaming assembly and disassembly of tar -archives. - -Using the `github.com/vbatts/tar-split/tar/storage` for Packing/Unpacking the -metadata for a stream, as well as an implementation of Getting/Putting the file -entries' payload. -*/ -package asm diff --git a/vendor/github.com/vbatts/tar-split/tar/storage/doc.go b/vendor/github.com/vbatts/tar-split/tar/storage/doc.go deleted file mode 100644 index 83f7089ff1..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/storage/doc.go +++ /dev/null @@ -1,12 +0,0 @@ -/* -Package storage is for metadata of a tar archive. - -Packing and unpacking the Entries of the stream. The types of streams are -either segments of raw bytes (for the raw headers and various padding) and for -an entry marking a file payload. - -The raw bytes are stored precisely in the packed (marshalled) Entry, whereas -the file payload marker include the name of the file, size, and crc64 checksum -(for basic file integrity). -*/ -package storage diff --git a/vendor/github.com/vbatts/tar-split/tar/storage/entry.go b/vendor/github.com/vbatts/tar-split/tar/storage/entry.go deleted file mode 100644 index c91e7ea1e8..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/storage/entry.go +++ /dev/null @@ -1,78 +0,0 @@ -package storage - -import "unicode/utf8" - -// Entries is for sorting by Position -type Entries []Entry - -func (e Entries) Len() int { return len(e) } -func (e Entries) Swap(i, j int) { e[i], e[j] = e[j], e[i] } -func (e Entries) Less(i, j int) bool { return e[i].Position < e[j].Position } - -// Type of Entry -type Type int - -const ( - // FileType represents a file payload from the tar stream. - // - // This will be used to map to relative paths on disk. Only Size > 0 will get - // read into a resulting output stream (due to hardlinks). - FileType Type = 1 + iota - // SegmentType represents a raw bytes segment from the archive stream. These raw - // byte segments consist of the raw headers and various padding. - // - // Its payload is to be marshalled base64 encoded. - SegmentType -) - -// Entry is the structure for packing and unpacking the information read from -// the Tar archive. -// -// FileType Payload checksum is using `hash/crc64` for basic file integrity, -// _not_ for cryptography. -// From http://www.backplane.com/matt/crc64.html, CRC32 has almost 40,000 -// collisions in a sample of 18.2 million, CRC64 had none. -type Entry struct { - Type Type `json:"type"` - Name string `json:"name,omitempty"` - NameRaw []byte `json:"name_raw,omitempty"` - Size int64 `json:"size,omitempty"` - Payload []byte `json:"payload"` // SegmentType stores payload here; FileType stores crc64 checksum here; - Position int `json:"position"` -} - -// SetName will check name for valid UTF-8 string, and set the appropriate -// field. See https://github.com/vbatts/tar-split/issues/17 -func (e *Entry) SetName(name string) { - if utf8.ValidString(name) { - e.Name = name - } else { - e.NameRaw = []byte(name) - } -} - -// SetNameBytes will check name for valid UTF-8 string, and set the appropriate -// field -func (e *Entry) SetNameBytes(name []byte) { - if utf8.Valid(name) { - e.Name = string(name) - } else { - e.NameRaw = name - } -} - -// GetName returns the string for the entry's name, regardless of the field stored in -func (e *Entry) GetName() string { - if len(e.NameRaw) > 0 { - return string(e.NameRaw) - } - return e.Name -} - -// GetNameBytes returns the bytes for the entry's name, regardless of the field stored in -func (e *Entry) GetNameBytes() []byte { - if len(e.NameRaw) > 0 { - return e.NameRaw - } - return []byte(e.Name) -} diff --git a/vendor/github.com/vbatts/tar-split/tar/storage/getter.go b/vendor/github.com/vbatts/tar-split/tar/storage/getter.go deleted file mode 100644 index ae11f8ffd4..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/storage/getter.go +++ /dev/null @@ -1,104 +0,0 @@ -package storage - -import ( - "bytes" - "errors" - "hash/crc64" - "io" - "os" - "path/filepath" -) - -// FileGetter is the interface for getting a stream of a file payload, -// addressed by name/filename. Presumably, the names will be scoped to relative -// file paths. -type FileGetter interface { - // Get returns a stream for the provided file path - Get(filename string) (output io.ReadCloser, err error) -} - -// FilePutter is the interface for storing a stream of a file payload, -// addressed by name/filename. -type FilePutter interface { - // Put returns the size of the stream received, and the crc64 checksum for - // the provided stream - Put(filename string, input io.Reader) (size int64, checksum []byte, err error) -} - -// FileGetPutter is the interface that groups both Getting and Putting file -// payloads. -type FileGetPutter interface { - FileGetter - FilePutter -} - -// NewPathFileGetter returns a FileGetter that is for files relative to path -// relpath. -func NewPathFileGetter(relpath string) FileGetter { - return &pathFileGetter{root: relpath} -} - -type pathFileGetter struct { - root string -} - -func (pfg pathFileGetter) Get(filename string) (io.ReadCloser, error) { - return os.Open(filepath.Join(pfg.root, filename)) -} - -type bufferFileGetPutter struct { - files map[string][]byte -} - -func (bfgp bufferFileGetPutter) Get(name string) (io.ReadCloser, error) { - if _, ok := bfgp.files[name]; !ok { - return nil, errors.New("no such file") - } - b := bytes.NewBuffer(bfgp.files[name]) - return &readCloserWrapper{b}, nil -} - -func (bfgp *bufferFileGetPutter) Put(name string, r io.Reader) (int64, []byte, error) { - crc := crc64.New(CRCTable) - buf := bytes.NewBuffer(nil) - cw := io.MultiWriter(crc, buf) - i, err := io.Copy(cw, r) - if err != nil { - return 0, nil, err - } - bfgp.files[name] = buf.Bytes() - return i, crc.Sum(nil), nil -} - -type readCloserWrapper struct { - io.Reader -} - -func (w *readCloserWrapper) Close() error { return nil } - -// NewBufferFileGetPutter is a simple in-memory FileGetPutter -// -// Implication is this is memory intensive... -// Probably best for testing or light weight cases. -func NewBufferFileGetPutter() FileGetPutter { - return &bufferFileGetPutter{ - files: map[string][]byte{}, - } -} - -// NewDiscardFilePutter is a bit bucket FilePutter -func NewDiscardFilePutter() FilePutter { - return &bitBucketFilePutter{} -} - -type bitBucketFilePutter struct { -} - -func (bbfp *bitBucketFilePutter) Put(name string, r io.Reader) (int64, []byte, error) { - c := crc64.New(CRCTable) - i, err := io.Copy(c, r) - return i, c.Sum(nil), err -} - -// CRCTable is the default table used for crc64 sum calculations -var CRCTable = crc64.MakeTable(crc64.ISO) diff --git a/vendor/github.com/vbatts/tar-split/tar/storage/packer.go b/vendor/github.com/vbatts/tar-split/tar/storage/packer.go deleted file mode 100644 index aba6948185..0000000000 --- a/vendor/github.com/vbatts/tar-split/tar/storage/packer.go +++ /dev/null @@ -1,127 +0,0 @@ -package storage - -import ( - "encoding/json" - "errors" - "io" - "path/filepath" - "unicode/utf8" -) - -// ErrDuplicatePath occurs when a tar archive has more than one entry for the -// same file path -var ErrDuplicatePath = errors.New("duplicates of file paths not supported") - -// Packer describes the methods to pack Entries to a storage destination -type Packer interface { - // AddEntry packs the Entry and returns its position - AddEntry(e Entry) (int, error) -} - -// Unpacker describes the methods to read Entries from a source -type Unpacker interface { - // Next returns the next Entry being unpacked, or error, until io.EOF - Next() (*Entry, error) -} - -/* TODO(vbatts) figure out a good model for this -type PackUnpacker interface { - Packer - Unpacker -} -*/ - -type jsonUnpacker struct { - seen seenNames - dec *json.Decoder -} - -func (jup *jsonUnpacker) Next() (*Entry, error) { - var e Entry - err := jup.dec.Decode(&e) - if err != nil { - return nil, err - } - - // check for dup name - if e.Type == FileType { - cName := filepath.Clean(e.GetName()) - if _, ok := jup.seen[cName]; ok { - return nil, ErrDuplicatePath - } - jup.seen[cName] = struct{}{} - } - - return &e, err -} - -// NewJSONUnpacker provides an Unpacker that reads Entries (SegmentType and -// FileType) as a json document. -// -// Each Entry read are expected to be delimited by new line. -func NewJSONUnpacker(r io.Reader) Unpacker { - return &jsonUnpacker{ - dec: json.NewDecoder(r), - seen: seenNames{}, - } -} - -type jsonPacker struct { - w io.Writer - e *json.Encoder - pos int - seen seenNames -} - -type seenNames map[string]struct{} - -func (jp *jsonPacker) AddEntry(e Entry) (int, error) { - // if Name is not valid utf8, switch it to raw first. - if e.Name != "" { - if !utf8.ValidString(e.Name) { - e.NameRaw = []byte(e.Name) - e.Name = "" - } - } - - // check early for dup name - if e.Type == FileType { - cName := filepath.Clean(e.GetName()) - if _, ok := jp.seen[cName]; ok { - return -1, ErrDuplicatePath - } - jp.seen[cName] = struct{}{} - } - - e.Position = jp.pos - err := jp.e.Encode(e) - if err != nil { - return -1, err - } - - // made it this far, increment now - jp.pos++ - return e.Position, nil -} - -// NewJSONPacker provides a Packer that writes each Entry (SegmentType and -// FileType) as a json document. -// -// The Entries are delimited by new line. -func NewJSONPacker(w io.Writer) Packer { - return &jsonPacker{ - w: w, - e: json.NewEncoder(w), - seen: seenNames{}, - } -} - -/* -TODO(vbatts) perhaps have a more compact packer/unpacker, maybe using msgapck -(https://github.com/ugorji/go) - - -Even though, since our jsonUnpacker and jsonPacker just take -io.Reader/io.Writer, then we can get away with passing them a -gzip.Reader/gzip.Writer -*/ diff --git a/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go deleted file mode 100644 index 0b4af37bdc..0000000000 --- a/vendor/golang.org/x/crypto/cast5/cast5.go +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common -// OpenPGP cipher. -package cast5 // import "golang.org/x/crypto/cast5" - -import "errors" - -const BlockSize = 8 -const KeySize = 16 - -type Cipher struct { - masking [16]uint32 - rotate [16]uint8 -} - -func NewCipher(key []byte) (c *Cipher, err error) { - if len(key) != KeySize { - return nil, errors.New("CAST5: keys must be 16 bytes") - } - - c = new(Cipher) - c.keySchedule(key) - return -} - -func (c *Cipher) BlockSize() int { - return BlockSize -} - -func (c *Cipher) Encrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - - l, r = r, l^f1(r, c.masking[0], c.rotate[0]) - l, r = r, l^f2(r, c.masking[1], c.rotate[1]) - l, r = r, l^f3(r, c.masking[2], c.rotate[2]) - l, r = r, l^f1(r, c.masking[3], c.rotate[3]) - - l, r = r, l^f2(r, c.masking[4], c.rotate[4]) - l, r = r, l^f3(r, c.masking[5], c.rotate[5]) - l, r = r, l^f1(r, c.masking[6], c.rotate[6]) - l, r = r, l^f2(r, c.masking[7], c.rotate[7]) - - l, r = r, l^f3(r, c.masking[8], c.rotate[8]) - l, r = r, l^f1(r, c.masking[9], c.rotate[9]) - l, r = r, l^f2(r, c.masking[10], c.rotate[10]) - l, r = r, l^f3(r, c.masking[11], c.rotate[11]) - - l, r = r, l^f1(r, c.masking[12], c.rotate[12]) - l, r = r, l^f2(r, c.masking[13], c.rotate[13]) - l, r = r, l^f3(r, c.masking[14], c.rotate[14]) - l, r = r, l^f1(r, c.masking[15], c.rotate[15]) - - dst[0] = uint8(r >> 24) - dst[1] = uint8(r >> 16) - dst[2] = uint8(r >> 8) - dst[3] = uint8(r) - dst[4] = uint8(l >> 24) - dst[5] = uint8(l >> 16) - dst[6] = uint8(l >> 8) - dst[7] = uint8(l) -} - -func (c *Cipher) Decrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - - l, r = r, l^f1(r, c.masking[15], c.rotate[15]) - l, r = r, l^f3(r, c.masking[14], c.rotate[14]) - l, r = r, l^f2(r, c.masking[13], c.rotate[13]) - l, r = r, l^f1(r, c.masking[12], c.rotate[12]) - - l, r = r, l^f3(r, c.masking[11], c.rotate[11]) - l, r = r, l^f2(r, c.masking[10], c.rotate[10]) - l, r = r, l^f1(r, c.masking[9], c.rotate[9]) - l, r = r, l^f3(r, c.masking[8], c.rotate[8]) - - l, r = r, l^f2(r, c.masking[7], c.rotate[7]) - l, r = r, l^f1(r, c.masking[6], c.rotate[6]) - l, r = r, l^f3(r, c.masking[5], c.rotate[5]) - l, r = r, l^f2(r, c.masking[4], c.rotate[4]) - - l, r = r, l^f1(r, c.masking[3], c.rotate[3]) - l, r = r, l^f3(r, c.masking[2], c.rotate[2]) - l, r = r, l^f2(r, c.masking[1], c.rotate[1]) - l, r = r, l^f1(r, c.masking[0], c.rotate[0]) - - dst[0] = uint8(r >> 24) - dst[1] = uint8(r >> 16) - dst[2] = uint8(r >> 8) - dst[3] = uint8(r) - dst[4] = uint8(l >> 24) - dst[5] = uint8(l >> 16) - dst[6] = uint8(l >> 8) - dst[7] = uint8(l) -} - -type keyScheduleA [4][7]uint8 -type keyScheduleB [4][5]uint8 - -// keyScheduleRound contains the magic values for a round of the key schedule. -// The keyScheduleA deals with the lines like: -// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] -// Conceptually, both x and z are in the same array, x first. The first -// element describes which word of this array gets written to and the -// second, which word gets read. So, for the line above, it's "4, 0", because -// it's writing to the first word of z, which, being after x, is word 4, and -// reading from the first word of x: word 0. -// -// Next are the indexes into the S-boxes. Now the array is treated as bytes. So -// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear -// that it's z that we're indexing. -// -// keyScheduleB deals with lines like: -// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] -// "K1" is ignored because key words are always written in order. So the five -// elements are the S-box indexes. They use the same form as in keyScheduleA, -// above. - -type keyScheduleRound struct{} -type keySchedule []keyScheduleRound - -var schedule = []struct { - a keyScheduleA - b keyScheduleB -}{ - { - keyScheduleA{ - {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, - {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, - {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, - {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, - }, - keyScheduleB{ - {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, - {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, - {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, - {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, - }, - }, - { - keyScheduleA{ - {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, - {1, 4, 0, 2, 1, 3, 16 + 2}, - {2, 5, 7, 6, 5, 4, 16 + 1}, - {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, - }, - keyScheduleB{ - {3, 2, 0xc, 0xd, 8}, - {1, 0, 0xe, 0xf, 0xd}, - {7, 6, 8, 9, 3}, - {5, 4, 0xa, 0xb, 7}, - }, - }, - { - keyScheduleA{ - {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, - {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, - {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, - {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, - }, - keyScheduleB{ - {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, - {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, - {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, - {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, - }, - }, - { - keyScheduleA{ - {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, - {1, 4, 0, 2, 1, 3, 16 + 2}, - {2, 5, 7, 6, 5, 4, 16 + 1}, - {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, - }, - keyScheduleB{ - {8, 9, 7, 6, 3}, - {0xa, 0xb, 5, 4, 7}, - {0xc, 0xd, 3, 2, 8}, - {0xe, 0xf, 1, 0, 0xd}, - }, - }, -} - -func (c *Cipher) keySchedule(in []byte) { - var t [8]uint32 - var k [32]uint32 - - for i := 0; i < 4; i++ { - j := i * 4 - t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) - } - - x := []byte{6, 7, 4, 5} - ki := 0 - - for half := 0; half < 2; half++ { - for _, round := range schedule { - for j := 0; j < 4; j++ { - var a [7]uint8 - copy(a[:], round.a[j][:]) - w := t[a[1]] - w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] - w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] - w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] - w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] - w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] - t[a[0]] = w - } - - for j := 0; j < 4; j++ { - var b [5]uint8 - copy(b[:], round.b[j][:]) - w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] - w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] - w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] - w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] - w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] - k[ki] = w - ki++ - } - } - } - - for i := 0; i < 16; i++ { - c.masking[i] = k[i] - c.rotate[i] = uint8(k[16+i] & 0x1f) - } -} - -// These are the three 'f' functions. See RFC 2144, section 2.2. -func f1(d, m uint32, r uint8) uint32 { - t := m + d - I := (t << r) | (t >> (32 - r)) - return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] -} - -func f2(d, m uint32, r uint8) uint32 { - t := m ^ d - I := (t << r) | (t >> (32 - r)) - return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] -} - -func f3(d, m uint32, r uint8) uint32 { - t := m - d - I := (t << r) | (t >> (32 - r)) - return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] -} - -var sBox = [8][256]uint32{ - { - 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, - }, - { - 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, - }, - { - 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, - }, - { - 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, - }, - { - 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, - }, - { - 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, - }, - { - 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, - }, - { - 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, - }, -} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go deleted file mode 100644 index 592d186436..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/armor/armor.go +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is -// very similar to PEM except that it has an additional CRC checksum. -package armor // import "golang.org/x/crypto/openpgp/armor" - -import ( - "bufio" - "bytes" - "encoding/base64" - "golang.org/x/crypto/openpgp/errors" - "io" -) - -// A Block represents an OpenPGP armored structure. -// -// The encoded form is: -// -----BEGIN Type----- -// Headers -// -// base64-encoded Bytes -// '=' base64 encoded checksum -// -----END Type----- -// where Headers is a possibly empty sequence of Key: Value lines. -// -// Since the armored data can be very large, this package presents a streaming -// interface. -type Block struct { - Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). - Header map[string]string // Optional headers. - Body io.Reader // A Reader from which the contents can be read - lReader lineReader - oReader openpgpReader -} - -var ArmorCorrupt error = errors.StructuralError("armor invalid") - -const crc24Init = 0xb704ce -const crc24Poly = 0x1864cfb -const crc24Mask = 0xffffff - -// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 -func crc24(crc uint32, d []byte) uint32 { - for _, b := range d { - crc ^= uint32(b) << 16 - for i := 0; i < 8; i++ { - crc <<= 1 - if crc&0x1000000 != 0 { - crc ^= crc24Poly - } - } - } - return crc -} - -var armorStart = []byte("-----BEGIN ") -var armorEnd = []byte("-----END ") -var armorEndOfLine = []byte("-----") - -// lineReader wraps a line based reader. It watches for the end of an armor -// block and records the expected CRC value. -type lineReader struct { - in *bufio.Reader - buf []byte - eof bool - crc uint32 -} - -func (l *lineReader) Read(p []byte) (n int, err error) { - if l.eof { - return 0, io.EOF - } - - if len(l.buf) > 0 { - n = copy(p, l.buf) - l.buf = l.buf[n:] - return - } - - line, isPrefix, err := l.in.ReadLine() - if err != nil { - return - } - if isPrefix { - return 0, ArmorCorrupt - } - - if len(line) == 5 && line[0] == '=' { - // This is the checksum line - var expectedBytes [3]byte - var m int - m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) - if m != 3 || err != nil { - return - } - l.crc = uint32(expectedBytes[0])<<16 | - uint32(expectedBytes[1])<<8 | - uint32(expectedBytes[2]) - - line, _, err = l.in.ReadLine() - if err != nil && err != io.EOF { - return - } - if !bytes.HasPrefix(line, armorEnd) { - return 0, ArmorCorrupt - } - - l.eof = true - return 0, io.EOF - } - - if len(line) > 96 { - return 0, ArmorCorrupt - } - - n = copy(p, line) - bytesToSave := len(line) - n - if bytesToSave > 0 { - if cap(l.buf) < bytesToSave { - l.buf = make([]byte, 0, bytesToSave) - } - l.buf = l.buf[0:bytesToSave] - copy(l.buf, line[n:]) - } - - return -} - -// openpgpReader passes Read calls to the underlying base64 decoder, but keeps -// a running CRC of the resulting data and checks the CRC against the value -// found by the lineReader at EOF. -type openpgpReader struct { - lReader *lineReader - b64Reader io.Reader - currentCRC uint32 -} - -func (r *openpgpReader) Read(p []byte) (n int, err error) { - n, err = r.b64Reader.Read(p) - r.currentCRC = crc24(r.currentCRC, p[:n]) - - if err == io.EOF { - if r.lReader.crc != uint32(r.currentCRC&crc24Mask) { - return 0, ArmorCorrupt - } - } - - return -} - -// Decode reads a PGP armored block from the given Reader. It will ignore -// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The -// given Reader is not usable after calling this function: an arbitrary amount -// of data may have been read past the end of the block. -func Decode(in io.Reader) (p *Block, err error) { - r := bufio.NewReaderSize(in, 100) - var line []byte - ignoreNext := false - -TryNextBlock: - p = nil - - // Skip leading garbage - for { - ignoreThis := ignoreNext - line, ignoreNext, err = r.ReadLine() - if err != nil { - return - } - if ignoreNext || ignoreThis { - continue - } - line = bytes.TrimSpace(line) - if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { - break - } - } - - p = new(Block) - p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) - p.Header = make(map[string]string) - nextIsContinuation := false - var lastKey string - - // Read headers - for { - isContinuation := nextIsContinuation - line, nextIsContinuation, err = r.ReadLine() - if err != nil { - p = nil - return - } - if isContinuation { - p.Header[lastKey] += string(line) - continue - } - line = bytes.TrimSpace(line) - if len(line) == 0 { - break - } - - i := bytes.Index(line, []byte(": ")) - if i == -1 { - goto TryNextBlock - } - lastKey = string(line[:i]) - p.Header[lastKey] = string(line[i+2:]) - } - - p.lReader.in = r - p.oReader.currentCRC = crc24Init - p.oReader.lReader = &p.lReader - p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) - p.Body = &p.oReader - - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go deleted file mode 100644 index 6f07582c37..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/armor/encode.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package armor - -import ( - "encoding/base64" - "io" -) - -var armorHeaderSep = []byte(": ") -var blockEnd = []byte("\n=") -var newline = []byte("\n") -var armorEndOfLineOut = []byte("-----\n") - -// writeSlices writes its arguments to the given Writer. -func writeSlices(out io.Writer, slices ...[]byte) (err error) { - for _, s := range slices { - _, err = out.Write(s) - if err != nil { - return err - } - } - return -} - -// lineBreaker breaks data across several lines, all of the same byte length -// (except possibly the last). Lines are broken with a single '\n'. -type lineBreaker struct { - lineLength int - line []byte - used int - out io.Writer - haveWritten bool -} - -func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { - return &lineBreaker{ - lineLength: lineLength, - line: make([]byte, lineLength), - used: 0, - out: out, - } -} - -func (l *lineBreaker) Write(b []byte) (n int, err error) { - n = len(b) - - if n == 0 { - return - } - - if l.used == 0 && l.haveWritten { - _, err = l.out.Write([]byte{'\n'}) - if err != nil { - return - } - } - - if l.used+len(b) < l.lineLength { - l.used += copy(l.line[l.used:], b) - return - } - - l.haveWritten = true - _, err = l.out.Write(l.line[0:l.used]) - if err != nil { - return - } - excess := l.lineLength - l.used - l.used = 0 - - _, err = l.out.Write(b[0:excess]) - if err != nil { - return - } - - _, err = l.Write(b[excess:]) - return -} - -func (l *lineBreaker) Close() (err error) { - if l.used > 0 { - _, err = l.out.Write(l.line[0:l.used]) - if err != nil { - return - } - } - - return -} - -// encoding keeps track of a running CRC24 over the data which has been written -// to it and outputs a OpenPGP checksum when closed, followed by an armor -// trailer. -// -// It's built into a stack of io.Writers: -// encoding -> base64 encoder -> lineBreaker -> out -type encoding struct { - out io.Writer - breaker *lineBreaker - b64 io.WriteCloser - crc uint32 - blockType []byte -} - -func (e *encoding) Write(data []byte) (n int, err error) { - e.crc = crc24(e.crc, data) - return e.b64.Write(data) -} - -func (e *encoding) Close() (err error) { - err = e.b64.Close() - if err != nil { - return - } - e.breaker.Close() - - var checksumBytes [3]byte - checksumBytes[0] = byte(e.crc >> 16) - checksumBytes[1] = byte(e.crc >> 8) - checksumBytes[2] = byte(e.crc) - - var b64ChecksumBytes [4]byte - base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) - - return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) -} - -// Encode returns a WriteCloser which will encode the data written to it in -// OpenPGP armor. -func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { - bType := []byte(blockType) - err = writeSlices(out, armorStart, bType, armorEndOfLineOut) - if err != nil { - return - } - - for k, v := range headers { - err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) - if err != nil { - return - } - } - - _, err = out.Write(newline) - if err != nil { - return - } - - e := &encoding{ - out: out, - breaker: newLineBreaker(out, 64), - crc: crc24Init, - blockType: bType, - } - e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) - return e, nil -} diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go deleted file mode 100644 index e601e389f1..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/canonical_text.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package openpgp - -import "hash" - -// NewCanonicalTextHash reformats text written to it into the canonical -// form and then applies the hash h. See RFC 4880, section 5.2.1. -func NewCanonicalTextHash(h hash.Hash) hash.Hash { - return &canonicalTextHash{h, 0} -} - -type canonicalTextHash struct { - h hash.Hash - s int -} - -var newline = []byte{'\r', '\n'} - -func (cth *canonicalTextHash) Write(buf []byte) (int, error) { - start := 0 - - for i, c := range buf { - switch cth.s { - case 0: - if c == '\r' { - cth.s = 1 - } else if c == '\n' { - cth.h.Write(buf[start:i]) - cth.h.Write(newline) - start = i + 1 - } - case 1: - cth.s = 0 - } - } - - cth.h.Write(buf[start:]) - return len(buf), nil -} - -func (cth *canonicalTextHash) Sum(in []byte) []byte { - return cth.h.Sum(in) -} - -func (cth *canonicalTextHash) Reset() { - cth.h.Reset() - cth.s = 0 -} - -func (cth *canonicalTextHash) Size() int { - return cth.h.Size() -} - -func (cth *canonicalTextHash) BlockSize() int { - return cth.h.BlockSize() -} diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go deleted file mode 100644 index 73f4fe3785..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package elgamal implements ElGamal encryption, suitable for OpenPGP, -// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on -// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, -// n. 4, 1985, pp. 469-472. -// -// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it -// unsuitable for other protocols. RSA should be used in preference in any -// case. -package elgamal // import "golang.org/x/crypto/openpgp/elgamal" - -import ( - "crypto/rand" - "crypto/subtle" - "errors" - "io" - "math/big" -) - -// PublicKey represents an ElGamal public key. -type PublicKey struct { - G, P, Y *big.Int -} - -// PrivateKey represents an ElGamal private key. -type PrivateKey struct { - PublicKey - X *big.Int -} - -// Encrypt encrypts the given message to the given public key. The result is a -// pair of integers. Errors can result from reading random, or because msg is -// too large to be encrypted to the public key. -func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { - pLen := (pub.P.BitLen() + 7) / 8 - if len(msg) > pLen-11 { - err = errors.New("elgamal: message too long") - return - } - - // EM = 0x02 || PS || 0x00 || M - em := make([]byte, pLen-1) - em[0] = 2 - ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] - err = nonZeroRandomBytes(ps, random) - if err != nil { - return - } - em[len(em)-len(msg)-1] = 0 - copy(mm, msg) - - m := new(big.Int).SetBytes(em) - - k, err := rand.Int(random, pub.P) - if err != nil { - return - } - - c1 = new(big.Int).Exp(pub.G, k, pub.P) - s := new(big.Int).Exp(pub.Y, k, pub.P) - c2 = s.Mul(s, m) - c2.Mod(c2, pub.P) - - return -} - -// Decrypt takes two integers, resulting from an ElGamal encryption, and -// returns the plaintext of the message. An error can result only if the -// ciphertext is invalid. Users should keep in mind that this is a padding -// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can -// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks -// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel -// Bleichenbacher, Advances in Cryptology (Crypto '98), -func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { - s := new(big.Int).Exp(c1, priv.X, priv.P) - s.ModInverse(s, priv.P) - s.Mul(s, c2) - s.Mod(s, priv.P) - em := s.Bytes() - - firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) - - // The remainder of the plaintext must be a string of non-zero random - // octets, followed by a 0, followed by the message. - // lookingForIndex: 1 iff we are still looking for the zero. - // index: the offset of the first zero byte. - var lookingForIndex, index int - lookingForIndex = 1 - - for i := 1; i < len(em); i++ { - equals0 := subtle.ConstantTimeByteEq(em[i], 0) - index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) - lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) - } - - if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { - return nil, errors.New("elgamal: decryption error") - } - return em[index+1:], nil -} - -// nonZeroRandomBytes fills the given slice with non-zero random octets. -func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { - _, err = io.ReadFull(rand, s) - if err != nil { - return - } - - for i := 0; i < len(s); i++ { - for s[i] == 0 { - _, err = io.ReadFull(rand, s[i:i+1]) - if err != nil { - return - } - } - } - - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go deleted file mode 100644 index eb0550b2d0..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/errors/errors.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package errors contains common error types for the OpenPGP packages. -package errors // import "golang.org/x/crypto/openpgp/errors" - -import ( - "strconv" -) - -// A StructuralError is returned when OpenPGP data is found to be syntactically -// invalid. -type StructuralError string - -func (s StructuralError) Error() string { - return "openpgp: invalid data: " + string(s) -} - -// UnsupportedError indicates that, although the OpenPGP data is valid, it -// makes use of currently unimplemented features. -type UnsupportedError string - -func (s UnsupportedError) Error() string { - return "openpgp: unsupported feature: " + string(s) -} - -// InvalidArgumentError indicates that the caller is in error and passed an -// incorrect value. -type InvalidArgumentError string - -func (i InvalidArgumentError) Error() string { - return "openpgp: invalid argument: " + string(i) -} - -// SignatureError indicates that a syntactically valid signature failed to -// validate. -type SignatureError string - -func (b SignatureError) Error() string { - return "openpgp: invalid signature: " + string(b) -} - -type keyIncorrectError int - -func (ki keyIncorrectError) Error() string { - return "openpgp: incorrect key" -} - -var ErrKeyIncorrect error = keyIncorrectError(0) - -type unknownIssuerError int - -func (unknownIssuerError) Error() string { - return "openpgp: signature made by unknown entity" -} - -var ErrUnknownIssuer error = unknownIssuerError(0) - -type keyRevokedError int - -func (keyRevokedError) Error() string { - return "openpgp: signature made by revoked key" -} - -var ErrKeyRevoked error = keyRevokedError(0) - -type UnknownPacketTypeError uint8 - -func (upte UnknownPacketTypeError) Error() string { - return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) -} diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go deleted file mode 100644 index fd582a89c0..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ /dev/null @@ -1,641 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package openpgp - -import ( - "crypto/rsa" - "io" - "time" - - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" -) - -// PublicKeyType is the armor type for a PGP public key. -var PublicKeyType = "PGP PUBLIC KEY BLOCK" - -// PrivateKeyType is the armor type for a PGP private key. -var PrivateKeyType = "PGP PRIVATE KEY BLOCK" - -// An Entity represents the components of an OpenPGP key: a primary public key -// (which must be a signing key), one or more identities claimed by that key, -// and zero or more subkeys, which may be encryption keys. -type Entity struct { - PrimaryKey *packet.PublicKey - PrivateKey *packet.PrivateKey - Identities map[string]*Identity // indexed by Identity.Name - Revocations []*packet.Signature - Subkeys []Subkey -} - -// An Identity represents an identity claimed by an Entity and zero or more -// assertions by other entities about that claim. -type Identity struct { - Name string // by convention, has the form "Full Name (comment) " - UserId *packet.UserId - SelfSignature *packet.Signature - Signatures []*packet.Signature -} - -// A Subkey is an additional public key in an Entity. Subkeys can be used for -// encryption. -type Subkey struct { - PublicKey *packet.PublicKey - PrivateKey *packet.PrivateKey - Sig *packet.Signature -} - -// A Key identifies a specific public key in an Entity. This is either the -// Entity's primary key or a subkey. -type Key struct { - Entity *Entity - PublicKey *packet.PublicKey - PrivateKey *packet.PrivateKey - SelfSignature *packet.Signature -} - -// A KeyRing provides access to public and private keys. -type KeyRing interface { - // KeysById returns the set of keys that have the given key id. - KeysById(id uint64) []Key - // KeysByIdAndUsage returns the set of keys with the given id - // that also meet the key usage given by requiredUsage. - // The requiredUsage is expressed as the bitwise-OR of - // packet.KeyFlag* values. - KeysByIdUsage(id uint64, requiredUsage byte) []Key - // DecryptionKeys returns all private keys that are valid for - // decryption. - DecryptionKeys() []Key -} - -// primaryIdentity returns the Identity marked as primary or the first identity -// if none are so marked. -func (e *Entity) primaryIdentity() *Identity { - var firstIdentity *Identity - for _, ident := range e.Identities { - if firstIdentity == nil { - firstIdentity = ident - } - if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { - return ident - } - } - return firstIdentity -} - -// encryptionKey returns the best candidate Key for encrypting a message to the -// given Entity. -func (e *Entity) encryptionKey(now time.Time) (Key, bool) { - candidateSubkey := -1 - - // Iterate the keys to find the newest key - var maxTime time.Time - for i, subkey := range e.Subkeys { - if subkey.Sig.FlagsValid && - subkey.Sig.FlagEncryptCommunications && - subkey.PublicKey.PubKeyAlgo.CanEncrypt() && - !subkey.Sig.KeyExpired(now) && - (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { - candidateSubkey = i - maxTime = subkey.Sig.CreationTime - } - } - - if candidateSubkey != -1 { - subkey := e.Subkeys[candidateSubkey] - return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true - } - - // If we don't have any candidate subkeys for encryption and - // the primary key doesn't have any usage metadata then we - // assume that the primary key is ok. Or, if the primary key is - // marked as ok to encrypt to, then we can obviously use it. - i := e.primaryIdentity() - if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && - e.PrimaryKey.PubKeyAlgo.CanEncrypt() && - !i.SelfSignature.KeyExpired(now) { - return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true - } - - // This Entity appears to be signing only. - return Key{}, false -} - -// signingKey return the best candidate Key for signing a message with this -// Entity. -func (e *Entity) signingKey(now time.Time) (Key, bool) { - candidateSubkey := -1 - - for i, subkey := range e.Subkeys { - if subkey.Sig.FlagsValid && - subkey.Sig.FlagSign && - subkey.PublicKey.PubKeyAlgo.CanSign() && - !subkey.Sig.KeyExpired(now) { - candidateSubkey = i - break - } - } - - if candidateSubkey != -1 { - subkey := e.Subkeys[candidateSubkey] - return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true - } - - // If we have no candidate subkey then we assume that it's ok to sign - // with the primary key. - i := e.primaryIdentity() - if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && - !i.SelfSignature.KeyExpired(now) { - return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true - } - - return Key{}, false -} - -// An EntityList contains one or more Entities. -type EntityList []*Entity - -// KeysById returns the set of keys that have the given key id. -func (el EntityList) KeysById(id uint64) (keys []Key) { - for _, e := range el { - if e.PrimaryKey.KeyId == id { - var selfSig *packet.Signature - for _, ident := range e.Identities { - if selfSig == nil { - selfSig = ident.SelfSignature - } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { - selfSig = ident.SelfSignature - break - } - } - keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) - } - - for _, subKey := range e.Subkeys { - if subKey.PublicKey.KeyId == id { - keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) - } - } - } - return -} - -// KeysByIdAndUsage returns the set of keys with the given id that also meet -// the key usage given by requiredUsage. The requiredUsage is expressed as -// the bitwise-OR of packet.KeyFlag* values. -func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { - for _, key := range el.KeysById(id) { - if len(key.Entity.Revocations) > 0 { - continue - } - - if key.SelfSignature.RevocationReason != nil { - continue - } - - if key.SelfSignature.FlagsValid && requiredUsage != 0 { - var usage byte - if key.SelfSignature.FlagCertify { - usage |= packet.KeyFlagCertify - } - if key.SelfSignature.FlagSign { - usage |= packet.KeyFlagSign - } - if key.SelfSignature.FlagEncryptCommunications { - usage |= packet.KeyFlagEncryptCommunications - } - if key.SelfSignature.FlagEncryptStorage { - usage |= packet.KeyFlagEncryptStorage - } - if usage&requiredUsage != requiredUsage { - continue - } - } - - keys = append(keys, key) - } - return -} - -// DecryptionKeys returns all private keys that are valid for decryption. -func (el EntityList) DecryptionKeys() (keys []Key) { - for _, e := range el { - for _, subKey := range e.Subkeys { - if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { - keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) - } - } - } - return -} - -// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. -func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { - block, err := armor.Decode(r) - if err == io.EOF { - return nil, errors.InvalidArgumentError("no armored data found") - } - if err != nil { - return nil, err - } - if block.Type != PublicKeyType && block.Type != PrivateKeyType { - return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) - } - - return ReadKeyRing(block.Body) -} - -// ReadKeyRing reads one or more public/private keys. Unsupported keys are -// ignored as long as at least a single valid key is found. -func ReadKeyRing(r io.Reader) (el EntityList, err error) { - packets := packet.NewReader(r) - var lastUnsupportedError error - - for { - var e *Entity - e, err = ReadEntity(packets) - if err != nil { - // TODO: warn about skipped unsupported/unreadable keys - if _, ok := err.(errors.UnsupportedError); ok { - lastUnsupportedError = err - err = readToNextPublicKey(packets) - } else if _, ok := err.(errors.StructuralError); ok { - // Skip unreadable, badly-formatted keys - lastUnsupportedError = err - err = readToNextPublicKey(packets) - } - if err == io.EOF { - err = nil - break - } - if err != nil { - el = nil - break - } - } else { - el = append(el, e) - } - } - - if len(el) == 0 && err == nil { - err = lastUnsupportedError - } - return -} - -// readToNextPublicKey reads packets until the start of the entity and leaves -// the first packet of the new entity in the Reader. -func readToNextPublicKey(packets *packet.Reader) (err error) { - var p packet.Packet - for { - p, err = packets.Next() - if err == io.EOF { - return - } else if err != nil { - if _, ok := err.(errors.UnsupportedError); ok { - err = nil - continue - } - return - } - - if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { - packets.Unread(p) - return - } - } -} - -// ReadEntity reads an entity (public key, identities, subkeys etc) from the -// given Reader. -func ReadEntity(packets *packet.Reader) (*Entity, error) { - e := new(Entity) - e.Identities = make(map[string]*Identity) - - p, err := packets.Next() - if err != nil { - return nil, err - } - - var ok bool - if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { - if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { - packets.Unread(p) - return nil, errors.StructuralError("first packet was not a public/private key") - } - e.PrimaryKey = &e.PrivateKey.PublicKey - } - - if !e.PrimaryKey.PubKeyAlgo.CanSign() { - return nil, errors.StructuralError("primary key cannot be used for signatures") - } - - var current *Identity - var revocations []*packet.Signature -EachPacket: - for { - p, err := packets.Next() - if err == io.EOF { - break - } else if err != nil { - return nil, err - } - - switch pkt := p.(type) { - case *packet.UserId: - current = new(Identity) - current.Name = pkt.Id - current.UserId = pkt - e.Identities[pkt.Id] = current - - for { - p, err = packets.Next() - if err == io.EOF { - return nil, io.ErrUnexpectedEOF - } else if err != nil { - return nil, err - } - - sig, ok := p.(*packet.Signature) - if !ok { - return nil, errors.StructuralError("user ID packet not followed by self-signature") - } - - if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { - if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { - return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) - } - current.SelfSignature = sig - break - } - current.Signatures = append(current.Signatures, sig) - } - case *packet.Signature: - if pkt.SigType == packet.SigTypeKeyRevocation { - revocations = append(revocations, pkt) - } else if pkt.SigType == packet.SigTypeDirectSignature { - // TODO: RFC4880 5.2.1 permits signatures - // directly on keys (eg. to bind additional - // revocation keys). - } else if current == nil { - return nil, errors.StructuralError("signature packet found before user id packet") - } else { - current.Signatures = append(current.Signatures, pkt) - } - case *packet.PrivateKey: - if pkt.IsSubkey == false { - packets.Unread(p) - break EachPacket - } - err = addSubkey(e, packets, &pkt.PublicKey, pkt) - if err != nil { - return nil, err - } - case *packet.PublicKey: - if pkt.IsSubkey == false { - packets.Unread(p) - break EachPacket - } - err = addSubkey(e, packets, pkt, nil) - if err != nil { - return nil, err - } - default: - // we ignore unknown packets - } - } - - if len(e.Identities) == 0 { - return nil, errors.StructuralError("entity without any identities") - } - - for _, revocation := range revocations { - err = e.PrimaryKey.VerifyRevocationSignature(revocation) - if err == nil { - e.Revocations = append(e.Revocations, revocation) - } else { - // TODO: RFC 4880 5.2.3.15 defines revocation keys. - return nil, errors.StructuralError("revocation signature signed by alternate key") - } - } - - return e, nil -} - -func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { - var subKey Subkey - subKey.PublicKey = pub - subKey.PrivateKey = priv - p, err := packets.Next() - if err == io.EOF { - return io.ErrUnexpectedEOF - } - if err != nil { - return errors.StructuralError("subkey signature invalid: " + err.Error()) - } - var ok bool - subKey.Sig, ok = p.(*packet.Signature) - if !ok { - return errors.StructuralError("subkey packet not followed by signature") - } - if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation { - return errors.StructuralError("subkey signature with wrong type") - } - err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig) - if err != nil { - return errors.StructuralError("subkey signature invalid: " + err.Error()) - } - e.Subkeys = append(e.Subkeys, subKey) - return nil -} - -const defaultRSAKeyBits = 2048 - -// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a -// single identity composed of the given full name, comment and email, any of -// which may be empty but must not contain any of "()<>\x00". -// If config is nil, sensible defaults will be used. -func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { - currentTime := config.Now() - - bits := defaultRSAKeyBits - if config != nil && config.RSABits != 0 { - bits = config.RSABits - } - - uid := packet.NewUserId(name, comment, email) - if uid == nil { - return nil, errors.InvalidArgumentError("user id field contained invalid characters") - } - signingPriv, err := rsa.GenerateKey(config.Random(), bits) - if err != nil { - return nil, err - } - encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) - if err != nil { - return nil, err - } - - e := &Entity{ - PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey), - PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv), - Identities: make(map[string]*Identity), - } - isPrimaryId := true - e.Identities[uid.Id] = &Identity{ - Name: uid.Id, - UserId: uid, - SelfSignature: &packet.Signature{ - CreationTime: currentTime, - SigType: packet.SigTypePositiveCert, - PubKeyAlgo: packet.PubKeyAlgoRSA, - Hash: config.Hash(), - IsPrimaryId: &isPrimaryId, - FlagsValid: true, - FlagSign: true, - FlagCertify: true, - IssuerKeyId: &e.PrimaryKey.KeyId, - }, - } - - // If the user passes in a DefaultHash via packet.Config, - // set the PreferredHash for the SelfSignature. - if config != nil && config.DefaultHash != 0 { - e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} - } - - // Likewise for DefaultCipher. - if config != nil && config.DefaultCipher != 0 { - e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} - } - - e.Subkeys = make([]Subkey, 1) - e.Subkeys[0] = Subkey{ - PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), - PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv), - Sig: &packet.Signature{ - CreationTime: currentTime, - SigType: packet.SigTypeSubkeyBinding, - PubKeyAlgo: packet.PubKeyAlgoRSA, - Hash: config.Hash(), - FlagsValid: true, - FlagEncryptStorage: true, - FlagEncryptCommunications: true, - IssuerKeyId: &e.PrimaryKey.KeyId, - }, - } - e.Subkeys[0].PublicKey.IsSubkey = true - e.Subkeys[0].PrivateKey.IsSubkey = true - - return e, nil -} - -// SerializePrivate serializes an Entity, including private key material, to -// the given Writer. For now, it must only be used on an Entity returned from -// NewEntity. -// If config is nil, sensible defaults will be used. -func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { - err = e.PrivateKey.Serialize(w) - if err != nil { - return - } - for _, ident := range e.Identities { - err = ident.UserId.Serialize(w) - if err != nil { - return - } - err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) - if err != nil { - return - } - err = ident.SelfSignature.Serialize(w) - if err != nil { - return - } - } - for _, subkey := range e.Subkeys { - err = subkey.PrivateKey.Serialize(w) - if err != nil { - return - } - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) - if err != nil { - return - } - err = subkey.Sig.Serialize(w) - if err != nil { - return - } - } - return nil -} - -// Serialize writes the public part of the given Entity to w. (No private -// key material will be output). -func (e *Entity) Serialize(w io.Writer) error { - err := e.PrimaryKey.Serialize(w) - if err != nil { - return err - } - for _, ident := range e.Identities { - err = ident.UserId.Serialize(w) - if err != nil { - return err - } - err = ident.SelfSignature.Serialize(w) - if err != nil { - return err - } - for _, sig := range ident.Signatures { - err = sig.Serialize(w) - if err != nil { - return err - } - } - } - for _, subkey := range e.Subkeys { - err = subkey.PublicKey.Serialize(w) - if err != nil { - return err - } - err = subkey.Sig.Serialize(w) - if err != nil { - return err - } - } - return nil -} - -// SignIdentity adds a signature to e, from signer, attesting that identity is -// associated with e. The provided identity must already be an element of -// e.Identities and the private key of signer must have been decrypted if -// necessary. -// If config is nil, sensible defaults will be used. -func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { - if signer.PrivateKey == nil { - return errors.InvalidArgumentError("signing Entity must have a private key") - } - if signer.PrivateKey.Encrypted { - return errors.InvalidArgumentError("signing Entity's private key must be decrypted") - } - ident, ok := e.Identities[identity] - if !ok { - return errors.InvalidArgumentError("given identity string not found in Entity") - } - - sig := &packet.Signature{ - SigType: packet.SigTypeGenericCert, - PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, - Hash: config.Hash(), - CreationTime: config.Now(), - IssuerKeyId: &signer.PrivateKey.KeyId, - } - if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { - return err - } - ident.Signatures = append(ident.Signatures, sig) - return nil -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go deleted file mode 100644 index e8f0b5caa7..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "compress/bzip2" - "compress/flate" - "compress/zlib" - "golang.org/x/crypto/openpgp/errors" - "io" - "strconv" -) - -// Compressed represents a compressed OpenPGP packet. The decompressed contents -// will contain more OpenPGP packets. See RFC 4880, section 5.6. -type Compressed struct { - Body io.Reader -} - -const ( - NoCompression = flate.NoCompression - BestSpeed = flate.BestSpeed - BestCompression = flate.BestCompression - DefaultCompression = flate.DefaultCompression -) - -// CompressionConfig contains compressor configuration settings. -type CompressionConfig struct { - // Level is the compression level to use. It must be set to - // between -1 and 9, with -1 causing the compressor to use the - // default compression level, 0 causing the compressor to use - // no compression and 1 to 9 representing increasing (better, - // slower) compression levels. If Level is less than -1 or - // more then 9, a non-nil error will be returned during - // encryption. See the constants above for convenient common - // settings for Level. - Level int -} - -func (c *Compressed) parse(r io.Reader) error { - var buf [1]byte - _, err := readFull(r, buf[:]) - if err != nil { - return err - } - - switch buf[0] { - case 1: - c.Body = flate.NewReader(r) - case 2: - c.Body, err = zlib.NewReader(r) - case 3: - c.Body = bzip2.NewReader(r) - default: - err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) - } - - return err -} - -// compressedWriterCloser represents the serialized compression stream -// header and the compressor. Its Close() method ensures that both the -// compressor and serialized stream header are closed. Its Write() -// method writes to the compressor. -type compressedWriteCloser struct { - sh io.Closer // Stream Header - c io.WriteCloser // Compressor -} - -func (cwc compressedWriteCloser) Write(p []byte) (int, error) { - return cwc.c.Write(p) -} - -func (cwc compressedWriteCloser) Close() (err error) { - err = cwc.c.Close() - if err != nil { - return err - } - - return cwc.sh.Close() -} - -// SerializeCompressed serializes a compressed data packet to w and -// returns a WriteCloser to which the literal data packets themselves -// can be written and which MUST be closed on completion. If cc is -// nil, sensible defaults will be used to configure the compression -// algorithm. -func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { - compressed, err := serializeStreamHeader(w, packetTypeCompressed) - if err != nil { - return - } - - _, err = compressed.Write([]byte{uint8(algo)}) - if err != nil { - return - } - - level := DefaultCompression - if cc != nil { - level = cc.Level - } - - var compressor io.WriteCloser - switch algo { - case CompressionZIP: - compressor, err = flate.NewWriter(compressed, level) - case CompressionZLIB: - compressor, err = zlib.NewWriterLevel(compressed, level) - default: - s := strconv.Itoa(int(algo)) - err = errors.UnsupportedError("Unsupported compression algorithm: " + s) - } - if err != nil { - return - } - - literaldata = compressedWriteCloser{compressed, compressor} - - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go deleted file mode 100644 index c76eecc963..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/config.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto" - "crypto/rand" - "io" - "time" -) - -// Config collects a number of parameters along with sensible defaults. -// A nil *Config is valid and results in all default values. -type Config struct { - // Rand provides the source of entropy. - // If nil, the crypto/rand Reader is used. - Rand io.Reader - // DefaultHash is the default hash function to be used. - // If zero, SHA-256 is used. - DefaultHash crypto.Hash - // DefaultCipher is the cipher to be used. - // If zero, AES-128 is used. - DefaultCipher CipherFunction - // Time returns the current time as the number of seconds since the - // epoch. If Time is nil, time.Now is used. - Time func() time.Time - // DefaultCompressionAlgo is the compression algorithm to be - // applied to the plaintext before encryption. If zero, no - // compression is done. - DefaultCompressionAlgo CompressionAlgo - // CompressionConfig configures the compression settings. - CompressionConfig *CompressionConfig - // S2KCount is only used for symmetric encryption. It - // determines the strength of the passphrase stretching when - // the said passphrase is hashed to produce a key. S2KCount - // should be between 1024 and 65011712, inclusive. If Config - // is nil or S2KCount is 0, the value 65536 used. Not all - // values in the above range can be represented. S2KCount will - // be rounded up to the next representable value if it cannot - // be encoded exactly. When set, it is strongly encrouraged to - // use a value that is at least 65536. See RFC 4880 Section - // 3.7.1.3. - S2KCount int - // RSABits is the number of bits in new RSA keys made with NewEntity. - // If zero, then 2048 bit keys are created. - RSABits int -} - -func (c *Config) Random() io.Reader { - if c == nil || c.Rand == nil { - return rand.Reader - } - return c.Rand -} - -func (c *Config) Hash() crypto.Hash { - if c == nil || uint(c.DefaultHash) == 0 { - return crypto.SHA256 - } - return c.DefaultHash -} - -func (c *Config) Cipher() CipherFunction { - if c == nil || uint8(c.DefaultCipher) == 0 { - return CipherAES128 - } - return c.DefaultCipher -} - -func (c *Config) Now() time.Time { - if c == nil || c.Time == nil { - return time.Now() - } - return c.Time() -} - -func (c *Config) Compression() CompressionAlgo { - if c == nil { - return CompressionNone - } - return c.DefaultCompressionAlgo -} - -func (c *Config) PasswordHashIterations() int { - if c == nil || c.S2KCount == 0 { - return 0 - } - return c.S2KCount -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go deleted file mode 100644 index 02b372cf37..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto/rsa" - "encoding/binary" - "io" - "math/big" - "strconv" - - "golang.org/x/crypto/openpgp/elgamal" - "golang.org/x/crypto/openpgp/errors" -) - -const encryptedKeyVersion = 3 - -// EncryptedKey represents a public-key encrypted session key. See RFC 4880, -// section 5.1. -type EncryptedKey struct { - KeyId uint64 - Algo PublicKeyAlgorithm - CipherFunc CipherFunction // only valid after a successful Decrypt - Key []byte // only valid after a successful Decrypt - - encryptedMPI1, encryptedMPI2 parsedMPI -} - -func (e *EncryptedKey) parse(r io.Reader) (err error) { - var buf [10]byte - _, err = readFull(r, buf[:]) - if err != nil { - return - } - if buf[0] != encryptedKeyVersion { - return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) - } - e.KeyId = binary.BigEndian.Uint64(buf[1:9]) - e.Algo = PublicKeyAlgorithm(buf[9]) - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) - if err != nil { - return - } - case PubKeyAlgoElGamal: - e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) - if err != nil { - return - } - e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) - if err != nil { - return - } - } - _, err = consumeAll(r) - return -} - -func checksumKeyMaterial(key []byte) uint16 { - var checksum uint16 - for _, v := range key { - checksum += uint16(v) - } - return checksum -} - -// Decrypt decrypts an encrypted session key with the given private key. The -// private key must have been decrypted first. -// If config is nil, sensible defaults will be used. -func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { - var err error - var b []byte - - // TODO(agl): use session key decryption routines here to avoid - // padding oracle attacks. - switch priv.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - k := priv.PrivateKey.(*rsa.PrivateKey) - b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes)) - case PubKeyAlgoElGamal: - c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) - c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) - b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) - default: - err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) - } - - if err != nil { - return err - } - - e.CipherFunc = CipherFunction(b[0]) - e.Key = b[1 : len(b)-2] - expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) - checksum := checksumKeyMaterial(e.Key) - if checksum != expectedChecksum { - return errors.StructuralError("EncryptedKey checksum incorrect") - } - - return nil -} - -// Serialize writes the encrypted key packet, e, to w. -func (e *EncryptedKey) Serialize(w io.Writer) error { - var mpiLen int - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - mpiLen = 2 + len(e.encryptedMPI1.bytes) - case PubKeyAlgoElGamal: - mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) - default: - return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) - } - - serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) - - w.Write([]byte{encryptedKeyVersion}) - binary.Write(w, binary.BigEndian, e.KeyId) - w.Write([]byte{byte(e.Algo)}) - - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - writeMPIs(w, e.encryptedMPI1) - case PubKeyAlgoElGamal: - writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) - default: - panic("internal error") - } - - return nil -} - -// SerializeEncryptedKey serializes an encrypted key packet to w that contains -// key, encrypted to pub. -// If config is nil, sensible defaults will be used. -func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { - var buf [10]byte - buf[0] = encryptedKeyVersion - binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) - buf[9] = byte(pub.PubKeyAlgo) - - keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) - keyBlock[0] = byte(cipherFunc) - copy(keyBlock[1:], key) - checksum := checksumKeyMaterial(key) - keyBlock[1+len(key)] = byte(checksum >> 8) - keyBlock[1+len(key)+1] = byte(checksum) - - switch pub.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) - case PubKeyAlgoElGamal: - return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) - case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: - return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) - } - - return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -} - -func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { - cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) - } - - packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - _, err = w.Write(header[:]) - if err != nil { - return err - } - return writeMPI(w, 8*uint16(len(cipherText)), cipherText) -} - -func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { - c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) - } - - packetLen := 10 /* header length */ - packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 - packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - _, err = w.Write(header[:]) - if err != nil { - return err - } - err = writeBig(w, c1) - if err != nil { - return err - } - return writeBig(w, c2) -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go deleted file mode 100644 index 1a9ec6e51e..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/literal.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "encoding/binary" - "io" -) - -// LiteralData represents an encrypted file. See RFC 4880, section 5.9. -type LiteralData struct { - IsBinary bool - FileName string - Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. - Body io.Reader -} - -// ForEyesOnly returns whether the contents of the LiteralData have been marked -// as especially sensitive. -func (l *LiteralData) ForEyesOnly() bool { - return l.FileName == "_CONSOLE" -} - -func (l *LiteralData) parse(r io.Reader) (err error) { - var buf [256]byte - - _, err = readFull(r, buf[:2]) - if err != nil { - return - } - - l.IsBinary = buf[0] == 'b' - fileNameLen := int(buf[1]) - - _, err = readFull(r, buf[:fileNameLen]) - if err != nil { - return - } - - l.FileName = string(buf[:fileNameLen]) - - _, err = readFull(r, buf[:4]) - if err != nil { - return - } - - l.Time = binary.BigEndian.Uint32(buf[:4]) - l.Body = r - return -} - -// SerializeLiteral serializes a literal data packet to w and returns a -// WriteCloser to which the data itself can be written and which MUST be closed -// on completion. The fileName is truncated to 255 bytes. -func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { - var buf [4]byte - buf[0] = 't' - if isBinary { - buf[0] = 'b' - } - if len(fileName) > 255 { - fileName = fileName[:255] - } - buf[1] = byte(len(fileName)) - - inner, err := serializeStreamHeader(w, packetTypeLiteralData) - if err != nil { - return - } - - _, err = inner.Write(buf[:2]) - if err != nil { - return - } - _, err = inner.Write([]byte(fileName)) - if err != nil { - return - } - binary.BigEndian.PutUint32(buf[:], time) - _, err = inner.Write(buf[:]) - if err != nil { - return - } - - plaintext = inner - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go deleted file mode 100644 index ce2a33a547..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 - -package packet - -import ( - "crypto/cipher" -) - -type ocfbEncrypter struct { - b cipher.Block - fre []byte - outUsed int -} - -// An OCFBResyncOption determines if the "resynchronization step" of OCFB is -// performed. -type OCFBResyncOption bool - -const ( - OCFBResync OCFBResyncOption = true - OCFBNoResync OCFBResyncOption = false -) - -// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's -// cipher feedback mode using the given cipher.Block, and an initial amount of -// ciphertext. randData must be random bytes and be the same length as the -// cipher.Block's block size. Resync determines if the "resynchronization step" -// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on -// this point. -func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { - blockSize := block.BlockSize() - if len(randData) != blockSize { - return nil, nil - } - - x := &ocfbEncrypter{ - b: block, - fre: make([]byte, blockSize), - outUsed: 0, - } - prefix := make([]byte, blockSize+2) - - block.Encrypt(x.fre, x.fre) - for i := 0; i < blockSize; i++ { - prefix[i] = randData[i] ^ x.fre[i] - } - - block.Encrypt(x.fre, prefix[:blockSize]) - prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] - prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] - - if resync { - block.Encrypt(x.fre, prefix[2:]) - } else { - x.fre[0] = prefix[blockSize] - x.fre[1] = prefix[blockSize+1] - x.outUsed = 2 - } - return x, prefix -} - -func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.fre) { - x.b.Encrypt(x.fre, x.fre) - x.outUsed = 0 - } - - x.fre[x.outUsed] ^= src[i] - dst[i] = x.fre[x.outUsed] - x.outUsed++ - } -} - -type ocfbDecrypter struct { - b cipher.Block - fre []byte - outUsed int -} - -// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's -// cipher feedback mode using the given cipher.Block. Prefix must be the first -// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's -// block size. If an incorrect key is detected then nil is returned. On -// successful exit, blockSize+2 bytes of decrypted data are written into -// prefix. Resync determines if the "resynchronization step" from RFC 4880, -// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. -func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { - blockSize := block.BlockSize() - if len(prefix) != blockSize+2 { - return nil - } - - x := &ocfbDecrypter{ - b: block, - fre: make([]byte, blockSize), - outUsed: 0, - } - prefixCopy := make([]byte, len(prefix)) - copy(prefixCopy, prefix) - - block.Encrypt(x.fre, x.fre) - for i := 0; i < blockSize; i++ { - prefixCopy[i] ^= x.fre[i] - } - - block.Encrypt(x.fre, prefix[:blockSize]) - prefixCopy[blockSize] ^= x.fre[0] - prefixCopy[blockSize+1] ^= x.fre[1] - - if prefixCopy[blockSize-2] != prefixCopy[blockSize] || - prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { - return nil - } - - if resync { - block.Encrypt(x.fre, prefix[2:]) - } else { - x.fre[0] = prefix[blockSize] - x.fre[1] = prefix[blockSize+1] - x.outUsed = 2 - } - copy(prefix, prefixCopy) - return x -} - -func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.fre) { - x.b.Encrypt(x.fre, x.fre) - x.outUsed = 0 - } - - c := src[i] - dst[i] = x.fre[x.outUsed] ^ src[i] - x.fre[x.outUsed] = c - x.outUsed++ - } -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go deleted file mode 100644 index 1713503395..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto" - "encoding/binary" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" - "io" - "strconv" -) - -// OnePassSignature represents a one-pass signature packet. See RFC 4880, -// section 5.4. -type OnePassSignature struct { - SigType SignatureType - Hash crypto.Hash - PubKeyAlgo PublicKeyAlgorithm - KeyId uint64 - IsLast bool -} - -const onePassSignatureVersion = 3 - -func (ops *OnePassSignature) parse(r io.Reader) (err error) { - var buf [13]byte - - _, err = readFull(r, buf[:]) - if err != nil { - return - } - if buf[0] != onePassSignatureVersion { - err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) - } - - var ok bool - ops.Hash, ok = s2k.HashIdToHash(buf[2]) - if !ok { - return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) - } - - ops.SigType = SignatureType(buf[1]) - ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) - ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) - ops.IsLast = buf[12] != 0 - return -} - -// Serialize marshals the given OnePassSignature to w. -func (ops *OnePassSignature) Serialize(w io.Writer) error { - var buf [13]byte - buf[0] = onePassSignatureVersion - buf[1] = uint8(ops.SigType) - var ok bool - buf[2], ok = s2k.HashToHashId(ops.Hash) - if !ok { - return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) - } - buf[3] = uint8(ops.PubKeyAlgo) - binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) - if ops.IsLast { - buf[12] = 1 - } - - if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { - return err - } - _, err := w.Write(buf[:]) - return err -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go deleted file mode 100644 index 456d807f25..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "io" - "io/ioutil" - - "golang.org/x/crypto/openpgp/errors" -) - -// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is -// useful for splitting and storing the original packet contents separately, -// handling unsupported packet types or accessing parts of the packet not yet -// implemented by this package. -type OpaquePacket struct { - // Packet type - Tag uint8 - // Reason why the packet was parsed opaquely - Reason error - // Binary contents of the packet data - Contents []byte -} - -func (op *OpaquePacket) parse(r io.Reader) (err error) { - op.Contents, err = ioutil.ReadAll(r) - return -} - -// Serialize marshals the packet to a writer in its original form, including -// the packet header. -func (op *OpaquePacket) Serialize(w io.Writer) (err error) { - err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) - if err == nil { - _, err = w.Write(op.Contents) - } - return -} - -// Parse attempts to parse the opaque contents into a structure supported by -// this package. If the packet is not known then the result will be another -// OpaquePacket. -func (op *OpaquePacket) Parse() (p Packet, err error) { - hdr := bytes.NewBuffer(nil) - err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) - if err != nil { - op.Reason = err - return op, err - } - p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) - if err != nil { - op.Reason = err - p = op - } - return -} - -// OpaqueReader reads OpaquePackets from an io.Reader. -type OpaqueReader struct { - r io.Reader -} - -func NewOpaqueReader(r io.Reader) *OpaqueReader { - return &OpaqueReader{r: r} -} - -// Read the next OpaquePacket. -func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { - tag, _, contents, err := readHeader(or.r) - if err != nil { - return - } - op = &OpaquePacket{Tag: uint8(tag), Reason: err} - err = op.parse(contents) - if err != nil { - consumeAll(contents) - } - return -} - -// OpaqueSubpacket represents an unparsed OpenPGP subpacket, -// as found in signature and user attribute packets. -type OpaqueSubpacket struct { - SubType uint8 - Contents []byte -} - -// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from -// their byte representation. -func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { - var ( - subHeaderLen int - subPacket *OpaqueSubpacket - ) - for len(contents) > 0 { - subHeaderLen, subPacket, err = nextSubpacket(contents) - if err != nil { - break - } - result = append(result, subPacket) - contents = contents[subHeaderLen+len(subPacket.Contents):] - } - return -} - -func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { - // RFC 4880, section 5.2.3.1 - var subLen uint32 - if len(contents) < 1 { - goto Truncated - } - subPacket = &OpaqueSubpacket{} - switch { - case contents[0] < 192: - subHeaderLen = 2 // 1 length byte, 1 subtype byte - if len(contents) < subHeaderLen { - goto Truncated - } - subLen = uint32(contents[0]) - contents = contents[1:] - case contents[0] < 255: - subHeaderLen = 3 // 2 length bytes, 1 subtype - if len(contents) < subHeaderLen { - goto Truncated - } - subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 - contents = contents[2:] - default: - subHeaderLen = 6 // 5 length bytes, 1 subtype - if len(contents) < subHeaderLen { - goto Truncated - } - subLen = uint32(contents[1])<<24 | - uint32(contents[2])<<16 | - uint32(contents[3])<<8 | - uint32(contents[4]) - contents = contents[5:] - } - if subLen > uint32(len(contents)) || subLen == 0 { - goto Truncated - } - subPacket.SubType = contents[0] - subPacket.Contents = contents[1:subLen] - return -Truncated: - err = errors.StructuralError("subpacket truncated") - return -} - -func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { - buf := make([]byte, 6) - n := serializeSubpacketLength(buf, len(osp.Contents)+1) - buf[n] = osp.SubType - if _, err = w.Write(buf[:n+1]); err != nil { - return - } - _, err = w.Write(osp.Contents) - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go deleted file mode 100644 index 625bb5ac80..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/packet.go +++ /dev/null @@ -1,549 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package packet implements parsing and serialization of OpenPGP packets, as -// specified in RFC 4880. -package packet // import "golang.org/x/crypto/openpgp/packet" - -import ( - "bufio" - "crypto/aes" - "crypto/cipher" - "crypto/des" - "crypto/rsa" - "io" - "math/big" - - "golang.org/x/crypto/cast5" - "golang.org/x/crypto/openpgp/errors" -) - -// readFull is the same as io.ReadFull except that reading zero bytes returns -// ErrUnexpectedEOF rather than EOF. -func readFull(r io.Reader, buf []byte) (n int, err error) { - n, err = io.ReadFull(r, buf) - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. -func readLength(r io.Reader) (length int64, isPartial bool, err error) { - var buf [4]byte - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - switch { - case buf[0] < 192: - length = int64(buf[0]) - case buf[0] < 224: - length = int64(buf[0]-192) << 8 - _, err = readFull(r, buf[0:1]) - if err != nil { - return - } - length += int64(buf[0]) + 192 - case buf[0] < 255: - length = int64(1) << (buf[0] & 0x1f) - isPartial = true - default: - _, err = readFull(r, buf[0:4]) - if err != nil { - return - } - length = int64(buf[0])<<24 | - int64(buf[1])<<16 | - int64(buf[2])<<8 | - int64(buf[3]) - } - return -} - -// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. -// The continuation lengths are parsed and removed from the stream and EOF is -// returned at the end of the packet. See RFC 4880, section 4.2.2.4. -type partialLengthReader struct { - r io.Reader - remaining int64 - isPartial bool -} - -func (r *partialLengthReader) Read(p []byte) (n int, err error) { - for r.remaining == 0 { - if !r.isPartial { - return 0, io.EOF - } - r.remaining, r.isPartial, err = readLength(r.r) - if err != nil { - return 0, err - } - } - - toRead := int64(len(p)) - if toRead > r.remaining { - toRead = r.remaining - } - - n, err = r.r.Read(p[:int(toRead)]) - r.remaining -= int64(n) - if n < int(toRead) && err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// partialLengthWriter writes a stream of data using OpenPGP partial lengths. -// See RFC 4880, section 4.2.2.4. -type partialLengthWriter struct { - w io.WriteCloser - lengthByte [1]byte -} - -func (w *partialLengthWriter) Write(p []byte) (n int, err error) { - for len(p) > 0 { - for power := uint(14); power < 32; power-- { - l := 1 << power - if len(p) >= l { - w.lengthByte[0] = 224 + uint8(power) - _, err = w.w.Write(w.lengthByte[:]) - if err != nil { - return - } - var m int - m, err = w.w.Write(p[:l]) - n += m - if err != nil { - return - } - p = p[l:] - break - } - } - } - return -} - -func (w *partialLengthWriter) Close() error { - w.lengthByte[0] = 0 - _, err := w.w.Write(w.lengthByte[:]) - if err != nil { - return err - } - return w.w.Close() -} - -// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the -// underlying Reader returns EOF before the limit has been reached. -type spanReader struct { - r io.Reader - n int64 -} - -func (l *spanReader) Read(p []byte) (n int, err error) { - if l.n <= 0 { - return 0, io.EOF - } - if int64(len(p)) > l.n { - p = p[0:l.n] - } - n, err = l.r.Read(p) - l.n -= int64(n) - if l.n > 0 && err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// readHeader parses a packet header and returns an io.Reader which will return -// the contents of the packet. See RFC 4880, section 4.2. -func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { - var buf [4]byte - _, err = io.ReadFull(r, buf[:1]) - if err != nil { - return - } - if buf[0]&0x80 == 0 { - err = errors.StructuralError("tag byte does not have MSB set") - return - } - if buf[0]&0x40 == 0 { - // Old format packet - tag = packetType((buf[0] & 0x3f) >> 2) - lengthType := buf[0] & 3 - if lengthType == 3 { - length = -1 - contents = r - return - } - lengthBytes := 1 << lengthType - _, err = readFull(r, buf[0:lengthBytes]) - if err != nil { - return - } - for i := 0; i < lengthBytes; i++ { - length <<= 8 - length |= int64(buf[i]) - } - contents = &spanReader{r, length} - return - } - - // New format packet - tag = packetType(buf[0] & 0x3f) - length, isPartial, err := readLength(r) - if err != nil { - return - } - if isPartial { - contents = &partialLengthReader{ - remaining: length, - isPartial: true, - r: r, - } - length = -1 - } else { - contents = &spanReader{r, length} - } - return -} - -// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section -// 4.2. -func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { - var buf [6]byte - var n int - - buf[0] = 0x80 | 0x40 | byte(ptype) - if length < 192 { - buf[1] = byte(length) - n = 2 - } else if length < 8384 { - length -= 192 - buf[1] = 192 + byte(length>>8) - buf[2] = byte(length) - n = 3 - } else { - buf[1] = 255 - buf[2] = byte(length >> 24) - buf[3] = byte(length >> 16) - buf[4] = byte(length >> 8) - buf[5] = byte(length) - n = 6 - } - - _, err = w.Write(buf[:n]) - return -} - -// serializeStreamHeader writes an OpenPGP packet header to w where the -// length of the packet is unknown. It returns a io.WriteCloser which can be -// used to write the contents of the packet. See RFC 4880, section 4.2. -func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { - var buf [1]byte - buf[0] = 0x80 | 0x40 | byte(ptype) - _, err = w.Write(buf[:]) - if err != nil { - return - } - out = &partialLengthWriter{w: w} - return -} - -// Packet represents an OpenPGP packet. Users are expected to try casting -// instances of this interface to specific packet types. -type Packet interface { - parse(io.Reader) error -} - -// consumeAll reads from the given Reader until error, returning the number of -// bytes read. -func consumeAll(r io.Reader) (n int64, err error) { - var m int - var buf [1024]byte - - for { - m, err = r.Read(buf[:]) - n += int64(m) - if err == io.EOF { - err = nil - return - } - if err != nil { - return - } - } -} - -// packetType represents the numeric ids of the different OpenPGP packet types. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 -type packetType uint8 - -const ( - packetTypeEncryptedKey packetType = 1 - packetTypeSignature packetType = 2 - packetTypeSymmetricKeyEncrypted packetType = 3 - packetTypeOnePassSignature packetType = 4 - packetTypePrivateKey packetType = 5 - packetTypePublicKey packetType = 6 - packetTypePrivateSubkey packetType = 7 - packetTypeCompressed packetType = 8 - packetTypeSymmetricallyEncrypted packetType = 9 - packetTypeLiteralData packetType = 11 - packetTypeUserId packetType = 13 - packetTypePublicSubkey packetType = 14 - packetTypeUserAttribute packetType = 17 - packetTypeSymmetricallyEncryptedMDC packetType = 18 -) - -// peekVersion detects the version of a public key packet about to -// be read. A bufio.Reader at the original position of the io.Reader -// is returned. -func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { - bufr = bufio.NewReader(r) - var verBuf []byte - if verBuf, err = bufr.Peek(1); err != nil { - return - } - ver = verBuf[0] - return -} - -// Read reads a single OpenPGP packet from the given io.Reader. If there is an -// error parsing a packet, the whole packet is consumed from the input. -func Read(r io.Reader) (p Packet, err error) { - tag, _, contents, err := readHeader(r) - if err != nil { - return - } - - switch tag { - case packetTypeEncryptedKey: - p = new(EncryptedKey) - case packetTypeSignature: - var version byte - // Detect signature version - if contents, version, err = peekVersion(contents); err != nil { - return - } - if version < 4 { - p = new(SignatureV3) - } else { - p = new(Signature) - } - case packetTypeSymmetricKeyEncrypted: - p = new(SymmetricKeyEncrypted) - case packetTypeOnePassSignature: - p = new(OnePassSignature) - case packetTypePrivateKey, packetTypePrivateSubkey: - pk := new(PrivateKey) - if tag == packetTypePrivateSubkey { - pk.IsSubkey = true - } - p = pk - case packetTypePublicKey, packetTypePublicSubkey: - var version byte - if contents, version, err = peekVersion(contents); err != nil { - return - } - isSubkey := tag == packetTypePublicSubkey - if version < 4 { - p = &PublicKeyV3{IsSubkey: isSubkey} - } else { - p = &PublicKey{IsSubkey: isSubkey} - } - case packetTypeCompressed: - p = new(Compressed) - case packetTypeSymmetricallyEncrypted: - p = new(SymmetricallyEncrypted) - case packetTypeLiteralData: - p = new(LiteralData) - case packetTypeUserId: - p = new(UserId) - case packetTypeUserAttribute: - p = new(UserAttribute) - case packetTypeSymmetricallyEncryptedMDC: - se := new(SymmetricallyEncrypted) - se.MDC = true - p = se - default: - err = errors.UnknownPacketTypeError(tag) - } - if p != nil { - err = p.parse(contents) - } - if err != nil { - consumeAll(contents) - } - return -} - -// SignatureType represents the different semantic meanings of an OpenPGP -// signature. See RFC 4880, section 5.2.1. -type SignatureType uint8 - -const ( - SigTypeBinary SignatureType = 0 - SigTypeText = 1 - SigTypeGenericCert = 0x10 - SigTypePersonaCert = 0x11 - SigTypeCasualCert = 0x12 - SigTypePositiveCert = 0x13 - SigTypeSubkeyBinding = 0x18 - SigTypePrimaryKeyBinding = 0x19 - SigTypeDirectSignature = 0x1F - SigTypeKeyRevocation = 0x20 - SigTypeSubkeyRevocation = 0x28 -) - -// PublicKeyAlgorithm represents the different public key system specified for -// OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 -type PublicKeyAlgorithm uint8 - -const ( - PubKeyAlgoRSA PublicKeyAlgorithm = 1 - PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 - PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 - PubKeyAlgoElGamal PublicKeyAlgorithm = 16 - PubKeyAlgoDSA PublicKeyAlgorithm = 17 - // RFC 6637, Section 5. - PubKeyAlgoECDH PublicKeyAlgorithm = 18 - PubKeyAlgoECDSA PublicKeyAlgorithm = 19 -) - -// CanEncrypt returns true if it's possible to encrypt a message to a public -// key of the given type. -func (pka PublicKeyAlgorithm) CanEncrypt() bool { - switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: - return true - } - return false -} - -// CanSign returns true if it's possible for a public key of the given type to -// sign a message. -func (pka PublicKeyAlgorithm) CanSign() bool { - switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: - return true - } - return false -} - -// CipherFunction represents the different block ciphers specified for OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -type CipherFunction uint8 - -const ( - Cipher3DES CipherFunction = 2 - CipherCAST5 CipherFunction = 3 - CipherAES128 CipherFunction = 7 - CipherAES192 CipherFunction = 8 - CipherAES256 CipherFunction = 9 -) - -// KeySize returns the key size, in bytes, of cipher. -func (cipher CipherFunction) KeySize() int { - switch cipher { - case Cipher3DES: - return 24 - case CipherCAST5: - return cast5.KeySize - case CipherAES128: - return 16 - case CipherAES192: - return 24 - case CipherAES256: - return 32 - } - return 0 -} - -// blockSize returns the block size, in bytes, of cipher. -func (cipher CipherFunction) blockSize() int { - switch cipher { - case Cipher3DES: - return des.BlockSize - case CipherCAST5: - return 8 - case CipherAES128, CipherAES192, CipherAES256: - return 16 - } - return 0 -} - -// new returns a fresh instance of the given cipher. -func (cipher CipherFunction) new(key []byte) (block cipher.Block) { - switch cipher { - case Cipher3DES: - block, _ = des.NewTripleDESCipher(key) - case CipherCAST5: - block, _ = cast5.NewCipher(key) - case CipherAES128, CipherAES192, CipherAES256: - block, _ = aes.NewCipher(key) - } - return -} - -// readMPI reads a big integer from r. The bit length returned is the bit -// length that was specified in r. This is preserved so that the integer can be -// reserialized exactly. -func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { - var buf [2]byte - _, err = readFull(r, buf[0:]) - if err != nil { - return - } - bitLength = uint16(buf[0])<<8 | uint16(buf[1]) - numBytes := (int(bitLength) + 7) / 8 - mpi = make([]byte, numBytes) - _, err = readFull(r, mpi) - // According to RFC 4880 3.2. we should check that the MPI has no leading - // zeroes (at least when not an encrypted MPI?), but this implementation - // does generate leading zeroes, so we keep accepting them. - return -} - -// writeMPI serializes a big integer to w. -func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { - // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. - // Implementations seem to be tolerant of them, and stripping them would - // make it complex to guarantee matching re-serialization. - _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) - if err == nil { - _, err = w.Write(mpiBytes) - } - return -} - -// writeBig serializes a *big.Int to w. -func writeBig(w io.Writer, i *big.Int) error { - return writeMPI(w, uint16(i.BitLen()), i.Bytes()) -} - -// padToKeySize left-pads a MPI with zeroes to match the length of the -// specified RSA public. -func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { - k := (pub.N.BitLen() + 7) / 8 - if len(b) >= k { - return b - } - bb := make([]byte, k) - copy(bb[len(bb)-len(b):], b) - return bb -} - -// CompressionAlgo Represents the different compression algorithms -// supported by OpenPGP (except for BZIP2, which is not currently -// supported). See Section 9.3 of RFC 4880. -type CompressionAlgo uint8 - -const ( - CompressionNone CompressionAlgo = 0 - CompressionZIP CompressionAlgo = 1 - CompressionZLIB CompressionAlgo = 2 -) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go deleted file mode 100644 index 34734cc63d..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "crypto" - "crypto/cipher" - "crypto/dsa" - "crypto/ecdsa" - "crypto/rsa" - "crypto/sha1" - "io" - "io/ioutil" - "math/big" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/elgamal" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" -) - -// PrivateKey represents a possibly encrypted private key. See RFC 4880, -// section 5.5.3. -type PrivateKey struct { - PublicKey - Encrypted bool // if true then the private key is unavailable until Decrypt has been called. - encryptedData []byte - cipher CipherFunction - s2k func(out, in []byte) - PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. - sha1Checksum bool - iv []byte -} - -func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that -// implements RSA or ECDSA. -func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey { - pk := new(PrivateKey) - switch pubkey := signer.Public().(type) { - case rsa.PublicKey: - pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey) - pk.PubKeyAlgo = PubKeyAlgoRSASignOnly - case ecdsa.PublicKey: - pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey) - default: - panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") - } - pk.PrivateKey = signer - return pk -} - -func (pk *PrivateKey) parse(r io.Reader) (err error) { - err = (&pk.PublicKey).parse(r) - if err != nil { - return - } - var buf [1]byte - _, err = readFull(r, buf[:]) - if err != nil { - return - } - - s2kType := buf[0] - - switch s2kType { - case 0: - pk.s2k = nil - pk.Encrypted = false - case 254, 255: - _, err = readFull(r, buf[:]) - if err != nil { - return - } - pk.cipher = CipherFunction(buf[0]) - pk.Encrypted = true - pk.s2k, err = s2k.Parse(r) - if err != nil { - return - } - if s2kType == 254 { - pk.sha1Checksum = true - } - default: - return errors.UnsupportedError("deprecated s2k function in private key") - } - - if pk.Encrypted { - blockSize := pk.cipher.blockSize() - if blockSize == 0 { - return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) - } - pk.iv = make([]byte, blockSize) - _, err = readFull(r, pk.iv) - if err != nil { - return - } - } - - pk.encryptedData, err = ioutil.ReadAll(r) - if err != nil { - return - } - - if !pk.Encrypted { - return pk.parsePrivateKey(pk.encryptedData) - } - - return -} - -func mod64kHash(d []byte) uint16 { - var h uint16 - for _, b := range d { - h += uint16(b) - } - return h -} - -func (pk *PrivateKey) Serialize(w io.Writer) (err error) { - // TODO(agl): support encrypted private keys - buf := bytes.NewBuffer(nil) - err = pk.PublicKey.serializeWithoutHeaders(buf) - if err != nil { - return - } - buf.WriteByte(0 /* no encryption */) - - privateKeyBuf := bytes.NewBuffer(nil) - - switch priv := pk.PrivateKey.(type) { - case *rsa.PrivateKey: - err = serializeRSAPrivateKey(privateKeyBuf, priv) - case *dsa.PrivateKey: - err = serializeDSAPrivateKey(privateKeyBuf, priv) - case *elgamal.PrivateKey: - err = serializeElGamalPrivateKey(privateKeyBuf, priv) - case *ecdsa.PrivateKey: - err = serializeECDSAPrivateKey(privateKeyBuf, priv) - default: - err = errors.InvalidArgumentError("unknown private key type") - } - if err != nil { - return - } - - ptype := packetTypePrivateKey - contents := buf.Bytes() - privateKeyBytes := privateKeyBuf.Bytes() - if pk.IsSubkey { - ptype = packetTypePrivateSubkey - } - err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) - if err != nil { - return - } - _, err = w.Write(contents) - if err != nil { - return - } - _, err = w.Write(privateKeyBytes) - if err != nil { - return - } - - checksum := mod64kHash(privateKeyBytes) - var checksumBytes [2]byte - checksumBytes[0] = byte(checksum >> 8) - checksumBytes[1] = byte(checksum) - _, err = w.Write(checksumBytes[:]) - - return -} - -func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { - err := writeBig(w, priv.D) - if err != nil { - return err - } - err = writeBig(w, priv.Primes[1]) - if err != nil { - return err - } - err = writeBig(w, priv.Primes[0]) - if err != nil { - return err - } - return writeBig(w, priv.Precomputed.Qinv) -} - -func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { - return writeBig(w, priv.X) -} - -func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { - return writeBig(w, priv.X) -} - -func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { - return writeBig(w, priv.D) -} - -// Decrypt decrypts an encrypted private key using a passphrase. -func (pk *PrivateKey) Decrypt(passphrase []byte) error { - if !pk.Encrypted { - return nil - } - - key := make([]byte, pk.cipher.KeySize()) - pk.s2k(key, passphrase) - block := pk.cipher.new(key) - cfb := cipher.NewCFBDecrypter(block, pk.iv) - - data := make([]byte, len(pk.encryptedData)) - cfb.XORKeyStream(data, pk.encryptedData) - - if pk.sha1Checksum { - if len(data) < sha1.Size { - return errors.StructuralError("truncated private key data") - } - h := sha1.New() - h.Write(data[:len(data)-sha1.Size]) - sum := h.Sum(nil) - if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { - return errors.StructuralError("private key checksum failure") - } - data = data[:len(data)-sha1.Size] - } else { - if len(data) < 2 { - return errors.StructuralError("truncated private key data") - } - var sum uint16 - for i := 0; i < len(data)-2; i++ { - sum += uint16(data[i]) - } - if data[len(data)-2] != uint8(sum>>8) || - data[len(data)-1] != uint8(sum) { - return errors.StructuralError("private key checksum failure") - } - data = data[:len(data)-2] - } - - return pk.parsePrivateKey(data) -} - -func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { - switch pk.PublicKey.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: - return pk.parseRSAPrivateKey(data) - case PubKeyAlgoDSA: - return pk.parseDSAPrivateKey(data) - case PubKeyAlgoElGamal: - return pk.parseElGamalPrivateKey(data) - case PubKeyAlgoECDSA: - return pk.parseECDSAPrivateKey(data) - } - panic("impossible") -} - -func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { - rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) - rsaPriv := new(rsa.PrivateKey) - rsaPriv.PublicKey = *rsaPub - - buf := bytes.NewBuffer(data) - d, _, err := readMPI(buf) - if err != nil { - return - } - p, _, err := readMPI(buf) - if err != nil { - return - } - q, _, err := readMPI(buf) - if err != nil { - return - } - - rsaPriv.D = new(big.Int).SetBytes(d) - rsaPriv.Primes = make([]*big.Int, 2) - rsaPriv.Primes[0] = new(big.Int).SetBytes(p) - rsaPriv.Primes[1] = new(big.Int).SetBytes(q) - if err := rsaPriv.Validate(); err != nil { - return err - } - rsaPriv.Precompute() - pk.PrivateKey = rsaPriv - pk.Encrypted = false - pk.encryptedData = nil - - return nil -} - -func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { - dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) - dsaPriv := new(dsa.PrivateKey) - dsaPriv.PublicKey = *dsaPub - - buf := bytes.NewBuffer(data) - x, _, err := readMPI(buf) - if err != nil { - return - } - - dsaPriv.X = new(big.Int).SetBytes(x) - pk.PrivateKey = dsaPriv - pk.Encrypted = false - pk.encryptedData = nil - - return nil -} - -func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { - pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) - priv := new(elgamal.PrivateKey) - priv.PublicKey = *pub - - buf := bytes.NewBuffer(data) - x, _, err := readMPI(buf) - if err != nil { - return - } - - priv.X = new(big.Int).SetBytes(x) - pk.PrivateKey = priv - pk.Encrypted = false - pk.encryptedData = nil - - return nil -} - -func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { - ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) - - buf := bytes.NewBuffer(data) - d, _, err := readMPI(buf) - if err != nil { - return - } - - pk.PrivateKey = &ecdsa.PrivateKey{ - PublicKey: *ecdsaPub, - D: new(big.Int).SetBytes(d), - } - pk.Encrypted = false - pk.encryptedData = nil - - return nil -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go deleted file mode 100644 index fcd5f52519..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go +++ /dev/null @@ -1,753 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "crypto" - "crypto/dsa" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rsa" - "crypto/sha1" - _ "crypto/sha256" - _ "crypto/sha512" - "encoding/binary" - "fmt" - "hash" - "io" - "math/big" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/elgamal" - "golang.org/x/crypto/openpgp/errors" -) - -var ( - // NIST curve P-256 - oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} - // NIST curve P-384 - oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} - // NIST curve P-521 - oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} -) - -const maxOIDLength = 8 - -// ecdsaKey stores the algorithm-specific fields for ECDSA keys. -// as defined in RFC 6637, Section 9. -type ecdsaKey struct { - // oid contains the OID byte sequence identifying the elliptic curve used - oid []byte - // p contains the elliptic curve point that represents the public key - p parsedMPI -} - -// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. -func parseOID(r io.Reader) (oid []byte, err error) { - buf := make([]byte, maxOIDLength) - if _, err = readFull(r, buf[:1]); err != nil { - return - } - oidLen := buf[0] - if int(oidLen) > len(buf) { - err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) - return - } - oid = buf[:oidLen] - _, err = readFull(r, oid) - return -} - -func (f *ecdsaKey) parse(r io.Reader) (err error) { - if f.oid, err = parseOID(r); err != nil { - return err - } - f.p.bytes, f.p.bitLength, err = readMPI(r) - return -} - -func (f *ecdsaKey) serialize(w io.Writer) (err error) { - buf := make([]byte, maxOIDLength+1) - buf[0] = byte(len(f.oid)) - copy(buf[1:], f.oid) - if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { - return - } - return writeMPIs(w, f.p) -} - -func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { - var c elliptic.Curve - if bytes.Equal(f.oid, oidCurveP256) { - c = elliptic.P256() - } else if bytes.Equal(f.oid, oidCurveP384) { - c = elliptic.P384() - } else if bytes.Equal(f.oid, oidCurveP521) { - c = elliptic.P521() - } else { - return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) - } - x, y := elliptic.Unmarshal(c, f.p.bytes) - if x == nil { - return nil, errors.UnsupportedError("failed to parse EC point") - } - return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil -} - -func (f *ecdsaKey) byteLen() int { - return 1 + len(f.oid) + 2 + len(f.p.bytes) -} - -type kdfHashFunction byte -type kdfAlgorithm byte - -// ecdhKdf stores key derivation function parameters -// used for ECDH encryption. See RFC 6637, Section 9. -type ecdhKdf struct { - KdfHash kdfHashFunction - KdfAlgo kdfAlgorithm -} - -func (f *ecdhKdf) parse(r io.Reader) (err error) { - buf := make([]byte, 1) - if _, err = readFull(r, buf); err != nil { - return - } - kdfLen := int(buf[0]) - if kdfLen < 3 { - return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) - } - buf = make([]byte, kdfLen) - if _, err = readFull(r, buf); err != nil { - return - } - reserved := int(buf[0]) - f.KdfHash = kdfHashFunction(buf[1]) - f.KdfAlgo = kdfAlgorithm(buf[2]) - if reserved != 0x01 { - return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) - } - return -} - -func (f *ecdhKdf) serialize(w io.Writer) (err error) { - buf := make([]byte, 4) - // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. - buf[0] = byte(0x03) // Length of the following fields - buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now - buf[2] = byte(f.KdfHash) - buf[3] = byte(f.KdfAlgo) - _, err = w.Write(buf[:]) - return -} - -func (f *ecdhKdf) byteLen() int { - return 4 -} - -// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. -type PublicKey struct { - CreationTime time.Time - PubKeyAlgo PublicKeyAlgorithm - PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey - Fingerprint [20]byte - KeyId uint64 - IsSubkey bool - - n, e, p, q, g, y parsedMPI - - // RFC 6637 fields - ec *ecdsaKey - ecdh *ecdhKdf -} - -// signingKey provides a convenient abstraction over signature verification -// for v3 and v4 public keys. -type signingKey interface { - SerializeSignaturePrefix(io.Writer) - serializeWithoutHeaders(io.Writer) error -} - -func fromBig(n *big.Int) parsedMPI { - return parsedMPI{ - bytes: n.Bytes(), - bitLength: uint16(n.BitLen()), - } -} - -// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. -func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { - pk := &PublicKey{ - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoRSA, - PublicKey: pub, - n: fromBig(pub.N), - e: fromBig(big.NewInt(int64(pub.E))), - } - - pk.setFingerPrintAndKeyId() - return pk -} - -// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. -func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { - pk := &PublicKey{ - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoDSA, - PublicKey: pub, - p: fromBig(pub.P), - q: fromBig(pub.Q), - g: fromBig(pub.G), - y: fromBig(pub.Y), - } - - pk.setFingerPrintAndKeyId() - return pk -} - -// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. -func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { - pk := &PublicKey{ - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoElGamal, - PublicKey: pub, - p: fromBig(pub.P), - g: fromBig(pub.G), - y: fromBig(pub.Y), - } - - pk.setFingerPrintAndKeyId() - return pk -} - -func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { - pk := &PublicKey{ - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoECDSA, - PublicKey: pub, - ec: new(ecdsaKey), - } - - switch pub.Curve { - case elliptic.P256(): - pk.ec.oid = oidCurveP256 - case elliptic.P384(): - pk.ec.oid = oidCurveP384 - case elliptic.P521(): - pk.ec.oid = oidCurveP521 - default: - panic("unknown elliptic curve") - } - - pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) - - // The bit length is 3 (for the 0x04 specifying an uncompressed key) - // plus two field elements (for x and y), which are rounded up to the - // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 - fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 - pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) - - pk.setFingerPrintAndKeyId() - return pk -} - -func (pk *PublicKey) parse(r io.Reader) (err error) { - // RFC 4880, section 5.5.2 - var buf [6]byte - _, err = readFull(r, buf[:]) - if err != nil { - return - } - if buf[0] != 4 { - return errors.UnsupportedError("public key version") - } - pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) - pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - err = pk.parseRSA(r) - case PubKeyAlgoDSA: - err = pk.parseDSA(r) - case PubKeyAlgoElGamal: - err = pk.parseElGamal(r) - case PubKeyAlgoECDSA: - pk.ec = new(ecdsaKey) - if err = pk.ec.parse(r); err != nil { - return err - } - pk.PublicKey, err = pk.ec.newECDSA() - case PubKeyAlgoECDH: - pk.ec = new(ecdsaKey) - if err = pk.ec.parse(r); err != nil { - return - } - pk.ecdh = new(ecdhKdf) - if err = pk.ecdh.parse(r); err != nil { - return - } - // The ECDH key is stored in an ecdsa.PublicKey for convenience. - pk.PublicKey, err = pk.ec.newECDSA() - default: - err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) - } - if err != nil { - return - } - - pk.setFingerPrintAndKeyId() - return -} - -func (pk *PublicKey) setFingerPrintAndKeyId() { - // RFC 4880, section 12.2 - fingerPrint := sha1.New() - pk.SerializeSignaturePrefix(fingerPrint) - pk.serializeWithoutHeaders(fingerPrint) - copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) - pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) -} - -// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -// section 5.5.2. -func (pk *PublicKey) parseRSA(r io.Reader) (err error) { - pk.n.bytes, pk.n.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.e.bytes, pk.e.bitLength, err = readMPI(r) - if err != nil { - return - } - - if len(pk.e.bytes) > 3 { - err = errors.UnsupportedError("large public exponent") - return - } - rsa := &rsa.PublicKey{ - N: new(big.Int).SetBytes(pk.n.bytes), - E: 0, - } - for i := 0; i < len(pk.e.bytes); i++ { - rsa.E <<= 8 - rsa.E |= int(pk.e.bytes[i]) - } - pk.PublicKey = rsa - return -} - -// parseDSA parses DSA public key material from the given Reader. See RFC 4880, -// section 5.5.2. -func (pk *PublicKey) parseDSA(r io.Reader) (err error) { - pk.p.bytes, pk.p.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.q.bytes, pk.q.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.g.bytes, pk.g.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.y.bytes, pk.y.bitLength, err = readMPI(r) - if err != nil { - return - } - - dsa := new(dsa.PublicKey) - dsa.P = new(big.Int).SetBytes(pk.p.bytes) - dsa.Q = new(big.Int).SetBytes(pk.q.bytes) - dsa.G = new(big.Int).SetBytes(pk.g.bytes) - dsa.Y = new(big.Int).SetBytes(pk.y.bytes) - pk.PublicKey = dsa - return -} - -// parseElGamal parses ElGamal public key material from the given Reader. See -// RFC 4880, section 5.5.2. -func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { - pk.p.bytes, pk.p.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.g.bytes, pk.g.bitLength, err = readMPI(r) - if err != nil { - return - } - pk.y.bytes, pk.y.bitLength, err = readMPI(r) - if err != nil { - return - } - - elgamal := new(elgamal.PublicKey) - elgamal.P = new(big.Int).SetBytes(pk.p.bytes) - elgamal.G = new(big.Int).SetBytes(pk.g.bytes) - elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) - pk.PublicKey = elgamal - return -} - -// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -// The prefix is used when calculating a signature over this public key. See -// RFC 4880, section 5.2.4. -func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { - var pLength uint16 - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - pLength += 2 + uint16(len(pk.n.bytes)) - pLength += 2 + uint16(len(pk.e.bytes)) - case PubKeyAlgoDSA: - pLength += 2 + uint16(len(pk.p.bytes)) - pLength += 2 + uint16(len(pk.q.bytes)) - pLength += 2 + uint16(len(pk.g.bytes)) - pLength += 2 + uint16(len(pk.y.bytes)) - case PubKeyAlgoElGamal: - pLength += 2 + uint16(len(pk.p.bytes)) - pLength += 2 + uint16(len(pk.g.bytes)) - pLength += 2 + uint16(len(pk.y.bytes)) - case PubKeyAlgoECDSA: - pLength += uint16(pk.ec.byteLen()) - case PubKeyAlgoECDH: - pLength += uint16(pk.ec.byteLen()) - pLength += uint16(pk.ecdh.byteLen()) - default: - panic("unknown public key algorithm") - } - pLength += 6 - h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) - return -} - -func (pk *PublicKey) Serialize(w io.Writer) (err error) { - length := 6 // 6 byte header - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - length += 2 + len(pk.n.bytes) - length += 2 + len(pk.e.bytes) - case PubKeyAlgoDSA: - length += 2 + len(pk.p.bytes) - length += 2 + len(pk.q.bytes) - length += 2 + len(pk.g.bytes) - length += 2 + len(pk.y.bytes) - case PubKeyAlgoElGamal: - length += 2 + len(pk.p.bytes) - length += 2 + len(pk.g.bytes) - length += 2 + len(pk.y.bytes) - case PubKeyAlgoECDSA: - length += pk.ec.byteLen() - case PubKeyAlgoECDH: - length += pk.ec.byteLen() - length += pk.ecdh.byteLen() - default: - panic("unknown public key algorithm") - } - - packetType := packetTypePublicKey - if pk.IsSubkey { - packetType = packetTypePublicSubkey - } - err = serializeHeader(w, packetType, length) - if err != nil { - return - } - return pk.serializeWithoutHeaders(w) -} - -// serializeWithoutHeaders marshals the PublicKey to w in the form of an -// OpenPGP public key packet, not including the packet header. -func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { - var buf [6]byte - buf[0] = 4 - t := uint32(pk.CreationTime.Unix()) - buf[1] = byte(t >> 24) - buf[2] = byte(t >> 16) - buf[3] = byte(t >> 8) - buf[4] = byte(t) - buf[5] = byte(pk.PubKeyAlgo) - - _, err = w.Write(buf[:]) - if err != nil { - return - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - return writeMPIs(w, pk.n, pk.e) - case PubKeyAlgoDSA: - return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) - case PubKeyAlgoElGamal: - return writeMPIs(w, pk.p, pk.g, pk.y) - case PubKeyAlgoECDSA: - return pk.ec.serialize(w) - case PubKeyAlgoECDH: - if err = pk.ec.serialize(w); err != nil { - return - } - return pk.ecdh.serialize(w) - } - return errors.InvalidArgumentError("bad public-key algorithm") -} - -// CanSign returns true iff this public key can generate signatures -func (pk *PublicKey) CanSign() bool { - return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal -} - -// VerifySignature returns nil iff sig is a valid signature, made by this -// public key, of the data hashed into signed. signed is mutated by this call. -func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { - if !pk.CanSign() { - return errors.InvalidArgumentError("public key cannot generate signatures") - } - - signed.Write(sig.HashSuffix) - hashBytes := signed.Sum(nil) - - if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { - return errors.SignatureError("hash tag doesn't match") - } - - if pk.PubKeyAlgo != sig.PubKeyAlgo { - return errors.InvalidArgumentError("public key and signature use different algorithms") - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) - err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) - if err != nil { - return errors.SignatureError("RSA verification failure") - } - return nil - case PubKeyAlgoDSA: - dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) - // Need to truncate hashBytes to match FIPS 186-3 section 4.6. - subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 - if len(hashBytes) > subgroupSize { - hashBytes = hashBytes[:subgroupSize] - } - if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { - return errors.SignatureError("DSA verification failure") - } - return nil - case PubKeyAlgoECDSA: - ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) - if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { - return errors.SignatureError("ECDSA verification failure") - } - return nil - default: - return errors.SignatureError("Unsupported public key algorithm used in signature") - } -} - -// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -// public key, of the data hashed into signed. signed is mutated by this call. -func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { - if !pk.CanSign() { - return errors.InvalidArgumentError("public key cannot generate signatures") - } - - suffix := make([]byte, 5) - suffix[0] = byte(sig.SigType) - binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) - signed.Write(suffix) - hashBytes := signed.Sum(nil) - - if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { - return errors.SignatureError("hash tag doesn't match") - } - - if pk.PubKeyAlgo != sig.PubKeyAlgo { - return errors.InvalidArgumentError("public key and signature use different algorithms") - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) - if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { - return errors.SignatureError("RSA verification failure") - } - return - case PubKeyAlgoDSA: - dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) - // Need to truncate hashBytes to match FIPS 186-3 section 4.6. - subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 - if len(hashBytes) > subgroupSize { - hashBytes = hashBytes[:subgroupSize] - } - if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { - return errors.SignatureError("DSA verification failure") - } - return nil - default: - panic("shouldn't happen") - } -} - -// keySignatureHash returns a Hash of the message that needs to be signed for -// pk to assert a subkey relationship to signed. -func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { - if !hashFunc.Available() { - return nil, errors.UnsupportedError("hash function") - } - h = hashFunc.New() - - // RFC 4880, section 5.2.4 - pk.SerializeSignaturePrefix(h) - pk.serializeWithoutHeaders(h) - signed.SerializeSignaturePrefix(h) - signed.serializeWithoutHeaders(h) - return -} - -// VerifyKeySignature returns nil iff sig is a valid signature, made by this -// public key, of signed. -func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { - h, err := keySignatureHash(pk, signed, sig.Hash) - if err != nil { - return err - } - if err = pk.VerifySignature(h, sig); err != nil { - return err - } - - if sig.FlagSign { - // Signing subkeys must be cross-signed. See - // https://www.gnupg.org/faq/subkey-cross-certify.html. - if sig.EmbeddedSignature == nil { - return errors.StructuralError("signing subkey is missing cross-signature") - } - // Verify the cross-signature. This is calculated over the same - // data as the main signature, so we cannot just recursively - // call signed.VerifyKeySignature(...) - if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { - return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) - } - if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { - return errors.StructuralError("error while verifying cross-signature: " + err.Error()) - } - } - - return nil -} - -func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { - if !hashFunc.Available() { - return nil, errors.UnsupportedError("hash function") - } - h = hashFunc.New() - - // RFC 4880, section 5.2.4 - pk.SerializeSignaturePrefix(h) - pk.serializeWithoutHeaders(h) - - return -} - -// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this -// public key. -func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { - h, err := keyRevocationHash(pk, sig.Hash) - if err != nil { - return err - } - return pk.VerifySignature(h, sig) -} - -// userIdSignatureHash returns a Hash of the message that needs to be signed -// to assert that pk is a valid key for id. -func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { - if !hashFunc.Available() { - return nil, errors.UnsupportedError("hash function") - } - h = hashFunc.New() - - // RFC 4880, section 5.2.4 - pk.SerializeSignaturePrefix(h) - pk.serializeWithoutHeaders(h) - - var buf [5]byte - buf[0] = 0xb4 - buf[1] = byte(len(id) >> 24) - buf[2] = byte(len(id) >> 16) - buf[3] = byte(len(id) >> 8) - buf[4] = byte(len(id)) - h.Write(buf[:]) - h.Write([]byte(id)) - - return -} - -// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this -// public key, that id is the identity of pub. -func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { - h, err := userIdSignatureHash(id, pub, sig.Hash) - if err != nil { - return err - } - return pk.VerifySignature(h, sig) -} - -// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -// public key, that id is the identity of pub. -func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { - h, err := userIdSignatureV3Hash(id, pub, sig.Hash) - if err != nil { - return err - } - return pk.VerifySignatureV3(h, sig) -} - -// KeyIdString returns the public key's fingerprint in capital hex -// (e.g. "6C7EE1B8621CC013"). -func (pk *PublicKey) KeyIdString() string { - return fmt.Sprintf("%X", pk.Fingerprint[12:20]) -} - -// KeyIdShortString returns the short form of public key's fingerprint -// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -func (pk *PublicKey) KeyIdShortString() string { - return fmt.Sprintf("%X", pk.Fingerprint[16:20]) -} - -// A parsedMPI is used to store the contents of a big integer, along with the -// bit length that was specified in the original input. This allows the MPI to -// be reserialized exactly. -type parsedMPI struct { - bytes []byte - bitLength uint16 -} - -// writeMPIs is a utility function for serializing several big integers to the -// given Writer. -func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { - for _, mpi := range mpis { - err = writeMPI(w, mpi.bitLength, mpi.bytes) - if err != nil { - return - } - } - return -} - -// BitLength returns the bit length for the given public key. -func (pk *PublicKey) BitLength() (bitLength uint16, err error) { - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - bitLength = pk.n.bitLength - case PubKeyAlgoDSA: - bitLength = pk.p.bitLength - case PubKeyAlgoElGamal: - bitLength = pk.p.bitLength - default: - err = errors.InvalidArgumentError("bad public-key algorithm") - } - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go deleted file mode 100644 index 5daf7b6cfd..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto" - "crypto/md5" - "crypto/rsa" - "encoding/binary" - "fmt" - "hash" - "io" - "math/big" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/errors" -) - -// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and -// should not be used for signing or encrypting. They are supported here only for -// parsing version 3 key material and validating signatures. -// See RFC 4880, section 5.5.2. -type PublicKeyV3 struct { - CreationTime time.Time - DaysToExpire uint16 - PubKeyAlgo PublicKeyAlgorithm - PublicKey *rsa.PublicKey - Fingerprint [16]byte - KeyId uint64 - IsSubkey bool - - n, e parsedMPI -} - -// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. -// Included here for testing purposes only. RFC 4880, section 5.5.2: -// "an implementation MUST NOT generate a V3 key, but MAY accept it." -func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { - pk := &PublicKeyV3{ - CreationTime: creationTime, - PublicKey: pub, - n: fromBig(pub.N), - e: fromBig(big.NewInt(int64(pub.E))), - } - - pk.setFingerPrintAndKeyId() - return pk -} - -func (pk *PublicKeyV3) parse(r io.Reader) (err error) { - // RFC 4880, section 5.5.2 - var buf [8]byte - if _, err = readFull(r, buf[:]); err != nil { - return - } - if buf[0] < 2 || buf[0] > 3 { - return errors.UnsupportedError("public key version") - } - pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) - pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) - pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - err = pk.parseRSA(r) - default: - err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) - } - if err != nil { - return - } - - pk.setFingerPrintAndKeyId() - return -} - -func (pk *PublicKeyV3) setFingerPrintAndKeyId() { - // RFC 4880, section 12.2 - fingerPrint := md5.New() - fingerPrint.Write(pk.n.bytes) - fingerPrint.Write(pk.e.bytes) - fingerPrint.Sum(pk.Fingerprint[:0]) - pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) -} - -// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -// section 5.5.2. -func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { - if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { - return - } - if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { - return - } - - // RFC 4880 Section 12.2 requires the low 8 bytes of the - // modulus to form the key id. - if len(pk.n.bytes) < 8 { - return errors.StructuralError("v3 public key modulus is too short") - } - if len(pk.e.bytes) > 3 { - err = errors.UnsupportedError("large public exponent") - return - } - rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} - for i := 0; i < len(pk.e.bytes); i++ { - rsa.E <<= 8 - rsa.E |= int(pk.e.bytes[i]) - } - pk.PublicKey = rsa - return -} - -// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -// The prefix is used when calculating a signature over this public key. See -// RFC 4880, section 5.2.4. -func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { - var pLength uint16 - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - pLength += 2 + uint16(len(pk.n.bytes)) - pLength += 2 + uint16(len(pk.e.bytes)) - default: - panic("unknown public key algorithm") - } - pLength += 6 - w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) - return -} - -func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { - length := 8 // 8 byte header - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - length += 2 + len(pk.n.bytes) - length += 2 + len(pk.e.bytes) - default: - panic("unknown public key algorithm") - } - - packetType := packetTypePublicKey - if pk.IsSubkey { - packetType = packetTypePublicSubkey - } - if err = serializeHeader(w, packetType, length); err != nil { - return - } - return pk.serializeWithoutHeaders(w) -} - -// serializeWithoutHeaders marshals the PublicKey to w in the form of an -// OpenPGP public key packet, not including the packet header. -func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { - var buf [8]byte - // Version 3 - buf[0] = 3 - // Creation time - t := uint32(pk.CreationTime.Unix()) - buf[1] = byte(t >> 24) - buf[2] = byte(t >> 16) - buf[3] = byte(t >> 8) - buf[4] = byte(t) - // Days to expire - buf[5] = byte(pk.DaysToExpire >> 8) - buf[6] = byte(pk.DaysToExpire) - // Public key algorithm - buf[7] = byte(pk.PubKeyAlgo) - - if _, err = w.Write(buf[:]); err != nil { - return - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - return writeMPIs(w, pk.n, pk.e) - } - return errors.InvalidArgumentError("bad public-key algorithm") -} - -// CanSign returns true iff this public key can generate signatures -func (pk *PublicKeyV3) CanSign() bool { - return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly -} - -// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -// public key, of the data hashed into signed. signed is mutated by this call. -func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { - if !pk.CanSign() { - return errors.InvalidArgumentError("public key cannot generate signatures") - } - - suffix := make([]byte, 5) - suffix[0] = byte(sig.SigType) - binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) - signed.Write(suffix) - hashBytes := signed.Sum(nil) - - if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { - return errors.SignatureError("hash tag doesn't match") - } - - if pk.PubKeyAlgo != sig.PubKeyAlgo { - return errors.InvalidArgumentError("public key and signature use different algorithms") - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { - return errors.SignatureError("RSA verification failure") - } - return - default: - // V3 public keys only support RSA. - panic("shouldn't happen") - } -} - -// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -// public key, that id is the identity of pub. -func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { - h, err := userIdSignatureV3Hash(id, pk, sig.Hash) - if err != nil { - return err - } - return pk.VerifySignatureV3(h, sig) -} - -// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this -// public key, of signed. -func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { - h, err := keySignatureHash(pk, signed, sig.Hash) - if err != nil { - return err - } - return pk.VerifySignatureV3(h, sig) -} - -// userIdSignatureV3Hash returns a Hash of the message that needs to be signed -// to assert that pk is a valid key for id. -func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { - if !hfn.Available() { - return nil, errors.UnsupportedError("hash function") - } - h = hfn.New() - - // RFC 4880, section 5.2.4 - pk.SerializeSignaturePrefix(h) - pk.serializeWithoutHeaders(h) - - h.Write([]byte(id)) - - return -} - -// KeyIdString returns the public key's fingerprint in capital hex -// (e.g. "6C7EE1B8621CC013"). -func (pk *PublicKeyV3) KeyIdString() string { - return fmt.Sprintf("%X", pk.KeyId) -} - -// KeyIdShortString returns the short form of public key's fingerprint -// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -func (pk *PublicKeyV3) KeyIdShortString() string { - return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) -} - -// BitLength returns the bit length for the given public key. -func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - bitLength = pk.n.bitLength - default: - err = errors.InvalidArgumentError("bad public-key algorithm") - } - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go deleted file mode 100644 index 34bc7c613e..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/reader.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "golang.org/x/crypto/openpgp/errors" - "io" -) - -// Reader reads packets from an io.Reader and allows packets to be 'unread' so -// that they result from the next call to Next. -type Reader struct { - q []Packet - readers []io.Reader -} - -// New io.Readers are pushed when a compressed or encrypted packet is processed -// and recursively treated as a new source of packets. However, a carefully -// crafted packet can trigger an infinite recursive sequence of packets. See -// http://mumble.net/~campbell/misc/pgp-quine -// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 -// This constant limits the number of recursive packets that may be pushed. -const maxReaders = 32 - -// Next returns the most recently unread Packet, or reads another packet from -// the top-most io.Reader. Unknown packet types are skipped. -func (r *Reader) Next() (p Packet, err error) { - if len(r.q) > 0 { - p = r.q[len(r.q)-1] - r.q = r.q[:len(r.q)-1] - return - } - - for len(r.readers) > 0 { - p, err = Read(r.readers[len(r.readers)-1]) - if err == nil { - return - } - if err == io.EOF { - r.readers = r.readers[:len(r.readers)-1] - continue - } - if _, ok := err.(errors.UnknownPacketTypeError); !ok { - return nil, err - } - } - - return nil, io.EOF -} - -// Push causes the Reader to start reading from a new io.Reader. When an EOF -// error is seen from the new io.Reader, it is popped and the Reader continues -// to read from the next most recent io.Reader. Push returns a StructuralError -// if pushing the reader would exceed the maximum recursion level, otherwise it -// returns nil. -func (r *Reader) Push(reader io.Reader) (err error) { - if len(r.readers) >= maxReaders { - return errors.StructuralError("too many layers of packets") - } - r.readers = append(r.readers, reader) - return nil -} - -// Unread causes the given Packet to be returned from the next call to Next. -func (r *Reader) Unread(p Packet) { - r.q = append(r.q, p) -} - -func NewReader(r io.Reader) *Reader { - return &Reader{ - q: nil, - readers: []io.Reader{r}, - } -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go deleted file mode 100644 index 6ce0cbedbe..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/signature.go +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "crypto" - "crypto/dsa" - "crypto/ecdsa" - "encoding/asn1" - "encoding/binary" - "hash" - "io" - "math/big" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" -) - -const ( - // See RFC 4880, section 5.2.3.21 for details. - KeyFlagCertify = 1 << iota - KeyFlagSign - KeyFlagEncryptCommunications - KeyFlagEncryptStorage -) - -// Signature represents a signature. See RFC 4880, section 5.2. -type Signature struct { - SigType SignatureType - PubKeyAlgo PublicKeyAlgorithm - Hash crypto.Hash - - // HashSuffix is extra data that is hashed in after the signed data. - HashSuffix []byte - // HashTag contains the first two bytes of the hash for fast rejection - // of bad signed data. - HashTag [2]byte - CreationTime time.Time - - RSASignature parsedMPI - DSASigR, DSASigS parsedMPI - ECDSASigR, ECDSASigS parsedMPI - - // rawSubpackets contains the unparsed subpackets, in order. - rawSubpackets []outputSubpacket - - // The following are optional so are nil when not included in the - // signature. - - SigLifetimeSecs, KeyLifetimeSecs *uint32 - PreferredSymmetric, PreferredHash, PreferredCompression []uint8 - IssuerKeyId *uint64 - IsPrimaryId *bool - - // FlagsValid is set if any flags were given. See RFC 4880, section - // 5.2.3.21 for details. - FlagsValid bool - FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool - - // RevocationReason is set if this signature has been revoked. - // See RFC 4880, section 5.2.3.23 for details. - RevocationReason *uint8 - RevocationReasonText string - - // MDC is set if this signature has a feature packet that indicates - // support for MDC subpackets. - MDC bool - - // EmbeddedSignature, if non-nil, is a signature of the parent key, by - // this key. This prevents an attacker from claiming another's signing - // subkey as their own. - EmbeddedSignature *Signature - - outSubpackets []outputSubpacket -} - -func (sig *Signature) parse(r io.Reader) (err error) { - // RFC 4880, section 5.2.3 - var buf [5]byte - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - if buf[0] != 4 { - err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) - return - } - - _, err = readFull(r, buf[:5]) - if err != nil { - return - } - sig.SigType = SignatureType(buf[0]) - sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: - default: - err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) - return - } - - var ok bool - sig.Hash, ok = s2k.HashIdToHash(buf[2]) - if !ok { - return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) - } - - hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) - l := 6 + hashedSubpacketsLength - sig.HashSuffix = make([]byte, l+6) - sig.HashSuffix[0] = 4 - copy(sig.HashSuffix[1:], buf[:5]) - hashedSubpackets := sig.HashSuffix[6:l] - _, err = readFull(r, hashedSubpackets) - if err != nil { - return - } - // See RFC 4880, section 5.2.4 - trailer := sig.HashSuffix[l:] - trailer[0] = 4 - trailer[1] = 0xff - trailer[2] = uint8(l >> 24) - trailer[3] = uint8(l >> 16) - trailer[4] = uint8(l >> 8) - trailer[5] = uint8(l) - - err = parseSignatureSubpackets(sig, hashedSubpackets, true) - if err != nil { - return - } - - _, err = readFull(r, buf[:2]) - if err != nil { - return - } - unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) - unhashedSubpackets := make([]byte, unhashedSubpacketsLength) - _, err = readFull(r, unhashedSubpackets) - if err != nil { - return - } - err = parseSignatureSubpackets(sig, unhashedSubpackets, false) - if err != nil { - return - } - - _, err = readFull(r, sig.HashTag[:2]) - if err != nil { - return - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) - case PubKeyAlgoDSA: - sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) - if err == nil { - sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) - } - case PubKeyAlgoECDSA: - sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) - if err == nil { - sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) - } - default: - panic("unreachable") - } - return -} - -// parseSignatureSubpackets parses subpackets of the main signature packet. See -// RFC 4880, section 5.2.3.1. -func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { - for len(subpackets) > 0 { - subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) - if err != nil { - return - } - } - - if sig.CreationTime.IsZero() { - err = errors.StructuralError("no creation time in signature") - } - - return -} - -type signatureSubpacketType uint8 - -const ( - creationTimeSubpacket signatureSubpacketType = 2 - signatureExpirationSubpacket signatureSubpacketType = 3 - keyExpirationSubpacket signatureSubpacketType = 9 - prefSymmetricAlgosSubpacket signatureSubpacketType = 11 - issuerSubpacket signatureSubpacketType = 16 - prefHashAlgosSubpacket signatureSubpacketType = 21 - prefCompressionSubpacket signatureSubpacketType = 22 - primaryUserIdSubpacket signatureSubpacketType = 25 - keyFlagsSubpacket signatureSubpacketType = 27 - reasonForRevocationSubpacket signatureSubpacketType = 29 - featuresSubpacket signatureSubpacketType = 30 - embeddedSignatureSubpacket signatureSubpacketType = 32 -) - -// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. -func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { - // RFC 4880, section 5.2.3.1 - var ( - length uint32 - packetType signatureSubpacketType - isCritical bool - ) - switch { - case subpacket[0] < 192: - length = uint32(subpacket[0]) - subpacket = subpacket[1:] - case subpacket[0] < 255: - if len(subpacket) < 2 { - goto Truncated - } - length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 - subpacket = subpacket[2:] - default: - if len(subpacket) < 5 { - goto Truncated - } - length = uint32(subpacket[1])<<24 | - uint32(subpacket[2])<<16 | - uint32(subpacket[3])<<8 | - uint32(subpacket[4]) - subpacket = subpacket[5:] - } - if length > uint32(len(subpacket)) { - goto Truncated - } - rest = subpacket[length:] - subpacket = subpacket[:length] - if len(subpacket) == 0 { - err = errors.StructuralError("zero length signature subpacket") - return - } - packetType = signatureSubpacketType(subpacket[0] & 0x7f) - isCritical = subpacket[0]&0x80 == 0x80 - subpacket = subpacket[1:] - sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) - switch packetType { - case creationTimeSubpacket: - if !isHashed { - err = errors.StructuralError("signature creation time in non-hashed area") - return - } - if len(subpacket) != 4 { - err = errors.StructuralError("signature creation time not four bytes") - return - } - t := binary.BigEndian.Uint32(subpacket) - sig.CreationTime = time.Unix(int64(t), 0) - case signatureExpirationSubpacket: - // Signature expiration time, section 5.2.3.10 - if !isHashed { - return - } - if len(subpacket) != 4 { - err = errors.StructuralError("expiration subpacket with bad length") - return - } - sig.SigLifetimeSecs = new(uint32) - *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) - case keyExpirationSubpacket: - // Key expiration time, section 5.2.3.6 - if !isHashed { - return - } - if len(subpacket) != 4 { - err = errors.StructuralError("key expiration subpacket with bad length") - return - } - sig.KeyLifetimeSecs = new(uint32) - *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) - case prefSymmetricAlgosSubpacket: - // Preferred symmetric algorithms, section 5.2.3.7 - if !isHashed { - return - } - sig.PreferredSymmetric = make([]byte, len(subpacket)) - copy(sig.PreferredSymmetric, subpacket) - case issuerSubpacket: - // Issuer, section 5.2.3.5 - if len(subpacket) != 8 { - err = errors.StructuralError("issuer subpacket with bad length") - return - } - sig.IssuerKeyId = new(uint64) - *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) - case prefHashAlgosSubpacket: - // Preferred hash algorithms, section 5.2.3.8 - if !isHashed { - return - } - sig.PreferredHash = make([]byte, len(subpacket)) - copy(sig.PreferredHash, subpacket) - case prefCompressionSubpacket: - // Preferred compression algorithms, section 5.2.3.9 - if !isHashed { - return - } - sig.PreferredCompression = make([]byte, len(subpacket)) - copy(sig.PreferredCompression, subpacket) - case primaryUserIdSubpacket: - // Primary User ID, section 5.2.3.19 - if !isHashed { - return - } - if len(subpacket) != 1 { - err = errors.StructuralError("primary user id subpacket with bad length") - return - } - sig.IsPrimaryId = new(bool) - if subpacket[0] > 0 { - *sig.IsPrimaryId = true - } - case keyFlagsSubpacket: - // Key flags, section 5.2.3.21 - if !isHashed { - return - } - if len(subpacket) == 0 { - err = errors.StructuralError("empty key flags subpacket") - return - } - sig.FlagsValid = true - if subpacket[0]&KeyFlagCertify != 0 { - sig.FlagCertify = true - } - if subpacket[0]&KeyFlagSign != 0 { - sig.FlagSign = true - } - if subpacket[0]&KeyFlagEncryptCommunications != 0 { - sig.FlagEncryptCommunications = true - } - if subpacket[0]&KeyFlagEncryptStorage != 0 { - sig.FlagEncryptStorage = true - } - case reasonForRevocationSubpacket: - // Reason For Revocation, section 5.2.3.23 - if !isHashed { - return - } - if len(subpacket) == 0 { - err = errors.StructuralError("empty revocation reason subpacket") - return - } - sig.RevocationReason = new(uint8) - *sig.RevocationReason = subpacket[0] - sig.RevocationReasonText = string(subpacket[1:]) - case featuresSubpacket: - // Features subpacket, section 5.2.3.24 specifies a very general - // mechanism for OpenPGP implementations to signal support for new - // features. In practice, the subpacket is used exclusively to - // indicate support for MDC-protected encryption. - sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 - case embeddedSignatureSubpacket: - // Only usage is in signatures that cross-certify - // signing subkeys. section 5.2.3.26 describes the - // format, with its usage described in section 11.1 - if sig.EmbeddedSignature != nil { - err = errors.StructuralError("Cannot have multiple embedded signatures") - return - } - sig.EmbeddedSignature = new(Signature) - // Embedded signatures are required to be v4 signatures see - // section 12.1. However, we only parse v4 signatures in this - // file anyway. - if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { - return nil, err - } - if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { - return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) - } - default: - if isCritical { - err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) - return - } - } - return - -Truncated: - err = errors.StructuralError("signature subpacket truncated") - return -} - -// subpacketLengthLength returns the length, in bytes, of an encoded length value. -func subpacketLengthLength(length int) int { - if length < 192 { - return 1 - } - if length < 16320 { - return 2 - } - return 5 -} - -// serializeSubpacketLength marshals the given length into to. -func serializeSubpacketLength(to []byte, length int) int { - // RFC 4880, Section 4.2.2. - if length < 192 { - to[0] = byte(length) - return 1 - } - if length < 16320 { - length -= 192 - to[0] = byte((length >> 8) + 192) - to[1] = byte(length) - return 2 - } - to[0] = 255 - to[1] = byte(length >> 24) - to[2] = byte(length >> 16) - to[3] = byte(length >> 8) - to[4] = byte(length) - return 5 -} - -// subpacketsLength returns the serialized length, in bytes, of the given -// subpackets. -func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { - for _, subpacket := range subpackets { - if subpacket.hashed == hashed { - length += subpacketLengthLength(len(subpacket.contents) + 1) - length += 1 // type byte - length += len(subpacket.contents) - } - } - return -} - -// serializeSubpackets marshals the given subpackets into to. -func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { - for _, subpacket := range subpackets { - if subpacket.hashed == hashed { - n := serializeSubpacketLength(to, len(subpacket.contents)+1) - to[n] = byte(subpacket.subpacketType) - to = to[1+n:] - n = copy(to, subpacket.contents) - to = to[n:] - } - } - return -} - -// KeyExpired returns whether sig is a self-signature of a key that has -// expired. -func (sig *Signature) KeyExpired(currentTime time.Time) bool { - if sig.KeyLifetimeSecs == nil { - return false - } - expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) - return currentTime.After(expiry) -} - -// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. -func (sig *Signature) buildHashSuffix() (err error) { - hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) - - var ok bool - l := 6 + hashedSubpacketsLen - sig.HashSuffix = make([]byte, l+6) - sig.HashSuffix[0] = 4 - sig.HashSuffix[1] = uint8(sig.SigType) - sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) - sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) - if !ok { - sig.HashSuffix = nil - return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) - } - sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) - sig.HashSuffix[5] = byte(hashedSubpacketsLen) - serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) - trailer := sig.HashSuffix[l:] - trailer[0] = 4 - trailer[1] = 0xff - trailer[2] = byte(l >> 24) - trailer[3] = byte(l >> 16) - trailer[4] = byte(l >> 8) - trailer[5] = byte(l) - return -} - -func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { - err = sig.buildHashSuffix() - if err != nil { - return - } - - h.Write(sig.HashSuffix) - digest = h.Sum(nil) - copy(sig.HashTag[:], digest) - return -} - -// Sign signs a message with a private key. The hash, h, must contain -// the hash of the message to be signed and will be mutated by this function. -// On success, the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { - sig.outSubpackets = sig.buildSubpackets() - digest, err := sig.signPrepareHash(h) - if err != nil { - return - } - - switch priv.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - // supports both *rsa.PrivateKey and crypto.Signer - sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) - sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) - case PubKeyAlgoDSA: - dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) - - // Need to truncate hashBytes to match FIPS 186-3 section 4.6. - subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 - if len(digest) > subgroupSize { - digest = digest[:subgroupSize] - } - r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) - if err == nil { - sig.DSASigR.bytes = r.Bytes() - sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) - sig.DSASigS.bytes = s.Bytes() - sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) - } - case PubKeyAlgoECDSA: - var r, s *big.Int - if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { - // direct support, avoid asn1 wrapping/unwrapping - r, s, err = ecdsa.Sign(config.Random(), pk, digest) - } else { - var b []byte - b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil) - if err == nil { - r, s, err = unwrapECDSASig(b) - } - } - if err == nil { - sig.ECDSASigR = fromBig(r) - sig.ECDSASigS = fromBig(s) - } - default: - err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) - } - - return -} - -// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA -// signature. -func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { - var ecsdaSig struct { - R, S *big.Int - } - _, err = asn1.Unmarshal(b, &ecsdaSig) - if err != nil { - return - } - return ecsdaSig.R, ecsdaSig.S, nil -} - -// SignUserId computes a signature from priv, asserting that pub is a valid -// key for the identity id. On success, the signature is stored in sig. Call -// Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { - h, err := userIdSignatureHash(id, pub, sig.Hash) - if err != nil { - return err - } - return sig.Sign(h, priv, config) -} - -// SignKey computes a signature from priv, asserting that pub is a subkey. On -// success, the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { - h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) - if err != nil { - return err - } - return sig.Sign(h, priv, config) -} - -// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -// called first. -func (sig *Signature) Serialize(w io.Writer) (err error) { - if len(sig.outSubpackets) == 0 { - sig.outSubpackets = sig.rawSubpackets - } - if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { - return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") - } - - sigLength := 0 - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sigLength = 2 + len(sig.RSASignature.bytes) - case PubKeyAlgoDSA: - sigLength = 2 + len(sig.DSASigR.bytes) - sigLength += 2 + len(sig.DSASigS.bytes) - case PubKeyAlgoECDSA: - sigLength = 2 + len(sig.ECDSASigR.bytes) - sigLength += 2 + len(sig.ECDSASigS.bytes) - default: - panic("impossible") - } - - unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) - length := len(sig.HashSuffix) - 6 /* trailer not included */ + - 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + - 2 /* hash tag */ + sigLength - err = serializeHeader(w, packetTypeSignature, length) - if err != nil { - return - } - - _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) - if err != nil { - return - } - - unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) - unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) - unhashedSubpackets[1] = byte(unhashedSubpacketsLen) - serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) - - _, err = w.Write(unhashedSubpackets) - if err != nil { - return - } - _, err = w.Write(sig.HashTag[:]) - if err != nil { - return - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - err = writeMPIs(w, sig.RSASignature) - case PubKeyAlgoDSA: - err = writeMPIs(w, sig.DSASigR, sig.DSASigS) - case PubKeyAlgoECDSA: - err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) - default: - panic("impossible") - } - return -} - -// outputSubpacket represents a subpacket to be marshaled. -type outputSubpacket struct { - hashed bool // true if this subpacket is in the hashed area. - subpacketType signatureSubpacketType - isCritical bool - contents []byte -} - -func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { - creationTime := make([]byte, 4) - binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) - subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) - - if sig.IssuerKeyId != nil { - keyId := make([]byte, 8) - binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) - subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) - } - - if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { - sigLifetime := make([]byte, 4) - binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) - subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) - } - - // Key flags may only appear in self-signatures or certification signatures. - - if sig.FlagsValid { - var flags byte - if sig.FlagCertify { - flags |= KeyFlagCertify - } - if sig.FlagSign { - flags |= KeyFlagSign - } - if sig.FlagEncryptCommunications { - flags |= KeyFlagEncryptCommunications - } - if sig.FlagEncryptStorage { - flags |= KeyFlagEncryptStorage - } - subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) - } - - // The following subpackets may only appear in self-signatures - - if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { - keyLifetime := make([]byte, 4) - binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) - subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) - } - - if sig.IsPrimaryId != nil && *sig.IsPrimaryId { - subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) - } - - if len(sig.PreferredSymmetric) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) - } - - if len(sig.PreferredHash) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) - } - - if len(sig.PreferredCompression) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) - } - - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go deleted file mode 100644 index 6edff88934..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto" - "encoding/binary" - "fmt" - "io" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" -) - -// SignatureV3 represents older version 3 signatures. These signatures are less secure -// than version 4 and should not be used to create new signatures. They are included -// here for backwards compatibility to read and validate with older key material. -// See RFC 4880, section 5.2.2. -type SignatureV3 struct { - SigType SignatureType - CreationTime time.Time - IssuerKeyId uint64 - PubKeyAlgo PublicKeyAlgorithm - Hash crypto.Hash - HashTag [2]byte - - RSASignature parsedMPI - DSASigR, DSASigS parsedMPI -} - -func (sig *SignatureV3) parse(r io.Reader) (err error) { - // RFC 4880, section 5.2.2 - var buf [8]byte - if _, err = readFull(r, buf[:1]); err != nil { - return - } - if buf[0] < 2 || buf[0] > 3 { - err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) - return - } - if _, err = readFull(r, buf[:1]); err != nil { - return - } - if buf[0] != 5 { - err = errors.UnsupportedError( - "invalid hashed material length " + strconv.Itoa(int(buf[0]))) - return - } - - // Read hashed material: signature type + creation time - if _, err = readFull(r, buf[:5]); err != nil { - return - } - sig.SigType = SignatureType(buf[0]) - t := binary.BigEndian.Uint32(buf[1:5]) - sig.CreationTime = time.Unix(int64(t), 0) - - // Eight-octet Key ID of signer. - if _, err = readFull(r, buf[:8]); err != nil { - return - } - sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) - - // Public-key and hash algorithm - if _, err = readFull(r, buf[:2]); err != nil { - return - } - sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: - default: - err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) - return - } - var ok bool - if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { - return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) - } - - // Two-octet field holding left 16 bits of signed hash value. - if _, err = readFull(r, sig.HashTag[:2]); err != nil { - return - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) - case PubKeyAlgoDSA: - if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { - return - } - sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) - default: - panic("unreachable") - } - return -} - -// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -// called first. -func (sig *SignatureV3) Serialize(w io.Writer) (err error) { - buf := make([]byte, 8) - - // Write the sig type and creation time - buf[0] = byte(sig.SigType) - binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) - if _, err = w.Write(buf[:5]); err != nil { - return - } - - // Write the issuer long key ID - binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) - if _, err = w.Write(buf[:8]); err != nil { - return - } - - // Write public key algorithm, hash ID, and hash value - buf[0] = byte(sig.PubKeyAlgo) - hashId, ok := s2k.HashToHashId(sig.Hash) - if !ok { - return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) - } - buf[1] = hashId - copy(buf[2:4], sig.HashTag[:]) - if _, err = w.Write(buf[:4]); err != nil { - return - } - - if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { - return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - err = writeMPIs(w, sig.RSASignature) - case PubKeyAlgoDSA: - err = writeMPIs(w, sig.DSASigR, sig.DSASigS) - default: - panic("impossible") - } - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go deleted file mode 100644 index 744c2d2c42..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "crypto/cipher" - "io" - "strconv" - - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" -) - -// This is the largest session key that we'll support. Since no 512-bit cipher -// has even been seriously used, this is comfortably large. -const maxSessionKeySizeInBytes = 64 - -// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC -// 4880, section 5.3. -type SymmetricKeyEncrypted struct { - CipherFunc CipherFunction - s2k func(out, in []byte) - encryptedKey []byte -} - -const symmetricKeyEncryptedVersion = 4 - -func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { - // RFC 4880, section 5.3. - var buf [2]byte - if _, err := readFull(r, buf[:]); err != nil { - return err - } - if buf[0] != symmetricKeyEncryptedVersion { - return errors.UnsupportedError("SymmetricKeyEncrypted version") - } - ske.CipherFunc = CipherFunction(buf[1]) - - if ske.CipherFunc.KeySize() == 0 { - return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) - } - - var err error - ske.s2k, err = s2k.Parse(r) - if err != nil { - return err - } - - encryptedKey := make([]byte, maxSessionKeySizeInBytes) - // The session key may follow. We just have to try and read to find - // out. If it exists then we limit it to maxSessionKeySizeInBytes. - n, err := readFull(r, encryptedKey) - if err != nil && err != io.ErrUnexpectedEOF { - return err - } - - if n != 0 { - if n == maxSessionKeySizeInBytes { - return errors.UnsupportedError("oversized encrypted session key") - } - ske.encryptedKey = encryptedKey[:n] - } - - return nil -} - -// Decrypt attempts to decrypt an encrypted session key and returns the key and -// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data -// packet. -func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { - key := make([]byte, ske.CipherFunc.KeySize()) - ske.s2k(key, passphrase) - - if len(ske.encryptedKey) == 0 { - return key, ske.CipherFunc, nil - } - - // the IV is all zeros - iv := make([]byte, ske.CipherFunc.blockSize()) - c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) - plaintextKey := make([]byte, len(ske.encryptedKey)) - c.XORKeyStream(plaintextKey, ske.encryptedKey) - cipherFunc := CipherFunction(plaintextKey[0]) - if cipherFunc.blockSize() == 0 { - return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) - } - plaintextKey = plaintextKey[1:] - if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { - return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + - "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") - } - return plaintextKey, cipherFunc, nil -} - -// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The -// packet contains a random session key, encrypted by a key derived from the -// given passphrase. The session key is returned and must be passed to -// SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { - cipherFunc := config.Cipher() - keySize := cipherFunc.KeySize() - if keySize == 0 { - return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) - } - - s2kBuf := new(bytes.Buffer) - keyEncryptingKey := make([]byte, keySize) - // s2k.Serialize salts and stretches the passphrase, and writes the - // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. - err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) - if err != nil { - return - } - s2kBytes := s2kBuf.Bytes() - - packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize - err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) - if err != nil { - return - } - - var buf [2]byte - buf[0] = symmetricKeyEncryptedVersion - buf[1] = byte(cipherFunc) - _, err = w.Write(buf[:]) - if err != nil { - return - } - _, err = w.Write(s2kBytes) - if err != nil { - return - } - - sessionKey := make([]byte, keySize) - _, err = io.ReadFull(config.Random(), sessionKey) - if err != nil { - return - } - iv := make([]byte, cipherFunc.blockSize()) - c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) - encryptedCipherAndKey := make([]byte, keySize+1) - c.XORKeyStream(encryptedCipherAndKey, buf[1:]) - c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) - _, err = w.Write(encryptedCipherAndKey) - if err != nil { - return - } - - key = sessionKey - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go deleted file mode 100644 index 6126030eb9..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto/cipher" - "crypto/sha1" - "crypto/subtle" - "golang.org/x/crypto/openpgp/errors" - "hash" - "io" - "strconv" -) - -// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The -// encrypted contents will consist of more OpenPGP packets. See RFC 4880, -// sections 5.7 and 5.13. -type SymmetricallyEncrypted struct { - MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. - contents io.Reader - prefix []byte -} - -const symmetricallyEncryptedVersion = 1 - -func (se *SymmetricallyEncrypted) parse(r io.Reader) error { - if se.MDC { - // See RFC 4880, section 5.13. - var buf [1]byte - _, err := readFull(r, buf[:]) - if err != nil { - return err - } - if buf[0] != symmetricallyEncryptedVersion { - return errors.UnsupportedError("unknown SymmetricallyEncrypted version") - } - } - se.contents = r - return nil -} - -// Decrypt returns a ReadCloser, from which the decrypted contents of the -// packet can be read. An incorrect key can, with high probability, be detected -// immediately and this will result in a KeyIncorrect error being returned. -func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { - keySize := c.KeySize() - if keySize == 0 { - return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) - } - if len(key) != keySize { - return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") - } - - if se.prefix == nil { - se.prefix = make([]byte, c.blockSize()+2) - _, err := readFull(se.contents, se.prefix) - if err != nil { - return nil, err - } - } else if len(se.prefix) != c.blockSize()+2 { - return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") - } - - ocfbResync := OCFBResync - if se.MDC { - // MDC packets use a different form of OCFB mode. - ocfbResync = OCFBNoResync - } - - s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) - if s == nil { - return nil, errors.ErrKeyIncorrect - } - - plaintext := cipher.StreamReader{S: s, R: se.contents} - - if se.MDC { - // MDC packets have an embedded hash that we need to check. - h := sha1.New() - h.Write(se.prefix) - return &seMDCReader{in: plaintext, h: h}, nil - } - - // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. - return seReader{plaintext}, nil -} - -// seReader wraps an io.Reader with a no-op Close method. -type seReader struct { - in io.Reader -} - -func (ser seReader) Read(buf []byte) (int, error) { - return ser.in.Read(buf) -} - -func (ser seReader) Close() error { - return nil -} - -const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size - -// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold -// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an -// MDC packet containing a hash of the previous contents which is checked -// against the running hash. See RFC 4880, section 5.13. -type seMDCReader struct { - in io.Reader - h hash.Hash - trailer [mdcTrailerSize]byte - scratch [mdcTrailerSize]byte - trailerUsed int - error bool - eof bool -} - -func (ser *seMDCReader) Read(buf []byte) (n int, err error) { - if ser.error { - err = io.ErrUnexpectedEOF - return - } - if ser.eof { - err = io.EOF - return - } - - // If we haven't yet filled the trailer buffer then we must do that - // first. - for ser.trailerUsed < mdcTrailerSize { - n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) - ser.trailerUsed += n - if err == io.EOF { - if ser.trailerUsed != mdcTrailerSize { - n = 0 - err = io.ErrUnexpectedEOF - ser.error = true - return - } - ser.eof = true - n = 0 - return - } - - if err != nil { - n = 0 - return - } - } - - // If it's a short read then we read into a temporary buffer and shift - // the data into the caller's buffer. - if len(buf) <= mdcTrailerSize { - n, err = readFull(ser.in, ser.scratch[:len(buf)]) - copy(buf, ser.trailer[:n]) - ser.h.Write(buf[:n]) - copy(ser.trailer[:], ser.trailer[n:]) - copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) - if n < len(buf) { - ser.eof = true - err = io.EOF - } - return - } - - n, err = ser.in.Read(buf[mdcTrailerSize:]) - copy(buf, ser.trailer[:]) - ser.h.Write(buf[:n]) - copy(ser.trailer[:], buf[n:]) - - if err == io.EOF { - ser.eof = true - } - return -} - -// This is a new-format packet tag byte for a type 19 (MDC) packet. -const mdcPacketTagByte = byte(0x80) | 0x40 | 19 - -func (ser *seMDCReader) Close() error { - if ser.error { - return errors.SignatureError("error during reading") - } - - for !ser.eof { - // We haven't seen EOF so we need to read to the end - var buf [1024]byte - _, err := ser.Read(buf[:]) - if err == io.EOF { - break - } - if err != nil { - return errors.SignatureError("error during reading") - } - } - - if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { - return errors.SignatureError("MDC packet not found") - } - ser.h.Write(ser.trailer[:2]) - - final := ser.h.Sum(nil) - if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { - return errors.SignatureError("hash mismatch") - } - return nil -} - -// An seMDCWriter writes through to an io.WriteCloser while maintains a running -// hash of the data written. On close, it emits an MDC packet containing the -// running hash. -type seMDCWriter struct { - w io.WriteCloser - h hash.Hash -} - -func (w *seMDCWriter) Write(buf []byte) (n int, err error) { - w.h.Write(buf) - return w.w.Write(buf) -} - -func (w *seMDCWriter) Close() (err error) { - var buf [mdcTrailerSize]byte - - buf[0] = mdcPacketTagByte - buf[1] = sha1.Size - w.h.Write(buf[:2]) - digest := w.h.Sum(nil) - copy(buf[2:], digest) - - _, err = w.w.Write(buf[:]) - if err != nil { - return - } - return w.w.Close() -} - -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. -type noOpCloser struct { - w io.Writer -} - -func (c noOpCloser) Write(data []byte) (n int, err error) { - return c.w.Write(data) -} - -func (c noOpCloser) Close() error { - return nil -} - -// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet -// to w and returns a WriteCloser to which the to-be-encrypted packets can be -// written. -// If config is nil, sensible defaults will be used. -func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { - if c.KeySize() != len(key) { - return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") - } - writeCloser := noOpCloser{w} - ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) - if err != nil { - return - } - - _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) - if err != nil { - return - } - - block := c.new(key) - blockSize := block.BlockSize() - iv := make([]byte, blockSize) - _, err = config.Random().Read(iv) - if err != nil { - return - } - s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) - _, err = ciphertext.Write(prefix) - if err != nil { - return - } - plaintext := cipher.StreamWriter{S: s, W: ciphertext} - - h := sha1.New() - h.Write(iv) - h.Write(iv[blockSize-2:]) - contents = &seMDCWriter{w: plaintext, h: h} - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go deleted file mode 100644 index 96a2b382a1..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "image" - "image/jpeg" - "io" - "io/ioutil" -) - -const UserAttrImageSubpacket = 1 - -// UserAttribute is capable of storing other types of data about a user -// beyond name, email and a text comment. In practice, user attributes are typically used -// to store a signed thumbnail photo JPEG image of the user. -// See RFC 4880, section 5.12. -type UserAttribute struct { - Contents []*OpaqueSubpacket -} - -// NewUserAttributePhoto creates a user attribute packet -// containing the given images. -func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { - uat = new(UserAttribute) - for _, photo := range photos { - var buf bytes.Buffer - // RFC 4880, Section 5.12.1. - data := []byte{ - 0x10, 0x00, // Little-endian image header length (16 bytes) - 0x01, // Image header version 1 - 0x01, // JPEG - 0, 0, 0, 0, // 12 reserved octets, must be all zero. - 0, 0, 0, 0, - 0, 0, 0, 0} - if _, err = buf.Write(data); err != nil { - return - } - if err = jpeg.Encode(&buf, photo, nil); err != nil { - return - } - uat.Contents = append(uat.Contents, &OpaqueSubpacket{ - SubType: UserAttrImageSubpacket, - Contents: buf.Bytes()}) - } - return -} - -// NewUserAttribute creates a new user attribute packet containing the given subpackets. -func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { - return &UserAttribute{Contents: contents} -} - -func (uat *UserAttribute) parse(r io.Reader) (err error) { - // RFC 4880, section 5.13 - b, err := ioutil.ReadAll(r) - if err != nil { - return - } - uat.Contents, err = OpaqueSubpackets(b) - return -} - -// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including -// header. -func (uat *UserAttribute) Serialize(w io.Writer) (err error) { - var buf bytes.Buffer - for _, sp := range uat.Contents { - sp.Serialize(&buf) - } - if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { - return err - } - _, err = w.Write(buf.Bytes()) - return -} - -// ImageData returns zero or more byte slices, each containing -// JPEG File Interchange Format (JFIF), for each photo in the -// the user attribute packet. -func (uat *UserAttribute) ImageData() (imageData [][]byte) { - for _, sp := range uat.Contents { - if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { - imageData = append(imageData, sp.Contents[16:]) - } - } - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go deleted file mode 100644 index d6bea7d4ac..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/packet/userid.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "io" - "io/ioutil" - "strings" -) - -// UserId contains text that is intended to represent the name and email -// address of the key holder. See RFC 4880, section 5.11. By convention, this -// takes the form "Full Name (Comment) " -type UserId struct { - Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. - - Name, Comment, Email string -} - -func hasInvalidCharacters(s string) bool { - for _, c := range s { - switch c { - case '(', ')', '<', '>', 0: - return true - } - } - return false -} - -// NewUserId returns a UserId or nil if any of the arguments contain invalid -// characters. The invalid characters are '\x00', '(', ')', '<' and '>' -func NewUserId(name, comment, email string) *UserId { - // RFC 4880 doesn't deal with the structure of userid strings; the - // name, comment and email form is just a convention. However, there's - // no convention about escaping the metacharacters and GPG just refuses - // to create user ids where, say, the name contains a '('. We mirror - // this behaviour. - - if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { - return nil - } - - uid := new(UserId) - uid.Name, uid.Comment, uid.Email = name, comment, email - uid.Id = name - if len(comment) > 0 { - if len(uid.Id) > 0 { - uid.Id += " " - } - uid.Id += "(" - uid.Id += comment - uid.Id += ")" - } - if len(email) > 0 { - if len(uid.Id) > 0 { - uid.Id += " " - } - uid.Id += "<" - uid.Id += email - uid.Id += ">" - } - return uid -} - -func (uid *UserId) parse(r io.Reader) (err error) { - // RFC 4880, section 5.11 - b, err := ioutil.ReadAll(r) - if err != nil { - return - } - uid.Id = string(b) - uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) - return -} - -// Serialize marshals uid to w in the form of an OpenPGP packet, including -// header. -func (uid *UserId) Serialize(w io.Writer) error { - err := serializeHeader(w, packetTypeUserId, len(uid.Id)) - if err != nil { - return err - } - _, err = w.Write([]byte(uid.Id)) - return err -} - -// parseUserId extracts the name, comment and email from a user id string that -// is formatted as "Full Name (Comment) ". -func parseUserId(id string) (name, comment, email string) { - var n, c, e struct { - start, end int - } - var state int - - for offset, rune := range id { - switch state { - case 0: - // Entering name - n.start = offset - state = 1 - fallthrough - case 1: - // In name - if rune == '(' { - state = 2 - n.end = offset - } else if rune == '<' { - state = 5 - n.end = offset - } - case 2: - // Entering comment - c.start = offset - state = 3 - fallthrough - case 3: - // In comment - if rune == ')' { - state = 4 - c.end = offset - } - case 4: - // Between comment and email - if rune == '<' { - state = 5 - } - case 5: - // Entering email - e.start = offset - state = 6 - fallthrough - case 6: - // In email - if rune == '>' { - state = 7 - e.end = offset - } - default: - // After email - } - } - switch state { - case 1: - // ended in the name - n.end = len(id) - case 3: - // ended in comment - c.end = len(id) - case 6: - // ended in email - e.end = len(id) - } - - name = strings.TrimSpace(id[n.start:n.end]) - comment = strings.TrimSpace(id[c.start:c.end]) - email = strings.TrimSpace(id[e.start:e.end]) - return -} diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go deleted file mode 100644 index 6ec664f44a..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/read.go +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package openpgp implements high level operations on OpenPGP messages. -package openpgp // import "golang.org/x/crypto/openpgp" - -import ( - "crypto" - _ "crypto/sha256" - "hash" - "io" - "strconv" - - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" -) - -// SignatureType is the armor type for a PGP signature. -var SignatureType = "PGP SIGNATURE" - -// readArmored reads an armored block with the given type. -func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { - block, err := armor.Decode(r) - if err != nil { - return - } - - if block.Type != expectedType { - return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) - } - - return block.Body, nil -} - -// MessageDetails contains the result of parsing an OpenPGP encrypted and/or -// signed message. -type MessageDetails struct { - IsEncrypted bool // true if the message was encrypted. - EncryptedToKeyIds []uint64 // the list of recipient key ids. - IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. - DecryptedWith Key // the private key used to decrypt the message, if any. - IsSigned bool // true if the message is signed. - SignedByKeyId uint64 // the key id of the signer, if any. - SignedBy *Key // the key of the signer, if available. - LiteralData *packet.LiteralData // the metadata of the contents - UnverifiedBody io.Reader // the contents of the message. - - // If IsSigned is true and SignedBy is non-zero then the signature will - // be verified as UnverifiedBody is read. The signature cannot be - // checked until the whole of UnverifiedBody is read so UnverifiedBody - // must be consumed until EOF before the data can be trusted. Even if a - // message isn't signed (or the signer is unknown) the data may contain - // an authentication code that is only checked once UnverifiedBody has - // been consumed. Once EOF has been seen, the following fields are - // valid. (An authentication code failure is reported as a - // SignatureError error when reading from UnverifiedBody.) - SignatureError error // nil if the signature is good. - Signature *packet.Signature // the signature packet itself, if v4 (default) - SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature - - decrypted io.ReadCloser -} - -// A PromptFunction is used as a callback by functions that may need to decrypt -// a private key, or prompt for a passphrase. It is called with a list of -// acceptable, encrypted private keys and a boolean that indicates whether a -// passphrase is usable. It should either decrypt a private key or return a -// passphrase to try. If the decrypted private key or given passphrase isn't -// correct, the function will be called again, forever. Any error returned will -// be passed up. -type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) - -// A keyEnvelopePair is used to store a private key with the envelope that -// contains a symmetric key, encrypted with that key. -type keyEnvelopePair struct { - key Key - encryptedKey *packet.EncryptedKey -} - -// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. -// The given KeyRing should contain both public keys (for signature -// verification) and, possibly encrypted, private keys for decrypting. -// If config is nil, sensible defaults will be used. -func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { - var p packet.Packet - - var symKeys []*packet.SymmetricKeyEncrypted - var pubKeys []keyEnvelopePair - var se *packet.SymmetricallyEncrypted - - packets := packet.NewReader(r) - md = new(MessageDetails) - md.IsEncrypted = true - - // The message, if encrypted, starts with a number of packets - // containing an encrypted decryption key. The decryption key is either - // encrypted to a public key, or with a passphrase. This loop - // collects these packets. -ParsePackets: - for { - p, err = packets.Next() - if err != nil { - return nil, err - } - switch p := p.(type) { - case *packet.SymmetricKeyEncrypted: - // This packet contains the decryption key encrypted with a passphrase. - md.IsSymmetricallyEncrypted = true - symKeys = append(symKeys, p) - case *packet.EncryptedKey: - // This packet contains the decryption key encrypted to a public key. - md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) - switch p.Algo { - case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: - break - default: - continue - } - var keys []Key - if p.KeyId == 0 { - keys = keyring.DecryptionKeys() - } else { - keys = keyring.KeysById(p.KeyId) - } - for _, k := range keys { - pubKeys = append(pubKeys, keyEnvelopePair{k, p}) - } - case *packet.SymmetricallyEncrypted: - se = p - break ParsePackets - case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: - // This message isn't encrypted. - if len(symKeys) != 0 || len(pubKeys) != 0 { - return nil, errors.StructuralError("key material not followed by encrypted message") - } - packets.Unread(p) - return readSignedMessage(packets, nil, keyring) - } - } - - var candidates []Key - var decrypted io.ReadCloser - - // Now that we have the list of encrypted keys we need to decrypt at - // least one of them or, if we cannot, we need to call the prompt - // function so that it can decrypt a key or give us a passphrase. -FindKey: - for { - // See if any of the keys already have a private key available - candidates = candidates[:0] - candidateFingerprints := make(map[string]bool) - - for _, pk := range pubKeys { - if pk.key.PrivateKey == nil { - continue - } - if !pk.key.PrivateKey.Encrypted { - if len(pk.encryptedKey.Key) == 0 { - pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) - } - if len(pk.encryptedKey.Key) == 0 { - continue - } - decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) - if err != nil && err != errors.ErrKeyIncorrect { - return nil, err - } - if decrypted != nil { - md.DecryptedWith = pk.key - break FindKey - } - } else { - fpr := string(pk.key.PublicKey.Fingerprint[:]) - if v := candidateFingerprints[fpr]; v { - continue - } - candidates = append(candidates, pk.key) - candidateFingerprints[fpr] = true - } - } - - if len(candidates) == 0 && len(symKeys) == 0 { - return nil, errors.ErrKeyIncorrect - } - - if prompt == nil { - return nil, errors.ErrKeyIncorrect - } - - passphrase, err := prompt(candidates, len(symKeys) != 0) - if err != nil { - return nil, err - } - - // Try the symmetric passphrase first - if len(symKeys) != 0 && passphrase != nil { - for _, s := range symKeys { - key, cipherFunc, err := s.Decrypt(passphrase) - if err == nil { - decrypted, err = se.Decrypt(cipherFunc, key) - if err != nil && err != errors.ErrKeyIncorrect { - return nil, err - } - if decrypted != nil { - break FindKey - } - } - - } - } - } - - md.decrypted = decrypted - if err := packets.Push(decrypted); err != nil { - return nil, err - } - return readSignedMessage(packets, md, keyring) -} - -// readSignedMessage reads a possibly signed message if mdin is non-zero then -// that structure is updated and returned. Otherwise a fresh MessageDetails is -// used. -func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { - if mdin == nil { - mdin = new(MessageDetails) - } - md = mdin - - var p packet.Packet - var h hash.Hash - var wrappedHash hash.Hash -FindLiteralData: - for { - p, err = packets.Next() - if err != nil { - return nil, err - } - switch p := p.(type) { - case *packet.Compressed: - if err := packets.Push(p.Body); err != nil { - return nil, err - } - case *packet.OnePassSignature: - if !p.IsLast { - return nil, errors.UnsupportedError("nested signatures") - } - - h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) - if err != nil { - md = nil - return - } - - md.IsSigned = true - md.SignedByKeyId = p.KeyId - keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) - if len(keys) > 0 { - md.SignedBy = &keys[0] - } - case *packet.LiteralData: - md.LiteralData = p - break FindLiteralData - } - } - - if md.SignedBy != nil { - md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} - } else if md.decrypted != nil { - md.UnverifiedBody = checkReader{md} - } else { - md.UnverifiedBody = md.LiteralData.Body - } - - return md, nil -} - -// hashForSignature returns a pair of hashes that can be used to verify a -// signature. The signature may specify that the contents of the signed message -// should be preprocessed (i.e. to normalize line endings). Thus this function -// returns two hashes. The second should be used to hash the message itself and -// performs any needed preprocessing. -func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { - if !hashId.Available() { - return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) - } - h := hashId.New() - - switch sigType { - case packet.SigTypeBinary: - return h, h, nil - case packet.SigTypeText: - return h, NewCanonicalTextHash(h), nil - } - - return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) -} - -// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF -// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger -// MDC checks. -type checkReader struct { - md *MessageDetails -} - -func (cr checkReader) Read(buf []byte) (n int, err error) { - n, err = cr.md.LiteralData.Body.Read(buf) - if err == io.EOF { - mdcErr := cr.md.decrypted.Close() - if mdcErr != nil { - err = mdcErr - } - } - return -} - -// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes -// the data as it is read. When it sees an EOF from the underlying io.Reader -// it parses and checks a trailing Signature packet and triggers any MDC checks. -type signatureCheckReader struct { - packets *packet.Reader - h, wrappedHash hash.Hash - md *MessageDetails -} - -func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { - n, err = scr.md.LiteralData.Body.Read(buf) - scr.wrappedHash.Write(buf[:n]) - if err == io.EOF { - var p packet.Packet - p, scr.md.SignatureError = scr.packets.Next() - if scr.md.SignatureError != nil { - return - } - - var ok bool - if scr.md.Signature, ok = p.(*packet.Signature); ok { - scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) - } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { - scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) - } else { - scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") - return - } - - // The SymmetricallyEncrypted packet, if any, might have an - // unsigned hash of its own. In order to check this we need to - // close that Reader. - if scr.md.decrypted != nil { - mdcErr := scr.md.decrypted.Close() - if mdcErr != nil { - err = mdcErr - } - } - } - return -} - -// CheckDetachedSignature takes a signed file and a detached signature and -// returns the signer if the signature is valid. If the signer isn't known, -// ErrUnknownIssuer is returned. -func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { - var issuerKeyId uint64 - var hashFunc crypto.Hash - var sigType packet.SignatureType - var keys []Key - var p packet.Packet - - packets := packet.NewReader(signature) - for { - p, err = packets.Next() - if err == io.EOF { - return nil, errors.ErrUnknownIssuer - } - if err != nil { - return nil, err - } - - switch sig := p.(type) { - case *packet.Signature: - if sig.IssuerKeyId == nil { - return nil, errors.StructuralError("signature doesn't have an issuer") - } - issuerKeyId = *sig.IssuerKeyId - hashFunc = sig.Hash - sigType = sig.SigType - case *packet.SignatureV3: - issuerKeyId = sig.IssuerKeyId - hashFunc = sig.Hash - sigType = sig.SigType - default: - return nil, errors.StructuralError("non signature packet found") - } - - keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) - if len(keys) > 0 { - break - } - } - - if len(keys) == 0 { - panic("unreachable") - } - - h, wrappedHash, err := hashForSignature(hashFunc, sigType) - if err != nil { - return nil, err - } - - if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { - return nil, err - } - - for _, key := range keys { - switch sig := p.(type) { - case *packet.Signature: - err = key.PublicKey.VerifySignature(h, sig) - case *packet.SignatureV3: - err = key.PublicKey.VerifySignatureV3(h, sig) - default: - panic("unreachable") - } - - if err == nil { - return key.Entity, nil - } - } - - return nil, err -} - -// CheckArmoredDetachedSignature performs the same actions as -// CheckDetachedSignature but expects the signature to be armored. -func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { - body, err := readArmored(signature, SignatureType) - if err != nil { - return - } - - return CheckDetachedSignature(keyring, signed, body) -} diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go deleted file mode 100644 index 4b9a44ca26..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package s2k implements the various OpenPGP string-to-key transforms as -// specified in RFC 4800 section 3.7.1. -package s2k // import "golang.org/x/crypto/openpgp/s2k" - -import ( - "crypto" - "hash" - "io" - "strconv" - - "golang.org/x/crypto/openpgp/errors" -) - -// Config collects configuration parameters for s2k key-stretching -// transformatioms. A nil *Config is valid and results in all default -// values. Currently, Config is used only by the Serialize function in -// this package. -type Config struct { - // Hash is the default hash function to be used. If - // nil, SHA1 is used. - Hash crypto.Hash - // S2KCount is only used for symmetric encryption. It - // determines the strength of the passphrase stretching when - // the said passphrase is hashed to produce a key. S2KCount - // should be between 1024 and 65011712, inclusive. If Config - // is nil or S2KCount is 0, the value 65536 used. Not all - // values in the above range can be represented. S2KCount will - // be rounded up to the next representable value if it cannot - // be encoded exactly. When set, it is strongly encrouraged to - // use a value that is at least 65536. See RFC 4880 Section - // 3.7.1.3. - S2KCount int -} - -func (c *Config) hash() crypto.Hash { - if c == nil || uint(c.Hash) == 0 { - // SHA1 is the historical default in this package. - return crypto.SHA1 - } - - return c.Hash -} - -func (c *Config) encodedCount() uint8 { - if c == nil || c.S2KCount == 0 { - return 96 // The common case. Correspoding to 65536 - } - - i := c.S2KCount - switch { - // Behave like GPG. Should we make 65536 the lowest value used? - case i < 1024: - i = 1024 - case i > 65011712: - i = 65011712 - } - - return encodeCount(i) -} - -// encodeCount converts an iterative "count" in the range 1024 to -// 65011712, inclusive, to an encoded count. The return value is the -// octet that is actually stored in the GPG file. encodeCount panics -// if i is not in the above range (encodedCount above takes care to -// pass i in the correct range). See RFC 4880 Section 3.7.7.1. -func encodeCount(i int) uint8 { - if i < 1024 || i > 65011712 { - panic("count arg i outside the required range") - } - - for encoded := 0; encoded < 256; encoded++ { - count := decodeCount(uint8(encoded)) - if count >= i { - return uint8(encoded) - } - } - - return 255 -} - -// decodeCount returns the s2k mode 3 iterative "count" corresponding to -// the encoded octet c. -func decodeCount(c uint8) int { - return (16 + int(c&15)) << (uint32(c>>4) + 6) -} - -// Simple writes to out the result of computing the Simple S2K function (RFC -// 4880, section 3.7.1.1) using the given hash and input passphrase. -func Simple(out []byte, h hash.Hash, in []byte) { - Salted(out, h, in, nil) -} - -var zero [1]byte - -// Salted writes to out the result of computing the Salted S2K function (RFC -// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. -func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { - done := 0 - var digest []byte - - for i := 0; done < len(out); i++ { - h.Reset() - for j := 0; j < i; j++ { - h.Write(zero[:]) - } - h.Write(salt) - h.Write(in) - digest = h.Sum(digest[:0]) - n := copy(out[done:], digest) - done += n - } -} - -// Iterated writes to out the result of computing the Iterated and Salted S2K -// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, -// salt and iteration count. -func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { - combined := make([]byte, len(in)+len(salt)) - copy(combined, salt) - copy(combined[len(salt):], in) - - if count < len(combined) { - count = len(combined) - } - - done := 0 - var digest []byte - for i := 0; done < len(out); i++ { - h.Reset() - for j := 0; j < i; j++ { - h.Write(zero[:]) - } - written := 0 - for written < count { - if written+len(combined) > count { - todo := count - written - h.Write(combined[:todo]) - written = count - } else { - h.Write(combined) - written += len(combined) - } - } - digest = h.Sum(digest[:0]) - n := copy(out[done:], digest) - done += n - } -} - -// Parse reads a binary specification for a string-to-key transformation from r -// and returns a function which performs that transform. -func Parse(r io.Reader) (f func(out, in []byte), err error) { - var buf [9]byte - - _, err = io.ReadFull(r, buf[:2]) - if err != nil { - return - } - - hash, ok := HashIdToHash(buf[1]) - if !ok { - return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) - } - if !hash.Available() { - return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) - } - h := hash.New() - - switch buf[0] { - case 0: - f := func(out, in []byte) { - Simple(out, h, in) - } - return f, nil - case 1: - _, err = io.ReadFull(r, buf[:8]) - if err != nil { - return - } - f := func(out, in []byte) { - Salted(out, h, in, buf[:8]) - } - return f, nil - case 3: - _, err = io.ReadFull(r, buf[:9]) - if err != nil { - return - } - count := decodeCount(buf[8]) - f := func(out, in []byte) { - Iterated(out, h, in, buf[:8], count) - } - return f, nil - } - - return nil, errors.UnsupportedError("S2K function") -} - -// Serialize salts and stretches the given passphrase and writes the -// resulting key into key. It also serializes an S2K descriptor to -// w. The key stretching can be configured with c, which may be -// nil. In that case, sensible defaults will be used. -func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { - var buf [11]byte - buf[0] = 3 /* iterated and salted */ - buf[1], _ = HashToHashId(c.hash()) - salt := buf[2:10] - if _, err := io.ReadFull(rand, salt); err != nil { - return err - } - encodedCount := c.encodedCount() - count := decodeCount(encodedCount) - buf[10] = encodedCount - if _, err := w.Write(buf[:]); err != nil { - return err - } - - Iterated(key, c.hash().New(), passphrase, salt, count) - return nil -} - -// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with -// Go's crypto.Hash type. See RFC 4880, section 9.4. -var hashToHashIdMapping = []struct { - id byte - hash crypto.Hash - name string -}{ - {1, crypto.MD5, "MD5"}, - {2, crypto.SHA1, "SHA1"}, - {3, crypto.RIPEMD160, "RIPEMD160"}, - {8, crypto.SHA256, "SHA256"}, - {9, crypto.SHA384, "SHA384"}, - {10, crypto.SHA512, "SHA512"}, - {11, crypto.SHA224, "SHA224"}, -} - -// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP -// hash id. -func HashIdToHash(id byte) (h crypto.Hash, ok bool) { - for _, m := range hashToHashIdMapping { - if m.id == id { - return m.hash, true - } - } - return 0, false -} - -// HashIdToString returns the name of the hash function corresponding to the -// given OpenPGP hash id. -func HashIdToString(id byte) (name string, ok bool) { - for _, m := range hashToHashIdMapping { - if m.id == id { - return m.name, true - } - } - - return "", false -} - -// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. -func HashToHashId(h crypto.Hash) (id byte, ok bool) { - for _, m := range hashToHashIdMapping { - if m.hash == h { - return m.id, true - } - } - return 0, false -} diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go deleted file mode 100644 index 65a304cc86..0000000000 --- a/vendor/golang.org/x/crypto/openpgp/write.go +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package openpgp - -import ( - "crypto" - "hash" - "io" - "strconv" - "time" - - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" - "golang.org/x/crypto/openpgp/s2k" -) - -// DetachSign signs message with the private key from signer (which must -// already have been decrypted) and writes the signature to w. -// If config is nil, sensible defaults will be used. -func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return detachSign(w, signer, message, packet.SigTypeBinary, config) -} - -// ArmoredDetachSign signs message with the private key from signer (which -// must already have been decrypted) and writes an armored signature to w. -// If config is nil, sensible defaults will be used. -func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { - return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) -} - -// DetachSignText signs message (after canonicalising the line endings) with -// the private key from signer (which must already have been decrypted) and -// writes the signature to w. -// If config is nil, sensible defaults will be used. -func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return detachSign(w, signer, message, packet.SigTypeText, config) -} - -// ArmoredDetachSignText signs message (after canonicalising the line endings) -// with the private key from signer (which must already have been decrypted) -// and writes an armored signature to w. -// If config is nil, sensible defaults will be used. -func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return armoredDetachSign(w, signer, message, packet.SigTypeText, config) -} - -func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - out, err := armor.Encode(w, SignatureType, nil) - if err != nil { - return - } - err = detachSign(out, signer, message, sigType, config) - if err != nil { - return - } - return out.Close() -} - -func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - if signer.PrivateKey == nil { - return errors.InvalidArgumentError("signing key doesn't have a private key") - } - if signer.PrivateKey.Encrypted { - return errors.InvalidArgumentError("signing key is encrypted") - } - - sig := new(packet.Signature) - sig.SigType = sigType - sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo - sig.Hash = config.Hash() - sig.CreationTime = config.Now() - sig.IssuerKeyId = &signer.PrivateKey.KeyId - - h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) - if err != nil { - return - } - io.Copy(wrappedHash, message) - - err = sig.Sign(h, signer.PrivateKey, config) - if err != nil { - return - } - - return sig.Serialize(w) -} - -// FileHints contains metadata about encrypted files. This metadata is, itself, -// encrypted. -type FileHints struct { - // IsBinary can be set to hint that the contents are binary data. - IsBinary bool - // FileName hints at the name of the file that should be written. It's - // truncated to 255 bytes if longer. It may be empty to suggest that the - // file should not be written to disk. It may be equal to "_CONSOLE" to - // suggest the data should not be written to disk. - FileName string - // ModTime contains the modification time of the file, or the zero time if not applicable. - ModTime time.Time -} - -// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. -// The resulting WriteCloser must be closed after the contents of the file have -// been written. -// If config is nil, sensible defaults will be used. -func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - if hints == nil { - hints = &FileHints{} - } - - key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) - if err != nil { - return - } - w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) - if err != nil { - return - } - - literaldata := w - if algo := config.Compression(); algo != packet.CompressionNone { - var compConfig *packet.CompressionConfig - if config != nil { - compConfig = config.CompressionConfig - } - literaldata, err = packet.SerializeCompressed(w, algo, compConfig) - if err != nil { - return - } - } - - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) -} - -// intersectPreferences mutates and returns a prefix of a that contains only -// the values in the intersection of a and b. The order of a is preserved. -func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { - var j int - for _, v := range a { - for _, v2 := range b { - if v == v2 { - a[j] = v - j++ - break - } - } - } - - return a[:j] -} - -func hashToHashId(h crypto.Hash) uint8 { - v, ok := s2k.HashToHashId(h) - if !ok { - panic("tried to convert unknown hash") - } - return v -} - -// Encrypt encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - var signer *packet.PrivateKey - if signed != nil { - signKey, ok := signed.signingKey(config.Now()) - if !ok { - return nil, errors.InvalidArgumentError("no valid signing keys") - } - signer = signKey.PrivateKey - if signer == nil { - return nil, errors.InvalidArgumentError("no private key in signing key") - } - if signer.Encrypted { - return nil, errors.InvalidArgumentError("signing key must be decrypted") - } - } - - // These are the possible ciphers that we'll use for the message. - candidateCiphers := []uint8{ - uint8(packet.CipherAES128), - uint8(packet.CipherAES256), - uint8(packet.CipherCAST5), - } - // These are the possible hash functions that we'll use for the signature. - candidateHashes := []uint8{ - hashToHashId(crypto.SHA256), - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA1), - hashToHashId(crypto.RIPEMD160), - } - // In the event that a recipient doesn't specify any supported ciphers - // or hash functions, these are the ones that we assume that every - // implementation supports. - defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] - defaultHashes := candidateHashes[len(candidateHashes)-1:] - - encryptKeys := make([]Key, len(to)) - for i := range to { - var ok bool - encryptKeys[i], ok = to[i].encryptionKey(config.Now()) - if !ok { - return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") - } - - sig := to[i].primaryIdentity().SelfSignature - - preferredSymmetric := sig.PreferredSymmetric - if len(preferredSymmetric) == 0 { - preferredSymmetric = defaultCiphers - } - preferredHashes := sig.PreferredHash - if len(preferredHashes) == 0 { - preferredHashes = defaultHashes - } - candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) - candidateHashes = intersectPreferences(candidateHashes, preferredHashes) - } - - if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { - return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") - } - - cipher := packet.CipherFunction(candidateCiphers[0]) - // If the cipher specified by config is a candidate, we'll use that. - configuredCipher := config.Cipher() - for _, c := range candidateCiphers { - cipherFunc := packet.CipherFunction(c) - if cipherFunc == configuredCipher { - cipher = cipherFunc - break - } - } - - var hash crypto.Hash - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { - hash = h - break - } - } - - // If the hash specified by config is a candidate, we'll use that. - if configuredHash := config.Hash(); configuredHash.Available() { - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { - hash = h - break - } - } - } - - if hash == 0 { - hashId := candidateHashes[0] - name, ok := s2k.HashIdToString(hashId) - if !ok { - name = "#" + strconv.Itoa(int(hashId)) - } - return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") - } - - symKey := make([]byte, cipher.KeySize()) - if _, err := io.ReadFull(config.Random(), symKey); err != nil { - return nil, err - } - - for _, key := range encryptKeys { - if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { - return nil, err - } - } - - encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) - if err != nil { - return - } - - if signer != nil { - ops := &packet.OnePassSignature{ - SigType: packet.SigTypeBinary, - Hash: hash, - PubKeyAlgo: signer.PubKeyAlgo, - KeyId: signer.KeyId, - IsLast: true, - } - if err := ops.Serialize(encryptedData); err != nil { - return nil, err - } - } - - if hints == nil { - hints = &FileHints{} - } - - w := encryptedData - if signer != nil { - // If we need to write a signature packet after the literal - // data then we need to stop literalData from closing - // encryptedData. - w = noOpCloser{encryptedData} - - } - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) - if err != nil { - return nil, err - } - - if signer != nil { - return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil - } - return literalData, nil -} - -// signatureWriter hashes the contents of a message while passing it along to -// literalData. When closed, it closes literalData, writes a signature packet -// to encryptedData and then also closes encryptedData. -type signatureWriter struct { - encryptedData io.WriteCloser - literalData io.WriteCloser - hashType crypto.Hash - h hash.Hash - signer *packet.PrivateKey - config *packet.Config -} - -func (s signatureWriter) Write(data []byte) (int, error) { - s.h.Write(data) - return s.literalData.Write(data) -} - -func (s signatureWriter) Close() error { - sig := &packet.Signature{ - SigType: packet.SigTypeBinary, - PubKeyAlgo: s.signer.PubKeyAlgo, - Hash: s.hashType, - CreationTime: s.config.Now(), - IssuerKeyId: &s.signer.KeyId, - } - - if err := sig.Sign(s.h, s.signer, s.config); err != nil { - return err - } - if err := s.literalData.Close(); err != nil { - return err - } - if err := sig.Serialize(s.encryptedData); err != nil { - return err - } - return s.encryptedData.Close() -} - -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. -// TODO: we have two of these in OpenPGP packages alone. This probably needs -// to be promoted somewhere more common. -type noOpCloser struct { - w io.Writer -} - -func (c noOpCloser) Write(data []byte) (n int, err error) { - return c.w.Write(data) -} - -func (c noOpCloser) Close() error { - return nil -} diff --git a/vendor/golang.org/x/net/internal/socks/client.go b/vendor/golang.org/x/net/internal/socks/client.go deleted file mode 100644 index 3d6f516a59..0000000000 --- a/vendor/golang.org/x/net/internal/socks/client.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" - "time" -) - -var ( - noDeadline = time.Time{} - aLongTimeAgo = time.Unix(1, 0) -) - -func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) { - host, port, err := splitHostPort(address) - if err != nil { - return nil, err - } - if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { - c.SetDeadline(deadline) - defer c.SetDeadline(noDeadline) - } - if ctx != context.Background() { - errCh := make(chan error, 1) - done := make(chan struct{}) - defer func() { - close(done) - if ctxErr == nil { - ctxErr = <-errCh - } - }() - go func() { - select { - case <-ctx.Done(): - c.SetDeadline(aLongTimeAgo) - errCh <- ctx.Err() - case <-done: - errCh <- nil - } - }() - } - - b := make([]byte, 0, 6+len(host)) // the size here is just an estimate - b = append(b, Version5) - if len(d.AuthMethods) == 0 || d.Authenticate == nil { - b = append(b, 1, byte(AuthMethodNotRequired)) - } else { - ams := d.AuthMethods - if len(ams) > 255 { - return nil, errors.New("too many authentication methods") - } - b = append(b, byte(len(ams))) - for _, am := range ams { - b = append(b, byte(am)) - } - } - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - am := AuthMethod(b[1]) - if am == AuthMethodNoAcceptableMethods { - return nil, errors.New("no acceptable authentication methods") - } - if d.Authenticate != nil { - if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil { - return - } - } - - b = b[:0] - b = append(b, Version5, byte(d.cmd), 0) - if ip := net.ParseIP(host); ip != nil { - if ip4 := ip.To4(); ip4 != nil { - b = append(b, AddrTypeIPv4) - b = append(b, ip4...) - } else if ip6 := ip.To16(); ip6 != nil { - b = append(b, AddrTypeIPv6) - b = append(b, ip6...) - } else { - return nil, errors.New("unknown address type") - } - } else { - if len(host) > 255 { - return nil, errors.New("FQDN too long") - } - b = append(b, AddrTypeFQDN) - b = append(b, byte(len(host))) - b = append(b, host...) - } - b = append(b, byte(port>>8), byte(port)) - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded { - return nil, errors.New("unknown error " + cmdErr.String()) - } - if b[2] != 0 { - return nil, errors.New("non-zero reserved field") - } - l := 2 - var a Addr - switch b[3] { - case AddrTypeIPv4: - l += net.IPv4len - a.IP = make(net.IP, net.IPv4len) - case AddrTypeIPv6: - l += net.IPv6len - a.IP = make(net.IP, net.IPv6len) - case AddrTypeFQDN: - if _, err := io.ReadFull(c, b[:1]); err != nil { - return nil, err - } - l += int(b[0]) - default: - return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3]))) - } - if cap(b) < l { - b = make([]byte, l) - } else { - b = b[:l] - } - if _, ctxErr = io.ReadFull(c, b); ctxErr != nil { - return - } - if a.IP != nil { - copy(a.IP, b) - } else { - a.Name = string(b[:len(b)-2]) - } - a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1]) - return &a, nil -} - -func splitHostPort(address string) (string, int, error) { - host, port, err := net.SplitHostPort(address) - if err != nil { - return "", 0, err - } - portnum, err := strconv.Atoi(port) - if err != nil { - return "", 0, err - } - if 1 > portnum || portnum > 0xffff { - return "", 0, errors.New("port number out of range " + port) - } - return host, portnum, nil -} diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go deleted file mode 100644 index 9158595366..0000000000 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package socks provides a SOCKS version 5 client implementation. -// -// SOCKS protocol version 5 is defined in RFC 1928. -// Username/Password authentication for SOCKS version 5 is defined in -// RFC 1929. -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" -) - -// A Command represents a SOCKS command. -type Command int - -func (cmd Command) String() string { - switch cmd { - case CmdConnect: - return "socks connect" - case cmdBind: - return "socks bind" - default: - return "socks " + strconv.Itoa(int(cmd)) - } -} - -// An AuthMethod represents a SOCKS authentication method. -type AuthMethod int - -// A Reply represents a SOCKS command reply code. -type Reply int - -func (code Reply) String() string { - switch code { - case StatusSucceeded: - return "succeeded" - case 0x01: - return "general SOCKS server failure" - case 0x02: - return "connection not allowed by ruleset" - case 0x03: - return "network unreachable" - case 0x04: - return "host unreachable" - case 0x05: - return "connection refused" - case 0x06: - return "TTL expired" - case 0x07: - return "command not supported" - case 0x08: - return "address type not supported" - default: - return "unknown code: " + strconv.Itoa(int(code)) - } -} - -// Wire protocol constants. -const ( - Version5 = 0x05 - - AddrTypeIPv4 = 0x01 - AddrTypeFQDN = 0x03 - AddrTypeIPv6 = 0x04 - - CmdConnect Command = 0x01 // establishes an active-open forward proxy connection - cmdBind Command = 0x02 // establishes a passive-open forward proxy connection - - AuthMethodNotRequired AuthMethod = 0x00 // no authentication required - AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password - AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authetication methods - - StatusSucceeded Reply = 0x00 -) - -// An Addr represents a SOCKS-specific address. -// Either Name or IP is used exclusively. -type Addr struct { - Name string // fully-qualified domain name - IP net.IP - Port int -} - -func (a *Addr) Network() string { return "socks" } - -func (a *Addr) String() string { - if a == nil { - return "" - } - port := strconv.Itoa(a.Port) - if a.IP == nil { - return net.JoinHostPort(a.Name, port) - } - return net.JoinHostPort(a.IP.String(), port) -} - -// A Conn represents a forward proxy connection. -type Conn struct { - net.Conn - - boundAddr net.Addr -} - -// BoundAddr returns the address assigned by the proxy server for -// connecting to the command target address from the proxy server. -func (c *Conn) BoundAddr() net.Addr { - if c == nil { - return nil - } - return c.boundAddr -} - -// A Dialer holds SOCKS-specific options. -type Dialer struct { - cmd Command // either CmdConnect or cmdBind - proxyNetwork string // network between a proxy server and a client - proxyAddress string // proxy server address - - // ProxyDial specifies the optional dial function for - // establishing the transport connection. - ProxyDial func(context.Context, string, string) (net.Conn, error) - - // AuthMethods specifies the list of request authention - // methods. - // If empty, SOCKS client requests only AuthMethodNotRequired. - AuthMethods []AuthMethod - - // Authenticate specifies the optional authentication - // function. It must be non-nil when AuthMethods is not empty. - // It must return an error when the authentication is failed. - Authenticate func(context.Context, io.ReadWriter, AuthMethod) error -} - -// DialContext connects to the provided address on the provided -// network. -// -// The returned error value may be a net.OpError. When the Op field of -// net.OpError contains "socks", the Source field contains a proxy -// server address and the Addr field contains a command target -// address. -// -// See func Dial of the net package of standard library for a -// description of the network and address parameters. -func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - switch network { - case "tcp", "tcp6", "tcp4": - default: - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("network not implemented")} - } - switch d.cmd { - case CmdConnect, cmdBind: - default: - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("command not implemented")} - } - if ctx == nil { - ctx = context.Background() - } - var err error - var c net.Conn - if d.ProxyDial != nil { - c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress) - } else { - var dd net.Dialer - c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress) - } - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - a, err := d.connect(ctx, c, address) - if err != nil { - c.Close() - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - return &Conn{Conn: c, boundAddr: a}, nil -} - -// Dial connects to the provided address on the provided network. -// -// Deprecated: Use DialContext instead. -func (d *Dialer) Dial(network, address string) (net.Conn, error) { - return d.DialContext(context.Background(), network, address) -} - -func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) { - for i, s := range []string{d.proxyAddress, address} { - host, port, err := splitHostPort(s) - if err != nil { - return nil, nil, err - } - a := &Addr{Port: port} - a.IP = net.ParseIP(host) - if a.IP == nil { - a.Name = host - } - if i == 0 { - proxy = a - } else { - dst = a - } - } - return -} - -// NewDialer returns a new Dialer that dials through the provided -// proxy server's network and address. -func NewDialer(network, address string) *Dialer { - return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect} -} - -const ( - authUsernamePasswordVersion = 0x01 - authStatusSucceeded = 0x00 -) - -// UsernamePassword are the credentials for the username/password -// authentication method. -type UsernamePassword struct { - Username string - Password string -} - -// Authenticate authenticates a pair of username and password with the -// proxy server. -func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error { - switch auth { - case AuthMethodNotRequired: - return nil - case AuthMethodUsernamePassword: - if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 { - return errors.New("invalid username/password") - } - b := []byte{authUsernamePasswordVersion} - b = append(b, byte(len(up.Username))) - b = append(b, up.Username...) - b = append(b, byte(len(up.Password))) - b = append(b, up.Password...) - // TODO(mikio): handle IO deadlines and cancelation if - // necessary - if _, err := rw.Write(b); err != nil { - return err - } - if _, err := io.ReadFull(rw, b[:2]); err != nil { - return err - } - if b[0] != authUsernamePasswordVersion { - return errors.New("invalid username/password version") - } - if b[1] != authStatusSucceeded { - return errors.New("username/password authentication failed") - } - return nil - } - return errors.New("unsupported authentication method " + strconv.Itoa(int(auth))) -} diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go deleted file mode 100644 index 4c5ad88b1e..0000000000 --- a/vendor/golang.org/x/net/proxy/direct.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package proxy - -import ( - "net" -) - -type direct struct{} - -// Direct is a direct proxy: one that makes network connections directly. -var Direct = direct{} - -func (direct) Dial(network, addr string) (net.Conn, error) { - return net.Dial(network, addr) -} diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go deleted file mode 100644 index 0689bb6a70..0000000000 --- a/vendor/golang.org/x/net/proxy/per_host.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package proxy - -import ( - "net" - "strings" -) - -// A PerHost directs connections to a default Dialer unless the host name -// requested matches one of a number of exceptions. -type PerHost struct { - def, bypass Dialer - - bypassNetworks []*net.IPNet - bypassIPs []net.IP - bypassZones []string - bypassHosts []string -} - -// NewPerHost returns a PerHost Dialer that directs connections to either -// defaultDialer or bypass, depending on whether the connection matches one of -// the configured rules. -func NewPerHost(defaultDialer, bypass Dialer) *PerHost { - return &PerHost{ - def: defaultDialer, - bypass: bypass, - } -} - -// Dial connects to the address addr on the given network through either -// defaultDialer or bypass. -func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - - return p.dialerForRequest(host).Dial(network, addr) -} - -func (p *PerHost) dialerForRequest(host string) Dialer { - if ip := net.ParseIP(host); ip != nil { - for _, net := range p.bypassNetworks { - if net.Contains(ip) { - return p.bypass - } - } - for _, bypassIP := range p.bypassIPs { - if bypassIP.Equal(ip) { - return p.bypass - } - } - return p.def - } - - for _, zone := range p.bypassZones { - if strings.HasSuffix(host, zone) { - return p.bypass - } - if host == zone[1:] { - // For a zone ".example.com", we match "example.com" - // too. - return p.bypass - } - } - for _, bypassHost := range p.bypassHosts { - if bypassHost == host { - return p.bypass - } - } - return p.def -} - -// AddFromString parses a string that contains comma-separated values -// specifying hosts that should use the bypass proxy. Each value is either an -// IP address, a CIDR range, a zone (*.example.com) or a host name -// (localhost). A best effort is made to parse the string and errors are -// ignored. -func (p *PerHost) AddFromString(s string) { - hosts := strings.Split(s, ",") - for _, host := range hosts { - host = strings.TrimSpace(host) - if len(host) == 0 { - continue - } - if strings.Contains(host, "/") { - // We assume that it's a CIDR address like 127.0.0.0/8 - if _, net, err := net.ParseCIDR(host); err == nil { - p.AddNetwork(net) - } - continue - } - if ip := net.ParseIP(host); ip != nil { - p.AddIP(ip) - continue - } - if strings.HasPrefix(host, "*.") { - p.AddZone(host[1:]) - continue - } - p.AddHost(host) - } -} - -// AddIP specifies an IP address that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match an IP. -func (p *PerHost) AddIP(ip net.IP) { - p.bypassIPs = append(p.bypassIPs, ip) -} - -// AddNetwork specifies an IP range that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match. -func (p *PerHost) AddNetwork(net *net.IPNet) { - p.bypassNetworks = append(p.bypassNetworks, net) -} - -// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of -// "example.com" matches "example.com" and all of its subdomains. -func (p *PerHost) AddZone(zone string) { - if strings.HasSuffix(zone, ".") { - zone = zone[:len(zone)-1] - } - if !strings.HasPrefix(zone, ".") { - zone = "." + zone - } - p.bypassZones = append(p.bypassZones, zone) -} - -// AddHost specifies a host name that will use the bypass proxy. -func (p *PerHost) AddHost(host string) { - if strings.HasSuffix(host, ".") { - host = host[:len(host)-1] - } - p.bypassHosts = append(p.bypassHosts, host) -} diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go deleted file mode 100644 index 553ead7cf0..0000000000 --- a/vendor/golang.org/x/net/proxy/proxy.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package proxy provides support for a variety of protocols to proxy network -// data. -package proxy // import "golang.org/x/net/proxy" - -import ( - "errors" - "net" - "net/url" - "os" - "sync" -) - -// A Dialer is a means to establish a connection. -type Dialer interface { - // Dial connects to the given address via the proxy. - Dial(network, addr string) (c net.Conn, err error) -} - -// Auth contains authentication parameters that specific Dialers may require. -type Auth struct { - User, Password string -} - -// FromEnvironment returns the dialer specified by the proxy related variables in -// the environment. -func FromEnvironment() Dialer { - allProxy := allProxyEnv.Get() - if len(allProxy) == 0 { - return Direct - } - - proxyURL, err := url.Parse(allProxy) - if err != nil { - return Direct - } - proxy, err := FromURL(proxyURL, Direct) - if err != nil { - return Direct - } - - noProxy := noProxyEnv.Get() - if len(noProxy) == 0 { - return proxy - } - - perHost := NewPerHost(proxy, Direct) - perHost.AddFromString(noProxy) - return perHost -} - -// proxySchemes is a map from URL schemes to a function that creates a Dialer -// from a URL with such a scheme. -var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) - -// RegisterDialerType takes a URL scheme and a function to generate Dialers from -// a URL with that scheme and a forwarding Dialer. Registered schemes are used -// by FromURL. -func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { - if proxySchemes == nil { - proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) - } - proxySchemes[scheme] = f -} - -// FromURL returns a Dialer given a URL specification and an underlying -// Dialer for it to make network requests. -func FromURL(u *url.URL, forward Dialer) (Dialer, error) { - var auth *Auth - if u.User != nil { - auth = new(Auth) - auth.User = u.User.Username() - if p, ok := u.User.Password(); ok { - auth.Password = p - } - } - - switch u.Scheme { - case "socks5": - return SOCKS5("tcp", u.Host, auth, forward) - } - - // If the scheme doesn't match any of the built-in schemes, see if it - // was registered by another package. - if proxySchemes != nil { - if f, ok := proxySchemes[u.Scheme]; ok { - return f(u, forward) - } - } - - return nil, errors.New("proxy: unknown scheme: " + u.Scheme) -} - -var ( - allProxyEnv = &envOnce{ - names: []string{"ALL_PROXY", "all_proxy"}, - } - noProxyEnv = &envOnce{ - names: []string{"NO_PROXY", "no_proxy"}, - } -) - -// envOnce looks up an environment variable (optionally by multiple -// names) once. It mitigates expensive lookups on some platforms -// (e.g. Windows). -// (Borrowed from net/http/transport.go) -type envOnce struct { - names []string - once sync.Once - val string -} - -func (e *envOnce) Get() string { - e.once.Do(e.init) - return e.val -} - -func (e *envOnce) init() { - for _, n := range e.names { - e.val = os.Getenv(n) - if e.val != "" { - return - } - } -} - -// reset is used by tests -func (e *envOnce) reset() { - e.once = sync.Once{} - e.val = "" -} diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go deleted file mode 100644 index 56345ec8b6..0000000000 --- a/vendor/golang.org/x/net/proxy/socks5.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package proxy - -import ( - "context" - "net" - - "golang.org/x/net/internal/socks" -) - -// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given -// address with an optional username and password. -// See RFC 1928 and RFC 1929. -func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) { - d := socks.NewDialer(network, address) - if forward != nil { - d.ProxyDial = func(_ context.Context, network string, address string) (net.Conn, error) { - return forward.Dial(network, address) - } - } - if auth != nil { - up := socks.UsernamePassword{ - Username: auth.User, - Password: auth.Password, - } - d.AuthMethods = []socks.AuthMethod{ - socks.AuthMethodNotRequired, - socks.AuthMethodUsernamePassword, - } - d.Authenticate = up.Authenticate - } - return d, nil -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/LICENSE b/vendor/gopkg.in/cheggaaa/pb.v1/LICENSE deleted file mode 100644 index 5119703339..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -Copyright (c) 2012-2015, Sergey Cherepanov -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/format.go b/vendor/gopkg.in/cheggaaa/pb.v1/format.go deleted file mode 100644 index 0723561c2e..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/format.go +++ /dev/null @@ -1,118 +0,0 @@ -package pb - -import ( - "fmt" - "time" -) - -type Units int - -const ( - // U_NO are default units, they represent a simple value and are not formatted at all. - U_NO Units = iota - // U_BYTES units are formatted in a human readable way (B, KiB, MiB, ...) - U_BYTES - // U_BYTES_DEC units are like U_BYTES, but base 10 (B, KB, MB, ...) - U_BYTES_DEC - // U_DURATION units are formatted in a human readable way (3h14m15s) - U_DURATION -) - -const ( - KiB = 1024 - MiB = 1048576 - GiB = 1073741824 - TiB = 1099511627776 - - KB = 1e3 - MB = 1e6 - GB = 1e9 - TB = 1e12 -) - -func Format(i int64) *formatter { - return &formatter{n: i} -} - -type formatter struct { - n int64 - unit Units - width int - perSec bool -} - -func (f *formatter) To(unit Units) *formatter { - f.unit = unit - return f -} - -func (f *formatter) Width(width int) *formatter { - f.width = width - return f -} - -func (f *formatter) PerSec() *formatter { - f.perSec = true - return f -} - -func (f *formatter) String() (out string) { - switch f.unit { - case U_BYTES: - out = formatBytes(f.n) - case U_BYTES_DEC: - out = formatBytesDec(f.n) - case U_DURATION: - out = formatDuration(f.n) - default: - out = fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n) - } - if f.perSec { - out += "/s" - } - return -} - -// Convert bytes to human readable string. Like 2 MiB, 64.2 KiB, 52 B -func formatBytes(i int64) (result string) { - switch { - case i >= TiB: - result = fmt.Sprintf("%.02f TiB", float64(i)/TiB) - case i >= GiB: - result = fmt.Sprintf("%.02f GiB", float64(i)/GiB) - case i >= MiB: - result = fmt.Sprintf("%.02f MiB", float64(i)/MiB) - case i >= KiB: - result = fmt.Sprintf("%.02f KiB", float64(i)/KiB) - default: - result = fmt.Sprintf("%d B", i) - } - return -} - -// Convert bytes to base-10 human readable string. Like 2 MB, 64.2 KB, 52 B -func formatBytesDec(i int64) (result string) { - switch { - case i >= TB: - result = fmt.Sprintf("%.02f TB", float64(i)/TB) - case i >= GB: - result = fmt.Sprintf("%.02f GB", float64(i)/GB) - case i >= MB: - result = fmt.Sprintf("%.02f MB", float64(i)/MB) - case i >= KB: - result = fmt.Sprintf("%.02f KB", float64(i)/KB) - default: - result = fmt.Sprintf("%d B", i) - } - return -} - -func formatDuration(n int64) (result string) { - d := time.Duration(n) - if d > time.Hour*24 { - result = fmt.Sprintf("%dd", d/24/time.Hour) - d -= (d / time.Hour / 24) * (time.Hour * 24) - } - result = fmt.Sprintf("%s%v", result, d) - return -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pb.go b/vendor/gopkg.in/cheggaaa/pb.v1/pb.go deleted file mode 100644 index eddc807b1b..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pb.go +++ /dev/null @@ -1,475 +0,0 @@ -// Simple console progress bars -package pb - -import ( - "fmt" - "io" - "math" - "strings" - "sync" - "sync/atomic" - "time" - "unicode/utf8" -) - -// Current version -const Version = "1.0.22" - -const ( - // Default refresh rate - 200ms - DEFAULT_REFRESH_RATE = time.Millisecond * 200 - FORMAT = "[=>-]" -) - -// DEPRECATED -// variables for backward compatibility, from now do not work -// use pb.Format and pb.SetRefreshRate -var ( - DefaultRefreshRate = DEFAULT_REFRESH_RATE - BarStart, BarEnd, Empty, Current, CurrentN string -) - -// Create new progress bar object -func New(total int) *ProgressBar { - return New64(int64(total)) -} - -// Create new progress bar object using int64 as total -func New64(total int64) *ProgressBar { - pb := &ProgressBar{ - Total: total, - RefreshRate: DEFAULT_REFRESH_RATE, - ShowPercent: true, - ShowCounters: true, - ShowBar: true, - ShowTimeLeft: true, - ShowElapsedTime: false, - ShowFinalTime: true, - Units: U_NO, - ManualUpdate: false, - finish: make(chan struct{}), - } - return pb.Format(FORMAT) -} - -// Create new object and start -func StartNew(total int) *ProgressBar { - return New(total).Start() -} - -// Callback for custom output -// For example: -// bar.Callback = func(s string) { -// mySuperPrint(s) -// } -// -type Callback func(out string) - -type ProgressBar struct { - current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278) - previous int64 - - Total int64 - RefreshRate time.Duration - ShowPercent, ShowCounters bool - ShowSpeed, ShowTimeLeft, ShowBar bool - ShowFinalTime, ShowElapsedTime bool - Output io.Writer - Callback Callback - NotPrint bool - Units Units - Width int - ForceWidth bool - ManualUpdate bool - AutoStat bool - - // Default width for the time box. - UnitsWidth int - TimeBoxWidth int - - finishOnce sync.Once //Guards isFinish - finish chan struct{} - isFinish bool - - startTime time.Time - startValue int64 - - changeTime time.Time - - prefix, postfix string - - mu sync.Mutex - lastPrint string - - BarStart string - BarEnd string - Empty string - Current string - CurrentN string - - AlwaysUpdate bool -} - -// Start print -func (pb *ProgressBar) Start() *ProgressBar { - pb.startTime = time.Now() - pb.startValue = atomic.LoadInt64(&pb.current) - if pb.Total == 0 { - pb.ShowTimeLeft = false - pb.ShowPercent = false - pb.AutoStat = false - } - if !pb.ManualUpdate { - pb.Update() // Initial printing of the bar before running the bar refresher. - go pb.refresher() - } - return pb -} - -// Increment current value -func (pb *ProgressBar) Increment() int { - return pb.Add(1) -} - -// Get current value -func (pb *ProgressBar) Get() int64 { - c := atomic.LoadInt64(&pb.current) - return c -} - -// Set current value -func (pb *ProgressBar) Set(current int) *ProgressBar { - return pb.Set64(int64(current)) -} - -// Set64 sets the current value as int64 -func (pb *ProgressBar) Set64(current int64) *ProgressBar { - atomic.StoreInt64(&pb.current, current) - return pb -} - -// Add to current value -func (pb *ProgressBar) Add(add int) int { - return int(pb.Add64(int64(add))) -} - -func (pb *ProgressBar) Add64(add int64) int64 { - return atomic.AddInt64(&pb.current, add) -} - -// Set prefix string -func (pb *ProgressBar) Prefix(prefix string) *ProgressBar { - pb.prefix = prefix - return pb -} - -// Set postfix string -func (pb *ProgressBar) Postfix(postfix string) *ProgressBar { - pb.postfix = postfix - return pb -} - -// Set custom format for bar -// Example: bar.Format("[=>_]") -// Example: bar.Format("[\x00=\x00>\x00-\x00]") // \x00 is the delimiter -func (pb *ProgressBar) Format(format string) *ProgressBar { - var formatEntries []string - if utf8.RuneCountInString(format) == 5 { - formatEntries = strings.Split(format, "") - } else { - formatEntries = strings.Split(format, "\x00") - } - if len(formatEntries) == 5 { - pb.BarStart = formatEntries[0] - pb.BarEnd = formatEntries[4] - pb.Empty = formatEntries[3] - pb.Current = formatEntries[1] - pb.CurrentN = formatEntries[2] - } - return pb -} - -// Set bar refresh rate -func (pb *ProgressBar) SetRefreshRate(rate time.Duration) *ProgressBar { - pb.RefreshRate = rate - return pb -} - -// Set units -// bar.SetUnits(U_NO) - by default -// bar.SetUnits(U_BYTES) - for Mb, Kb, etc -func (pb *ProgressBar) SetUnits(units Units) *ProgressBar { - pb.Units = units - return pb -} - -// Set max width, if width is bigger than terminal width, will be ignored -func (pb *ProgressBar) SetMaxWidth(width int) *ProgressBar { - pb.Width = width - pb.ForceWidth = false - return pb -} - -// Set bar width -func (pb *ProgressBar) SetWidth(width int) *ProgressBar { - pb.Width = width - pb.ForceWidth = true - return pb -} - -// End print -func (pb *ProgressBar) Finish() { - //Protect multiple calls - pb.finishOnce.Do(func() { - close(pb.finish) - pb.write(atomic.LoadInt64(&pb.current)) - pb.mu.Lock() - defer pb.mu.Unlock() - switch { - case pb.Output != nil: - fmt.Fprintln(pb.Output) - case !pb.NotPrint: - fmt.Println() - } - pb.isFinish = true - }) -} - -// IsFinished return boolean -func (pb *ProgressBar) IsFinished() bool { - pb.mu.Lock() - defer pb.mu.Unlock() - return pb.isFinish -} - -// End print and write string 'str' -func (pb *ProgressBar) FinishPrint(str string) { - pb.Finish() - if pb.Output != nil { - fmt.Fprintln(pb.Output, str) - } else { - fmt.Println(str) - } -} - -// implement io.Writer -func (pb *ProgressBar) Write(p []byte) (n int, err error) { - n = len(p) - pb.Add(n) - return -} - -// implement io.Reader -func (pb *ProgressBar) Read(p []byte) (n int, err error) { - n = len(p) - pb.Add(n) - return -} - -// Create new proxy reader over bar -// Takes io.Reader or io.ReadCloser -func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader { - return &Reader{r, pb} -} - -func (pb *ProgressBar) write(current int64) { - width := pb.GetWidth() - - var percentBox, countersBox, timeLeftBox, timeSpentBox, speedBox, barBox, end, out string - - // percents - if pb.ShowPercent { - var percent float64 - if pb.Total > 0 { - percent = float64(current) / (float64(pb.Total) / float64(100)) - } else { - percent = float64(current) / float64(100) - } - percentBox = fmt.Sprintf(" %6.02f%%", percent) - } - - // counters - if pb.ShowCounters { - current := Format(current).To(pb.Units).Width(pb.UnitsWidth) - if pb.Total > 0 { - total := Format(pb.Total).To(pb.Units).Width(pb.UnitsWidth) - countersBox = fmt.Sprintf(" %s / %s ", current, total) - } else { - countersBox = fmt.Sprintf(" %s / ? ", current) - } - } - - // time left - pb.mu.Lock() - currentFromStart := current - pb.startValue - fromStart := time.Now().Sub(pb.startTime) - lastChangeTime := pb.changeTime - fromChange := lastChangeTime.Sub(pb.startTime) - pb.mu.Unlock() - - if pb.ShowElapsedTime { - timeSpentBox = fmt.Sprintf(" %s ", (fromStart/time.Second)*time.Second) - } - - select { - case <-pb.finish: - if pb.ShowFinalTime { - var left time.Duration - left = (fromStart / time.Second) * time.Second - timeLeftBox = fmt.Sprintf(" %s", left.String()) - } - default: - if pb.ShowTimeLeft && currentFromStart > 0 { - perEntry := fromChange / time.Duration(currentFromStart) - var left time.Duration - if pb.Total > 0 { - left = time.Duration(pb.Total-currentFromStart) * perEntry - left -= time.Since(lastChangeTime) - left = (left / time.Second) * time.Second - } else { - left = time.Duration(currentFromStart) * perEntry - left = (left / time.Second) * time.Second - } - if left > 0 { - timeLeft := Format(int64(left)).To(U_DURATION).String() - timeLeftBox = fmt.Sprintf(" %s", timeLeft) - } - } - } - - if len(timeLeftBox) < pb.TimeBoxWidth { - timeLeftBox = fmt.Sprintf("%s%s", strings.Repeat(" ", pb.TimeBoxWidth-len(timeLeftBox)), timeLeftBox) - } - - // speed - if pb.ShowSpeed && currentFromStart > 0 { - fromStart := time.Now().Sub(pb.startTime) - speed := float64(currentFromStart) / (float64(fromStart) / float64(time.Second)) - speedBox = " " + Format(int64(speed)).To(pb.Units).Width(pb.UnitsWidth).PerSec().String() - } - - barWidth := escapeAwareRuneCountInString(countersBox + pb.BarStart + pb.BarEnd + percentBox + timeSpentBox + timeLeftBox + speedBox + pb.prefix + pb.postfix) - // bar - if pb.ShowBar { - size := width - barWidth - if size > 0 { - if pb.Total > 0 { - curSize := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size))) - emptySize := size - curSize - barBox = pb.BarStart - if emptySize < 0 { - emptySize = 0 - } - if curSize > size { - curSize = size - } - - cursorLen := escapeAwareRuneCountInString(pb.Current) - if emptySize <= 0 { - barBox += strings.Repeat(pb.Current, curSize/cursorLen) - } else if curSize > 0 { - cursorEndLen := escapeAwareRuneCountInString(pb.CurrentN) - cursorRepetitions := (curSize - cursorEndLen) / cursorLen - barBox += strings.Repeat(pb.Current, cursorRepetitions) - barBox += pb.CurrentN - } - - emptyLen := escapeAwareRuneCountInString(pb.Empty) - barBox += strings.Repeat(pb.Empty, emptySize/emptyLen) - barBox += pb.BarEnd - } else { - pos := size - int(current)%int(size) - barBox = pb.BarStart - if pos-1 > 0 { - barBox += strings.Repeat(pb.Empty, pos-1) - } - barBox += pb.Current - if size-pos-1 > 0 { - barBox += strings.Repeat(pb.Empty, size-pos-1) - } - barBox += pb.BarEnd - } - } - } - - // check len - out = pb.prefix + timeSpentBox + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix - if cl := escapeAwareRuneCountInString(out); cl < width { - end = strings.Repeat(" ", width-cl) - } - - // and print! - pb.mu.Lock() - pb.lastPrint = out + end - isFinish := pb.isFinish - pb.mu.Unlock() - switch { - case isFinish: - return - case pb.Output != nil: - fmt.Fprint(pb.Output, "\r"+out+end) - case pb.Callback != nil: - pb.Callback(out + end) - case !pb.NotPrint: - fmt.Print("\r" + out + end) - } -} - -// GetTerminalWidth - returns terminal width for all platforms. -func GetTerminalWidth() (int, error) { - return terminalWidth() -} - -func (pb *ProgressBar) GetWidth() int { - if pb.ForceWidth { - return pb.Width - } - - width := pb.Width - termWidth, _ := terminalWidth() - if width == 0 || termWidth <= width { - width = termWidth - } - - return width -} - -// Write the current state of the progressbar -func (pb *ProgressBar) Update() { - c := atomic.LoadInt64(&pb.current) - p := atomic.LoadInt64(&pb.previous) - if p != c { - pb.mu.Lock() - pb.changeTime = time.Now() - pb.mu.Unlock() - atomic.StoreInt64(&pb.previous, c) - } - pb.write(c) - if pb.AutoStat { - if c == 0 { - pb.startTime = time.Now() - pb.startValue = 0 - } else if c >= pb.Total && pb.isFinish != true { - pb.Finish() - } - } -} - -// String return the last bar print -func (pb *ProgressBar) String() string { - pb.mu.Lock() - defer pb.mu.Unlock() - return pb.lastPrint -} - -// Internal loop for refreshing the progressbar -func (pb *ProgressBar) refresher() { - for { - select { - case <-pb.finish: - return - case <-time.After(pb.RefreshRate): - pb.Update() - } - } -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go b/vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go deleted file mode 100644 index d85dbc3b2b..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build appengine - -package pb - -import "errors" - -// terminalWidth returns width of the terminal, which is not supported -// and should always failed on appengine classic which is a sandboxed PaaS. -func terminalWidth() (int, error) { - return 0, errors.New("Not supported") -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go b/vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go deleted file mode 100644 index 2c67e19471..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go +++ /dev/null @@ -1,141 +0,0 @@ -// +build windows - -package pb - -import ( - "errors" - "fmt" - "os" - "sync" - "syscall" - "unsafe" -) - -var tty = os.Stdin - -var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - - // GetConsoleScreenBufferInfo retrieves information about the - // specified console screen buffer. - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") - - // GetConsoleMode retrieves the current input mode of a console's - // input buffer or the current output mode of a console screen buffer. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx - getConsoleMode = kernel32.NewProc("GetConsoleMode") - - // SetConsoleMode sets the input mode of a console's input buffer - // or the output mode of a console screen buffer. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx - setConsoleMode = kernel32.NewProc("SetConsoleMode") - - // SetConsoleCursorPosition sets the cursor position in the - // specified console screen buffer. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx - setConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") -) - -type ( - // Defines the coordinates of the upper left and lower right corners - // of a rectangle. - // See - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311(v=vs.85).aspx - smallRect struct { - Left, Top, Right, Bottom int16 - } - - // Defines the coordinates of a character cell in a console screen - // buffer. The origin of the coordinate system (0,0) is at the top, left cell - // of the buffer. - // See - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx - coordinates struct { - X, Y int16 - } - - word int16 - - // Contains information about a console screen buffer. - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx - consoleScreenBufferInfo struct { - dwSize coordinates - dwCursorPosition coordinates - wAttributes word - srWindow smallRect - dwMaximumWindowSize coordinates - } -) - -// terminalWidth returns width of the terminal. -func terminalWidth() (width int, err error) { - var info consoleScreenBufferInfo - _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) - if e != 0 { - return 0, error(e) - } - return int(info.dwSize.X) - 1, nil -} - -func getCursorPos() (pos coordinates, err error) { - var info consoleScreenBufferInfo - _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) - if e != 0 { - return info.dwCursorPosition, error(e) - } - return info.dwCursorPosition, nil -} - -func setCursorPos(pos coordinates) error { - _, _, e := syscall.Syscall(setConsoleCursorPosition.Addr(), 2, uintptr(syscall.Stdout), uintptr(uint32(uint16(pos.Y))<<16|uint32(uint16(pos.X))), 0) - if e != 0 { - return error(e) - } - return nil -} - -var ErrPoolWasStarted = errors.New("Bar pool was started") - -var echoLocked bool -var echoLockMutex sync.Mutex - -var oldState word - -func lockEcho() (shutdownCh chan struct{}, err error) { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - if echoLocked { - err = ErrPoolWasStarted - return - } - echoLocked = true - - if _, _, e := syscall.Syscall(getConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&oldState)), 0); e != 0 { - err = fmt.Errorf("Can't get terminal settings: %v", e) - return - } - - newState := oldState - const ENABLE_ECHO_INPUT = 0x0004 - const ENABLE_LINE_INPUT = 0x0002 - newState = newState & (^(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)) - if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(newState), 0); e != 0 { - err = fmt.Errorf("Can't set terminal settings: %v", e) - return - } - return -} - -func unlockEcho() (err error) { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - if !echoLocked { - return - } - echoLocked = false - if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(oldState), 0); e != 0 { - err = fmt.Errorf("Can't set terminal settings") - } - return -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go b/vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go deleted file mode 100644 index 8e05770ceb..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go +++ /dev/null @@ -1,108 +0,0 @@ -// +build linux darwin freebsd netbsd openbsd solaris dragonfly -// +build !appengine - -package pb - -import ( - "errors" - "fmt" - "os" - "os/signal" - "sync" - "syscall" - - "golang.org/x/sys/unix" -) - -var ErrPoolWasStarted = errors.New("Bar pool was started") - -var ( - echoLockMutex sync.Mutex - origTermStatePtr *unix.Termios - tty *os.File -) - -func init() { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - - var err error - tty, err = os.Open("/dev/tty") - if err != nil { - tty = os.Stdin - } -} - -// terminalWidth returns width of the terminal. -func terminalWidth() (int, error) { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - - fd := int(tty.Fd()) - - ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) - if err != nil { - return 0, err - } - - return int(ws.Col), nil -} - -func lockEcho() (shutdownCh chan struct{}, err error) { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - if origTermStatePtr != nil { - return shutdownCh, ErrPoolWasStarted - } - - fd := int(tty.Fd()) - - origTermStatePtr, err = unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, fmt.Errorf("Can't get terminal settings: %v", err) - } - - oldTermios := *origTermStatePtr - newTermios := oldTermios - newTermios.Lflag &^= syscall.ECHO - newTermios.Lflag |= syscall.ICANON | syscall.ISIG - newTermios.Iflag |= syscall.ICRNL - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newTermios); err != nil { - return nil, fmt.Errorf("Can't set terminal settings: %v", err) - } - - shutdownCh = make(chan struct{}) - go catchTerminate(shutdownCh) - return -} - -func unlockEcho() error { - echoLockMutex.Lock() - defer echoLockMutex.Unlock() - if origTermStatePtr == nil { - return nil - } - - fd := int(tty.Fd()) - - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, origTermStatePtr); err != nil { - return fmt.Errorf("Can't set terminal settings: %v", err) - } - - origTermStatePtr = nil - - return nil -} - -// listen exit signals and restore terminal state -func catchTerminate(shutdownCh chan struct{}) { - sig := make(chan os.Signal, 1) - signal.Notify(sig, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL) - defer signal.Stop(sig) - select { - case <-shutdownCh: - unlockEcho() - case <-sig: - unlockEcho() - } -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pool.go b/vendor/gopkg.in/cheggaaa/pb.v1/pool.go deleted file mode 100644 index f44baa01fc..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pool.go +++ /dev/null @@ -1,102 +0,0 @@ -// +build linux darwin freebsd netbsd openbsd solaris dragonfly windows - -package pb - -import ( - "io" - "sync" - "time" -) - -// Create and start new pool with given bars -// You need call pool.Stop() after work -func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) { - pool = new(Pool) - if err = pool.Start(); err != nil { - return - } - pool.Add(pbs...) - return -} - -// NewPool initialises a pool with progress bars, but -// doesn't start it. You need to call Start manually -func NewPool(pbs ...*ProgressBar) (pool *Pool) { - pool = new(Pool) - pool.Add(pbs...) - return -} - -type Pool struct { - Output io.Writer - RefreshRate time.Duration - bars []*ProgressBar - lastBarsCount int - shutdownCh chan struct{} - workerCh chan struct{} - m sync.Mutex - finishOnce sync.Once -} - -// Add progress bars. -func (p *Pool) Add(pbs ...*ProgressBar) { - p.m.Lock() - defer p.m.Unlock() - for _, bar := range pbs { - bar.ManualUpdate = true - bar.NotPrint = true - bar.Start() - p.bars = append(p.bars, bar) - } -} - -func (p *Pool) Start() (err error) { - p.RefreshRate = DefaultRefreshRate - p.shutdownCh, err = lockEcho() - if err != nil { - return - } - p.workerCh = make(chan struct{}) - go p.writer() - return -} - -func (p *Pool) writer() { - var first = true - defer func() { - if first == false { - p.print(false) - } else { - p.print(true) - p.print(false) - } - close(p.workerCh) - }() - - for { - select { - case <-time.After(p.RefreshRate): - if p.print(first) { - p.print(false) - return - } - first = false - case <-p.shutdownCh: - return - } - } -} - -// Restore terminal state and close pool -func (p *Pool) Stop() error { - p.finishOnce.Do(func() { - close(p.shutdownCh) - }) - - // Wait for the worker to complete - select { - case <-p.workerCh: - } - - return unlockEcho() -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go b/vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go deleted file mode 100644 index 63598d378a..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build windows - -package pb - -import ( - "fmt" - "log" -) - -func (p *Pool) print(first bool) bool { - p.m.Lock() - defer p.m.Unlock() - var out string - if !first { - coords, err := getCursorPos() - if err != nil { - log.Panic(err) - } - coords.Y -= int16(p.lastBarsCount) - if coords.Y < 0 { - coords.Y = 0 - } - coords.X = 0 - - err = setCursorPos(coords) - if err != nil { - log.Panic(err) - } - } - isFinished := true - for _, bar := range p.bars { - if !bar.IsFinished() { - isFinished = false - } - bar.Update() - out += fmt.Sprintf("\r%s\n", bar.String()) - } - if p.Output != nil { - fmt.Fprint(p.Output, out) - } else { - fmt.Print(out) - } - p.lastBarsCount = len(p.bars) - return isFinished -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go b/vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go deleted file mode 100644 index a8ae14d2f6..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go +++ /dev/null @@ -1,29 +0,0 @@ -// +build linux darwin freebsd netbsd openbsd solaris dragonfly - -package pb - -import "fmt" - -func (p *Pool) print(first bool) bool { - p.m.Lock() - defer p.m.Unlock() - var out string - if !first { - out = fmt.Sprintf("\033[%dA", p.lastBarsCount) - } - isFinished := true - for _, bar := range p.bars { - if !bar.IsFinished() { - isFinished = false - } - bar.Update() - out += fmt.Sprintf("\r%s\n", bar.String()) - } - if p.Output != nil { - fmt.Fprint(p.Output, out) - } else { - fmt.Print(out) - } - p.lastBarsCount = len(p.bars) - return isFinished -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/reader.go b/vendor/gopkg.in/cheggaaa/pb.v1/reader.go deleted file mode 100644 index 9f3148b546..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/reader.go +++ /dev/null @@ -1,25 +0,0 @@ -package pb - -import ( - "io" -) - -// It's proxy reader, implement io.Reader -type Reader struct { - io.Reader - bar *ProgressBar -} - -func (r *Reader) Read(p []byte) (n int, err error) { - n, err = r.Reader.Read(p) - r.bar.Add(n) - return -} - -// Close the reader when it implements io.Closer -func (r *Reader) Close() (err error) { - if closer, ok := r.Reader.(io.Closer); ok { - return closer.Close() - } - return -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/runecount.go b/vendor/gopkg.in/cheggaaa/pb.v1/runecount.go deleted file mode 100644 index c617c55ec3..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/runecount.go +++ /dev/null @@ -1,17 +0,0 @@ -package pb - -import ( - "github.com/mattn/go-runewidth" - "regexp" -) - -// Finds the control character sequences (like colors) -var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9]+\x6d") - -func escapeAwareRuneCountInString(s string) int { - n := runewidth.StringWidth(s) - for _, sm := range ctrlFinder.FindAllString(s, -1) { - n -= runewidth.StringWidth(sm) - } - return n -} diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go b/vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go deleted file mode 100644 index 517ea8ed72..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build darwin freebsd netbsd openbsd dragonfly -// +build !appengine - -package pb - -import "syscall" - -const ioctlReadTermios = syscall.TIOCGETA -const ioctlWriteTermios = syscall.TIOCSETA diff --git a/vendor/gopkg.in/cheggaaa/pb.v1/termios_sysv.go b/vendor/gopkg.in/cheggaaa/pb.v1/termios_sysv.go deleted file mode 100644 index b10f61859c..0000000000 --- a/vendor/gopkg.in/cheggaaa/pb.v1/termios_sysv.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux solaris -// +build !appengine - -package pb - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TCGETS -const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/k8s.io/client-go/LICENSE b/vendor/k8s.io/client-go/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/k8s.io/client-go/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/k8s.io/client-go/util/homedir/homedir.go b/vendor/k8s.io/client-go/util/homedir/homedir.go deleted file mode 100644 index 816db57f59..0000000000 --- a/vendor/k8s.io/client-go/util/homedir/homedir.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package homedir - -import ( - "os" - "runtime" -) - -// HomeDir returns the home directory for the current user -func HomeDir() string { - if runtime.GOOS == "windows" { - - // First prefer the HOME environmental variable - if home := os.Getenv("HOME"); len(home) > 0 { - if _, err := os.Stat(home); err == nil { - return home - } - } - if homeDrive, homePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"); len(homeDrive) > 0 && len(homePath) > 0 { - homeDir := homeDrive + homePath - if _, err := os.Stat(homeDir); err == nil { - return homeDir - } - } - if userProfile := os.Getenv("USERPROFILE"); len(userProfile) > 0 { - if _, err := os.Stat(userProfile); err == nil { - return userProfile - } - } - } - return os.Getenv("HOME") -} From 1c44571bbdeda6afccee5b19cae32191084ad156 Mon Sep 17 00:00:00 2001 From: Carlos Garcia <37964430+ggcarlosr@users.noreply.github.com> Date: Wed, 25 Apr 2018 23:50:39 -0400 Subject: [PATCH 23/69] Create Logo (#147) --- Logo | 1 + 1 file changed, 1 insertion(+) create mode 100644 Logo diff --git a/Logo b/Logo new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Logo @@ -0,0 +1 @@ + From ebdf0eafc3718544a3e4b3a0ee13d8243491108c Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Thu, 26 Apr 2018 09:59:43 -0700 Subject: [PATCH 24/69] Build kaniko with docker --- deploy/Dockerfile | 8 ++++---- deploy/Dockerfile_debug | 10 +++++----- deploy/executor-release.yaml | 19 ++++++++++--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 5d811327ec..0323d5d347 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -15,10 +15,10 @@ # Builds the static Go image to execute in a Kubernetes job FROM scratch -ADD out/executor /kaniko/executor -ADD files/ca-certificates.crt /kaniko/ssl/certs/ -ADD files/docker-credential-gcr /usr/local/bin/ -ADD files/config.json /root/.docker/ +COPY out/executor /kaniko/executor +COPY files/ca-certificates.crt /kaniko/ssl/certs/ +COPY files/docker-credential-gcr /usr/local/bin/ +COPY files/config.json /root/.docker/ RUN ["docker-credential-gcr", "config", "--token-source=env"] ENV HOME /root ENV USER /root diff --git a/deploy/Dockerfile_debug b/deploy/Dockerfile_debug index a7af94fe5e..29ecbeef99 100644 --- a/deploy/Dockerfile_debug +++ b/deploy/Dockerfile_debug @@ -15,11 +15,11 @@ # Builds the executor from debian FROM gcr.io/google-appengine/debian9:latest -ADD out/executor /kaniko/executor -ADD files/ca-certificates.crt /kaniko/ssl/certs/ -ADD files/docker-credential-gcr /usr/local/bin/ -ADD files/config.json /root/.docker/ +COPY out/executor /kaniko/executor +COPY files/ca-certificates.crt /kaniko/ssl/certs/ +COPY files/docker-credential-gcr /usr/local/bin/ +COPY files/config.json /root/.docker/ +RUN ["docker-credential-gcr", "config", "--token-source=env"] ENV HOME /root ENV SSL_CERT_DIR=/kaniko/ssl/certs -RUN ["docker-credential-gcr", "config", "--token-source=env"] ENTRYPOINT ["/kaniko/executor"] diff --git a/deploy/executor-release.yaml b/deploy/executor-release.yaml index db3d5c5def..6344ebdff6 100644 --- a/deploy/executor-release.yaml +++ b/deploy/executor-release.yaml @@ -18,13 +18,14 @@ steps: path: "/usr/bin" dir: go/src/github.com/GoogleContainerTools/kaniko env: ["GOPATH=/workspace/go/"] - # Then, build kaniko with kaniko - - name: "gcr.io/kaniko-project/executor:latest" - args: ["--dockerfile=/workspace/deploy/Dockerfile", - "--context=/workspace/go/src/github.com/GoogleContainerTools/kaniko/", - "--destination=gcr.io/kaniko-project/executor:${COMMIT_SHA}"] + # First, build kaniko + - name: "gcr.io/cloud-builders/docker" + args: ["build", "-f", "deploy/Dockerfile", + "-t", "gcr.io/kaniko-project/executor:${COMMIT_SHA}", "."] + dir: go/src/github.com/GoogleContainerTools/kaniko # Then, build kaniko:debug - - name: "gcr.io/kaniko-project/executor:latest" - args: ["--dockerfile=/workspace/deploy/Dockerfile_debug", - "--context=/workspace/go/src/github.com/GoogleContainerTools/kaniko/", - "--destination=gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}"] + - name: "gcr.io/cloud-builders/docker" + args: ["build", "-f", "deploy/Dockerfile_debug", + "-t", "gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}", "."] + dir: go/src/github.com/GoogleContainerTools/kaniko +images: ["gcr.io/kaniko-project/executor:${COMMIT_SHA}", "gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}"] From 842fc2f8d74e33ba0e091002757938432d43b51b Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Thu, 26 Apr 2018 14:00:25 -0700 Subject: [PATCH 25/69] move kaniko logo into directory Move kaniko logo into directory --- Logo | 1 - logo/Kaniko-Logo-Monochrome.png | Bin 0 -> 9206 bytes logo/Kaniko-Logo.png | Bin 0 -> 20081 bytes logo/README.md | 1 + 4 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 Logo create mode 100644 logo/Kaniko-Logo-Monochrome.png create mode 100644 logo/Kaniko-Logo.png create mode 100644 logo/README.md diff --git a/Logo b/Logo deleted file mode 100644 index 8b13789179..0000000000 --- a/Logo +++ /dev/null @@ -1 +0,0 @@ - diff --git a/logo/Kaniko-Logo-Monochrome.png b/logo/Kaniko-Logo-Monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..b6ca283741449d69f5aeae435aaa2b4d38f50934 GIT binary patch literal 9206 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 literal 0 HcmV?d00001 diff --git a/logo/Kaniko-Logo.png b/logo/Kaniko-Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a37917bf8a0b14e47f67208f709a74c8d69dd14 GIT binary patch literal 20081 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

9M&S{WA)l7j^ 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 Date: Thu, 26 Apr 2018 15:40:41 -0700 Subject: [PATCH 26/69] support multi stage builds --- cmd/executor/cmd/root.go | 23 ++- .../dockerfiles/Dockerfile_test_multistage | 9 + .../dockerfiles/config_test_multistage.json | 12 ++ integration_tests/integration_test_yaml.go | 18 +- pkg/commands/copy.go | 13 ++ pkg/commands/env.go | 6 + pkg/dockerfile/dockerfile.go | 96 +++++++++- pkg/dockerfile/dockerfile_test.go | 96 ++++++++++ pkg/executor/executor.go | 181 +++++++++++------- pkg/util/command_util.go | 2 +- pkg/util/fs_util.go | 35 +++- pkg/util/fs_util_test.go | 3 - 12 files changed, 402 insertions(+), 92 deletions(-) create mode 100644 integration_tests/dockerfiles/Dockerfile_test_multistage create mode 100644 integration_tests/dockerfiles/config_test_multistage.json create mode 100644 pkg/dockerfile/dockerfile_test.go diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 6a4fd546ef..adeed0e580 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -32,14 +32,13 @@ import ( ) var ( - dockerfilePath string - destination string - srcContext string - snapshotMode string - bucket string - dockerInsecureSkipTLSVerify bool - logLevel string - force bool + dockerfilePath string + destination string + srcContext string + snapshotMode string + bucket string + logLevel string + force bool ) func init() { @@ -48,7 +47,6 @@ func init() { RootCmd.PersistentFlags().StringVarP(&bucket, "bucket", "b", "", "Name of the GCS bucket from which to access build context as tarball.") RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)") RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting") - RootCmd.PersistentFlags().BoolVarP(&dockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic") RootCmd.PersistentFlags().BoolVarP(&force, "force", "", false, "Force building outside of a container") } @@ -76,7 +74,12 @@ var RootCmd = &cobra.Command{ logrus.Error(err) os.Exit(1) } - if err := executor.DoBuild(dockerfilePath, srcContext, destination, snapshotMode, dockerInsecureSkipTLSVerify); err != nil { + ref, image, err := executor.DoBuild(dockerfilePath, srcContext, snapshotMode) + if err != nil { + logrus.Error(err) + os.Exit(1) + } + if err := executor.DoPush(ref, image, destination); err != nil { logrus.Error(err) os.Exit(1) } diff --git a/integration_tests/dockerfiles/Dockerfile_test_multistage b/integration_tests/dockerfiles/Dockerfile_test_multistage new file mode 100644 index 0000000000..18fa2d2c15 --- /dev/null +++ b/integration_tests/dockerfiles/Dockerfile_test_multistage @@ -0,0 +1,9 @@ +FROM gcr.io/distroless/base:latest +COPY . . + +FROM scratch as second +ENV foopath context/foo +COPY --from=0 $foopath context/b* /foo/ + +FROM gcr.io/distroless/base:latest +COPY --from=second /foo /foo2 diff --git a/integration_tests/dockerfiles/config_test_multistage.json b/integration_tests/dockerfiles/config_test_multistage.json new file mode 100644 index 0000000000..9aa0494cb8 --- /dev/null +++ b/integration_tests/dockerfiles/config_test_multistage.json @@ -0,0 +1,12 @@ +[ + { + "Image1": "gcr.io/kaniko-test/docker-test-multistage:latest", + "Image2": "gcr.io/kaniko-test/kaniko-test-multistage:latest", + "DiffType": "File", + "Diff": { + "Adds": null, + "Dels": null, + "Mods": null + } + } +] \ No newline at end of file diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index 7c1d646070..a9f09e3a4d 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -115,14 +115,6 @@ var fileTests = []struct { kanikoContext: buildcontextPath, repo: "test-add", }, - { - description: "test mv add", - dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_mv_add", - configPath: "/workspace/integration_tests/dockerfiles/config_test_mv_add.json", - dockerContext: buildcontextPath, - kanikoContext: buildcontextPath, - repo: "test-mv-add", - }, { description: "test registry", dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_registry", @@ -147,6 +139,14 @@ var fileTests = []struct { kanikoContext: buildcontextPath, repo: "test-scratch", }, + { + description: "test multistage", + dockerfilePath: "/workspace/integration_tests/dockerfiles/Dockerfile_test_multistage", + configPath: "/workspace/integration_tests/dockerfiles/config_test_multistage.json", + dockerContext: buildcontextPath, + kanikoContext: buildcontextPath, + repo: "test-multistage", + }, } var structureTests = []struct { @@ -288,7 +288,7 @@ func main() { } compareOutputs := step{ Name: ubuntuImage, - Args: []string{"cmp", "-b", test.configPath, containerDiffOutputFile}, + Args: []string{"cmp", test.configPath, containerDiffOutputFile}, } y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, containerDiff, catContainerDiffOutput, compareOutputs) diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 91e60d82da..2610799b99 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -17,6 +17,7 @@ limitations under the License. package commands import ( + "github.com/GoogleContainerTools/kaniko/pkg/constants" "os" "path/filepath" "strings" @@ -40,6 +41,10 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config) error { logrus.Infof("cmd: copy %s", srcs) logrus.Infof("dest: %s", dest) + // Resolve from + if c.cmd.From != "" { + c.buildcontext = filepath.Join(constants.BuildContextDir, c.cmd.From) + } // First, resolve any environment replacement resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.cmd.SourcesAndDest, config.Env, true) if err != nil { @@ -58,11 +63,19 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config) error { if err != nil { return err } + cwd := config.WorkingDir + if cwd == "" { + cwd = constants.RootDir + } destPath, err := util.DestinationFilepath(src, dest, config.WorkingDir) if err != nil { return err } if fi.IsDir() { + if !filepath.IsAbs(dest) { + // we need to add '/' to the end to indicate the destination is a directory + dest = filepath.Join(cwd, dest) + "/" + } if err := util.CopyDir(fullPath, dest); err != nil { return err } diff --git a/pkg/commands/env.go b/pkg/commands/env.go index 4e576a3f89..1cb8e974a7 100644 --- a/pkg/commands/env.go +++ b/pkg/commands/env.go @@ -29,6 +29,12 @@ type EnvCommand struct { cmd *instructions.EnvCommand } +func NewEnvCommand(cmd *instructions.EnvCommand) EnvCommand { + return EnvCommand{ + cmd: cmd, + } +} + func (e *EnvCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: ENV") newEnvs := e.cmd.Env diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index f755a547e8..c3eb8ed95d 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -18,10 +18,20 @@ package dockerfile import ( "bytes" - "strings" - + "github.com/GoogleContainerTools/kaniko/pkg/commands" + "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/docker/docker/builder/dockerfile/parser" + "github.com/google/go-containerregistry/authn" + "github.com/google/go-containerregistry/name" + "github.com/google/go-containerregistry/v1" + "github.com/google/go-containerregistry/v1/empty" + "github.com/google/go-containerregistry/v1/remote" + "net/http" + "path/filepath" + "strconv" + "strings" ) // Parse parses the contents of a Dockerfile and returns a list of commands @@ -37,6 +47,25 @@ func Parse(b []byte) ([]instructions.Stage, error) { return stages, err } +// ResolveStages resolves any calls to previous stages with names to indices +// Ex. --from=second_stage should be --from=1 for easier processing later on +func ResolveStages(stages []instructions.Stage) { + nameToIndex := make(map[string]string) + for i, stage := range stages { + index := strconv.Itoa(i) + nameToIndex[stage.Name] = index + nameToIndex[index] = index + for _, cmd := range stage.Commands { + switch c := cmd.(type) { + case *instructions.CopyCommand: + if c.From != "" { + c.From = nameToIndex[c.From] + } + } + } + } +} + // ParseCommands parses an array of commands into an array of instructions.Command; used for onbuild func ParseCommands(cmdArray []string) ([]instructions.Command, error) { var cmds []instructions.Command @@ -54,3 +83,66 @@ func ParseCommands(cmdArray []string) ([]instructions.Command, error) { } return cmds, nil } + +// Dependencies returns a list of files in this stage that will be needed in later stages +func Dependencies(index int, stages []instructions.Stage) ([]string, error) { + var dependencies []string + for stageIndex, stage := range stages { + if stageIndex <= index { + continue + } + var sourceImage v1.Image + if stage.BaseName == constants.NoBaseImage { + sourceImage = empty.Image + } else { + // Initialize source image + ref, err := name.ParseReference(stage.BaseName, name.WeakValidation) + if err != nil { + return nil, err + + } + auth, err := authn.DefaultKeychain.Resolve(ref.Context().Registry) + if err != nil { + return nil, err + } + sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) + if err != nil { + return nil, err + } + } + imageConfig, err := sourceImage.ConfigFile() + if err != nil { + return nil, err + } + for _, cmd := range stage.Commands { + switch c := cmd.(type) { + case *instructions.EnvCommand: + envCommand := commands.NewEnvCommand(c) + if err := envCommand.ExecuteCommand(&imageConfig.Config); err != nil { + return nil, err + } + case *instructions.CopyCommand: + if c.From != strconv.Itoa(index) { + continue + } + // First, resolve any environment replacement + resolvedEnvs, err := util.ResolveEnvironmentReplacementList(c.SourcesAndDest, imageConfig.Config.Env, true) + if err != nil { + return nil, err + } + // Resolve wildcards and get a list of resolved sources + srcs, err := util.ResolveSources(resolvedEnvs, constants.RootDir) + if err != nil { + return nil, err + } + for index, src := range srcs { + if !filepath.IsAbs(src) { + srcs[index] = filepath.Join(constants.RootDir, src) + } + } + dependencies = append(dependencies, srcs...) + } + } + } + return dependencies, nil +} diff --git a/pkg/dockerfile/dockerfile_test.go b/pkg/dockerfile/dockerfile_test.go new file mode 100644 index 0000000000..4c4c7e39c6 --- /dev/null +++ b/pkg/dockerfile/dockerfile_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockerfile + +import ( + "fmt" + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "testing" +) + +var dockerfile = ` +FROM scratch +RUN echo hi > /hi + +FROM scratch AS second +COPY --from=0 /hi /hi2 + +FROM scratch +COPY --from=second /hi2 /hi3 +` + +func Test_ResolveStages(t *testing.T) { + stages, err := Parse([]byte(dockerfile)) + if err != nil { + t.Fatal(err) + } + ResolveStages(stages) + for index, stage := range stages { + if index == 0 { + continue + } + copyCmd := stage.Commands[0].(*instructions.CopyCommand) + expectedStage := strconv.Itoa(index - 1) + if copyCmd.From != expectedStage { + t.Fatalf("unexpected copy command: %s resolved to stage %s, expected %s", copyCmd.String(), copyCmd.From, expectedStage) + } + } +} + +func Test_Dependencies(t *testing.T) { + testDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + helloPath := filepath.Join(testDir, "hello") + if err := os.Mkdir(helloPath, 0755); err != nil { + t.Fatal(err) + } + + dockerfile := fmt.Sprintf(` + FROM scratch + COPY %s %s + + FROM scratch AS second + ENV hienv %s + COPY a b + COPY --from=0 /$hienv %s /hi2/ + `, helloPath, helloPath, helloPath, testDir) + + stages, err := Parse([]byte(dockerfile)) + if err != nil { + t.Fatal(err) + } + + expectedDependencies := [][]string{ + { + helloPath, + testDir, + }, + nil, + } + + for index := range stages { + actualDeps, err := Dependencies(index, stages) + testutil.CheckErrorAndDeepEqual(t, false, err, expectedDependencies[index], actualDeps) + } +} diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index d3b2039b13..8f3976da53 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -19,10 +19,13 @@ package executor import ( "bytes" "fmt" + "github.com/GoogleContainerTools/kaniko/pkg/snapshot" "io" "io/ioutil" "net/http" "os" + "path/filepath" + "strconv" "github.com/google/go-containerregistry/v1/empty" @@ -37,98 +40,88 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/commands" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" - "github.com/GoogleContainerTools/kaniko/pkg/image" - "github.com/GoogleContainerTools/kaniko/pkg/snapshot" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/sirupsen/logrus" ) -func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, dockerInsecureSkipTLSVerify bool) error { +func DoBuild(dockerfilePath, srcContext, snapshotMode string) (name.Reference, v1.Image, error) { // Parse dockerfile and unpack base image to root d, err := ioutil.ReadFile(dockerfilePath) if err != nil { - return err + return nil, nil, err } stages, err := dockerfile.Parse(d) if err != nil { - return err - } - baseImage := stages[0].BaseName - - // Unpack file system to root - var sourceImage v1.Image - var ref name.Reference - logrus.Infof("Unpacking filesystem of %s...", baseImage) - if baseImage == constants.NoBaseImage { - logrus.Info("No base image, nothing to extract") - sourceImage = empty.Image - } else { - // Initialize source image - ref, err = name.ParseReference(baseImage, name.WeakValidation) - if err != nil { - return err - } - auth, err := authn.DefaultKeychain.Resolve(ref.Context().Registry) - if err != nil { - return err - } - sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) - if err != nil { - return err - } - } - if err := util.GetFSFromImage(sourceImage); err != nil { - return err + return nil, nil, err } + dockerfile.ResolveStages(stages) hasher, err := getHasher(snapshotMode) if err != nil { - return err + return nil, nil, err } - l := snapshot.NewLayeredMap(hasher) - snapshotter := snapshot.NewSnapshotter(l, constants.RootDir) - - // Take initial snapshot - if err := snapshotter.Init(); err != nil { - return err - } - - destRef, err := name.ParseReference(destination, name.WeakValidation) - if err != nil { - return err - } - // Set environment variables within the image - if err := image.SetEnvVariables(sourceImage); err != nil { - return err - } - - imageConfig, err := sourceImage.ConfigFile() - if err != nil { - return err - } - // Currently only supports single stage builds - for _, stage := range stages { + for index, stage := range stages { + baseImage := stage.BaseName + finalStage := index == len(stages)-1 + // Unpack file system to root + logrus.Infof("Unpacking filesystem of %s...", baseImage) + var sourceImage v1.Image + var ref name.Reference + if baseImage == constants.NoBaseImage { + logrus.Info("No base image, nothing to extract") + sourceImage = empty.Image + } else { + // Initialize source image + ref, err = name.ParseReference(baseImage, name.WeakValidation) + if err != nil { + return nil, nil, err + } + auth, err := authn.DefaultKeychain.Resolve(ref.Context().Registry) + if err != nil { + return nil, nil, err + } + sourceImage, err = remote.Image(ref, auth, http.DefaultTransport) + if err != nil { + return nil, nil, err + } + } + if err := util.GetFSFromImage(sourceImage); err != nil { + return nil, nil, err + } + l := snapshot.NewLayeredMap(hasher) + snapshotter := snapshot.NewSnapshotter(l, constants.RootDir) + // Take initial snapshot + if err := snapshotter.Init(); err != nil { + return nil, nil, err + } + imageConfig, err := sourceImage.ConfigFile() + if err != nil { + return nil, nil, err + } if err := resolveOnBuild(&stage, &imageConfig.Config); err != nil { - return err + return nil, nil, err } for _, cmd := range stage.Commands { dockerCommand, err := commands.GetCommand(cmd, srcContext) if err != nil { - return err + return nil, nil, err } if dockerCommand == nil { continue } if err := dockerCommand.ExecuteCommand(&imageConfig.Config); err != nil { - return err + return nil, nil, err + } + if !finalStage { + continue } // Now, we get the files to snapshot from this command and take the snapshot snapshotFiles := dockerCommand.FilesToSnapshot() contents, err := snapshotter.TakeSnapshot(snapshotFiles) if err != nil { - return err + return nil, nil, err } util.MoveVolumeWhitelistToWhitelist() if contents == nil { @@ -141,7 +134,7 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke } layer, err := tarball.LayerFromOpener(opener) if err != nil { - return err + return nil, nil, err } sourceImage, err = mutate.Append(sourceImage, mutate.Addendum{ @@ -152,15 +145,36 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke }, ) if err != nil { - return err + return nil, nil, err } } + if finalStage { + return ref, sourceImage, nil + } + if err := saveStageDependencies(index, stages); err != nil { + return nil, nil, err + } + // Delete the filesystem + if err := util.DeleteFilesystem(); err != nil { + return nil, nil, err + } } + return nil, nil, nil +} + +func DoPush(ref name.Reference, image v1.Image, destination string) error { // Push the image if err := setDefaultEnv(); err != nil { return err } - + imageConfig, err := image.ConfigFile() + if err != nil { + return err + } + destRef, err := name.ParseReference(destination, name.WeakValidation) + if err != nil { + return err + } wo := remote.WriteOptions{} if ref != nil { wo.MountPaths = []name.Repository{ref.Context()} @@ -169,12 +183,47 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke if err != nil { return err } - sourceImage, err = mutate.Config(sourceImage, imageConfig.Config) + image, err = mutate.Config(image, imageConfig.Config) if err != nil { return err } - - return remote.Write(destRef, sourceImage, pushAuth, http.DefaultTransport, wo) + return remote.Write(destRef, image, pushAuth, http.DefaultTransport, wo) +} +func saveStageDependencies(index int, stages []instructions.Stage) error { + // First, get the files in this stage later stages will need + dependencies, err := dockerfile.Dependencies(index, stages) + logrus.Infof("saving dependencies %s", dependencies) + if err != nil { + return err + } + // Then, create the directory they will exist in + i := strconv.Itoa(index) + dependencyDir := filepath.Join(constants.BuildContextDir, i) + if err := os.MkdirAll(dependencyDir, 0755); err != nil { + return err + } + // Now, copy over dependencies to this dir + for _, d := range dependencies { + fi, err := os.Lstat(d) + if err != nil { + return err + } + dest := filepath.Join(dependencyDir, d) + if fi.IsDir() { + if err := util.CopyDir(d, dest); err != nil { + return err + } + } else if fi.Mode()&os.ModeSymlink != 0 { + if err := util.CopySymlink(d, dest); err != nil { + return err + } + } else { + if err := util.CopyFile(d, dest); err != nil { + return err + } + } + } + return nil } func getHasher(snapshotMode string) (func(string) (string, error), error) { diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 20efd19a37..c8788a4941 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -178,7 +178,7 @@ func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSources []stri } if len(resolvedSources) == 1 { - fi, err := os.Stat(filepath.Join(root, resolvedSources[0])) + fi, err := os.Lstat(filepath.Join(root, resolvedSources[0])) if err != nil { return err } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index d639740dfe..a103e8bfbd 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -104,6 +104,33 @@ func GetFSFromImage(img v1.Image) error { return nil } +// DeleteFilesystem deletes the extracted image file system +func DeleteFilesystem() error { + logrus.Info("Deleting filesystem...") + err := filepath.Walk(constants.RootDir, func(path string, info os.FileInfo, err error) error { + if PathInWhitelist(path, constants.RootDir) || ChildDirInWhitelist(path, constants.RootDir) { + logrus.Debugf("Not deleting %s, as it's whitelisted", path) + return nil + } + if path == constants.RootDir { + return nil + } + return os.RemoveAll(path) + }) + return err +} + +// ChildDirInWhitelist returns true if there is a child file or directory of the path in the whitelist +func ChildDirInWhitelist(path, directory string) bool { + for _, d := range whitelist { + dirPath := filepath.Join(directory, d) + if HasFilepathPrefix(dirPath, path) { + return true + } + } + return false +} + func unTar(r io.Reader, dest string) error { tr := tar.NewReader(r) for { @@ -269,6 +296,9 @@ func RelativeFiles(fp string, root string) ([]string, error) { if err != nil { return err } + if PathInWhitelist(path, root) { + return nil + } relPath, err := filepath.Rel(root, path) if err != nil { return err @@ -284,6 +314,9 @@ func Files(root string) ([]string, error) { var files []string logrus.Debugf("Getting files and contents at root %s", root) err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if PathInWhitelist(path, root) { + return nil + } files = append(files, path) return err }) @@ -368,7 +401,7 @@ func CopyDir(src, dest string) error { } for _, file := range files { fullPath := filepath.Join(src, file) - fi, err := os.Stat(fullPath) + fi, err := os.Lstat(fullPath) if err != nil { return err } diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 0334d8c56c..62e9b6091f 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -103,16 +103,13 @@ var tests = []struct { files: map[string]string{ "/workspace/foo/a": "baz1", "/workspace/foo/b": "baz2", - "/kaniko/file": "file", }, directory: "", expectedFiles: []string{ "workspace/foo/a", "workspace/foo/b", - "kaniko/file", "workspace", "workspace/foo", - "kaniko", ".", }, }, From 3705de22983692a0fa0c8b6012b219d8f52dfb1b Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 27 Apr 2018 14:34:32 -0700 Subject: [PATCH 27/69] Switch to multi-stage dockerfile for building kaniko --- deploy/Dockerfile | 8 +++++++- deploy/executor-release.yaml | 27 +-------------------------- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 0323d5d347..83c5627c4f 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -14,8 +14,14 @@ # Builds the static Go image to execute in a Kubernetes job +FROM golang +WORKDIR /go/src/github.com/GoogleContainerTools/kaniko +RUN apt-get update && apt-get install -y make +COPY . . +RUN make -B + FROM scratch -COPY out/executor /kaniko/executor +COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor COPY files/ca-certificates.crt /kaniko/ssl/certs/ COPY files/docker-credential-gcr /usr/local/bin/ COPY files/config.json /root/.docker/ diff --git a/deploy/executor-release.yaml b/deploy/executor-release.yaml index 6344ebdff6..b2a2d2e69d 100644 --- a/deploy/executor-release.yaml +++ b/deploy/executor-release.yaml @@ -1,31 +1,6 @@ steps: - # First, install make - - name: "gcr.io/google-appengine/debian9" - args: ["sh", "-c", "apt-get update && apt-get install -y make"] - volumes: - - name: "make" - path: "/usr/bin" - - name: "gcr.io/google-appengine/debian9" - args: ["sh", "-c", "cp -r . /kaniko/ && mkdir -p /workspace/go/src/github.com/GoogleContainerTools/ && cp -r /kaniko/ /workspace/go/src/github.com/GoogleContainerTools/"] - volumes: - - name: "make" - path: "/usr/bin" - # Then, build the binary - - name: "gcr.io/google-appengine/golang" - args: ["sh", "-c", "make"] - volumes: - - name: "make" - path: "/usr/bin" - dir: go/src/github.com/GoogleContainerTools/kaniko - env: ["GOPATH=/workspace/go/"] # First, build kaniko - name: "gcr.io/cloud-builders/docker" args: ["build", "-f", "deploy/Dockerfile", "-t", "gcr.io/kaniko-project/executor:${COMMIT_SHA}", "."] - dir: go/src/github.com/GoogleContainerTools/kaniko - # Then, build kaniko:debug - - name: "gcr.io/cloud-builders/docker" - args: ["build", "-f", "deploy/Dockerfile_debug", - "-t", "gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}", "."] - dir: go/src/github.com/GoogleContainerTools/kaniko -images: ["gcr.io/kaniko-project/executor:${COMMIT_SHA}", "gcr.io/kaniko-project/executor:debug-${COMMIT_SHA}"] +images: ["gcr.io/kaniko-project/executor:${COMMIT_SHA}"] From b9435943ec689dbaf73df263698483e36e586be3 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 27 Apr 2018 14:58:25 -0700 Subject: [PATCH 28/69] clean up makefile --- Makefile | 6 ++---- deploy/Dockerfile | 5 ++--- test.sh | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d913360edd..a00b2d386a 100644 --- a/Makefile +++ b/Makefile @@ -34,13 +34,11 @@ GO_LDFLAGS += -X $(VERSION_PACKAGE).version=$(VERSION) GO_LDFLAGS += -w -s # Drop debugging symbols. GO_LDFLAGS += ' -GO_BUILD_TAGS := "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs exclude_graphdriver_overlay" - EXECUTOR_PACKAGE = $(REPOPATH)/cmd/executor KANIKO_PROJECT = $(REPOPATH)/kaniko out/executor: $(GO_FILES) - GOARCH=$(GOARCH) GOOS=linux CGO_ENABLED=0 go build -ldflags $(GO_LDFLAGS) -tags $(GO_BUILD_TAGS) -o $@ $(EXECUTOR_PACKAGE) + GOARCH=$(GOARCH) GOOS=linux CGO_ENABLED=0 go build -ldflags $(GO_LDFLAGS) -o $@ $(EXECUTOR_PACKAGE) .PHONY: test test: out/executor @@ -51,5 +49,5 @@ integration-test: @ ./integration-test.sh .PHONY: images -images: out/executor +images: docker build -t $(REGISTRY)/executor:latest -f deploy/Dockerfile . diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 83c5627c4f..227a184c74 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -14,11 +14,10 @@ # Builds the static Go image to execute in a Kubernetes job -FROM golang +FROM golang:1.10 WORKDIR /go/src/github.com/GoogleContainerTools/kaniko -RUN apt-get update && apt-get install -y make COPY . . -RUN make -B +RUN make FROM scratch COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor diff --git a/test.sh b/test.sh index 1ca29155d2..d797d9f7a2 100755 --- a/test.sh +++ b/test.sh @@ -21,7 +21,7 @@ GREEN='\033[0;32m' RESET='\033[0m' echo "Running go tests..." -go test -cover -v -tags "containers_image_ostree_stub containers_image_openpgp exclude_graphdriver_devicemapper exclude_graphdriver_btrfs" -timeout 60s `go list ./... | grep -v vendor` | sed ''/PASS/s//$(printf "${GREEN}PASS${RESET}")/'' | sed ''/FAIL/s//$(printf "${RED}FAIL${RESET}")/'' +go test -cover -v -timeout 60s `go list ./... | grep -v vendor` | sed ''/PASS/s//$(printf "${GREEN}PASS${RESET}")/'' | sed ''/FAIL/s//$(printf "${RED}FAIL${RESET}")/'' GO_TEST_EXIT_CODE=${PIPESTATUS[0]} if [[ $GO_TEST_EXIT_CODE -ne 0 ]]; then exit $GO_TEST_EXIT_CODE From e9c1e1d518db81bf6d327618c76056e7c5146a41 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 27 Apr 2018 16:20:11 -0700 Subject: [PATCH 29/69] Integration test for base image specifying sha --- integration_tests/dockerfiles/Dockerfile_test_workdir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/dockerfiles/Dockerfile_test_workdir b/integration_tests/dockerfiles/Dockerfile_test_workdir index 6c89e4c11e..beb508d2bf 100644 --- a/integration_tests/dockerfiles/Dockerfile_test_workdir +++ b/integration_tests/dockerfiles/Dockerfile_test_workdir @@ -1,4 +1,4 @@ -FROM gcr.io/google-appengine/debian9:latest +FROM gcr.io/google-appengine/debian9@sha256:6b3aa04751aa2ac3b0c7be4ee71148b66d693ad212ce6d3244bd2a2a147f314a COPY context/foo foo WORKDIR /test # Test that this will be appended on to the previous command, to create /test/workdir From bccc664b19d00475c8eedb4cd00299bd59fc0521 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 15:02:33 +0200 Subject: [PATCH 30/69] added shell command input to commands prepending shell --- pkg/commands/cmd.go | 9 +++++++-- pkg/commands/entrypoint.go | 9 +++++++-- pkg/commands/run.go | 9 +++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 9d53bd98e7..79f13770e3 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -35,8 +35,13 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if c.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(c.cmd.CmdLine, " ")) } else { newCommand = c.cmd.CmdLine diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index a753dc5ee0..7310c2faf5 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -34,8 +34,13 @@ func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if e.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(e.cmd.CmdLine, " ")) } else { newCommand = e.cmd.CmdLine diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 849f012d75..7eb545f196 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -36,8 +36,13 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if r.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(r.cmd.CmdLine, " ")) } else { newCommand = r.cmd.CmdLine From ae47a03023fc263a56367009f800712b77f7fe94 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 15:12:04 +0200 Subject: [PATCH 31/69] Added shell command and test --- pkg/commands/shell.go | 54 +++++++++++++++++++++++++++++++++++++ pkg/commands/shell_test.go | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 pkg/commands/shell.go create mode 100644 pkg/commands/shell_test.go diff --git a/pkg/commands/shell.go b/pkg/commands/shell.go new file mode 100644 index 0000000000..89a4539141 --- /dev/null +++ b/pkg/commands/shell.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "strings" + + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" + "github.com/sirupsen/logrus" +) + +type ShellCommand struct { + cmd *instructions.ShellCommand +} + +// ExecuteCommand handles command processing similar to CMD and RUN, +func (s *ShellCommand) ExecuteCommand(config *v1.Config) error { + logrus.Info("cmd: SHELL") + var newShell []string + + newShell = s.cmd.Shell + + logrus.Infof("Replacing Shell in config with %v", newShell) + config.Shell = newShell + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (s *ShellCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (s *ShellCommand) CreatedBy() string { + entrypoint := []string{"SHELL"} + cmdLine := strings.Join(s.cmd.Shell, " ") + + return strings.Join(append(entrypoint, cmdLine), " ") +} diff --git a/pkg/commands/shell_test.go b/pkg/commands/shell_test.go new file mode 100644 index 0000000000..524138aabf --- /dev/null +++ b/pkg/commands/shell_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package commands + +import ( + "testing" + + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" +) + +var shellTests = []struct { + cmdLine []string + expectedShell []string +}{ + { + cmdLine: []string{"/bin/bash", "-c"}, + expectedShell: []string{"/bin/bash", "-c"}, + }, + { + cmdLine: []string{"/bin/bash"}, + expectedShell: []string{"/bin/bash"}, + }, +} + +func TestShellExecuteCmd(t *testing.T) { + + cfg := &v1.Config{ + Shell: nil, + } + + for _, test := range shellTests { + cmd := ShellCommand{ + &instructions.ShellCommand{ + Shell: test.cmdLine, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell) + } +} From d73f8c031fad403bf9990785cbab8db661f8dd64 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 17:30:18 +0200 Subject: [PATCH 32/69] added stopsignal implementation --- pkg/commands/commands.go | 2 ++ pkg/commands/stopsignal.go | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 pkg/commands/stopsignal.go diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index 96a5bed02f..0d8e6cafab 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -61,6 +61,8 @@ func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, e return &OnBuildCommand{cmd: c}, nil case *instructions.VolumeCommand: return &VolumeCommand{cmd: c}, nil + case *instructions.StopSignalCommand: + return &StopSignalCommand{cmd: c}, nil case *instructions.MaintainerCommand: logrus.Warnf("%s is deprecated, skipping", cmd.Name()) return nil, nil diff --git a/pkg/commands/stopsignal.go b/pkg/commands/stopsignal.go new file mode 100644 index 0000000000..d9122da743 --- /dev/null +++ b/pkg/commands/stopsignal.go @@ -0,0 +1,58 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "strings" + + "github.com/GoogleContainerTools/kaniko/pkg/util" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" + "github.com/sirupsen/logrus" +) + +type StopSignalCommand struct { + cmd *instructions.StopSignalCommand +} + +// ExecuteCommand handles command processing similar to CMD and RUN, +func (s *StopSignalCommand) ExecuteCommand(config *v1.Config) error { + logrus.Info("cmd: STOPSIGNAL") + + // resolve possible environment variables + resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, config.Env, true) + if err != nil { + return err + } + signal := resolvedEnvs[len(resolvedEnvs)-1] + + logrus.Infof("Replacing StopSignal in config with %v", signal) + config.StopSignal = signal + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (s *StopSignalCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (s *StopSignalCommand) CreatedBy() string { + entrypoint := []string{"STOPSIGNAL"} + + return strings.Join(append(entrypoint, s.cmd.Signal), " ") +} From fd8d4b6170738879533e36e3dd50a9c3eb2fd67d Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 17:41:40 +0200 Subject: [PATCH 33/69] added test for stopsignal command implementation --- pkg/commands/stopsignal_test.go | 60 +++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 pkg/commands/stopsignal_test.go diff --git a/pkg/commands/stopsignal_test.go b/pkg/commands/stopsignal_test.go new file mode 100644 index 0000000000..c6e717f761 --- /dev/null +++ b/pkg/commands/stopsignal_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package commands + +import ( + "testing" + + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" +) + +var stopsignalTests = []struct { + signal string + expectedSignal string +}{ + { + signal: "SIGKILL", + expectedSignal: "SIGKILL", + }, + { + signal: "${STOPSIG}", + expectedSignal: "SIGKILL", + }, + { + signal: "1", + expectedSignal: "1", + }, +} + +func TestStopsignalExecuteCmd(t *testing.T) { + + cfg := &v1.Config{ + StopSignal: "", + Env: []string{"STOPSIG=SIGKILL"}, + } + + for _, test := range stopsignalTests { + cmd := StopSignalCommand{ + &instructions.StopSignalCommand{ + Signal: test.signal, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedSignal, cfg.StopSignal) + } +} From 35b5f4b34adae2df3d1e1dbfc7a21fac329c66b9 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 17:43:34 +0200 Subject: [PATCH 34/69] Revert "Added shell command and test" This reverts commit ae47a03023fc263a56367009f800712b77f7fe94. --- pkg/commands/shell.go | 54 ------------------------------------- pkg/commands/shell_test.go | 55 -------------------------------------- 2 files changed, 109 deletions(-) delete mode 100644 pkg/commands/shell.go delete mode 100644 pkg/commands/shell_test.go diff --git a/pkg/commands/shell.go b/pkg/commands/shell.go deleted file mode 100644 index 89a4539141..0000000000 --- a/pkg/commands/shell.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2018 Google LLC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package commands - -import ( - "strings" - - "github.com/docker/docker/builder/dockerfile/instructions" - "github.com/google/go-containerregistry/v1" - "github.com/sirupsen/logrus" -) - -type ShellCommand struct { - cmd *instructions.ShellCommand -} - -// ExecuteCommand handles command processing similar to CMD and RUN, -func (s *ShellCommand) ExecuteCommand(config *v1.Config) error { - logrus.Info("cmd: SHELL") - var newShell []string - - newShell = s.cmd.Shell - - logrus.Infof("Replacing Shell in config with %v", newShell) - config.Shell = newShell - return nil -} - -// FilesToSnapshot returns an empty array since this is a metadata command -func (s *ShellCommand) FilesToSnapshot() []string { - return []string{} -} - -// CreatedBy returns some information about the command for the image config history -func (s *ShellCommand) CreatedBy() string { - entrypoint := []string{"SHELL"} - cmdLine := strings.Join(s.cmd.Shell, " ") - - return strings.Join(append(entrypoint, cmdLine), " ") -} diff --git a/pkg/commands/shell_test.go b/pkg/commands/shell_test.go deleted file mode 100644 index 524138aabf..0000000000 --- a/pkg/commands/shell_test.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2018 Google LLC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package commands - -import ( - "testing" - - "github.com/GoogleContainerTools/kaniko/testutil" - "github.com/docker/docker/builder/dockerfile/instructions" - "github.com/google/go-containerregistry/v1" -) - -var shellTests = []struct { - cmdLine []string - expectedShell []string -}{ - { - cmdLine: []string{"/bin/bash", "-c"}, - expectedShell: []string{"/bin/bash", "-c"}, - }, - { - cmdLine: []string{"/bin/bash"}, - expectedShell: []string{"/bin/bash"}, - }, -} - -func TestShellExecuteCmd(t *testing.T) { - - cfg := &v1.Config{ - Shell: nil, - } - - for _, test := range shellTests { - cmd := ShellCommand{ - &instructions.ShellCommand{ - Shell: test.cmdLine, - }, - } - err := cmd.ExecuteCommand(cfg) - testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell) - } -} From 281c69c6c618c20536aa689c0972900a57310a1f Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Sat, 28 Apr 2018 17:43:42 +0200 Subject: [PATCH 35/69] Revert "added shell command input to commands prepending shell" This reverts commit bccc664b19d00475c8eedb4cd00299bd59fc0521. --- pkg/commands/cmd.go | 9 ++------- pkg/commands/entrypoint.go | 9 ++------- pkg/commands/run.go | 9 ++------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 79f13770e3..9d53bd98e7 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -35,13 +35,8 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if c.cmd.PrependShell { // This is the default shell on Linux - var shell []string - if len(config.Shell) > 0 { - shell = config.Shell - } else { - shell = append(shell, "/bin/sh", "-c") - } - + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} newCommand = append(shell, strings.Join(c.cmd.CmdLine, " ")) } else { newCommand = c.cmd.CmdLine diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index 7310c2faf5..a753dc5ee0 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -34,13 +34,8 @@ func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if e.cmd.PrependShell { // This is the default shell on Linux - var shell []string - if len(config.Shell) > 0 { - shell = config.Shell - } else { - shell = append(shell, "/bin/sh", "-c") - } - + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} newCommand = append(shell, strings.Join(e.cmd.CmdLine, " ")) } else { newCommand = e.cmd.CmdLine diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 7eb545f196..849f012d75 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -36,13 +36,8 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if r.cmd.PrependShell { // This is the default shell on Linux - var shell []string - if len(config.Shell) > 0 { - shell = config.Shell - } else { - shell = append(shell, "/bin/sh", "-c") - } - + // TODO: Support shell command here + shell := []string{"/bin/sh", "-c"} newCommand = append(shell, strings.Join(r.cmd.CmdLine, " ")) } else { newCommand = r.cmd.CmdLine From 5af3645a837675e1479467c4d688b2b56ddf583a Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Mon, 30 Apr 2018 19:59:10 +0200 Subject: [PATCH 36/69] added shell command (#158) * added shell command input to commands prepending shell * Added shell command and test --- pkg/commands/cmd.go | 9 +++++-- pkg/commands/entrypoint.go | 9 +++++-- pkg/commands/run.go | 9 +++++-- pkg/commands/shell.go | 54 +++++++++++++++++++++++++++++++++++++ pkg/commands/shell_test.go | 55 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 pkg/commands/shell.go create mode 100644 pkg/commands/shell_test.go diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index 9d53bd98e7..79f13770e3 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -35,8 +35,13 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if c.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(c.cmd.CmdLine, " ")) } else { newCommand = c.cmd.CmdLine diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index a753dc5ee0..7310c2faf5 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -34,8 +34,13 @@ func (e *EntrypointCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if e.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(e.cmd.CmdLine, " ")) } else { newCommand = e.cmd.CmdLine diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 849f012d75..7eb545f196 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -36,8 +36,13 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config) error { var newCommand []string if r.cmd.PrependShell { // This is the default shell on Linux - // TODO: Support shell command here - shell := []string{"/bin/sh", "-c"} + var shell []string + if len(config.Shell) > 0 { + shell = config.Shell + } else { + shell = append(shell, "/bin/sh", "-c") + } + newCommand = append(shell, strings.Join(r.cmd.CmdLine, " ")) } else { newCommand = r.cmd.CmdLine diff --git a/pkg/commands/shell.go b/pkg/commands/shell.go new file mode 100644 index 0000000000..89a4539141 --- /dev/null +++ b/pkg/commands/shell.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "strings" + + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" + "github.com/sirupsen/logrus" +) + +type ShellCommand struct { + cmd *instructions.ShellCommand +} + +// ExecuteCommand handles command processing similar to CMD and RUN, +func (s *ShellCommand) ExecuteCommand(config *v1.Config) error { + logrus.Info("cmd: SHELL") + var newShell []string + + newShell = s.cmd.Shell + + logrus.Infof("Replacing Shell in config with %v", newShell) + config.Shell = newShell + return nil +} + +// FilesToSnapshot returns an empty array since this is a metadata command +func (s *ShellCommand) FilesToSnapshot() []string { + return []string{} +} + +// CreatedBy returns some information about the command for the image config history +func (s *ShellCommand) CreatedBy() string { + entrypoint := []string{"SHELL"} + cmdLine := strings.Join(s.cmd.Shell, " ") + + return strings.Join(append(entrypoint, cmdLine), " ") +} diff --git a/pkg/commands/shell_test.go b/pkg/commands/shell_test.go new file mode 100644 index 0000000000..524138aabf --- /dev/null +++ b/pkg/commands/shell_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package commands + +import ( + "testing" + + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/google/go-containerregistry/v1" +) + +var shellTests = []struct { + cmdLine []string + expectedShell []string +}{ + { + cmdLine: []string{"/bin/bash", "-c"}, + expectedShell: []string{"/bin/bash", "-c"}, + }, + { + cmdLine: []string{"/bin/bash"}, + expectedShell: []string{"/bin/bash"}, + }, +} + +func TestShellExecuteCmd(t *testing.T) { + + cfg := &v1.Config{ + Shell: nil, + } + + for _, test := range shellTests { + cmd := ShellCommand{ + &instructions.ShellCommand{ + Shell: test.cmdLine, + }, + } + err := cmd.ExecuteCommand(cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedShell, cfg.Shell) + } +} From 6ff3c588af57ef9fcab4a3e9325c8d8c5d9e22a8 Mon Sep 17 00:00:00 2001 From: priyawadhwa Date: Mon, 30 Apr 2018 15:59:04 -0700 Subject: [PATCH 37/69] Update readme (#160) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 9e7fa25346..54a086d400 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ After each command, we append a layer of changed files to the base image (if the The majority of Dockerfile commands can be executed with kaniko, but we're still working on supporting the following commands: -* SHELL * HEALTHCHECK * STOPSIGNAL * ARG From a1acbe8aa82fae7541ce29759cb94f989b9a57f4 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Mon, 30 Apr 2018 22:37:45 -0400 Subject: [PATCH 38/69] Fixed ResolveStages --- pkg/dockerfile/dockerfile.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index c3eb8ed95d..dd2f0311cc 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -53,13 +53,16 @@ func ResolveStages(stages []instructions.Stage) { nameToIndex := make(map[string]string) for i, stage := range stages { index := strconv.Itoa(i) - nameToIndex[stage.Name] = index - nameToIndex[index] = index + if stage.Name != index { + nameToIndex[stage.Name] = index + } for _, cmd := range stage.Commands { switch c := cmd.(type) { case *instructions.CopyCommand: if c.From != "" { - c.From = nameToIndex[c.From] + if val, ok := nameToIndex[c.From]; ok { + c.From = val + } } } } From b5e68f4b7bbfe49230bd84084f743b63e5766ba5 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Tue, 1 May 2018 12:12:36 +0200 Subject: [PATCH 39/69] added signal validation --- Gopkg.lock | 3 +- pkg/commands/stopsignal.go | 15 ++- .../docker/docker/pkg/signal/signal.go | 54 +++++++++ .../docker/docker/pkg/signal/signal_darwin.go | 41 +++++++ .../docker/pkg/signal/signal_freebsd.go | 43 ++++++++ .../docker/docker/pkg/signal/signal_linux.go | 81 ++++++++++++++ .../docker/docker/pkg/signal/signal_unix.go | 21 ++++ .../docker/pkg/signal/signal_unsupported.go | 10 ++ .../docker/pkg/signal/signal_windows.go | 26 +++++ .../docker/docker/pkg/signal/trap.go | 104 ++++++++++++++++++ 10 files changed, 393 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_darwin.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_linux.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/signal_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/signal/trap.go diff --git a/Gopkg.lock b/Gopkg.lock index 7a899bbe10..6c182e1d40 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -45,6 +45,7 @@ "pkg/longpath", "pkg/mount", "pkg/pools", + "pkg/signal", "pkg/system" ] revision = "b1a1234c60cf87048814aa37da523b03a7b0d344" @@ -332,6 +333,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "9ed51a63daab2be9e4864e4d97d90ccc0f540d076f891b80f01bd3f161c9ef7a" + inputs-digest = "18d970ab8a3487013ef13e0aed686929d30bcebc1b9adaa329e9db414189fcf6" solver-name = "gps-cdcl" solver-version = 1 diff --git a/pkg/commands/stopsignal.go b/pkg/commands/stopsignal.go index d9122da743..85d70e6b46 100644 --- a/pkg/commands/stopsignal.go +++ b/pkg/commands/stopsignal.go @@ -21,6 +21,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/docker/docker/pkg/signal" "github.com/google/go-containerregistry/v1" "github.com/sirupsen/logrus" ) @@ -34,14 +35,20 @@ func (s *StopSignalCommand) ExecuteCommand(config *v1.Config) error { logrus.Info("cmd: STOPSIGNAL") // resolve possible environment variables - resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, config.Env, true) + resolvedEnvs, err := util.ResolveEnvironmentReplacementList([]string{s.cmd.Signal}, config.Env, false) if err != nil { return err } - signal := resolvedEnvs[len(resolvedEnvs)-1] + stopsignal := resolvedEnvs[len(resolvedEnvs)-1] - logrus.Infof("Replacing StopSignal in config with %v", signal) - config.StopSignal = signal + // validate stopsignal + _, err = signal.ParseSignal(stopsignal) + if err != nil { + return err + } + + logrus.Infof("Replacing StopSignal in config with %v", stopsignal) + config.StopSignal = stopsignal return nil } diff --git a/vendor/github.com/docker/docker/pkg/signal/signal.go b/vendor/github.com/docker/docker/pkg/signal/signal.go new file mode 100644 index 0000000000..6a663091a1 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal.go @@ -0,0 +1,54 @@ +// Package signal provides helper functions for dealing with signals across +// various operating systems. +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "fmt" + "os" + "os/signal" + "strconv" + "strings" + "syscall" +) + +// CatchAll catches all signals and relays them to the specified channel. +func CatchAll(sigc chan os.Signal) { + handledSigs := []os.Signal{} + for _, s := range SignalMap { + handledSigs = append(handledSigs, s) + } + signal.Notify(sigc, handledSigs...) +} + +// StopCatch stops catching the signals and closes the specified channel. +func StopCatch(sigc chan os.Signal) { + signal.Stop(sigc) + close(sigc) +} + +// ParseSignal translates a string to a valid syscall signal. +// It returns an error if the signal map doesn't include the given signal. +func ParseSignal(rawSignal string) (syscall.Signal, error) { + s, err := strconv.Atoi(rawSignal) + if err == nil { + if s == 0 { + return -1, fmt.Errorf("Invalid signal: %s", rawSignal) + } + return syscall.Signal(s), nil + } + signal, ok := SignalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] + if !ok { + return -1, fmt.Errorf("Invalid signal: %s", rawSignal) + } + return signal, nil +} + +// ValidSignalForPlatform returns true if a signal is valid on the platform +func ValidSignalForPlatform(sig syscall.Signal) bool { + for _, v := range SignalMap { + if v == sig { + return true + } + } + return false +} diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_darwin.go b/vendor/github.com/docker/docker/pkg/signal/signal_darwin.go new file mode 100644 index 0000000000..ee5501e3d9 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_darwin.go @@ -0,0 +1,41 @@ +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" +) + +// SignalMap is a map of Darwin signals. +var SignalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUG": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INFO": syscall.SIGINFO, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, +} diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go b/vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go new file mode 100644 index 0000000000..764f90e264 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go @@ -0,0 +1,43 @@ +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" +) + +// SignalMap is a map of FreeBSD signals. +var SignalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUF": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INFO": syscall.SIGINFO, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "LWP": syscall.SIGLWP, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "THR": syscall.SIGTHR, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, +} diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_linux.go b/vendor/github.com/docker/docker/pkg/signal/signal_linux.go new file mode 100644 index 0000000000..caed97c963 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_linux.go @@ -0,0 +1,81 @@ +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +const ( + sigrtmin = 34 + sigrtmax = 64 +) + +// SignalMap is a map of Linux signals. +var SignalMap = map[string]syscall.Signal{ + "ABRT": unix.SIGABRT, + "ALRM": unix.SIGALRM, + "BUS": unix.SIGBUS, + "CHLD": unix.SIGCHLD, + "CLD": unix.SIGCLD, + "CONT": unix.SIGCONT, + "FPE": unix.SIGFPE, + "HUP": unix.SIGHUP, + "ILL": unix.SIGILL, + "INT": unix.SIGINT, + "IO": unix.SIGIO, + "IOT": unix.SIGIOT, + "KILL": unix.SIGKILL, + "PIPE": unix.SIGPIPE, + "POLL": unix.SIGPOLL, + "PROF": unix.SIGPROF, + "PWR": unix.SIGPWR, + "QUIT": unix.SIGQUIT, + "SEGV": unix.SIGSEGV, + "STKFLT": unix.SIGSTKFLT, + "STOP": unix.SIGSTOP, + "SYS": unix.SIGSYS, + "TERM": unix.SIGTERM, + "TRAP": unix.SIGTRAP, + "TSTP": unix.SIGTSTP, + "TTIN": unix.SIGTTIN, + "TTOU": unix.SIGTTOU, + "URG": unix.SIGURG, + "USR1": unix.SIGUSR1, + "USR2": unix.SIGUSR2, + "VTALRM": unix.SIGVTALRM, + "WINCH": unix.SIGWINCH, + "XCPU": unix.SIGXCPU, + "XFSZ": unix.SIGXFSZ, + "RTMIN": sigrtmin, + "RTMIN+1": sigrtmin + 1, + "RTMIN+2": sigrtmin + 2, + "RTMIN+3": sigrtmin + 3, + "RTMIN+4": sigrtmin + 4, + "RTMIN+5": sigrtmin + 5, + "RTMIN+6": sigrtmin + 6, + "RTMIN+7": sigrtmin + 7, + "RTMIN+8": sigrtmin + 8, + "RTMIN+9": sigrtmin + 9, + "RTMIN+10": sigrtmin + 10, + "RTMIN+11": sigrtmin + 11, + "RTMIN+12": sigrtmin + 12, + "RTMIN+13": sigrtmin + 13, + "RTMIN+14": sigrtmin + 14, + "RTMIN+15": sigrtmin + 15, + "RTMAX-14": sigrtmax - 14, + "RTMAX-13": sigrtmax - 13, + "RTMAX-12": sigrtmax - 12, + "RTMAX-11": sigrtmax - 11, + "RTMAX-10": sigrtmax - 10, + "RTMAX-9": sigrtmax - 9, + "RTMAX-8": sigrtmax - 8, + "RTMAX-7": sigrtmax - 7, + "RTMAX-6": sigrtmax - 6, + "RTMAX-5": sigrtmax - 5, + "RTMAX-4": sigrtmax - 4, + "RTMAX-3": sigrtmax - 3, + "RTMAX-2": sigrtmax - 2, + "RTMAX-1": sigrtmax - 1, + "RTMAX": sigrtmax, +} diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_unix.go b/vendor/github.com/docker/docker/pkg/signal/signal_unix.go new file mode 100644 index 0000000000..a2aa4248fa --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_unix.go @@ -0,0 +1,21 @@ +// +build !windows + +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" +) + +// Signals used in cli/command (no windows equivalent, use +// invalid signals so they don't get handled) + +const ( + // SIGCHLD is a signal sent to a process when a child process terminates, is interrupted, or resumes after being interrupted. + SIGCHLD = syscall.SIGCHLD + // SIGWINCH is a signal sent to a process when its controlling terminal changes its size + SIGWINCH = syscall.SIGWINCH + // SIGPIPE is a signal sent to a process when a pipe is written to before the other end is open for reading + SIGPIPE = syscall.SIGPIPE + // DefaultStopSignal is the syscall signal used to stop a container in unix systems. + DefaultStopSignal = "SIGTERM" +) diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go b/vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go new file mode 100644 index 0000000000..1fd25a83c6 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go @@ -0,0 +1,10 @@ +// +build !linux,!darwin,!freebsd,!windows + +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" +) + +// SignalMap is an empty map of signals for unsupported platform. +var SignalMap = map[string]syscall.Signal{} diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_windows.go b/vendor/github.com/docker/docker/pkg/signal/signal_windows.go new file mode 100644 index 0000000000..65752f24aa --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/signal_windows.go @@ -0,0 +1,26 @@ +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "syscall" +) + +// Signals used in cli/command (no windows equivalent, use +// invalid signals so they don't get handled) +const ( + SIGCHLD = syscall.Signal(0xff) + SIGWINCH = syscall.Signal(0xff) + SIGPIPE = syscall.Signal(0xff) + // DefaultStopSignal is the syscall signal used to stop a container in windows systems. + DefaultStopSignal = "15" +) + +// SignalMap is a map of "supported" signals. As per the comment in GOLang's +// ztypes_windows.go: "More invented values for signals". Windows doesn't +// really support signals in any way, shape or form that Unix does. +// +// We have these so that docker kill can be used to gracefully (TERM) and +// forcibly (KILL) terminate a container on Windows. +var SignalMap = map[string]syscall.Signal{ + "KILL": syscall.SIGKILL, + "TERM": syscall.SIGTERM, +} diff --git a/vendor/github.com/docker/docker/pkg/signal/trap.go b/vendor/github.com/docker/docker/pkg/signal/trap.go new file mode 100644 index 0000000000..2a6e69fb50 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/signal/trap.go @@ -0,0 +1,104 @@ +package signal // import "github.com/docker/docker/pkg/signal" + +import ( + "fmt" + "os" + gosignal "os/signal" + "path/filepath" + "runtime" + "strings" + "sync/atomic" + "syscall" + "time" + + "github.com/pkg/errors" +) + +// Trap sets up a simplified signal "trap", appropriate for common +// behavior expected from a vanilla unix command-line tool in general +// (and the Docker engine in particular). +// +// * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated. +// * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is +// skipped and the process is terminated immediately (allows force quit of stuck daemon) +// * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit. +// * Ignore SIGPIPE events. These are generated by systemd when journald is restarted while +// the docker daemon is not restarted and also running under systemd. +// Fixes https://github.com/docker/docker/issues/19728 +// +func Trap(cleanup func(), logger interface { + Info(args ...interface{}) +}) { + c := make(chan os.Signal, 1) + // we will handle INT, TERM, QUIT, SIGPIPE here + signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE} + gosignal.Notify(c, signals...) + go func() { + interruptCount := uint32(0) + for sig := range c { + if sig == syscall.SIGPIPE { + continue + } + + go func(sig os.Signal) { + logger.Info(fmt.Sprintf("Processing signal '%v'", sig)) + switch sig { + case os.Interrupt, syscall.SIGTERM: + if atomic.LoadUint32(&interruptCount) < 3 { + // Initiate the cleanup only once + if atomic.AddUint32(&interruptCount, 1) == 1 { + // Call the provided cleanup handler + cleanup() + os.Exit(0) + } else { + return + } + } else { + // 3 SIGTERM/INT signals received; force exit without cleanup + logger.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received") + } + case syscall.SIGQUIT: + DumpStacks("") + logger.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT") + } + //for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal # + os.Exit(128 + int(sig.(syscall.Signal))) + }(sig) + } + }() +} + +const stacksLogNameTemplate = "goroutine-stacks-%s.log" + +// DumpStacks appends the runtime stack into file in dir and returns full path +// to that file. +func DumpStacks(dir string) (string, error) { + var ( + buf []byte + stackSize int + ) + bufferLen := 16384 + for stackSize == len(buf) { + buf = make([]byte, bufferLen) + stackSize = runtime.Stack(buf, true) + bufferLen *= 2 + } + buf = buf[:stackSize] + var f *os.File + if dir != "" { + path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1))) + var err error + f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + return "", errors.Wrap(err, "failed to open file to write the goroutine stacks") + } + defer f.Close() + defer f.Sync() + } else { + f = os.Stderr + } + if _, err := f.Write(buf); err != nil { + return "", errors.Wrap(err, "failed to write goroutine stacks") + } + return f.Name(), nil +} From d63bc6da4b4794547ca838ea96f618718cbd78bd Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Tue, 1 May 2018 12:29:57 +0200 Subject: [PATCH 40/69] set fixed index for resolvedEnv slice on environment replacement - will always be len 1 --- pkg/commands/stopsignal.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/commands/stopsignal.go b/pkg/commands/stopsignal.go index 85d70e6b46..65fb7d42fd 100644 --- a/pkg/commands/stopsignal.go +++ b/pkg/commands/stopsignal.go @@ -39,7 +39,7 @@ func (s *StopSignalCommand) ExecuteCommand(config *v1.Config) error { if err != nil { return err } - stopsignal := resolvedEnvs[len(resolvedEnvs)-1] + stopsignal := resolvedEnvs[0] // validate stopsignal _, err = signal.ParseSignal(stopsignal) From 36933a23d7e8b00e39966582f04eebd411435311 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Tue, 1 May 2018 13:33:28 -0400 Subject: [PATCH 41/69] Update to new structure tests --- integration_tests/integration_test_yaml.go | 29 ++++++---------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index 98b871717f..d79ccc8764 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -26,6 +26,7 @@ const ( executorImage = "executor-image" dockerImage = "gcr.io/cloud-builders/docker" ubuntuImage = "ubuntu" + structureTestImage = "gcr.io/gcp-runtimes/container-structure-test" testRepo = "gcr.io/kaniko-test/" dockerPrefix = "docker-" kanikoPrefix = "kaniko-" @@ -205,15 +206,6 @@ func main() { Name: ubuntuImage, Args: []string{"chmod", "+x", "container-diff-linux-amd64"}, } - structureTestsStep := step{ - Name: "gcr.io/cloud-builders/gsutil", - Args: []string{"cp", "gs://container-structure-test/latest/container-structure-test", "."}, - } - structureTestPermissions := step{ - Name: ubuntuImage, - Args: []string{"chmod", "+x", "container-structure-test"}, - } - GCSBucketTarBuildContext := step{ Name: ubuntuImage, Args: []string{"tar", "-C", "/workspace/integration_tests/", "-zcvf", "/workspace/context.tar.gz", "."}, @@ -239,7 +231,7 @@ func main() { Args: []string{"push", onbuildBaseImage}, } y := testyaml{ - Steps: []step{containerDiffStep, containerDiffPermissions, structureTestsStep, structureTestPermissions, GCSBucketTarBuildContext, uploadTarBuildContext, buildExecutorImage, + Steps: []step{containerDiffStep, containerDiffPermissions, GCSBucketTarBuildContext, uploadTarBuildContext, buildExecutorImage, buildOnbuildImage, pushOnbuildBase}, Timeout: "1200s", } @@ -315,20 +307,15 @@ func main() { Args: []string{"pull", kanikoImage}, } // Run structure tests on the kaniko and docker image - args := "container-structure-test -image " + kanikoImage + " " + test.structureTestYamlPath - structureTest := step{ - Name: ubuntuImage, - Args: []string{"sh", "-c", args}, - Env: []string{"PATH=/workspace:/bin"}, + kanikoStructureTest := step{ + Name: structureTestImage, + Args: []string{"test", "--image", kanikoImage, "--config", test.structureTestYamlPath}, } - args = "container-structure-test -image " + dockerImageTag + " " + test.structureTestYamlPath dockerStructureTest := step{ - Name: ubuntuImage, - Args: []string{"sh", "-c", args}, - Env: []string{"PATH=/workspace:/bin"}, + Name: structureTestImage, + Args: []string{"test", "--image", dockerImageTag, "--config", test.structureTestYamlPath}, } - - y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, structureTest, dockerStructureTest) + y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, kanikoStructureTest, dockerStructureTest) } d, _ := yaml.Marshal(&y) From ac8a110593667d89a6c1db5f26ddde5c17bb8ebd Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Tue, 1 May 2018 13:34:19 -0400 Subject: [PATCH 42/69] Update integration tests to use new cst --- integration_tests/integration_test_yaml.go | 29 ++++++---------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/integration_tests/integration_test_yaml.go b/integration_tests/integration_test_yaml.go index 7c1d646070..d5f7dc2a21 100644 --- a/integration_tests/integration_test_yaml.go +++ b/integration_tests/integration_test_yaml.go @@ -26,6 +26,7 @@ const ( executorImage = "executor-image" dockerImage = "gcr.io/cloud-builders/docker" ubuntuImage = "ubuntu" + structureTestImage = "gcr.io/gcp-runtimes/container-structure-test" testRepo = "gcr.io/kaniko-test/" dockerPrefix = "docker-" kanikoPrefix = "kaniko-" @@ -205,15 +206,6 @@ func main() { Name: ubuntuImage, Args: []string{"chmod", "+x", "container-diff-linux-amd64"}, } - structureTestsStep := step{ - Name: "gcr.io/cloud-builders/gsutil", - Args: []string{"cp", "gs://container-structure-test/latest/container-structure-test", "."}, - } - structureTestPermissions := step{ - Name: ubuntuImage, - Args: []string{"chmod", "+x", "container-structure-test"}, - } - GCSBucketTarBuildContext := step{ Name: ubuntuImage, Args: []string{"tar", "-C", "/workspace/integration_tests/", "-zcvf", "/workspace/context.tar.gz", "."}, @@ -239,7 +231,7 @@ func main() { Args: []string{"push", onbuildBaseImage}, } y := testyaml{ - Steps: []step{containerDiffStep, containerDiffPermissions, structureTestsStep, structureTestPermissions, GCSBucketTarBuildContext, uploadTarBuildContext, buildExecutorImage, + Steps: []step{containerDiffStep, containerDiffPermissions, GCSBucketTarBuildContext, uploadTarBuildContext, buildExecutorImage, buildOnbuildImage, pushOnbuildBase}, Timeout: "1200s", } @@ -315,20 +307,15 @@ func main() { Args: []string{"pull", kanikoImage}, } // Run structure tests on the kaniko and docker image - args := "container-structure-test -image " + kanikoImage + " " + test.structureTestYamlPath - structureTest := step{ - Name: ubuntuImage, - Args: []string{"sh", "-c", args}, - Env: []string{"PATH=/workspace:/bin"}, + kanikoStructureTest := step{ + Name: structureTestImage, + Args: []string{"test", "--image", kanikoImage, "--config", test.structureTestYamlPath}, } - args = "container-structure-test -image " + dockerImageTag + " " + test.structureTestYamlPath dockerStructureTest := step{ - Name: ubuntuImage, - Args: []string{"sh", "-c", args}, - Env: []string{"PATH=/workspace:/bin"}, + Name: structureTestImage, + Args: []string{"test", "--image", dockerImageTag, "--config", test.structureTestYamlPath}, } - - y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, structureTest, dockerStructureTest) + y.Steps = append(y.Steps, dockerBuild, kaniko, pullKanikoImage, kanikoStructureTest, dockerStructureTest) } d, _ := yaml.Marshal(&y) From e23003aff3f6f82aba82c57e8849999534c4d273 Mon Sep 17 00:00:00 2001 From: Christian Jantz Date: Wed, 2 May 2018 08:16:38 +0200 Subject: [PATCH 43/69] Removed stopsignal from README as missing command --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 54a086d400..a2c5b24f1b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ After each command, we append a layer of changed files to the base image (if the The majority of Dockerfile commands can be executed with kaniko, but we're still working on supporting the following commands: * HEALTHCHECK -* STOPSIGNAL * ARG Multi-Stage Dockerfiles are also unsupported currently, but will be ready soon. From 1fca51e6be139e2e95ba7937387ec7734d8cef99 Mon Sep 17 00:00:00 2001 From: priyawadhwa Date: Wed, 2 May 2018 03:36:12 -0400 Subject: [PATCH 44/69] Update CreatedBy field in config history (#163) --- pkg/executor/executor.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index d3b2039b13..4fbef060ef 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -147,7 +147,8 @@ func DoBuild(dockerfilePath, srcContext, destination, snapshotMode string, docke mutate.Addendum{ Layer: layer, History: v1.History{ - Author: constants.Author, + Author: constants.Author, + CreatedBy: dockerCommand.CreatedBy(), }, }, ) From c2516b4dcf5ffc2d7bc8b2ad4a0acc2789589234 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Wed, 2 May 2018 13:53:28 -0400 Subject: [PATCH 45/69] Use official version of docker-credential-gcr --- deploy/Dockerfile | 5 ++++- files/docker-credential-gcr | Bin 5095875 -> 0 bytes 2 files changed, 4 insertions(+), 1 deletion(-) delete mode 100755 files/docker-credential-gcr diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 227a184c74..1b93031bd4 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -18,11 +18,14 @@ FROM golang:1.10 WORKDIR /go/src/github.com/GoogleContainerTools/kaniko COPY . . RUN make +WORKDIR /usr/local/bin +ADD https://github.com/GoogleCloudPlatform/docker-credential-gcr/releases/download/v1.4.3-static/docker-credential-gcr_linux_amd64-1.4.3.tar.gz . +RUN tar -xvzf /usr/local/bin/docker-credential-gcr_linux_amd64-1.4.3.tar.gz FROM scratch COPY --from=0 /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor +COPY --from=0 /usr/local/bin/docker-credential-gcr /usr/local/bin/docker-credential-gcr COPY files/ca-certificates.crt /kaniko/ssl/certs/ -COPY files/docker-credential-gcr /usr/local/bin/ COPY files/config.json /root/.docker/ RUN ["docker-credential-gcr", "config", "--token-source=env"] ENV HOME /root diff --git a/files/docker-credential-gcr b/files/docker-credential-gcr deleted file mode 100755 index cff5a9be1769a971ed92d62200c6aa4ad8e3f4fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5095875 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 VxlO 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�ywZ_k6Hid> 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
9~78UeF^9pvZvhsiO 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

43gDC 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 ?fjs~vM$BKiuShF{CD$HOupIK8DqWmT+jEV(gB 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�u@DhM2BX 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

    7XaKMG^`RQAY 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%0DE_3%?Z4sNg=3e_GW) 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

    SKGNeQ9 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

    o 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

    C%h~1RKi;SKO$S{A zECH0BmxDeUzs1Y2g=OyCl0~Q+oLz__9+HlXr+CQ2Y$x_dcIE-!sqUyp1Vb*w36!L& zNX-uaCcIyjgU>+!0{j6e{v}^Y{zt^yw&g!|7*$NA1JPIR3={yJfRnnBBsX)~@`IAA zV|`pVEHA351i*_KJA4{ARf&cjv<*zRqgk}G{cUEPB!&Hpw9`_^Q3c7#AFcy^53mJL za()JyQfVfpQjlu*%KApxNt_otbj~6yq(M@|Z2!v^0oZ4W&j@RU} z9ph`T-H#$L>i;U`@B6iskK`W(`gGtNK*@iJ^Ly1VGn{>vN`7k8s^`<4Z8#SoMlyX9ldBVGN~;`slzd7qOvyT8)okauUM9mq(0SSmNW?~6t7j!V1A7Fp ztk1g`17X+#w5x93+sX`P+95kLNk}@(_!IvhajdXls~z0qMFt zP3arwoa3FF+vfkU`4`Svw19T8M-H-A^zUe67dCr&A>41eb~EB+GsNs*PfW77`BMx* z@`e5ojV~t{IG6fNmLuKq;44xd*S}F#!H@E@1L%{0fq;_ddeD@1e=6lT^l)2wuz&M{ zLGx!0TUtG1)chf{=ggf+ZrPxJE0?f(h=r_S8^QE9R&Q!6Ss%-AdMVUXIUa_Z`nzPymhZj{SH9>RrpT&ncreu z599(Z`h6$$TXU5xZ@*2KPvsX!>PPc=dG*Hq8S4yIZ#>S#1IO!=hK*S$@uRZbzOJ59 z1P@^j+{QUW*bb7Bke1-baiN`kX;Hrw3Z)hJLeY?~Ai3Bb@^?9t59a>Etglh{9dm~g zUgy5UIPET-3MyXF6&>DwSXC~t?S$SqYQ(g<oz^-oHDi)Y-!(yu~%6VFc-iw;<4{z&>u^kA$WDFHng7y&4MnFE?qd+iAM z3l)aSIW;sZ6{)E~1@aQZM@rxRktRL|iO&(@Gkcfeg}?_bbj{^q`Ncfb)05x9S!Y)#te150M0t)?9CY*k z*gVxWIfrVRvy3_D33Wu}4%0u+umC-YRvks!{!gh#9pucxPpDjO0R0H?IH2@+3pAyj zPTWCr%X+@-F9R@a-JG9{$pX=&G=C=L%lRQD-vH2O0Mh^^-wM!_d~xGjRc{FS zPMI@v#GIL}Y>gPRks`S4Eb;kw8E-}plJ$QO$^%*b0e4DzcmU7Al``k?{=6{tJYIn@ zn~-(||CI5en9Xt;z^X5#yiJg&0`ibO{|#FI5%V;FlD7afr9*ei`diIwDtRZ*oin4l zvUbsM+|?=PP{^p5ytqt`UdD)_OeT$Cey2+Yw_qKe&i^XI6!w`gXo+rn(s@^wh)p!e z>w$a*f1BYdCzbC9zm#$=CAl0quLHdv*Z?Rw?*L8d$T&io??dJ;SX@0}J{2*@msnG_ zzy*QE<9Gl}CG-_bD&qfF9FY7D;C(sx3EAbppxuWMF9axl1)wR#pOevIm+IQ_3+A6Y z*I90_SxH4XeSsHDcjKU1EF%}A&xalW_quX|#s z0(JvRjsgFXay(lk%j@Al+j6Vw6)LdXjc<%?2HS4DEgx6ooIrfLMn0B^FP)G0jBY~{ z^*gH%XloELV;8GGFS7dbqJ+FadQ!+5KH85?PJbNqlsM!u z%tyIG*y}b1ZE=7nSh>EA(7GebvPOqZbCB-t(79JPZg$GVYM$xu63*m>@YycOU2qsi znb+qwsS4Q6j4?QT1yeLLa54pNVC*T*SJUA38eASk`H*u^+N%NfsC4YL19T(sS3ue8 zGtiWpoj3$Fztxg&wbK{XRxVmF1LsVWBR8;XFabx|_7H+k^;qpIPdTI6E*CT_q55{3 zF<4c*T9YGB=}$2~IveyHU_PMaSqGZZ5&O!W@dfV5sIHwmXZ{5^__(%u60YyU0f0p% zwF^!|Uw*hal#0Zxd4c?^7|lc-U(2=r1qeb&#CE?V3^eExsZ=^$PyHhy2jC_|ArJYzhKj`n_yHwv0cc9`^CilDi1R#(z$9WFyBPB|b>OQ_q7X~!WZ(=} ztYP2;0o=gYo7VVdp(+shS@(nE|KO+Ett&zA1wICpJiQJ}c?>6x<1FWVI3Yooy$jB(;~bgR$dg8rF{#~n;O`XBL`-0CNRjVKs({HdUJ{zNnrbg@JyY9RPH z*J#V1aTCLAvD+#!@_YeYr8dSjK6Q*$>BXMo+z6K4-B!>_2F*oa{DfJsI8J7H-uQ&$WR`j2Gw=xpnspqLSzod71`p)< zJ(#fTkm^Q@bt=x{zMGkS-e<0Z%x!hdHA7`|gai4-J-RWTe~5;G8j0n+6MIHCT&#pq zQ5UK7ztRp{pri8N|AJ2Y1u-muvcoLU3xN!0e5B^zM;^ltqUa5(t)-pmO37A*l70g# zh)D6+Uo5Jf-pULO{6<4G-Sfm}qin$QDN?+Sud}rWc^`yj_<1+o!bOG|uu5UXZKa_< zn#TSNo20m{l;?QlE)JXIy6Kc<%)*v<&CswUSSS(DMf-WLZak-R%mQlKy^I&KFF3~X z5&b?=U!+EDgm~_O4b*t@Jk1I&@{I|1}GU?!mWt^j>3zDpG2?d%1)E+XbfFXulnEi0F1 z@NtAGu3f-+jJV~5Po{e>NS3D*EAjm;CPyM@N@|`<&3`Hf z7`zN?M%4F-b$qCjYhYC(sHq-}25Vp@#Wr2ZH*jrMSG0OAUXG?RkN3t>17x|L@e1zD zNj2zFt}5_V^AQ(=z7DtnQ1-bGG^O^&5hPce?ii%PkrSsOg<(~O zo@wCVUrZkv=g20k!jSSD1V1IuAE2%O8kz@C@??TOmOSGwK$I%UP*aH>*GhhYb}CwW zXEn`41b-)rof)K#N71%Bd}rgmDt|5ny#lxrP<(F(O-bcXd^@2RvL{qf!$d?&t#LH_~hf5iAEf~M3SU#!+T+Se$? zn~ue}(cxQ#_o{qf0D38K383`71vI6o6R#bg?-W(hQ)c{9nem7v`USySG_MiBz{3RK z^4u~qXnu06Q6cia%9eWX#ru`N{|fpKz|c&=lPb}kN3841RZo~gN z;*XE*t@z`P7bQU=Nl@pK`Zu@Y&vCna5|9cg`ws$5slECqW`|Se&p||WD>E3O%juxy zzCd?zKEz7?GlE?Z-Dl%iYL7(%QEwUtOJlte=jr0Wh_uiOJz~w%SNh4k605J&=L&2}db&d8)0ZRXKcDwc@)G^d8`KK;_dw z-N~m-M<2K2{Q4;il*>X?G~~D|0F6WueLN+|jp9=@9X0e*+U&5BUt?)|%>wQ(@pQ$} z_BbZoz@1d4k>nUCKdtyQ%*6X}#Q=6=hO8uB!3&t3=2_@T@EEu-0t&S@XnuZLi<0@X z)!Pv8q~6!nJ{{$BJpTn-R~WARM%M?nt?^6y;~t2X{$2ynXRC6Vp=M{JwUw(A%cV+v>`7PYmntZwK(xp0Ir;$|&eE#x}e?2IYKGHNR? z#0&?Yrdp1mlqbh9Tk5awphp7Z042{t(3I|Q=6{YZ57l7Vjrvb)myWfAtK}nW7kI7Y zFX`GUTZt9LTzD$R5(zQkf@PLCN*^PKXEDExK_A(xDJ11<1b4^JYopufD9aLK8PoGy!GB)v>*qfX+@riVA<4TS*Kex6B*M)aBCQ&7OA-`UA1P_L# z93#z`oz4P16POJsJ1qxIsWL9ELggE^uPw`2=-`~af_fKAwN<{h!6-ebg&T?!zVM(_ zlOXw{Y_-_oL(rcAUjmB%|A3~{UOk6a6-#NO=A(2`|LP3Eeu-A!ihVh;9&6+Y)(0KF z6;_Pzsi4mR&IJ_TMWBz*cT)9?xw3x~W4)n0*5Z9NiBj)IykF)2d!YXbd;uu_zkxnJ z|MAo3IsB_8V!<^sjq)BXTth1vQgC&1RF6_=J;@M(o#MqwQjU?hCq~I}D(LCJEI`Te zC(xAIYj4#&xj6P~G-3l+A=n8aoCT;%^3ZrhF_?1mB$^PfitQG{Op?QY58kiFiSL8{ z6!;QQ{C@>aDWjeCp7_&QN0F-DFu)WTU=@Fu;mA=XKweCM^IHi}mF(#6GF!%9XM?T* zmH>+X)u1W0H~zwfpz{~B+?A{y z-?(4QnOBVoEEsGOM4N=LW|Q}EAr_!NmjMCwjy&JDl4mOTo(W6?D3MI@a_}s?FAE{^ zCQqfm+3vij0sqH^@1)mLp#Ka!-|9W>%@fNl{Ut3s`x#!38*%9hACVfJ_v5^{mi)^G z-2>zZncG(K8;y_(wVcXZX6I9hw% zoaX2cKB~S9`r-RPCZOc#1)5TO^TJNQVL=VrOsWPjFu#b#XRFbH(7vGYnV1kZOiT&` zg;-=oMx3LjgSEPJDMuanRDutc>l;9C0`3Qt9Iu0>bZCd{_r{M8(Q;lm3u{#nA$z<2 zFWKX(q7L6`eu!&_T8t4NZP3FCSOfGTvy9|=kQt56X5&mL7p_ifS*Ixk-3RCoD7i+1 zru2jp_ZuHaG8wn3)KX^xQ%I+XxubJw&R{i1C9np|<{jak*~U5Ko#n=SUL-ofcwe)_ ze*@mH@@E_9oxpQ|;{O(CO6}zjmPDyv*E)Zy*DX^0}w`!tFFbrq>+>g36*o1-( zPF0qpe=x?s5Of*P7f}3%gFYsIFqgXj>Q7sip|(oWQ4w=1a@T zmVE1p4_-|EunF{oz$1X-`vPc6HF5FGs(B*2&zdv0np{%$BB>5sZMLn7deDg`t$LA~ z*5L4uhD@yj?(R`RIOPntOI*Rlg&H^|8{>yH{BzQ*cPq_i zYUg5RTxgc=3VS9P0i3)Vz)V`eD7=joZ6w|5nYE6E)-&ry=;pIcZx_;Tq*2FkXb3Lz z#+T1Yzuv9%Ln9zkX};928M3SL^8@LXU}_OS={E@USRm@$1EBJ;gSTxyE)nxyLOTSi zJs~4wm+unUb_Xd}2<5nwZ56nyp+J->%D2AUJshe{3>axsicaIBtx=)z*0?mr%`{S> zC*u9jW;1BKiGz4uxDlWTXS>SWs?h2?NIkYdMpYi30{t@Z5uo(&B$`?xaL9>gQ|li+ zITv;GZyf%MBGejl(x#04j89)lzP-a#;8-SR)Ag$Yyy-XZ-9Oei0@zZ zjO&+*b$_Z>>si%0I*hsVkP=`tjSvh;}^wOJ1vt$aUOG+g>2`=$jPts}Z121_$a);Z}G1*(8a*XfYN6!=p{f; z$G=p($jrEWL4RN-2GCBh$SrayXAy;otU>>_t%sFrJ8k%srsd4OlxgiWld14i3wZ`SY$|!!MR5*RsvRtpdNe`C9LK-*f&MqZQet{^2VD-t z$9L4m=`m)GyrQL^UC`RSPCvrEUUSE?1sgj5YD1Af+iN?DV6$SaXroV*_MV_0|KRp9bClRDNg?jOl>*dTVo>9%7wFRa=j@skY$h@zvHN zo>;Zjhr1tjL7DqpsJQNN6*ai{!!GL)SLgwk^`NU&^)*FRU)bsyUwvs6ouxjrA*-st zE(E<2xD8PH>;e525bs}`J8(zn^-gQHZSKRQem)%7#xZzuGxvjU| zq1WBk8}1YFEh_spU8EkR(U=|sK~Df?07{SRLEi?%>oGLG9;Udv6I0}1&{5=nC}Q** zKNR_wzi7W7iu~xe4*5gh`K^Qg6I7(3tJLE#WK{m;PQ{o9=n5!3rh%RfDF0IB{fVRG zhnzA(mRu`~`z%@9=fl0awyMH9X!l_i*^jE2?j%9=b$0;z+#CoP**6A?)&`)@odN5v zKMyh@lp0HjIF<|Y6E~0TcR>|Mq zP3ln(8I>LzK|cb#04P1a1^qw3s<{2gQ{u|~aN5sJYKR?utbv^)+m#tdRA4(2WTxbC z_qGsJ*c^ficZZ7Z3h{?R*49wy{*bjL9Kj5D$uim zxd1~RkuDd4rqtei4cd|O=1@sT@4X*pFxK!>wHp#MdA<>(6Bv6_P+6hJ?_K3D)|A6Y#gH9@1`FW^5iJ2s#_+ z2`D{gfnEsgeMF9LRR4c{ydKKmn%HyfO**h-`J1A1eD9I1%#Ng3D>I0@pC&~ffg))S zB@}H*;7=x4I}$>VCRmRpv}$F}!Lf%ksK1Q(mm^vk)B|NwpC-tv>a~5K{|&ILm_B_# z4+P@-WlzNEGr78&*7#9;j?*pMfIDhpaSx(iyDk_T{#L%^g z)|y1*4V9ncbj!4+o>HF%$g0}S$3VXTybq}S!NF5n3Q+5eLsdP!KdxR|92*Zun%M*F z6S|ja)+eH0hU;_McFa0xyOR;ok6N0#|J3!*Ko^a)dIDPIJ(^gwm9%;$(Rwy9^i-m? z6IzKOz+5#1z&Vvi3;{&>3-y+IErrZ#{%a-Zn}LS_rPs%x4*>Cgw>v(coNDd_+^#;- z#_euQrd&#f+g+7hba^sgmu%H1hptVw)+C>}+i5j@q&_2aVtzLj^lV@`p!9hJ^i#mr zxbfLLar#VG>y{X0ZjjxzS-V6oEj=QWevcq13zVx*>&c zOtBhLLbs<_cR(4@OE`8D+jNrDV<%)(di)LaUf>%*>5-9-xf~!~4!2vq{>!O<$;u<`%?JhDb^Dyp=~MF_7hO0sh`xN4l=6xZ9VACz|(-z<9pD*0&|`G zP<}QvPLK0i<~hmLa4@f|;m(mY+%55qP_Fh{i>t|6j%vCt-2ER?>MJOf_GL=Z{uKUw ziuFTE=-(;Uw@RrinQ^x41L0KJwk=UEd~JZ#Yifs>UUNY&2d)Q{UVj7qHqg_FS5V!a!fqsO z)<@97ULPr1gC$UYd&IgU61pW~Z6JM)-@;Z5l=^4|v2v6Qx+72yD1GLDUIY|6`(%{= zbvV-hTCK-mEOdn&3!M`i3w3NWE%ioftn$w1?w3iUXQ5H#=}6Iz2!AnR?T&7^>=b--sxI4x4DF;0mh}Wm*k@~cX2RQ+KK5eVd zhonyv>GOJ|=#>b6KVt2Tg#I3}-Z?RSss>4Y8X#+>qt9cYUjW_*RQ{NSSl0%Iz9;MJ zrA}PbJ8}9fimeY}-hH2(cVF^{C`HdxDQZ3KUZ(w&+QkTa78`;8k{&-mkB;9(ioPOG z`#EC$5()h$V*M0}s)?z)nX!nUNnVHTZEYvq%Vhi0JXq>e16fBp`qY802kr%wK5v2k z5U6$TM^*lIC{7>h&&hSAW}I6qdUNN?y6&F%I-#q!A*~47RB`v6QD}2R6t%#*XwjM| zzcp&z77g7LwQi0kGdFIhh6eRizg3bhIAx}7MbH(2#6zVXeT!mx3t7co_7P zz+NXFN}ca8B~Fid&S<*{w_=K6!z@{|ttBnmPDk%gYh4c@Ko5VRfZ2pkNVj*OTi#pI zqSvCxsSl&pN72yxQEM->6aCYLbO#tTTT7b7%}~pHsu?Erix$V`sS7~&0!9H!zlEUx z1ZZ(_cvr^hSL5vaY+&b$>0M_SJ{7XJou>W;mp&J9_m8B-0cer*d9>)$DE}^M9gK#) zj#}S92hl$mriS2Cp~De#)K$Z!{Cgo=j^k%vg8m8cbdJg28}vY+Dz2Zi{wVT`c$nkP zBdkp?z*%;gi++moD^jg1Q$v45t-90`>f}J~su5C;4Umx%)o1sC zeiHaApvLuko!=|}QctzsrVbOS$iiuC7XsPXBfJTRfc5aD%?Qs7c*CdRAd$)*JwEcM zT^9(i4Fo>)hr7c?`ttSUDitH89HB0;_BUnI&rK6<2TGyDqNuVP@IzWj848`%CH2tEO%IAVJK;uXJJG#b7U!kq0H8^~i zf``)gI?(mN`c{1F+vQ6tp9RKeY0o;0kFIeXie0R0du{>jY3_jWocawUu|GiPpl8d>^PXyxaOS3&j$bg4c?{xhEYqCHKYGunD-;*{|n1=C4bH! zPAhEFYg&KUV)NsoU9yz0b&4#PcJK}%-Bd15fPM~m9Z>Rp0QzGfUcSC@>$RwS-5P6B zy3B6r+(No9nD=w$|AM)NY*VA6xk*;-kRw+~NwmD?fnESC0#tb|0Zk#kykh)isiJcf z#bYmmqRfxt60Lfw%$E+tujHj?gc0p9hmd#tgf=?u_8WX~(tG z;a@T+y5Bk(^lacnK=D5rG=(GWb#~vY5KeXqqAGd*&~d0OWK(E@Mz@6qQQl`wbLs)& zQ|WyI^zVU}0mbh%&=lhHTO||s7Zg9Gns>|=((dq09USF55_Augd>+p3AiSjK5Jq#ED zD89#orVyXc$4GDYg$$AAMZ!SVxtehk+?7_YTmH0Z#&o|I?r;{OWWc z&b=75I#<-{Ce6T#VZPxbohRr~&XD=;8XDza0J;Pi3Ml@=K~wl2(oYv=MACb*4c6)K zZAH8)-M4|h7kB_rd>;l);a8{I;hIuC2}zzlgC;${gKaQCI~y)6rFAgO_N!&Oe?a^$ z#83Tf!Z3_|Kq^3i`r0Gyo~m|CGx%n@ZR40)P5`F_%}5Y`s&zQ=&qG`){?(w*0M`9) z@pl^vjpfkk#J?ADsr)+t`a|GjK;_?Oped}6)BBF8x2FsmGK74c!48Tjt~sKnHfu(+ z2D6}0p`yR9oGJ6Gq%_KJJm{IgTtM+V88n5X_P>X7OQ}5rdaKeo-d!jrKs&wLIUeFU z1x?{t=^QdRHkq?UGFNH_?p0RGYn%A{+F3H4sl%iE27oRD zMgfXn6=(`aPiHK*l-ic=WZsEn0$P(uW@xtLw;u7S^xX>jPT(Fu@!J8K!m-jP-2bUk z>^XT_tHbXH#HaZA$}rCb`T&Yw7HA4bPhSkTqbE-*sgdbxMto{MvlaCHz*9i?dXz6h-_@*3H=rgj@V}yq25PD#@(8{FZcSR$vxXSh&rm=7qRUAF@om`!AErq-uKvo zcg~gh-2s`(kPhmn{|0(xxv8xNl-%2oN1X!V?@u3e{9UzR`U|IRYg=ZwEFROahAuLT zuNqg6ZCpy;7sVS6b62&jKC!W-VQSNv^{d9zt*%FxXoR-vn4!@{PlXAfU!>cg_tVG4 z^idAf0rV?X&ilXU2lT~dI86-ob6%$4c|QH*Z}hE-lAaXp6Y6iy#tY31|HR-e?$$oq zHf%8jxND`g!We3u?BP{bl{L&7Y>nb@2#569 zBTSQ5T9IrM7ILh#pw|rKn#bE#vV{vlB~XQo3>QBs;jWAVvuK2kpZZ({<{8JYF*+Co zyFQ{t`1^VKHK#>f!xQH0M`XqxBKFpf6_TdN#VbuiM^l+3&+y5}cBg zJxTf(rEHiLA@stxy6weJ@E)Ld1{)GIaJ`UbAp5ir(X?TMKg@2kVZXJF!xz}aUT7P? zOx>LbhZf6v78-^94SYlOtPkh{U;v={#c`l1bUOaPls>+wJ}c^47Bz?pQ;Tx*12&3o zov{2~oZ8 zRL})LF`)R?fu>O7=nJcJ8^M<*LMt7!rO<)?Mi)BJe}oRS2fPnqv^L=%4mC`7C8H9B zO}d91ft@9Tr^A$z!Fu!M)|;$gIWvoFKZ=xW{l3mQtkl)AEzC%wU0E4A8l}9CLmpL5 z&w>6E@ByIY{Q)$E`1_7h-j*i#VIWnfHknI#BCiTIqKCf*D%{#dR<4n5qyi@I4-*{l zFk_^o6wrvU*tm{vO6*-G<*2NP?g!5V-2kirlpO7#DeQXr@N-om2R2erWv17OTbDSz z`#TpK+8@b%?E>1@zJ}k7NwJk}BOEkn$daJSyLKC3L5OR6xmF4VuDkN3Z{|a;~9HwA->g&J*4@ zerBwde}iKM67@Sv`wDj(3}=ISkd+5tVhNtXW*+V^4#RDvfU5|Ve;7Z-$g#)TBjNgJ zUeFBKy^*gA_&NL#=hY0V`|?V(kfW14{0XK~q>9cP~QZvyi*n zxD<@VehKd$Y%d>4W@4}5om|^z!yYGcHkZ3xv-x;)Bwe(8h#9L{HjVn&|6e8LD62BH zd3dMxxfApr;2@yJp$o_0zBZs0%X!O=0rJ`BkMbFnr%E&$C6)NTZsBU^caz_m=&w=j zSY40fYAA(?Z}SUlPz(jdEAg%K75?r-=gv#*u#T=yo2^Mab3a0m4&k+w=+Hh<4dlu zzbAQl0SryjuwkD*z{=mpJQc|>02M$-i!+RTS1~TFrokL=$aM;SE5QhPPWv4*cQX&H zX0Fi3vNZQ}a}q1|U%_1a*&WQkpSd~ipPOiso>FWRrlBNK-~y`*y}+l;|1M&+9%8P* z8_b_%Cwdah$PN}xip(~8^G8{)q_k5yS;_mh>jOLRzHM)?^;u_s&Jz3jr{weA-|>vS z`ka1Axf__v57SkN#<~$^DYSn~eceE_kKgc55Wki7qV9V^H(t~?v;Ij%8<=}twwbXm zJ@a_~0KXp>NzfVSMmvL*qIE&@gmt6LO8n^u;CY^O<=8FS(kxant;s*%QbN z5-`DjLAUqn_8#5dMTV7!*<@7tH0bp6zv=v@ME(i<ohsG5bZ+a~X4g z7vXO)cAD=uye5o4aY`N5Py?3Dbp2-L8pAW(FPOeDJk9S582)Q|2hat3Y#{Daxe6?U~}AdPl2;1B^Whxm9@V|>EOKnkB||CM>hxLqEP zdzsdGy-a87xac_84|D-g45)Nco=nI4ytwsreoag|p_H+54PD9miKcG&_{w93&D7Ea zoi1V|c_XM8Fq%9t9fM(n`^q(q<|nB2jKi4Z0=U2+*JL7e-XP^_2hS{gL;cPJpdSJr z1t^egW3Q6=uFio(H?U|;%j)L3MU=7S5TsmNk9i))X_X&YD?{i;8NX|MG~Hp)eSrc% z^{*2^Q`puMpVg-|BK2@;vzcMj<$C%chnE=oxpuP`J`Fjn`y!<&W@#{B!=y3z5+-EJVTQ_& zmwGmpexsgEGHP@*U|5!gTD%Dpv!7Z9Ch2Ubw%ymk3db6-8#VzpReHlTNxURJ= zbU(}xSM$(Vx8>%y>*gnVRT?JEo7vag`~tRrxVaJIRtD~pFTxVugF~jZm|MHW=hzea zaxdJNCgX(hV)imO;W-!zA1Ear_>-Gd> z^aJKx4&M;w_vq~DBy%k~rQ!TqcCl`5(9eV+rmR2_r1ilt`nBwKJ+at7z|Ob$c)qH? zS%S|&=Fo%?#)}gy<1tocj(?1eGfRi^(`WQE zC+EOX#!#Lx^PE|z#M8*(7?NwH!2lJ>epZ5+>`t;zw&)n?)XUj#%v1e~6FdoU>63i= z94ERk_vA_ld?eu7Juuc@ER9EyCz{o&vZy20)1 z^^8l|z3g&ER=MF{+0-+Ao_p{U>u%j+4A*sQ)cq{*tWHLAJp2YdGw~CB{>QpEBf*v6 zO3ZQdRd)q4dBo>x4`kdH@V5tGATTiKk>F_aT$tQ&<-tW}VxLKosV<)4cU=+~e`UbD zpLsC3Ewnt32lF|mz~1bC`2*2k`rbe0fq=_pJ{!1-O*eGmTvdx z59;>S`qkb*X8>cgjRj|t{W`OM$Ak}=_qcIB<3Dm#UVc93A2I%+#V_HQKK?^-<0mpSUzTPB{?PLZ0T>g}<54SGksO#Q|fle;Idr~)>X)^Q{3%}2b zE`bkAZu6l*+lDKV&u3oy0Tvj-T;2?y-#aJt6^HHAK5&1X z$y^EJ6HPWTxG*)KzDXGqfIhePcAka5NH;S4>0@%bf0#WrAAjBbS}-ZUCU0aGen0&Z z<{E(cIu6O~Ppy!hYG>Lu)Lxrkll^M#)aba?0(uK@JD~dW&p}g&x4R~KJkg)lV74oJ zLHOuvCm((3KngGrH~|>uyl3N?1T}|i_?IxuoB)3Wt^!vtxHUGdM3<4ulPsR9<4I;* zyw(WggaG_Nd%aeHQIyD2dl`w|-eDeb<36#O3TwYuNcBV3{)1z_N<)PRwVg6uWz(Yb zp$VXyfEGZdYYS)!N1T_?5=x|N!n7J1s@m8NxdzP{6dhl24yPH7Y2Xp{RzI~u6#P9EkdIFcLi?Q!5Eio9OOKAs< zOtKAkc3}PkLpF(N2K-#Z23pYN$51iYJ=m{j91l;h!VH_1^_G+)G$X3#nM*V<3{Y~+ z1Wlnj&Q4;i9OGBjEox~L&MA!0gCq=X1JO(*+!ub9vCgy%D}vQL76|Az6Z+|eBQ;!| zrp=%(M~-&zQS0wZ4 zoz~9=Yc*eG;_;bA|H<%d}6zBjK-G=ROQiVHgxP$HQd;4CuMN zdSa0=1XBdu<+nz_PPf}CfTe7m=bg_I5|ceS7(m+Om2>|SDgAGx{67)<+sNE+ zBBkF(%D;(tK8u*<><=SDx+3KtM(hKTHSa`94@An}iP*11=Dr*$eI-)VY4xQ)3F zM@n}^${&sdw@1>A{yZNy@aNtTDZMdLenZ5*JQCpJuZWaxh?HLuu`fxYt)b&?U}L@u z5BWY^{$1GqDxBxf)lHa}^V;WAUB8?gcXF(-jY7VSu|i`9)AOvo%q(MRQ?Ivm8rmxi9E_nFUJyvpz3)xXbSQ6iA23Rvq2i`${G#lvMHG^?MA*vtIR<^3-g9n(3?tU%XxePc3^9} zB)0@)f+xehr=0B#y}g4o3)!6uJBn| zdIoVFf?UEw>vZ^bAzsDzYta8DKC`2I`+%lUc86R)btrol)K5>ZKeGl;GFp++{1$^9 zkK zvIB>v+YeVSNNphua#V=P!QM|~I;#=C;(sdW24Fd$_^$;` z;Rt;Os&7l19OmK5k(kT$sh|pex^@7Gg{?*=Qd(j3rwU&AspPj8@u_j*WzYwJ_W{N4 zE6@~r+y^HkEtIXTY|(kFl_kUI_042TIbT}LD#YlWZlsWMbd@npBvb2h_?FF$j@M&A zPXT5Citj?u6yoi4iF)K*W_JwK+|1W%Wry47innrzeW=f5dOHxW3-MArdK&Z#z)OJQ z`zB}#@%LQ?-$mp!V~Mz3TbW(qLSm1nZp$s5B*V6xs7m7R+Z}%SCq~mb4D>8u0ied= zOF&-@#HaHu=iZ0l+e`_joQ7SyyE$cbHhm<}hp=!LIL`xNzGq7ZHS}H@Xqcr<#MO6e zB#hzY1=F#r!y46XP8c+~_oTq|h$}HA**5#wnJAYD{Bedg1C`D9WD&eK55UbiLghi3 zUk4$ZYIpwu&E}b!1t|IHcXRMw8MmL+;OIFD`PJS8%mIrH3l2|vo9N?B)DUu0hB3OA ze=25InO@Gq863-CnCLhBEP+9ZnnI@|&sy**!#kDVWuUJFt^s1@c>?ckS028fwP7c5e4^*w$>7T3UZ&rNr{`W4ybs&%Uc$Z1e1!QQW!^iPYdhn2lKTD*dV04r^G=q8 zPnm=wBq2u+!qjkx0a$_IOwH>RZpq>B5vPpsN`qwemdVn(zL4qq0Wz!ncb|-VfIuP; zo34>~k5AVtN96yw)7R9I1s6Dz-b5ci>3L64{y)p~=P3W5Wte3KUSol$mw z0g<@<(S5P)NYq;#)=*E-&YqSw^+(($q`8S}U&7LjiF4AxBStzlNCG=S_eR_AV`J^= z=8s?t#%#x&TPvqMeLTk*gIIu_k3ASBoP3hZUrBkpAd4#JZ%NMire*_5-eI6e0bAnQ z*})^^#er0}$R9|Nr$~`sMuoN^GM#7tS&IBN>?h;!h#M};lL)=$M1O^ke@BAvlY(C& ztaeJlAC3{c`fDk78)Pa$GN^xO2YnB4KcLEe4`>Rzobmgxd7{W)c<-Rr27`R_$l%*1 zzFK?Mjt(yw(lu#?V?wvn;R}nRS{C9ZzNw(IfqsDEI~+8HZ9T2~1mBbD>%<(Tjg6Ij z7ih1=@Qv^wjoTGQFEKwYIV97&9`UO5-URw~U^}47=|#}50Y{`ac6<^1os&aMTpnTA zeBZ?1VOpy@y7iq1zf`@Uz2WDXL7WpO1gQp{U~CkF#}q6wOemz$a$VRR4Sgf!%lb{U z9hQQg2FwCfzB~<@LXYiGEjm|4M0)5ys;jWSHfdSU+Ur=RmF@FHU1(6Rq%`f|@{ z))G&>HP4jX%BhxU43{)NcWSub%Q7B94DA2D36hhMgoB}?MY??Fi-l2l%oxN z)O_w1(A$Cg042u@pegh?pMxA~52OXV4*em;Hf()(6O2TxqmwWo*u0-BoM7+>d@O_a z^@6vE@Sl=@YHc(h@<0!vcRSvG{GWS*U*IT;W)A2mgli`pL;u4QnQHRTqn>=f$7QD&_-P2cy(q668Q&$kyqTD! zt*|02Nv{=R*Zxb&-AQud8*0BFg7(*8TmzKc^Fh}G@#C6rOZ<2}d(A?UyNxZ_ND4H) zV?JMj$FAH1 z#gpP`clbVzcqigrlr!kBf$srT&f!J4uLTTs^gz^k==vkZHPlZzRJ71+QdC(StEsIr zSZ%nKe@$LxeP4?beg$iO93@PGBQn>2ysl>h$VR zr>9zHAUeE-k%z+h%1C26ac=ub@;!uj)j0EC(4obqmISDLTLF4C5PyGtSL`^0d4Myz z8liV}^e|(9c|ZVyTyARb27J&NOhGT>_rV`4o*qvc^>%o((JVYhc#J;T{g%=Al3`gM z17}BlGO)xn6HOg2IH3=_ld_@X7s?Nt`;DSEjDDq}kNgR)wKVNtj5k7M4^3i-mi4nt z*Ivl1=85}3{}Ff>Q2F@4xk6RiVsf_Ej-P3`1gpo2@W z-w!DH#)6&$#MiTnV#`}JifPzHZm3&6dG?Iylv$l@o19C3Bp(~`pdN5`-JpeKb%BL{ zhtXl||H}h+oZ)?#IOwy)vQHBOUnUO1aqVp6>tHrs9~(p(s^C!$YB-Hp#IkH#7r{W2#%fD40g zHnfeT6>PGEy%JvWgnr)yqhX+2VbhU4}pFZcoI#Thvr9K0*8RKm1h>xyt7`1Fk$s^| zt<#aKq%o==G9L7azmUoR}{h`Za;FE#C}O!G=p7oYyC%)~bm z1BtzGNRPFj-+V1`s6W;A8@+W8a~)^i#0I5?++L4@U(n{|%$_1PrXO|jR)hDWx_JVr za$LkXj>_@>V&;B;`R04CVK}`o13KXMCx!wrWgo%CEi-rp^I?li{7Yp?Y#{1FrC-*Y zPUO9s|9ubIKF!p8fGVFN(8GZEdF$gx%v*6EwOiM6IXp(zG}Nt}Sht+KKVtjt6LubJ zWi#m`58I`ic&n~ml$`xzVyeiEr2k8FTSbq#eNSM4 zKB68*JOMiHN)FroBE4L;nV!KTQ0BI1+cb-N+2BcV4vqOx z5j1|j*Rd-lJwIh7$aJ?NO(CbfUl00rU^}4tp+`Yeh~J+SjXS?k&DaWxp>v0{hq2ON zC1nG>+V!YTSl`g0l+Oz4$C=4g;ZB0}2|TdR=kV87MCT8^KxYAc0mZ)vG=(0|@niXS zt3}h{lnd-?tM@>>Xc9dI6?(s2uD3P(BD ziz}tZ82kBS8!Fzmp)x?hf`Gr^{)lHgFP`t2l z=}_m;Ao``Ur5rjH-Q+-EJSL-C_&=DotZz60dF3MI44!P1q`N(XJf_>GD}jA6kE-S) zA-vFFNptG|>CyShOwjXzIzZ)D6KD!O?$<0Nr>pAXZA$YJoT#3FMco$udva$gJ*-w( z6*Q+i#aJlvsng-R7x7jiUg|%-C3+R+AAriI=U3xCC9tJU(|KPlhKQj9Yx9&vz$I z-qC$+W%-utK0*6-vfzXA+nx07W0HP?`JNJ#>sjV{K~T75;Cfa5^ffj!c^ogsJvP$} zTM7R_U!B5zxO?V%4Q?zwKjR&u(EHnLfYqXpe1o|sAJyc2>FQ9rzYq70v`1#Rtx>M6%$0?eB`t_?O9DEslf37PLiL*bLd0Nd>GGBI~cSe-Mk71KzHFeteu&+)Au*SnexcG z(pu9!a!zTD`Cle(3}j=&(`{dinu=Lo&zO!%^>1$6V)2FiUnZ0euhvQV@O+)WNMH5g zffW448a|q(zzzI!%o<~sxT@?RH0DcuW4yk=D8DN-I_OFqlW-wV9>m0*S{aoJ~--}H_5nx4sS({+MvTI0_l9`F&M+SzxYDfFlpz8v+uW?kdTB~4Vz;bw2fs*|P0 zdOM7Wi3Q8!@{vL7mMwgjE_%|5P(hlj&oG-G^Z zZt?h={BoBm-WG_@@8x%&GV!)pd^Ub9+TNACamcc%jlpIAWR0bQ_}LbOz3gN4&0U80 z9edg9@|W#pr#ip;4D>yWlf*SI_-cfv%YXDC|JA4dM-N_LWF^mp{>R+SM(Gw~>SiN& zK=+OITm6RnMy5~lP363vtC@cjOTUmo(Kh{J=3md! zFJ=DAS^7=PzXiqv2lBfZPLwZ(@>yxCIrV45-fo`Ehj`{bXqG-?PJPfME^p$rso!(V z_dHAB=`S$fi!7NB8?Kj?TK!&SXw#-KlaJ%GpE8F$ZBBj4w4XOm`Xe*;G5_z$_mO`O zGoEJtR~dhWnJ+VA6EiPl<^{|=pFxw$JkLDWypkCkn0dCj&Rlo_d&wNK-<N|ts~uTO+$m@7F<`c1`*9Ey#l`cxyxedb`74;O}f?tVU>_X!s8Ar@aSJ<*?# z9`T3Mll@8Qss5DoG=Hxv^**J&r}nXXf6OvU)2C+Ok2447__B-p`i{GY<@)-4#qx*b zP0hFSPQskl-`6cd^sfBiL?mwld zwExtiV5aW%dvv!SJvweQn$RMku(w>cr?$1x_H;Yw$AH~{YUlewQ}~5;PIIMpwof+d zX3@f(ru`$=elT-+wY5w?LpJMcnekrtPDJG>DM!{>(eZT%=*hr|fNIz0fxZ&hb+??i z`=c$qQ*SI;HmuQJHblG18iFgjBQWaW zjtuK-ACIk*tbp69zRoJS-WqnDWnW_z&=J9{%(#j3zHs(Nw!u4fT>lz|uHLb_h7jhD`($~s2x&>tAhI!2EYpVx5l zI9`0(4~(W>^CDY&!fJB*g@Ba>B~BNg!h53^^`n(oCnTH&1D*>KlJ!x^;?5^5V8Le& zRFzLf3u z!5+o#6zgEK#OH-vJjxzG&weZatD%j|_7%dfOpsRvj>Gm(5-v@6*l~K6_eAt@LvaFv z@7QrkkZ&0O7w7jfv}2FfF;2=k@obroBkdDFl&kk3Cm;kN-6F(dkYvq2ET= z!v&yAfsuep$0*Pgj741$`%Q51{z&0No?svzqIR ziyP`zHx!E^UnlNM!HQTE8mI~u z&7jiS3iB?2b^+sLYv_=}uL1EXeiwqi9JmTl{H_K~;fQ?gA$>Kg>Q<5tNl&KIs;A2I z9YB1F-#4It0Db}#zn?)JsHsIaQIC;H_Gofpicvu0L5<=XbMN9 zj}G7R3x&qcudXzRr(~K;=U&9C()k|fPk_$>#rN-^d*mCJuR>Mcxsi$!p*tClgSO&y zKr;YsC~wALr0ANaOTK02MfuJGy#QDYD83D#DI7b059eC_1Vc4?iHUl2rw%hgIu3Fe ztXAD3b`L4Ojv12wjNINVqZeSA9$+z@FD2WfG+@*FMkJ3;aK*g2K@^ASlVpKuk3;-ziFW70jC0r zUma))N9{jPiRE^515zChzq=8iO5Zb}_W`c}ir?#?DI7C>r^a^L;p(1DWM$RJ^rc=H zy>Zvfg7J_AF92we`}HpHvaxfApw!0!OX zcQu}<4h>8DP z&=&)j0V-V^KvOtYy2^gpe4CavSElCx;#2wfCFp+vKLLuLcJVKjUktaSS5K|e;a7?H z6u)}V4Zw1T2jyS9{z13dvgW4c%P{~_hYW|}hnq%#FY$I@9+Z|3IehL$oFT+V{om`L z-vr){;S+y<;@Er~t|(#)oGk5RXBQg`PITJAB~gA=pvM9e0Sc6^|B+wRpSr_wzQZx( z@N0|V_aNxKzzcvXw|7BPh(Aw=Pv?@w)7G@quPrEsiqookI=l;)jK(QK0LU1Ki5gBG zwT2v+W3piQ1$u@&=nuLwf@qGvHN?$H!A5I$`TPe?4T={7xZM1$%}KK-7c?t zYMt|(`VVq03~m4(EpRXi|f1dadLMaUc$8fj55)ULt`ILw}qGMH8B}j zdyOnttUtK&i;_llw!%HY=8$O~7xj>MIl=^FF=3X&Fj-_LTAHVxAD!u3!ShGqh$4$*V;q~3i! z8QG9=H#267`RAciqQ}9zD(cvkESZVI&&K)cR$j$8pRTp(wh4*yAPWwl^RcTx42Q3w zQzic&5WnJ|dC90XK8eGB^6=97@?C>izDQ8FsD zK;~2BmC^IkTF@(j)qs*?18545JO0lOUD$K`qiMj{`qhi56_Pnh(luExbWN(DX0iVsW`ddiXNd<@zXW>7g{JNqIW9b&*XQh5pOW==Ln zqUWxxljYJ3K3U*Ha@+v=R$wcj2T!u0erH+hvdj=GqpURKcM6o4w}OMEXRqCgWsqiTY3^CYoW}K_28q*c_MiPjVH_)hJpdLasDjwqbs(+92UeR^QkENvU~VO$&8plev~ zt6AWBT*DJ(HNud0DT{H|?_8x^B<0M%I+|ZoLC*$G1XO-40{y?`7s+=-q3!A^uPEMT zM~)8g$-+C8+aE!{2Xp~SjxRw|`1R#RavWJ`yN@DBmm^2zHBmWE2E76}15o954d|PJ zBmBVjSZ*+Hct-syTK!Oom5jw4gKqdI05zDRZR2IQ(72yz?_xe|8eSW&#QAn84_G|M zPV|-X3{q;@&Ug*YJIXMw;&){@v{;tkLCB)^jojCoS^|&+sC+8`O<`=@{jT_SN8{@3 z`j)Y1ZOa>1)>DgXW%JLYCU+)mi9{9g=@P{tYI@T|(`&Amax{aFlH)qiw*a>TN{&ZB z{||Cd1?pLrR$Lj6T0J{V7K;CnBagNzDo-xxVqh?!LlrWQ4G~*aZYygQ5 zTKX1GT77c;DnuZ@QM;4kC2EH4u&<@jO>)Ejt~@^)DNd1s;xkixrqGGfHq_AIl+ceX zm=q!-DTBJpB0}1Co{TGJRL}V`-1VU8^=6oEW^SypZ1y7zp+SSD`|>CHi3XXE2ardqo_!0NU5|U;fGXGC zpea;dC-YC8OC6qnavnL!nUPd4K~I_l*jS%#$E9R#d9DEs05VDI8f+Ro1$v|q@D!s` z?v*3{tVStM1NfA5BVtC9o>zD3{@c)RE%{@KJJvZ@?M}=nts+H3sxFAYKlm$9_xZPxlJG zb|$v?P6m#HWsdE99F}tTGOZnB4OU3?e97=oqAS(sa%Gsk3Lsz+4iUMqBQXwL7Jd_< zbD7f)AcKJ~1qkMROPUt!mbQdi%!r2E{ajcwP(QNlX$nI%4h;bYjNKcweU{*)WbILx#CMKsCxU>l9)!#GbKF6bdv?5nPH>OJy;DC*BH0euJX2%z%o zQ_$Z7Task{41HF%M_0VP{g@O}evu**HGnSmqW&Q%gx(|-LWAO^^h1%@cPOz?BV-eh zSlq?9L?0&-JJbbbc<2l_6qUi3XiyHc|f+=cnG zzK7v1OrH3BLtcy-D_(-)v%mPX_n_^F7oGkugu?m&+Rni95A54}4V?lTO0 zk_UEk?lF_}J{BzG40ca&Wtl;}P#<8sY@fRb$uCM38VXg&fEPKo>F;AOj6%IH)~5l6 z$eqyM;-r6bw47If-U!?TsPsPtdOxtOOO~%{7ejw3{WbV~8gDMpA0Xw0Jn`9Ie9BP= zG*#?JsI0$X+Lwk*^kCOKe%yU}U`<&+?`HXMP)KaTre0+DoJTD6LAz74VF+~ZQ z(sL;l;#OGZHYZRa8iQRW-0eCJHohXh>U)g9CWAv?D$#b~_JZz8Fh{vZm?2#_?U;hp zJp(hPd@YkB=A~3-hzp_pESWy-mS}y=0zCv61*r6$0=gcU7}vi>j!|A>GS;}NexKQ+xe#qDw`KE?N&>4I>tztd+7UT!~Gu8lIzP%3F%_IDmT7hd<^xy zpE8(r#2=uYoh{|=fJ|9NH0Qw!0{SashUpn@ijx{cfhr0_QYVD@OM}#iS zv@JOzl(X*fU}o%ip#4_LQ+aE2oLT^S39t-M@~i?)L5-)!nrECCyAr9cn&Cp0&DRcD zInZdsM0&7V!%}>;4*$J~U(It4fc_fz9#H%XZga*-$6smB`7s-YtsF%sG8V#LCu1RZ zV|>7)|Ldra_wqj&T83y@M%cgbhqZ11UE)pfV1P8hls z;#P{!iQ@BZnSxoAf*t&JOUudT!+ma7Uh*jH*juo~oWy4vRo>ZVfMHuHTle&F>%LU4 z9!RyPn>y^#=+J(r)-^Z?*+-$nz)Th$#}-aqA%#Qd%k)fakCww}pw9+c0hOMOpegJ< zW;w_a9qTLd!Q9mBSTjgz-a$M3L7*4Z<9EVxs+LxaULhA9b9eP@6xH+41yY^^4nNA@ zFG2qVxNncj(+4yKbw6A^5AV0sUK~zjSoK$QJX4CP?^d?p+(+0s3Fnrc12wD#ITfyQ zSNWiX!3lPP9mz( z!7C`H?qzYKSRuEvh3BzWHWP~lNyMD;T=-#f+6rXvwA*B!TYi%umIPR(?STmuhSHtgM@QZ;xNoyxe8@kdwm2T65 zU*vwsoYRe|xZ@3FzT^4x3^ke72_m#!Ci5%xj;OpRgI)_<4ybYAHPC+n-g-{TTl1uR z?wfctxt)ANg3er3*F0OgCv;}4_!2e-5C4v5cJSAX2RQ5Cv&831Og#RE2c`C9GPyNh zpJ!xa-3L|d-wcOug%m5vGm7(^lhC5w{rVgJjNINKV+hqX+8B433 zj~n~h3(OkRKh$W}?c?n#|=6J97ySBJqr5MqMTIscc(x92x_9GB6!b z<@y`Y6yo=xkm3oB=PvA3o`}85$N4H8!O6{vAZ{*4O!W07xP>EjEL$CZcOyQv9@+)^ zNnj74`28LM8fzG)f{9@@jHRX1jYKkSAs$+%!zXlSlusV$K|m>> z_>2TiA$~jqAM$R{(jZDUMx&>TJ%*XNS9_Gh5z$z3MpO!AGT};w;_28Z^K(7o4dI>o ztJ^{E06GB0_jjNv#GiY|^QCPK=n-Ht5N@804l|+22J7=Qm=GT#bF{)3fvw<@Hpy4p z9!+l==)OP!p!f~|O`*s1##Y>zB)7vj_-!J|JD64rAjy-QrFfUacP-*o>D>hSHsB6G z@!bKMLXYV^obS<+yd*BkBEH(IWx9Vr{Hi|LcftNCkO(OL8K5b|>+d1IC#{~|)G}^u z<7$!1l|xab9_2G&qDIzXTyIDHHG~aRl&{0D0r4q*XMt`7E&>$4Hqb}qS6#nqMdRw# z(xh;>o8$JLI9?;u*NOPD5Fyp4Pe308{_gOgzHEM+oid~g*PiQFEk6sp1Zq9~97D?R z@ig`_PYs1&HJiIqaWynmm%<{RPKV#byQAql5%fY}DWKBV0-8b(`PmqopDESzG0G0Y zDEkC|fN43{lK}Gw7q{Pr8mH3;N1^pvna;h4SLN#)px*;N0uA-A2@m&a-g0cgk^u3YKE9=j!Ue&Y+ zSIeoD)~>-O%x)-f(ACHsq}9NRJwj8(d_GYro#Ni`b&_uf;w6g8^%>AF1D$~4`xR&k zL!EhJ%sc{~`c}0>IYZa*I?+sb(+pxiHmNA5gSa+p!Y+$~%P6O059MR9H3Xv5k)!P1 zX!>V>o(r4|C^;5_rqE-*;Rr!f8kp{0T~GNSy5`;Jn%_mO7H3wuvGe_`>z(u?URB=D zgMJx!9Z-DV0sYH-r!+1X_J_KeeiF~L+2NOUU$h+!1ziqQ0E*uP&=h(Y=P(|~VlF7A zl?^4bx&n)u-8eR-lLB!%kgM#_IsDoXUq0fa^4$*le&9hs@p}d|g|;~RcXAw1{G`uk zQN1Q%h~3Q>YZt_9zvojIHBw}6M?C1mer{`~Q>kpIH9n z5|Xrw&q4+7;rrF}J@R6L$cr4_4@N4V;5nOFzgt;^By$cc7(v*_quvFB8rkqxBz?$?bA7`CBoW#AP9xSq`E(<d_KqKV?pt0PW`Q&hSGhSH)zXqcm-wM z398LBJNynJKE-e511LjaGoZ>fy#xE-faa{rwmJ5%e~QTaiLrcDxjHvHP>zf0unnu8 zRLSXA)?muD7MdP7j#fWX&zN74RrFW=(lO&1)3gdE?&%DWR9Uhz;WV#VO@c>@%xO8+>2tJ zG~8ci4UYh6Wz&XdmdziYP-YMJ!dr}0)@OLIY#z?{Q?NmF_Hd)j4baanWH3!WoV$bW z4cz}Vv%Y6KdfPu4D}yx%edK4%mE!)0*?(d1t@Sm7MPlo7 z76=FK<-uF{bnZDA_Ww1Uaxm=vG<^2m+_;Oo@p%uo-(zN9>oPtGd&m80l)!T04jo!f zyTq7T3CBEs({j17*=*XDOE)YS4KZ=2b6UuayVfT2`sYI_&mFXV_yNwxtZ<*?VA4F? zN=!*}_c|MQ3*D(kitREZR&S&bq4PG`p7x>cX5pRs%kMyk9>g3LQ1yEb=%v8Wr({1B zc|tzRR(JOcG5z$JqMwef^999phA1x;VYB^uERdp`?dOP>AvC>z7WN)Zzt!TM=_~i9 zT7C-`C@^{P!|n>adbz9!bPh2C4_IcBKc^h_Kq7r+_Af6=9p#6DS|B0UJCyQmI6sY7 z@D~0stXJ5JX$#>chC*&JX2SG8tXyCLM~O$M-Rh(tY0JkurT<&dX%C_A22}db1AQe> z`=Cs>+IQY?bx-ME-MDlm-IhB%2NpZYuU&^Tqc>=)Fb_xp=)9`}pu;4h$py%>yb_8P zZ7dren%dy!$h4kj>I)cU9i?de(4#dM!&ahMH)wJ8qCi6mFC1=;w5)XK|+q54DnVa)r1L_qbw8K5Z~yZ>Dkowrnv#W40PUw~bq9K(hc z+(c49sxnffzD={kw-)g#zNdq30oFRasI21k=tK#~eILj6M{n(U-dkJj7<6uP;@uk) z?>nGB0zLy&dcFo7o1P8##EjQd8&{qdw_eTc4mEMwf}b+E?VR=jU>#GyFR0)bntX6JU=SS|`ih!2jHM6 zKI|gBzj+)PAu$L1i${Lo=6~ROEKF^!-l&6~9hMzbWhjms;}ND0Gj3se1Qlxxr9A5% zneNI*qUoLmx)E3fsC3^CdNikuTs*>Gi_{dL2f(cM zW?rz+zrc-qpm4s-3$0Ycy@iLYOzUEH8|*>w{_yWhsTzC}Y@c&n62~5N*h$$k-pHq+ zH|Niav{8&5%s}rv%(x3(G_>VrI_0YEkm*Z(G`gQ#0(vA+0jPR412l!AJ7l`lzIsf( z73u1}28u(x^*HRIibZGQdN%q+C^7;|Deq4(iiEF<4u^j`;?GC?)UUk)`d#2tK;^Ib z7;G8>2Oa$dr7z%`)ZMR5J5B7CLLz7Aoz}D%<1yZ;deKWUEdZ$=wX**TUCUY6P<@`~ z!Iok!gZlkWJ@3!Vyn==;n8qS_-s9Ou80O|fiDVvQG3IyDB8HzHTC0kBi%V=ZJ< z>1YIfI|Jfa3Ev&`04j1{y#@Po%`<+gQ|Ko_i1o2b-=mh-^@Ml2r{~9!f zczv#z`WdIjh3zuR<(1mIrcApsgDX}`W1We0Wrvgg-$nV?fIbCS04V;eLH{y;>hhF= z5@koX3||~e28y@Ckz+6TsC;-I^e4bUK*{kF=wFuO2(_(lLH_#-f@D1?^P~ESs2s~c zpATFCsP=j%=tqG056S-G%SYtX__utbTqrZ3QwKGAyew&4I|hdM#PMVotR;w<*8TD^ z@k8_&FY?=P1E1WDD4^sX3wjC=UyruMu6yNh6{BoMeM<8nY`;zdLQN#?{Y=}( zbBB5cVK>W|Y=)@QYc|A*4II_6b3`fOJk61-9XwUJ?gsrb&bx(eKNv6cr?I=rDsiNz?Z>$Uw93sy zuPYgjGvQhfyF5ITx?Y4%hi~Om(e($+%4je!qn!vSzDq$<@Ey5dgOeZC4c1P?I(|Q2 z1hXE|zDI0=jdA=1R6Z)x*@5`-5g(;h&q%W(dmg_AmQ zJ7qp8JYwI=;kOs@l_5ULhc`ig415Ksdg$L{YQ2C4M-So^XMdw1IzJ%qN0cGco0c~% zr54-H?x0Skonb~LawQKZY`F$3#_Z;Kjfc+z{)?G$IJt}U88-=eu?BjF|75%`<%^sN z;EzP8eM06>17uP2|8<}*1}+0s{#*x|LXYbX*}o_?!*Jy&amR>i%sO%Z%Crjg9Lk+y zW1L)eXk8B9F2t+&ehXUPi~AUW;+qGWg1UEiqcfiq?P7^IcUBiaP;0J}wdP5u)_kXH zx5D6{8%74xtSjL)loz?n#N;}NiD(Xu+C%s#sxs%YIyr`S?Uwnm7JOCtT?YDU;5tCb zbsuO7)mO{<8?%qC&ciWn5iPbAhvAeL=V;GkexzoVGBmum%K@0mZ)vG=*dEKU3Xwhzju8FAC7*@L!Agvk*Vk-wQ!s3)~1O{*QpBu-DNC zQ1e@q%dGkpO=r}LA?7BI@nxkr=A%};Ti13PxgNu9dLl62ing1UWxc`7J}HTIA{})P zg?F}>gpO|e9+?lWXQTZ|0qA)^J)qjr9iSfuK5^QQYDf9eb|mK6RkWcF;U=x7L(tiD zHKwkmNi5RZ*gjcp`fenvHVNW0EI#i=MZ#A#;xlO@#>7|nI!tk4-j2%U>wD_wgH z8ZufT+?^YlxUUO$xt?BdOad!kv?p){#Lz;|NxrR!Hw*Dn`CkV5E?_sH^8Fy_pMcP# zvi^5C^QMW>e6L2gNwuI0>qRj=YLnBW%jDYvnk98Y6Q$S8w6VQX(@u4sW3<$4s6h^~ z3X(0?jqLcDRbxk|&Iw_f9p<6xnbXEjPn{Hi>`7r4?PpJ;yB6cgTIe+ENoJPNyaftP zGuc=;&pj0zQ)6))I7TaZQKqZ{%-Zvd~UOg;8S(wfzJL7M=!*4I*b2<6=GUzvfw*kfPPoOEp`-1~N=pn43 ztp(g@%g%Ix*YVm3a0r`@blF;$6MxnV(fIp=9t@NMD*h3mj~@ThxcFyv$Dj3kryk(% zmHd~1-UQqTsQB*$eU$iV_gF}ui~D%KOvNdCVtJQK?&o{I&cP{_+1G4DEy|bK7wK4Q5m*5{0<;KHQwpJNBaS?0oAT91-%h4;`|&pME8R+ z>Mf@cm(ojW*0Y^+EV>u68Z(ueCek=SPNY=74h6L8`^aF=+kAD^iKC4w|L8k;m1}fF zOUo5Y^}&BMI5us6RsWNZofH^Wjd)RwUI?FzZM7u)27q&&RC`S!i~g^+yLxp@e`HWpw{+^l&ckdRsFaM^liX4K*{wq zXbK1KmHl9hTvR=}=WcDd3nNC6%f;N}0N<`_$7f@{id`@^u(zH}Zr<4BuQGRKlOMqd3 z;#ULuDE!tahVASPOrSB3hRH>I25v(|eV4b3mAczXhGlUB9%9|l>geSO@YyMu$>eMu z(!9ucHC1Ya&NrO&gI^ZjsovfXdKd6Gpyb&DnnL_NL)6=eO{-g+@mU_czlVeO#B^Ai z6(fmwXeDn-KCYLee3C#92aX36pHo3oD7#tKLv>CHJ`GVmIc@HZ`bIZva~FxvB=MOg zJ_8$Zh2jIg)6gR0uw9X0^+N+0i^+4owaj#z+3sXLI}L_H$-3i7XwB7Fqscil@vVJJ z%Gm)qRDF0J^jpB603~Pem7|sq^=V?)GrA|+#a`9L)S)j;7WVOL4cM&{ZrEG}xFr)n z>+!K6KC%*TS+J7g&4#gnkkQ*75}MV^OoIa=Z8kM&k^a;RtK#dzz2D9)UzkhHrc0WJL$4P?dJ)_^s z4QN>O*~iUPJtY8L7dZ9Q*E2K2t!Z$wz)c+lg)T>~8^KfM@PX-=ElT(2=sTrzm5?v_ah3wHqGY{3LcCt6RTkAziN%Ud`xqU*1*YnTPZ* z*w;Ecq(37cIbZ8u?Jv*+?e8us>t9!t+&{IbS}Pgo>utdHQ0N514R+mbWC;=V40qUz(UfeIQL9F5bjG<-UrX>dZ&r{3v-VE6wVc9q~3@ zi+;seoK}IOarv)sY{dYx*OXZmWb$-P@)-&6GaQ-OZ(?K&p5hhoY%U@L^x3;-7-s+7iF>j#ow zE#g!BR)IbTxByW6E&)v;UO!RtgB{LTZVkw*d6;Z&Wq$!j031){X{@g^Xd<5G4<+9N zh*$Cb8uU-Z=glZz9W;gbbc+6Cyfae7T8OM1i#3^DVONrc$Tga=26k{`>_Z-M_|8MT zs=rzZ`b^+_K((vOL2m@&^?KimZC6qLYAEoB24jIu<`4^E0sl^xrx}HhGxISJTBQN| zXoZ+~g4U|Lob-c-O8+;Ye+2#usC?&t=sEp|mvi?4ITd#0Wzs0^1*--_}*5%fY}DWLeC z2AaaL(i_V)rMd;lT_Gy@g-9)+!A(g9t8(i2Co;W{BVLu>*FnDxybCD4?}MiB3+avO z;Z~mjJ&vvHB+WR9?$Agty~tmOU;ZDX{6>Ku3rqwQzbT+895bCU+M2AFbT#sYt6AiA0{O8RsIAydMe_9Xy4~Pi4Nk-j4Fk0o@NM z04Pu!KB^r^bR5obsJM+pc8=7Hk>YP#o%ow$;@<%JTHppirR!$U6po!P4C|zNsPxps zl`|`-@Rn-^b|Fi!{_IZIA&2il#H;d?zk~HJkO(Ng$)G75tNh})rc}>FRUIv=>LX|* zfOaNoDw%!OIzE&6S&MiT-?gC611p(9DngPZ4 zY|s?q=l}52w}><{sKZ|>_q8gEFyiE*U_ZkyU?Pl^@l-5YQD0|>9Xb(>*5&ZshjzB57B z0`-96dk*Mh^PSyXx2T>9wz33l!vMJ=J;-li+J9L;7%zn1RQL|p;gv0DhCF#>@bPTO zfd_>z{vUg98W?4DzHvX>JhNmnGuZmrA5s(YmB+6|G8CtZ1vIZpGHtxKz>FnkrS?-`{!8IhkQH!6fhh!~5Yqdd=K3 z8P0W|`z+77&norU4$nY7ivHLe$nD^NK31~hQ~;sh&p>}5)O*Gvt5g2&wfnVZQ@cFIaZQLUzy0 z;tt`{M26OF5Njo?z+jNa+Q^T^p`LFr8kWK6(-BS>mpW=!b5$Ty1j5(fU^?eXpTGUz zQm-a>tKk*-dJpo`;5nf6`Vd)!)cfJJUaN3lET`trCgmyyGC>ybqsvv6al4&k^$UwT zuZCE;@*R1DmVyeeU3yHVO5IXr}goU zGsvkw3LoQRtKJaD>p3|1-s1Hmtbz_lqh9ef5udKtzeRo=v;fW5iY!7`?aA!rN3rr- zR_h_8Tg>c#Y%Mi*vjEK}HgG!;E-@jA2TSrc#asCI1n(f^eZY92d1oN+op;vqv(oTh z<)r7WZI||KBwn4~+mTzqvq1BHio7@8BbRc{(W2?gmx+mug6d~Yj?n4@#0`3VK_(El z0)A}0Lhk!2t&Bh{%)}2Rps&T*sBS@o%e9=oSvmcR{1Gvi7WKw=p7dtYxbNb>QqS@K zka~!6IUV@~a5~U>mc1+gZmgC5^Qu<)uFHXT0$a?IttJOS{N+Z|dw;g?R$8`A=JXfL zM{YEqH}hXGTlzlFSI+d}q1+xk=l|fp;}7ybKIZ=_vi}Q({=XH+@i$uj){_4l`y79u zzbVcbZ%3{jpW(lo(;~$e$N2pJU7f#swa>@F#yn}F8y#OpRyZU?`QP74eFtVuPx?at zq37?96#H(pvTkA`u_N~XUrM&X|Mu}6lr`i3#yp{ZJj=$jm*Leyv&Q*Xon7Ppqri7S z-~-!#K&ZJ`j2Fjd&Gg!_b+i+rMG@^t&U?&nfOmlKHN+u1P4D}R&%m^~_1^C%o-f~* z`Q`p3&h}omXu&GZ0$xku9eDZ~Vh4l%-usSTrCLV5=hsu`pEh~nLLLr#etqy# zaRIRY?xbb&7qj6i`Kvw2I)={58+=Fp;Ft}*4;=5UzY z-8nq#2(C%z4{3YUb=aH=Ce-DVzH&Ao8uc=sK%rXmpc548%{gkqt6vRQ`i z{W8A)Qg@BJ($)Vkvyj`v3MXY-;_EdoHxW*=X5SRCZ-}@X#Oqc|M4u&o74NgiiaYO^ zi>tZys4TL-b8=`!S*+aW@1GO!MN8v;?>M~mrgb1wJx^H9VtbAI6YilJ931cN;~Wtj zA3nmGVIRQVXeS0AHu>`|hnL^`Vl9@n(AsR~TxrT*1jpwe&1RgRaW}On(4OfWI^yhI zYBf1lJiO|9rkM+!1=jGW)U#>6)HC)$;yjufy+1FSo)47{8XumlAA!Aiw4bbWQEAsbXt-3cgFh=Ib ztn2p7mm|-bFZ-1`;T`EyQ!b@#_9OP&w%KNHGrhN4y`W^ z#68FJnAGR4v4E9h+Sc6}M)5c*YQQR9YdYtfT#v^fZ&P6{mU@j z4Ci19$|?Nq0~0UQqU(oMA5wD8&xC_APb{M{-GDDAVEfU^XggWjch1g4|MgeMzXo>$ zZC{ZYPxCo--fHd6J?$$dZila$zj)RnTq$j1?@RI0`CD<}Z{mj>ltcIT1Y;L?!7uvx zpV3aow{Cd=x845l=rmg%jTs5wQZBmPmMoQy)=A4~x{9Sf09 z0k5U3Pkig;^y%<=sYvV*s;pUHW z771g|aUGi#TmIs(FSA6JW}{u{xg8yJdHyf5`7vkw0IlalB4!vIAAhN_Y%qnsI9OfLKv<7-@{1D)XTU-K+U5`Uk&7 zei}Rnbo=T5mux?$y(rtE+?V%kk6844s9dAR{@SN(Z-4Dp>uOHY*=61B8V?1=v5YV? z6hzHTRu&Gz6Dp?UPsy@#<&wAzYpfghahjLk7sE?uAA$E;bdK*FkpdnwTpn?wN#lBn zX&q_~cS=R~#;B>6`q!bK&Yv@oF9BBot^ZBPBBc7uy2y*xGI5t4YdNNgwH$NBi~l^4 zh!;%bzF-;dTYu+x+Z#lvv+8J1RfwG~_1FndjPHaUollte0#Ts#C_ok=bzVm6v0~B6 z<;%`obcF0~DU;?@4;m3bhiS$Gp>ny@tV(TstW&&o#H-W)GvxEZML_djgDiqBpL(6I z=Iv-!MNvHLB<~`Zn$bA%ySQ87Em+0qfp_G}aBs}MS@G^5Ud{U%@>k$Hpm~G;?k2Bz zXr=PL-4FXT_bE}+{1 z!CCR2&h2jQw|mx?4tp~ly!_Ntyl zPFH#+7PHh{A%@#>fS;kZU2MoUc4kyr{jPMp#;1WcUL3HTYkOOPMvD6C)t9N1Ts9ra z(5CbZ(g)D?jD6}eazFtPLFk(L{9=j9F0eZz;{C*ESMe<2-{^SGL%tfU2RglXB0m7? z)qahkYQMs4wJ)kuJ(#j|m3InTlR0UlSY34oORYp|FJkzXsSk#8{XNpo`z@0{MZe*)-TphIza&tAzeB<=`(p5d&c=~6dj_*wc)7uPmP$0 ze-3f!_|HII4bJIF{L_~%TDEXcl3zd)SMd*`Kd0m0LcG5RTlW$_3yOAuo5I;r&l(kv z@!v!|eUOVm9Ei{@J9N|*@pxz6G)$+6P^;pv7xD2~w7-8s-U!6BcD5-JiJZ|@cedBxKGo}uC;h;Cs4rc4po)O> zm9|-p?%S5xW*z6fPV!#IzwJFGuM8M>het3v8nCz$A;6ljC#%D%+syUgc= z1MWmN7-w(v`8N47xLC{dMb5Em`><{6Da-!Mwg2lzo@8m$fZzd>iuW%TOYx5sM_=#D zwg795wSX-m7g$z*;gMX$f!O8}Hd{Yqx<21-%d%aY!ztN3r$XHtS#DdfmCkqLbDm`& z7ifD9Mji=LpJy|E(uF+_J>yhq%4AD=r$L^?{EReZ(r=hc9mj-NG00{O2=$NlFZ}Q!5ZuFT=zPCf(+gf`g`tPz@ zqQ+&JbC>&9xXx0i$jauR>})IJ8J{m4wqg(a20Hoc?Y?gGdb`@1ewCf;=3ZkDqhHcw z_vb+N$gk`%x7ayIvD@sy)+?rSHhru)&P0du6bwCN+j;xnX@_pIeHC_I@m+T479?j_ z<_&h}3OjbCJ%77x5A)q@hZ=3)|E&Hu*^y^#?|Ap0amw#wrgfOrWC_Qw-Ly`y<^(5% zt1Rl@oXF4|uhE-})pwXqnLWuJ89BNXVTVU;ktRF513$*i@nkU)r)R`r2%tJ;A@t%=UK4oFg`P z++$jgT09ZuHrd4(t<1@?&o>$B$O;tuZ?hax5ql^Q~6u+PIS=yjvtUCU-GO2x?eT|Sp=5PP`bFy<;+AJ2Fk9N)$ni*|Mp9c71d=~ZoCgeN7T|nFIQREho z+I}tU%5GDa%s)*oo6V^nj-OdF!jD>ujmIM88!i7PF2c+4m59|I$Hx!lG7cO1E116_>OovLR881Z2@3;I9pi*C{ zQe8r&14SkfT9jU!;nex|GV;gZQ=s)4`4ww7L2AA^Pjpe=4qUc~BOi1txN5m*8PTwy z`am=s4MrrPf|;^i*2|Xh*GSb?%l|YN&bW^AZan->ysyt;BbxJ8Jp8wKU-9i5@$lgN@G&QB4|K!6ia^+35ef$@!r_c5Ub<>{NJKplTzsO3i3ABC--;?%R|0DW!G|#>_tgSw?#aFV`dp6!?8@ET7Tx$ET zu(6&ct@pI)yzZ&DL|9Ky8}Tcpeyibb;Imink?#ig1Fc^R^7CN5+JB?P+Dz6jU#yc1`zc)t^jbTeRvf+kcPku86pq%OhWuhW}Su zbh~K}i=5%-$Qr-2<}Xc-%Tg7`b&Bi=6{jd*+Y#IESoR2^HT%M^R{4)ky1n=h@>k$H zp!LrAjx(}AYI`xTtA63Zi^N4UIn@WCc%|2-o@cxkEq~PZKW@7L=Y!JlKTC^bGj@8S z84FRtYlL30MyXdloVvZg82K7-J0^AK(5DEw3JeBXp9#p5L8?Blb)^q|W8K8;sno7$`J1-?tuB;mSNb%AFcWBfmLi`H zQuW!O_7Um_OozXQeGc=^WiF^bgraniR|g(8jrFmruWbLfwmY73Z3V|gXWM!C`}?_G zz&}+t#Yx4#za4dLGoPX#wCR=_@oS~Nt>_ZxvuIa7K>jcI0%(0p4A-avsrB`WuIj5+ z_Dqyr=_z|T3r1p9mpc9{oY25*l+73r`9*2?`qH9lcHYQg{b z3+FnnJ%CoTE>PqbgX@I0>t#CMO7f$3lb&zD4?qNw)=uMGa-3&NR@D26(XQgDnnW1 zDJEI-*-|&0Ifs6qN~^pZJlZ-5wqQn`Gx_= zBfw~&%i&C95$;LZKdkFJ!;xn!ST&m^18grB4~_=&$n(T#^=Zb2Y`J?`oJ=8*YcUkb z4k_>&YPz&5j7_9168*kbl`^L@5EG|)$EJND<%-}Tvc*rl=;IvI!f z-I5ujICjw&?&m9ya@$4J--qEw!}!W_Mp>)GU`NAEG97j3Nq^2u$D_#4gO`9V4~0J0 zs08o7FUx_U&c|EWso%a*TGSiMQcoD2*nxxPAHA;!4WECS7_RQ(kIPRwi36I1IhxF` zKFX8{N1(;RvpOR%9WNgQ=FCP7q#!_R?O@}mnD~>gq(oiKRpx(&IuP~ z9AY%yBJH#e8|eP(J;;xPr+~K8KaoEN`;>^<#X3)Ar;1MF;hpT1)TwTW%4rXB&UbS!7u|i((%Zk@2zFQL)=I&PC+qzKK>zI4{pzHo(>B8%*nR(;6sJvzXLe zYPqVX@Nty;^t<{oMrCs z+s_~IA7}Xn9Uhp<>8)p2GkJE^n)~~Y$vW4cQ{)?E&**cxIWpUKfmxX4AL$?DKMpIs zYdWlO*=$=arggn(U13?P>|dJhXsgb8$+R|^_8(368`H`Y`_ul;tt93|E>z2KgT8tS z$fXf!UZeglY2VG*PM42ABJTwM2HL*G0oND`=Bo7yo7Fhsl1}~EH047(HBEsFos9vr zDexQ1dn@o>^EY}HzRYjDmA8^pdGo%BL>i+uXBp&K;madp^e_AS%-c-vJdOn2Us-l} zfzR=74tbhIH{$FSjt=$aT9_Uc_r~?Nuako;B8~T|@{jIuK8p5k1M^2|v&Urnduq|?q6yGuuqJ0py5 z^J6?&I3vpKC=YEa{zl@86OXXhy~ta@6F}SRMPw0H-5~AMv1%4xAd6Iy&W8? z%=MM>Ccm1a(WK7Pgv(%V^)$(1;Xr@e>o_0E4MvBcNy~#$k0yBH5D9yZ^3sGNhoi`3PmzaMLx3VaD)}(2$WNR)VUUK0q#p5bq8#s!Tmz;75k$VH z_7io!ca-0$%TE<&LV4GCveA1Nc(TA}6?-vIz7)>};?#b?J;?8Yoj|t-uVuQ1FT(R= zuzZfR{#w4jmAB`5P;VK$&i?Xt=WFLv$82|=x4gIQ^3x0Q(*W-P?-$k;XjO24nSAU+y!^Awx zhw`_7jm0{o!OT`%Y+jP(UY3CU&?Pkjui%>_$Z?00JcPY zzQW@R{e`R8uCqTFNoIdyI#b0|zz9w%Uuc~vX2=hT-fCvgwC*ykqxfni8?J|&&zP*> zj`Zgr%)z}Y#hKe`x@Eptpv?b*8FGUshs!dKij-yEV8*hdJIw5|tXOVY&SPf2n|E?y zS;1{)-?BbqVs_Zh@I|SeUTA(?ma`4ytnDfzJOnN!4|@Dq+iJ{c?rx?Y}-EW+AHWjnP{t((;KV#)k77tLHq^R$$WjCu^Z z(H!Zyf)`4Uu!T3_vTm@AoB9kyiAnA(E7x2QI7T>m^SJW>YP@6)!*_q2K*)p0|R(wI9m*4Z1ywHeRL z+cOHh56Q2mc;Ea&T*}&HAMCwe>3VNBboEb?|M?~IM-{bJ{p@guwAek2p3r79>=tq-{h5}x zoVl>DKkpgq%p%v#4pG@6S6K53GYW%+zYr_QZV-j*Ta%+52AHg{9AJKIIs>U;MSfn* z3*?74OfkXv5zAUl4kj0WKGpm4Xz!;-2O^>@9LE+#zugw37KW*XkD08S4Tt+@v;;(% z5Fz%0EEl`Ub1`lt%0*eWYm5YAfi4%zkuLy_DzE#f_bb-#SuR%5-k&5`OZ5M5ln zHNJA$QfZ_8oqM%yHrjbtd)e~1-?*=6gtd=*I6cQoXTSja-jMx9=rA|i?wdQ;%07V4 z8SSB2?#<@N{jI4X-_U`X{sMeVF+4NE`p~q#G{xn8uhDrHU(vI+xq$N{)3vP(|AW#o zX?;p_-0Xz-ZGD~ zPITSTi;GXT_-YDYwU}-;PG|-*h?(bE7qCV@9GJ}Vh+=C@IA#rHJ^NfChsNf{>6}$q zGr985Z%y7ef4>8B_Q??!|M`k}?dQwoHP093HPh$t>dVYKdXq^fub?E@KdXOc$xOfH z^)}u#9Sn+P>7k#+@mSVxO_p!)+$po$Om~=BW{(I|S|?hS{-d1n_KIM2?%+P}n#E%? z?l2>jW#oYoe^c7KHaF33&qrPX&H}nz8F{WT2;7q^?YuBwzRyZ2S7K2Dg-RH{$=Q*) z(J`Bx@9d49buY*^9*B?P$yj6uzKUkMSzkv_W=Yo=XFU54J~z$d-A~MnMW!z|>j(ZC zwxVB0vl$-C2}Bw9;>J^c`LJmpYx**re3#8`)9tB_ug{^DWu5N$K8o6T6L&>J=f`{v zv6+91G6}(_AELf{VmuxF{%@lGPsG+%u>e$*zUM44j>H0lIo1S5S9sfDS`C(UtaY08 z3)5O}W&I>JUewLiR)6!~evTl0&1K|vBB$;9?3n?vs)aSOW*$$^D(qPOuC(I@Y^2A3 zb|c5~T_X=@JN^SXv%oc$#HIb(ZGR&cF{LMdd%p4YhzW1^ z_rKde+x30e-@mheC{P=#EZ~yu%S=CO2{w@8LC!uFr7iRGQu6P!(t(t9zsVL|2AM|t zf+1fh^uJQEScJdTcz-MK{&tWrE5CxZ8hNzkBNp3B!U1t0)#GMhynC{HuNAq%v`)$E zA3QZDb8&Eq&&fW;UgrCz)XuBQ@ z(tl;#zccQC#4PqVs@XB-oSwC;3oYv$i(d`l{MzLXr^Su4CYkqIzWc1uE{lVSPZdk+ zgdabFL==#d>o|9ui*A-O<=;Q}s2Lue@kj=%Ols6B6A~E8G|vjzS$A4tQL0`O&5;-C z{;l$#yw&}mdy%(+=Yh`u35B$4AfV16o2Awbu6=UP{AUHcct-2hg01FP*305H<5s`- zHuzVb?ooD#Ed%p#5#wdUJVXQ9oYysyaR<8teGthLl!;=kGq`!XWoK*p>P zwNL%Wzm(x~X}4Bv66YK7T>B9D3-CSAcFXPK8pR;huV3}up8mGnFQ&>n#XYBbG7}&< zpoB?~c54Vj>2+*`=b+(tL+(2vznj5QxZI%EoU)g~o8lkB=BhfBAv7ud>fzSU-3yVg z0yhAy-!sTBftKG&ea=zmzV1rdU&CPmryMBiF}fAh&t)#a8~Vw@{n5gztFdBx3*ixA8@9E)-vZ;-uYH5 zoMGmfiThF8|0ng?3||aBk-v{4KL`E zo_fa0Ra3ki^iBs@Gf(8;Q;Z_nRbQFGZ_QkW4B?;3qmJ`#g(_HxyX?`Y?n|l97Pv&` zPT1ph@P0(St-|2yO#=U;KgY3cZH z?V7*lJINm?P523M2(fsQl!CtK?^G2id+Hv1q}fr3|x?2VA7} z0~cwTt=6UP%S^hoTjOY=_owr>%jD%zmPrN2t+)O7Movi}?@iP9S2IGP7MDp@F*_J4 z8CX!nC?#uczcGE^vJ&$Mr^RLIkvMGP4(cKcg*n$~c-B-fbE zDfT#btk0Y997oeGX_pnynW5esQV!#TNINH(PzM$mJHR7+w?R$YEi0Ihe-&+6|`B z7@B64iT%6oknhdlQ@HPgW@Lwk#bU)pR%xK{3fFh1o3q(izIvGx(Gd*~KT^=dQBacsU9`P1y4Pw93529|g_@sW@;nw|%w~_w? zJ_lOAV7Y5#f$Eg`jD_j-V~}>4w+^qMW(qa=bP)Gy^B1P^Kt|QoA?Ft%l(QHeXC zBGHRD*}1?|O`Lblnl2SuT&dp@!OeG~-Mt3+4)6%j`UU#q-vHgd=;!CQlzCv;zU{eq z^NiE>=nd5^$C!P=t0pf~J*yr=nTk-Rwwf%+x{Ur&#-Mvc&O@P4u}FpOh5}BmlNqv| zY&*&+OBwN?zwfLug_b`YdM?N`{qA7!s!IF2;hfO(WH7Wf6nUE8;(pS1FQ_iUGU5=d z1G(o?Hfth#hAPV6nGC@O8KB@chHxZfsWePuK-#5&G;2TadgM*u_dwfaH?mQ|++NE5 z(u$ONC+(u<#W_RjGI7w)ji#4pC(+>8z@mcroD43p3)*bQx+y&9%aHSRC>qEYQ{ExR zW|XDS{-5Lj+Ob~u`PzNHPkn)FL-uV>?uWi$tBb`;i zkH-oyejVU2onUS_nBndCY75GAE+GwZmH+1=UjeQGI-PeS-v?6b&#JWLbNaI7^SwFz znsFra#E#PWmT5F+R$Uo()`vyD_Mvq4lcjT>vr=d)3a41cYP5u;UPfiY{#D5Pfw@5I zwGH`2kZS*LjXmcXr2Wc)e{u7mc)soHtC4e1FxX#kAQaW4RfDf&eQZpN=@Mv*p|S zNxK>P)U^M@i4NWmh`|1dvbhksawrOW)5SMF^56;b1B>h zgosysiiTo#bYd=Y-sfK3ZVyZQ)l?<&^+@E?z)GO)cO&v`AT?jtrp?!x@}e)MqfBpp zY#{IXpa97B=RwQ3J5qH?X7H*^)?k~C>*uPV={ec1D;i722ny`NaFIBsVWIP^YL9{@ zi@j8+j!3=R(J9V%qCE-^aE$^`3`F9@j|U=)kgB)NTAAM*9D>S=R%l18dI;UV6TEI8 zCxf=K5x~b;5GRO|cc^oucxzMq^~A5+>r0Uv!Fr(iZ$}m(wY}bxKbbtI{!k9nYUfO= zosq->qhX?_cYwFF$cwKwD$~E4_;q_68|WItz$l>eZ8q|Jpxa|Tznc5Qo__L~;;fZq zHCWEJf%ys+vXy$T)!wUE+a~%xFWN>sR*7&GZX{grPNws5W=5dg9b^~9MwU*`Iw33_ zQtKp+J+H7%7Zy8?GWnm5{EKHv{kNc7oD_-tdl9(}{1a&XGY9cJ0jc@7K7F}cdFWEn zVJ`4WT^^;a9GvB~o_ATS^BwftNbunZ^9O8J;CbQTO#7lfC)dyQo0E$oT&h!4hOQ5q z&N89%Al$SsMOGTM*;3z^INwI=y9B*X0n35bSNwJjpHutww<~?wQ`s)|RmOauMx4)> z_+mYSW3o0;#lM|@tK(u(n?J4VPWqmwke!bp6fWz1-&lMTq`Hh3U*G%a= z{!?@~ZCc(o(|9Sy86##Oe+`f6JXZZ=(bnd?8qIDG1wU}?&2i_Bcow%e=U5Xm2K#)z zp?;sp>3ywd#8k{uI+h!~@rqY1#tw*-g+)Ya)aA?c)uFqtXJ;W_0&WC4eQn5JfgLe= zgoJJCeRo&sV;#B}er5T`?|t4{k0D~MN4vF#6vY|yVcC)2{?0OP%^D|?<%Ss{|2`VJ z(igne7r(|AxQgvK)Fk2G3Y$B9qP4bz@a?HxW~G%4OW#H-u)tB`*Q zHUXXQPa^*Tq_*#yQ|7N_xjqbE@}ytf^S) zwFORX-`9}e2JZu{*KTBEL}$HT+pAtjEma+mMIDO$%QPO(sk$-SY4Q}S)QVl1q!>eX zjs2uvwQ%b4wix;6;6kAFx*z!wkXr8FPpen0oNp0Nrn=*3d#8aCa8^e<%>9D@$r<#= z?BFZeA!ZDR+FVX-W#smAeLSV2(bB$?M?^TJA!}%XQ#6i@KGwOuqcwgGrDCO0??82; zohm{eB0dAHcP;X9V3j(TK;QGcE3MvKsVj7DHXmcMngz$h#8TsS>r$>#&J#nJ?69?c zm*+a`bEBLOb2x)zm3DE^C&pX{Gc)%bI4Fd@^eC`;=e4-rLP$JE;N%@vu z^hRBow8s|s^z)?^`7Q7c(E5Cd{NwttBKnAqp|d^p`J#LJ)RaqoYDXpN<;lorg0q1x zN7p0Y3R2q(C+++Tb`tBw^iaeR80uo_I(=;#S8#z5w>*B7>+H%6Gk3s(j10dsPg-k* z<+W@3P=uZqwy5bZ^=pSa&Sz160;63c2NVLW-zen$Kx+NW?MlCdD>@bJ&i1mg%``Sk zEl6s$WG{`st=t zEK_|{+U{4Du}!LXTVC+jd9E9?GW|{{Ov7P0lS47fj#}9<%gXVwKGQA;anDakRLrBe z!Bade_QC8QD7|YdrQS9BB=r6%@_cX-5I+;T{|s4#RJ}XZ3%#H1Fdp=Bs*Otr{=>3b zuTlh9xXt}$p4VDM&qNL)6K|W+V>>*$KlvW=SKxb~^%yut>hZqX?|H=od-^jS^)sm} zSIjK-IG;tnZ$$nLXa+jpKR|8=srK8at9Rn`%Sb~!#+>aiW38hC{L{*L@9u*N0qcOr5T-f+|AcYf!4zaM8kJYwF& zlAMy#5^;U$wWhP)GS6a&Mm!Y75KR+0Q0g2;Co_ZZnjDvg9x4oz_SivMb^qu;$j*4z z;M~iO@>GIc1ybALY3a+8THYl#&CJ*+jvKm#Z~+S9RmxYTbo+*-dYkek3=K$rKIk^cr#^_!hmKfQ3WZVeryd7u>B zWX=;AHU)p^6U+EVUvaH?f0*qo}awc%xpe_|rvI zPKYH2(clTLH&T3* zm_I*c{;CB_c*c}AS#=vNv&p*F+UPmNx7fx##Rsr@_cE`;dm_gSjbttJNXy&i*)m${ zVeFR}|BWD*f(oGX^JmD{fNf7pen;uEF2zrqy1ZWO563OPS8m7H=}5nPYrtsfH{qAX z!A-@vT#b->Z*lP9Vvbhl6oV|5Zf3H&CK8Gba0X^OZXnz08#^x}vTA9&dWu+CF z(Hv{apxnW}=wWt^8P3S}O)rcW6p5B#zQr=LpIGxaMDZcho?$O_&J2rIM4M+-741p!eZ_8Ci5^+zy4|) zZ^WytDmUT=-C*ES&T}#cGtKM$C+hxK77m_j&9crD&%CyMr9SoW>H2>@@;Yz@(E4mZ z79q9%>vAac;Sr6=bLx-q#yw9pZYq=Gp8JW%!@lye@7f6}{lurs+gHfG{n_&aG+$q2 z5n{K=bnEq0DSSsSTmtH|_leh|HvS$RYC;D}nFv4h3ueNZEwT@xxvQp#;&-wjS zy5Z63z83kH;0~b6oA_-jpO>iTrC!GpPFWx6J*N&kDY1ZW(aHt$S&EB63aZbeK2GF( zQ3ivV?pkWRglfT0SfSMKO*i;VDU&@(^I2O;%l_&Xn$|~dk;ttP)<84J?X%vDmCZ$^ zW~I=nW}?);dQw9FNyvwSqk-0c1@gJz+gtXu*bQH#& z-X%143*N~S({6W0E$e8fpWR=st`esjFOzni?y1S|jk^7%e%s;J_I(}s9q<9r`TPa4 z2&ww%d_Hv1S;B<1-ZeKeZ$HMnFBj?zat^Xp-cDm4`AD6&BEH&5lE3x<)(G%fw69B$ zF9FvBZJ)Q0zXD4}Qg#W|h4TGRDf=L0KV-hQX~^3!RN8JmZGLK*?bh{{_x7ax^ckN- zHDn~mvCHV2eBv4pmyff?h4M`Q^<|m2mIdz3cOJ+uw1fBN+s*m5)t4>r{i2cVKKGY7 z50_u;r7TAZ9g(Y#qe#-#`{Zj(6#be?VQu6_@YApy21=rmXtHnQpAp< z{Kfe;|3#uV7xZFO9xj;D1GbcbM-8zB`(-a*=6`Vl5qKRS&jzxMUxlc)#hTkAdR>YJ>2h(Gh(m_Ir?+n@D}nd{FXeT4W=Wd1diH~KmD6!MGUO`!8HV=D7L;BnQ@*ZH?C zW&NEvpIp1f7l;9v5uS&13gtP(DEbk`wu&lN;N-Ac(y}uw>%l^2TVd##!oW7Ra*0_- zoBloDXIK&DgBZmkO=F#yb)nZuKZQ;@S9Y66aG#9SdkH#ez0XFz1Y8HS-oHbB5~S+= zP#V1xLk<@T&9gntmnqH17(12bHamp^e<^g@3PW!f2HFby_`(#R4ow#em6s_+#|RsX z(4zD$oR+A+!;tp{2Li3{V&v1o`deka)pou;jlRi4IM)h|`*|9ltu(GN)>cYe3yljt z7hXi@o5H}ip2pFH#^-ysJzJ?<A=TKjM!a*CH6AnTS7c{d=FI)6z_F<3nH2IK+zwr>M zPc3{ils*fPPX#N0)@MDk2(LXa^+=~r#}HwY`I=IPI9P1>7>#)=X9-7yS5qUjkje?nZtPG^+gS z7;jGTqZXXGN>$@V^JY2k?8vERdIhgkR^3^Vb$5ll+kCb&l)K8vF@_3F)&O~-u2$+3 zI4Ge{ALKz`IMDj+hdd3W>a#GVyrYkH>e49mR%O+1E3zKii$c|hOMN!LrR{Ss@)O`` zp!Infc?U?pqj zR*1EvDzq!TTHw@ndL8+n;A5cm`V!fg*;y~AbG~7sj+V92ynPQly~sRTW!1|SS+7)F zq0}0au+uM0qvc3xr&_qQJ|`ic3C;#upLNLBfK)rJ>a342QIbM;NrlR#o&IeaYpbf> ztjKz+g6^4TrwP_k+D@D&r9$&;sngcMcGgRjr@bn6PgT|Vm04>m_oi6Q9I4m%SqZ&rk?X)Bp!HgTd^YH$SLgim z9&^cxy}F0RzBP@9tEw)q%(|-b_sU}P6Bc_`S*+$5saGqU+Fm=6cZ2VM)+=-fb3Pzd zuYEe(ORCiI5NT^jetEi!J3|s5w^ZwFFMBSA*aO z*8{EBCgk6U?^B+46`l3+9>aUJ*9%ou8!NLm?bTk#Nxh6i6M7XQ4+O)2)@uUtRFJCI zw9a}-l{z{JY3%h{Rn=XUS@-PKUUQ{h8{pLT`VI2K;P*i5^=IU_z|Lmbf7+?`N!{ML zd~q5s`x-qz?L@q-!{&+S%&VsHkE$xC*opkUGV(%YWw6jHa&pAFma)u7ms@eswX0>J z8uy!v5IADkJY!j`N3|IKvS zPG%h-yU5}=vqEdYzbhl3Rc5j}HJ5d!=X-AXB&*CinMFjSgZG0x=nzwS z-hg~7*aSp161v`jEP@^n+kTTU(oyab&9W@ z_%xsYaK^wvKG1xn$lc`|g^D@V1H1`K!C7Zims@?(yk#CQy|SN*p4nzrC}`r?iIR5?@oL`X$g9CQK=Yo5++ALrR4yi-2(Pg64C6!` zn#q>RSH-uT_%z?!$UDI&K=XZy++99-5%PG&H_ccwP3(G;e9ek){E-R1!;t5Ixj^&H zL+&o$xRmsrmXtnYfwbpl;?wEdio6~C3245Tk-N*scm(#Gpwc(pST&uc!YX~WiZ4Dp z!8Z>1AaFF$?Z>&umxA$Xyro_3FT5gUJTtj|?kmcV^daRGqA0wla{*V-8sH0ZAHWI5 z1?EU=1jp(IA1h)}d+@zz)GFLk#6)V~9YhYh%=9+eUTCrdx!fKmO5N$~HV$&UB^MX_ zPcZ5iN_*`bZmRJi0_nQ#*udfYQUnG3$$r@AKHt z$&JpU?u*c-^r(YJ>v1OXCEyC6^|%dLgl{*?cI}?K_iW$fITRhFTw?X1b+u(Sa_HLC zjQ{SkHaf-y@v+Wi9%FxCgSxrM$DvB1r+b{Zm}I^4ys!*wIetU;pTtz@aJs;7##Ud1b(OFu`x3fu}b z@4f2px}DeWy1m!;2G^Eg{ENjz%t$6;HktEYG7ovt%zDWj`67kFnfG+&Ax~vyJ)Jr7 zDRHpbcvfJDvO>RqiA;aHGA&ZwYbha&RGXBUle~x^F-hq3iOfPPiSEIN~;^W;%mv z{sa6qQ7mwl;V^|Uj*-@Uq5o2u&NkxJyt|Qob65`mG;bJr@4Vs$vTl+RQM2NmL%f=I z4RQlm3pDQ~$mw{+{O<7KOXja!GF+RSlPtWOsMKVCPVIuj0;KonhVyf=9=p=&L#3-e zS*CY8@oL@=kv|6iQCuQlcc-jJk$j6z?}}|4OydlPCR&Di#Zz-kqW&C>TnA1Dx_w-U zyc(pQ4;@IE4;whxD@z^MVrIswX_xb19r}{#yl7S!&d^&;=a&e^B!`?8+slw!l^!i{ z=z9DH@_XPzpzZuIvIwbqXybP9tMym4hf<~dhxuzokvh+C&SMnCiF-xLi>LM!Y3K3B zCU|Ef&j*Wu=3Ro^E#Bm%-Z@>fw<_Ld;??Q>Bk~UL7SOzJBX^g#V`+ESv_|bRncjiN zCCb%gwkh5w;??E(_sGwH z?LhPX2{|2antG(S=Q7KAt;zXko7lE!IDl^Q@l>Lah^OgPncl*=3Eq*&lfYDhin+`DUvI*8`zN}IB%ysVZePRc>uJlsS3GURsqOkb zvUvi}0w99mS=Yt6oqL|k+fjJ?z|zNX`WSU8{u<)a>6nW=4=hNEzkBIWODvMo(4gXP zN{at+=ea!%2$2NyTr>OX%MZISwj-womu;*Z0&V2wGJ9bxHAGfP4|Sw8!y# zEmmg|lx$Nx+mm?SNB$7}tH(V0j^?DYbh<3B1M3oYnvOgZ90Gb~C;326F0FAD|GK33 z??S!@H1|0E-a4Cf06m@kq3D|1W_Lv*2{i)YX5W3`q0t1Rb#1Y z!>KmvRs6NYRZl!3{#D3lfwPn1AFs}@?N0n1hu@EZWsKqA4;#&jXA5!adi@vVzk+`x z@pP|VCobLUsMv6b(5iUiCnk6%A|C*z0uj33eyHh z9nqb{WD;!9s(8jPN~Gf`uq}^`YAd5|nLLJjRklJ@1EH0R{p(s$M-Gf-FKe`rBeisKZB}l3d}T%Me?o`n|-f+sEsWZvwXh&3hZN2&v~hck3Z3XD*hVc(&?FtJP#~LiofgjJ`sQC-ZlB8;%_1@ zt^Z@lPk^VA;_r_BoqN}`V=8{*Gsrc)X;y)Yt=iq`K#-Fa^ z8#_amrseQxbNXf_xyD33_6uG`(x?iI(YDmlXf)$ajL@ z^f3O;y=$K9D*l~G@%xvt9t1={PxSA)ca1--cxs8Wj!4CGWf}5vuri6K>;843K6LI~ z8%B$YznQq|Rs63YzYg9^iofgrb!z5m@sB?(5&sQO)4q1@O*7u5;y0EvUW?MAycQvsfO4SIF}F*9 zFpd$Z{{rNTz@ zcs@e@1hn^#M-{8dq-L_=Octr39Z@{h^@)3*jzXRT<^mB!y@;uEG&}pZozf$Crt@s& zA11h36we0Yj1!-*TQl;5;E^PruKTA6p3Ytl`J&?AOyd8&H}^dL6z_(1L&d*?xZ)@)%Fln1cY)nW@pq^EboOp& zH&p!NS0>`0gM1vA2ef^<_6L&6XP4d$&pXA_l*IEi^0VOi9`bbU-B2GCPheFdJwuR( zgHfO->FL_LA(l0=Uept(t{08S*MS?7c)C-ry7q3UABv}qICcH@oxwT)5ChuJ$UzpN z2ma0UrK=Y$964${4MbP73X~7UUq}3!|3c)ez;!_L-+(MaxBZ+X_JZ2Q%q|S~W)~h| zb^)+XWiHoBhK#zONjvW#er@OP1@D>oJwSx+`8}F2z5mmocxs4Kr*k3lVsJ_l&yPQ! z6FlkspeDt$nK*TNUO;{k{5gr|$IDF;kKEANF(x8x(xP}`XC-(>A&&w30ug#@w{(6{ zo8noW#B($9tzc6xdD8hu#@VtQv?cKbR=Y+9h=SgvXK#K|T=CTsx6Y>($Y+2xz2r;h zFV!fXElE6YA-@gY>m^S*zo|~~#MdO!a}e@Rz@eZw_S>8P)S&npiMx)-#dGT+`BkxVWO;8*;`t2uf8eWL@}%>xsuj=pvlHdwc;q^;5NP}Lq&-UKXVog6rX-&2 z$bSSc_mXFC{#L!>i=C6mr%}jbz`j7It0(!C&hKheJgbRwHIa&Pelzl|U{ey$kNaJT z@|Vv4YE?XK#HszS(7DX}fGnWX^W*+k3Qre)SnOO`{%VO^^Q}QX2Q>V@<4fz0)hWIf z5x=tIzmeO)t|Y!6_s2S=FRfqJtoW*bp6DmmA|DBk2HKuK-mgyZrSs2P70(9Z)a}Ki z$d7}TB%Yp>!*qUHyW%mwC$Q&Tp$$ zJgrGQpCf+(zV1Cw%Ip;Lkcww~L&9!zk>`O0pf`3SJ)Qixdd1U3oN*!*?Zi{a+raiD zo}QGqbpBkU;t8Ce;HgF)4aNbTo*(z;lFId7{JLhvw>pV$6Y?G4u3qx(&A)3^d^?l) zaxP%L5A+4SN#EZ5ymrMmhq!e=umSl(a7hwhPwLg){Jq$D>bXzcy1m$i{0;a4Xn)JP zP^PuV{+`$r(6zf~G%EgD;@A8ukk17d0L_0fvIsr&_XPXi+&!bVL8gB@@oRhk8@V0q zQk*^UTgIk$_l$bQQ@u8k&Lfe33XTOL2%he?%kZRg_l!oxvw=8udLBi79JD0ybhrEn zo;2>B(X4okixNC#$Q589(CO&`PdazcXjME*l6Wpdz7ky1JD#-eUc2IHP2%|y`D^ff z?|Am+?isQ3Wx1=lIAOo}$P2*|&D)Y{N%6E1r}p!L>lg7-;+TpnXW^<{34LXI&D{{m2i1hkM7fH#g6yQ+&ILTjx`s%eV^z#DPv% z5ArFUn`bmAo;u=OO{AinUx0iOxHO5UyM7+!FP)obv?!kK#HszR|03@KyOVgj>*r~n zF5EoBxKNhA@s}s~>W~+J#X#Gy=X`11Jfl|eZ6@vpWyjZ${{sG&#MfOvFOj~qZl2Mk z__%AUqu)Iac>Uf3<2n`hK1o^`|-CsNT)Y)1YKxIc-f2jwlDn`bmAp7tc3f~)a? zKnc+4>8_tA%Jp8{JflhR)e*N&*QLl;fX3eO?aj@jZ!F7SYZBkr$ln38u~+Hao115} zDZU!w*5!RM^2y+|B)%ThtG&5-94V)s`^2r=i?@*910MqIXMKz;LQnlX?>3FS_<0SA zfBZEG{$r6Bfs=veKMh%gp80w5E|0xT>lrl{%k(!Bzqa@5$UDGWin9lP-sn+X_<41T zr|{ZDI`>1K1f~EHdf?{?p0s{mgW_o*PMx0HkZ%W@lX$vWemtIZeqNK}*_p%>ypDb_ zhyk6R9`K~~^I8;7t%#RMMLV_v`3$h8cRXqRyf($NC5h*4+aT+f5l)i@{|{Jl*v3MEOqZ=QS#x?ZjEHc>asL3+ztf>878T;OWB8YgK&Xf01Y( z<|5An3xEhcY#-A4dF_g)DT(JPGe%t`45A{JeI>7r!yVHv{=#a2U|`>p5R~ zKdYCyMf3>d+|8(R`5&`UpM`{r1Yit^BNVOaZ{pyT8dl_s(?;kH~Za!FRh=~ ztaz3Xr!I%B=P)!Z2gjR(11=)H~l=XT<^`#YgBwQh+C)YbmUcF zb?^B0>gP2pzAZ_7?;`&beAGL>z502rif`bpiSlt6@)6*tK-;qi<$bSyUc2IJB5vJY zJcIlKcnN4f>(9s{^wiH2XPNEA%`@sRm-Q~bF~L6>c@{VvX#S&+Md+EI=bfasH#g6y zzC!YEAb#DBJ&wE;Jfk>!;OFhrg_~#8DjuULkEJ!#!LBX*@M*Y!y}*CJmJZtN9L zTKCSVRy;eBc)ko8oCm;%P$u z6}YokJZarK!?;S8yPd?T+nuXx~&WJ0XTH@3^XCkiw=k|&xy?a-q zc(xFyem?F%{u_8ZiKqMdlh&;>>J(4>*9pIFGV(Mq18BQ-)32i(q;>0zCdIRkIJIBb zjQk*YB#Eb+ewOCx%B?fn6yNS7zS2AKdq5S?>FP0GdbiG~zFL;QCB)r8@`gMu)rFZL$2F167xZ{fN3*@iBcS(HR>}SKbr(4&g;vc^`QT~obJ{Ft+MCe(+ zA+0-Sv?!h?;?(tNEArFe4@o@TueWL4IipSS1nx@k3`HIRMgyIm?(?K|=hz^vo_|R^ z*C4M48+yyr*_|`uif2a>&)3M`0rT!&rl+$zXVfU38sdy&BvG#CA)g3NO5*8$IZNx# zaj&wp+vX&mmyrJqUQgobravdjb6R(!lTrzwf&56I7h7kkH( z){(1GJb~XP{J0^=!@($^)6-2qPSm5cj$FOssVB~QA{Ece8h zim#2hb^G8vz#RY}1L$=1pnXW|$h9h-8N{i1mLe|$^}XXs>&Ue$o@V0I_31U_zkt6b z@pSX~CG3~hk&CUD<-72~1kVA;Q^0hf?bZXH^p2bt6Xy#lzIDW{?ROXQJ)k*>uLt>* z)}gCaJnh7}8g5bkvLE8?OV9`Cbam686ZT8%&^0QaImD^`x$}|NiqAp#k2Y#L4N$c1(E1uQFsq66uq;>4t70(Rf)af}H`BZRvuX#EFn55E1tqFiSjlcc|ULf(01!Vc}wfq)heEbB%V8w?*{iJ@pRMQ^2&8u z$IjE3^NSQ;dlFxtM_Km{;y|aX2Yh>V@ER3gors^vMZLWY`ATq2@A&rW;5940R^ry> z@Jr;c!S_jgJt*(#9X!ucoFAz8W;~W?FHS*T0nP;4&su{lLQnm?@iaGko2RS2LDq-u z#IK*5A0h7oUjfbk9kK{L^YaAzUfnz+wn6gO{61mtg~*G+DL{lC_(kKpaPy36#j}|> zbvj=_ei8gRiKmPU6{sd^6bCE1tA& zp3$gy+LCz8Czt~Q0nqdGq;>O*X2mmuICZ@{4f%9%Mz46%yLqjOr#XqI75P>0mtOIt zckkL2PvMh^^h`kBA4~>4w_95G&WPP8>rX=x&mG8{!9Bg=N$cJj)rw~)an_-{Xoo{v z84m(kK&Pjh{vGuvt$SzGDV|#5tXDj%k^dj&-aEd^BKre=W}bHMb88AIq}@!k<-TTPN{d~HG;Qn7rq3& zANV#xUi;gHn8Q1z(UFte7?v|0^y$E4K-#bUa$*kelx9ax9eB!m^cd(Tfxkz{X=nch z`^6mIDavia?~X>u$$TDjKR{PN=BNE~Vh`^^j+_$kl;u+k`byxM2s!PyTg+jdQsl_l z0iLU%Jo)!GpuYzWMaXIAxDIxUIjmD^9XSOrgvWK$LC*r_0@7~n9M?%XZ4K*`Mn_(K zguGWlzYe_p|3+TyVVx4ZUHC=t#qhXp2SVo#VQ2{$da7uwT$=|G+y0=2UKX zfxZX0KSEwR<7~)lJ*=yB_&0->^uOOg^Ovv>4v_h2zyHM?&MEbdobli(>+J&2=K;$i zA&XqWFwnxZm2K^=Q^&gUR!eN|J>&VM}HJqq z?a$W!hKwX5Kw%eg7IkAT?igKr@Pfg${?RF6KVc@3-Iql9* z?BR@s~ z=ntH9eqs+_lv+nlRfL=kpl<|j`6F^-4_}meN6xMYIX{E`m1Ml}2l5kp_@XpAa*DuH z`t>}}6~LkhIqmlA*x|R*?8w;?A?H=luLE!Y5jnBLZ$-JwiGSV<`$1pO1AsxmN&7(? z;djW9vnoQ)ouKQ1&3{Br?C@JDa^y6Fr!1e}K=Zc{{{S*S?Jl3#;kQ!a$QciwtH6}{ zy@j9`1C+Q|%k3A^hb{`qclj;C z%dkQ{iHP(=pU!Lf9^m^^k3OGW)zC%KDL$msyOJ54Ze~fn%gl6?ApmgqvWy?$F zSL7F0+Kv;t1p3B)1-Gq#$vvVzPe*=ae!m6%Z{Qa|=JyzAN^P#k{QoJpqj1fB!DM=E z@eR0UAHZwJM{=)fAp`e{{1$x>_M>w_mjLAeB`V*x{iv#@`UE4Vki)+oyrez<0s2|s zg$Vv__aiO*V~&`L9RA9OVf|A1-93j;@{2L?q z?*{!T@WsjTk2x}`cld`s3fpHm=#ju!;3VwR#)!yfp)@*j)<(#=2lQrO%gM=!IU;Iy z_#cSiukJz&3|PQPo!sR+gPxvbL3Qkr>xKGL2m$VijdQe z`W$nl*x>MQis1hZ=y3 z$j@e>DEEuC-%s%*pYJxJVTBg^Ha2efFGcA;&ES# zoTw3>{ijNm!@n53q+cxry%?yB;NK3viW>0={&f!j2Jn*Y><-Xx0PjTbZ%6%$8u1DK z4G#a{XJP)mKo8|(mUkvZ;Igm9q1o`!za!E z_z_<40pX_wpNIWtJm}Mb$$+#^+vB?y|A`ve*?+1OIQ;7(_-_OKDDY$i|F*|nE&SUU z*$Fwtj+~b5=A#{QPB^lwa^#c{UofS5eFf;NfNM`q&Iw0!b&i}J;3@0H z*Py=zeu$9Mj(X9?NX|Bi(%{G`_#!N4GU&5_vjIvct{=;nEc%_b65`S1$k_y*vK@H> z^mgEx2sv%HBN1|9ME-{y{zt(}+ACo%-Uk451SqvTA2A~T;De%`Ob0K?e>vz2fD2ES ze~ie#z~R3=g8xp?9|3z#mVb=Mzu4iQ@?}{6L7;~MMZihf=LC^|l_RG%LeA}=?*i^U zSvfHx|2l_%a|HkY5#N2-0|%T`K4L`v4G#Yz@RH?R0=f)XaI*YkM*g;nN|PgJ3wV~` zN7RnI40;FfW`vx!+mnwA1?1npw9%R0n$!wx3dv; ziZKGHclg&u@c$d=$ARr9%l`x;fJR5oQSg-IknlCyKcFKZ^Uxxy<IiUk#IU_-j z0VV*_PA4NL)(D`%k+T*&YaM$%0{U;j6A^OSj{lF(Ps|a(UxeKbfoI5(1rUb4M?9rRnkyAk}`RsUj) z07@MG!EeL-dxP!^oB~Muw2Obt5rEA?sdeP6ijcDr^sT_{e?U(3NTA-~zbk_Ozd;`b ze*FXdqelXb4*$aM!hUoX=xM+VK-#HYeiUOQ(CqNv6v6*#(9Zyk5&YYZ&m;Xb<`ybZ z5D$y`pnMJ+c zG(t|h{PzSSff7ef(LclWd?x5ppaQ@ef!&TQ1WoA#>pF4)=YmDc7uDdeS|4{A#M61I zYT8Wj(d@|G4!*K|X#%|mXa=O*eV{3|xxR9|)MBi1bh1}D>afZIDAih`y~Y7PRa=Fh z6#NjDI}Y?D;4DDOod%jxbo)k&Q~CL{@RUER@4$1hy0d860z0!)CcCh(vP{vIDM}IV z#za<|9eMTOC-eCP=tkgWK+1a!G^L~0SK3eczIh?9;{4Xql1pmlvJ(GX4;K8uGNuZ|zGXN=XHfTyGD9__ouI7d2RaPzuudb~MwXDI0F1o~7QJZO- zVTGctpw*?8G7ml?^x6Ws(hmDT9|ZmdNWFdnO{vZD{$pB=gimBnHes%d6zw8KDc6F+ z7wa6o3J>8N4dhaMvkdh4zzTp8^`p5PT9?a$%KY3OExIgUy{s(%j1@H%tHRb<8WKM( ztqNVzJ%3_l*_xzm;{iIQw*NokV#{xRIXoC$g% zuoRHx@n_JKj%*hBpLmye&R<#s1K_iJ{>th_H5J9B<>jI#BsZ|z**3-+*k8oM+y=k= zg&*X~6)cDQji9D!x;Nm;<(#X`Wu$N)^9H=`&iIzdCkCvL+1XN*uNg1m1G%Y#MvZC^ z{&NWWgz%lpsl#DI=>?1fsEkx#G3cv-eP0PZH-9OfN6)LmZxtm%@2b*r`F-As`SUBP zyXT)nSwS&%tmRL!-x#aqA94Hf3m%k-3H)Lf&*!i+_*%xg@-mjmk1+h^NtVYua97&J zneiEOI`!vqURUq6tZ&yoWw}Y*)%^%dK`w4(+G2jDdO0&jW7&0tyUaVE_tZPM@v9cT z+FGV|)ymXN<8#JLZmK4@BOQ9o$v^TY>reK-u$K*(0?7QY1briL#L2hJf9~Q~`Jdu6 zU&1P_tRR0CVT;#e+oCAS7Q2Nl23|Zke$bp@-N+WFuVs_Eo>4X$wit7S^_R97eL`Cl zwPg#kNBvX69!HT^**^x47)lzD1xWwx37XP@8-*Y2y7D;xMds&H!&Xs>mYXLO4Ij>m zx(+u{+LtNESQl>cURuaRb3R(@-_n7FwhQ^S;4kGr0{S`NTR@h_ntvlM0HW(p{~u!N zv0~YxvdVI}phNUtQ8T|V|Ev|uDnyK%+{`}b@Qh~mSM77#BloKhvcML0GkcI(TbTYJ z^Vy#rB53^Nb*9wu9Bz0!8X8ZG@0!FlovYk34P>vQOXD56s&UQWhOTpsTlh%;&w%E_ zXCeM)=D4At(suB`%lI~iyLke>_iE(o6Po!w)8FRCQ=0iL)8FGA-sSp--1tAuJizqb z-1wJf-o{gPD=^NTd^Q}~?fg?gt7cC)!yeB2@#|GKK^soBeZR^B$Pl-fj;2B99h|3+ zvf-qre>mk2+ZNzw)E)$X!n+QEUO-Fv|3{SnTBrRw6ubPXBU?~Wjq*>fW4qN2jMcGs z#p54*gKg+*E#+!87un|AWf+D}^YX+*Ki9N`TrJ)3`naz7xLY^KY<@Q*198o(CUPC- z^i9wv89W7a;9LdXCK^fym4zM1LwFas z&7dCywgR#oc7Uejx=;9hjB>!Xpk-yHcKe%L%PKBowXB#v{FhP7yPqkCwH)r{2JeDQ z=&EXj^n8D29Gut#hQkOrssTZ{m%c*53 zIcKg5np7*->z%lUveAK5l#r#Pbr`I5;sGM;RQ!UFzX|+{@DuXSt)O27b^ua-(a%Eu zk~$&3jrM8zyj7xG`o^^Tqq{^?JW=#YKU>OedY+bQrMpz_<9;m;RXLE7?eg;^t-#=! z?u=xftR>(#=`+-smf`1d)`v{*z)XFHakj;(rl`gGWFV9RGbibB-PSNwHwR_w zmZkaPb&t#NsmWb^y1o!zqMD`|XPyqb->30^s(dip&-icz*-fvCeAgjg(jV>vy%lHx zWWHYqO=`>;R-52S8K$ z9X~vuTBv6BB(wW~b?6E_Fw2*!@}!Ximvli77hKZoGSEWL(#isT_)=65l+$QFndkA| z=$k|8GET0FA1X@Y>%vY&{|)zJXMvsrlmSw|6`(0a_hS+96xEY5(y!_oR>`W&N~*RE zO!?5r(R@Zcs%;*cbkhg9bG1HjF;bxF4I#e~{AEA-KIkui{eYDJ6KG1m(~qBTD^Sa> zWYlt;VYeKInev0Jf(H%kH0_Ky$Sr{`-C+x}WnB2C(4+X*u-{$=`aa-UK=$Xe|A%=! z;7wnZthrobGP8rLmU*dXH&lx+G3FRPqZ>yI+2toAgLl8ioVeE1t}%zNGgGcLFAgq0 zhQK_Skkqk&2eYSnRt!jFacWXBIuWgd(G@Ll&~0%~oGaiqk^=gVy152T0$PSta~%42 zpIywiGJcK9SMzO*ui{T~#EHCuFW~E#`!=r64;E5Mh`ebNRZSbNrf3(l<;a|7szYq^ zD!~s#xirJ((m#F%9XN(PE`aopp`as_e6ZDbe z$tKWyfUg1RN9;HJ9{BY-(f-Nt{*GZ`KU!9?vKZ3~IF=?o2!7N(f6+3UUWstDGK8+x z^Ouw^pk6Aus1osO=i!u>sfbv%TL(cE17GfOmsn_1v?W^QEZ)T`(5OX)Ec zQA1D-Aj>&q$0jEq(@9T!r~Ydp=o(-(Ankq~XiAUA?7yn2y64ZYuCUErRLh`Px~1a=5CEt98sJ*M03;VHTi^l*Q`Z7Yh8s*i=8T$pbv#CIyE zRM6dld_el!Fwmy~jdu%wljHc&t;Qj?-JCISaw7)t&oS1>=00cFjEA}MAMQ^;?q58Go(*dFz8o4aiV z_A+H76d-%(utyjHUIa^Y5tb<8lX!P(Lu)@1dhCK6smDIhM*wsSEq;>&x;G&8*zD-> zc!b}KsjjZ9wu`5pZH79mo_X&^rhny&Ut4_=3;|7P-@R>>AL&ug9&n0p z2U9+2ReYk@GDWfFq1ZaxU0=Z$LjGFtF9LtE!!4lef%^d||3%Q0+P1?IyJ2lazbq;g zEb&YGEm5#n=n*u+?M?>h9H1v4^%xGCQgK`L$W{X*kHs5oH@+4VC|X9VdeoQd&skb8 zyZ$sfa_hiX`t7HnzX$#e$o8%SCX#3}$>r3a?asW!mWY0TK}C(TQZ5%ajp|BVHGE-)XE`uz#?-9X|qLcb$ViKp^VIPS{rLH*#0 zWs8?pu3ScETF}o`%wJMbR?}i%Q4q8*W62`h(9P^YZjZ_SCm!WAJNGN^?oqwJ>BQ?J&R@>OiPHc@|{@y>>y>R5M7 zihHy?b%asFGfc}hlU11ZFw&KT-d8P&;g? zKU&5?^gh*i|W|v{d zgn~i6SwU)V^6RC_Ry`Z>T_z;cK8)gAh)4#~q#$|H0&b58h+&;0e>(U}`O83G z2wVn8`5%F%6upiZj>ADs2+yuojltBw{W|6b5GonUdpd@aos4XhS)$%Y%``ivCl_Uz z{Zsq#cs)+-(=jJ#3{yKXp5*66 zX*!kSB<*pXJg5G!uw%#@ZWsE4E&|2?G9Sx9Q<@la9>^)jv0^mOlS^h}`So%>mvZqN zS2odr*f3C>LpiiGOy1Wt6MYG0@RWed;;LKos~F$#Q&d~G3ayTlZj?etgnm09U-sLd zfj$Tv0c5?+@tH~=U|&?bnj6t?h;|G1ruF_M6|1NNXk>rpb`bwxbf={5lbZ63k!z?t znY(V)d*7>j^qv?P_IOAi`G_9;t3JiGV56>bPol4b&Xe!d&0DBLxS#RQInO1nPs1eA zB5kA^)TXcnY#@f}l$Da7L_XF+#}K}gzupP@A>a`}+W8aElzzRXb^p-HU&2v-$xs-2 zhcNU5s?tn`?r5lb2eqSVq^q6N%#^}p?st1E3?_559L#tYCRjmCXp<9+(LR!f4jvWy z75Kyb*J#kQfl@%)c^Ad)Z;ZpIci#y7HLgm2jCr|SLnKJHWE`00au zr<4uQztTJGqZ0c&(=O&soKI)(GCo(onrRPmEL`5iv{`(#+TFOG>)nkknvAR9H#6qe zI;#_nml+S4LDzJ3zA?_7V9hb-S~;Fdf40x^U&KQJJvc`#_3YLR^gK>uc}O|kF3+{F zne^YgKtBOI3rM?mLT^3<*w-lRIrUlbyyNv4c6H9^lK&oJYZ>Od4zZWr_M^i=+l%uM z$b4WayUo0(4DDGXiFfm=Jpw$N>D|>HXi>(a76jOnk>^WIGM_ z`^K5BP@|zgXUs8Y>^3@oY`n%?rMuB@bki~||G`KF zwH>wy;U`p2-Uj^@@Gn5xYjB*YOaj(CF6>nEfOzH|XD=+7lr1bS#loSmS3lcM&lvWD zj7N@m6@m!wKrCJFFq8*e*?g!g_c~L%-i-GKtawfP*o;4A++WP}hs?>3m{{-R=0j$v z!A#y}mYPqnb!P6h=4scPzU$0Ix0xOOY?`%{pI&?f|36OQ&fhpDb9&Ryu41ssKuq?I zGt<#K5AlXP$=*^no6RtD{ipeS{5?KM02?G79HueXFf8j)Ao&wLCzBi>Xx0kYjV z4>Tq16JdvxPSJj|uyk4Zk_xdU+OCv!X!tg8R>yaVM~CCT{4er1_eXxgf3}CuZe_n~ zI1ji+1QSxQENS^Nb2El$K|YH2#8O?7J|@^gXQ;eq@+d6hjly6tNe?B^Z~D>yawn0y zEar3INsD=!p2~~aVpp1(iroZ@tu%K$uVvP7_h|gD;()NnF61|a{E~ls4>~!)RC)l? zKVAjBAK17@*kiNPPOWXV&QJYT70n8as9r$c(Xw)Ik61w1h(%=9%s#g4$3Xk@bP>5? z!Z^;=%jB+yRfKro`jj2+d@LJu)q)+dpm~=U!JYS`u36lFmzUq}b!Vx0Rr7L<>9f*3 zJ}q9YS#PNS!2EO9S*gXt_%L3GI3u8@oT-oRGwz~bkASZrt@nklkZI*6cS{_aJmkDC z9XopyJ0(;WCJ*$cr==wpB@aJ$bn>XUyyTvhDapy+{vG>yLupw7_edU>rSncM3rnq7 zpVYINkDB@hrUm$)ncBxF;@5C~3BQ`Duen)&ej}sEW+S87aJ3ib>|quC2l69QV~Vi% z_{8vd@e$?fR(>9A|?paupK??U@w!Q7~L0iLyQKid9l$XdfupaoBBtyDr{-yl2^u=hEy)E!%)9_A5Ufo$iyVA=#RTr*ycL zsl!9w=R7&h9-r$X^9&yMg(q~tqkrw$%U|$Je9dzMd(&gR=*fB8{{2KA_mSrr<_hh0 z>mR$HXD@k1yx}>m$&>Jo=WB*R4)0WB@y^@0{y0y0jO%wXtIT`5HKxJp#`TA+#AmHP zvxKQ=ko`|s6JD@JKW$xRZep(Nzgzm#)-7zS(N9I|wl_)lx8E41Izzp@tYvV0#o8h^r?tf3!S_p?td-yZA2 zI&a`VY}9~M?n_XUjIZ3a{0F!DpYEsF5jPgwgN3Pjx~2K~uxveZSVo|W!AE!1dyMX` z=NY`Xm)^IyPf+d8l075%>AV*zP=Xp@`aAALZ<0q}&v`ej1YvUmpUV5`!(98Adz0#& zYr!0!-GY0J&Np zJQ2NXr{a04dV%>4b1fnzPsixB!qD_a=F-eR=~j+=KSP(GdzYc74EpD&^W77JH!$=; zIdNaH#AgtGbkLLLsAX{@Qcg=wNIB2EB(RQk9Fv-to|v|tXHLi%oqieL#CUd=9=e5P zrFIHs>z(HCP-neMsrxFHIyC17*0nIVu$!JcpP$w}p~rdZ%C4RA)SeylpJTly7F^5t zGYla`@15)vZ9sZq_P|+%s|QvL?l$OWHgw#O2iP$DkBs4ZQ3<<>otipysSz5Xk6bvy zH##&*A3eu?>7b!w??>!4_QEljv+=cjocpw=*o0qGYu)>__Go8JHW?)Y-bWuO(h+OoL#F&^E93sMqo)`m9cR9CqHN^Im2=_hqQ2?(eVnvnTQ& zW!jT=fU^WsE0a-tVAnW8=)VxU$vE#~(3^le0ohMK1)5UyIEC6rd)^0HV>|skxz}bB z+dzA5vh2@p_Gd`UxZTH<8~r(2qUFa(uNO9cWNTf~hG(Z@M*_`TZ?#oCG*alLbTpOm zkW2k#2hiPtd_d|o9yFyjZ;1Y~_5Ks;Cou;VR;=U{j5}^&_y_?AgJIcQx$>;PC;E|0 zmQF)Fjxj0ks%LxbX@l#SwmM?}NpQ5#s~&QLj$TiIeg${~kmdae=>0(S{K0`%>&c`a z=3|8Is3UJ+&x*~J|Az-Dcc-fC^5^``H||Ma(i6Tq{wPKEtFaov{ST3u%=Ih3h9Opd*Nu-~R5QhOST#MaXM@Ti|40`WxxKneWoZW1 zg}p|+w#^^^7Z};kX&aUiZ*VM-W0RPMO>n+hRblj5y*Z$VEmWqZ}~223M6Z8O_$69YSLhyjf#Nn zWpRByx~nf*oN2EG&b%TR;@Z=}_)|cs#!{|d8=O!VbZ-d0$8HG*-_~51lDj4|>t;-} zx-xDIo^eC4%)DfOqUWo`>zM0L%+&E`mk0N!l~a7#`h^Pp-x31~v?s zK2=Y3o2o1OOW%#`6Q8=r7d+teeeH|4>ATq4pm|NuJRC54nlA_Z>jKz*_CLS*w%<%M z`dz`=T;Wd0NznrOK`4vn<$XCydOE6gTtaJMxWqb<4oJGz;eLQkK6wq^96%09*oOMq~^cF8A)aA5`?|ip|eU3rp)r` zn7vt{F4dn_JMLhqx3Kh=S=w5bc_YhEGlLmEZ2DC*uVrp*e_+tpGTnZ|Of*yd>1JAo zOfv%mo6rp5zYUq;xc)`ZZvlG%>Az-{sl)+8o%PTfXTRL^i1uI1^Em#C)&RSeA5nj^ zmnj-)Vs;P4o33=_?YKhC^7cUZknp5NbFl|AI%#f|YiSP!Lk&TFTX5NDiRM#UJhi9u zv`hIn_P)MG3YCNEcx>ry>I4*&)OvVWKkno@zY zz8h>1`cuC(c6ph-H8`t@|DC^sap5t(k1I#mKzqm4bky|lO7AHc37<+DP1aWOv-n6N zDHY9e${%tH@txYQM$m5ndjM&_??4|0f>GxUY9iK8aPVMx_x!UeX#YAUmFHkm+27lO zRvB-wK5w!vZ!rIxu;Kxp@h;ESKKjH8%>J;w(rhuLYEC6KwF9J=ez^RvV-A;`ANDfx*WcKS=xgE)z zMv=@h{w`A_vwrNB;QEVLQ(O zT>&ftr2LhjDYb3yY0Ii3q+>U|3zBCl??Ezlox=w4SRPdRVC92270eU)ZUkRhzVCwG z1$+WXx!;4PG~4mJhQD%dCuj@+UyVY%mk zo(n7jWPMx#`ck08nXi^|*Bn#B_miyX&z_8V;In{2vrK+S$v9lBGUMD;F@ zm+&m|am>WwcSu!bPWeMt5x!IV@GhF5MkEl>1KvP~fGrds&5qn1 z5pq8S{VDJTAoKqXXiBl`i_*R@td#BVflLb>V4v6jX@(7375bvC}}$ z1Y+v{Z%k4hz2&__NYUu$3 zyEp@=21ztPE}^qCcq#?+gCUq_1-6X;FrbYU1tBVm;ISez49^M|6yirW!Voi-&V#SW{LKv zpz*o*Vdmb-ny`|4CELoX9%klNoOQbeGx3OA6X=}C+gf%49TRz7<31dnaMKx)9cU8h zh{!LR#|Ys^{$TfSRQLC4hGQnLtI+JJ1+0EF3S=r8tRzg+7rHTx9MHc}6R_908_&=} zuV8zX&U^Us^UMzB9@X5fnq6U7Y&~6s4X0R``%dNQWb*#l!I_P7C7dS$^z^aCh>Mz3 z?MkLrVLdAjyGw7X zp}p+BJI(I9vz2|Yn)#02=RG~`UERM6hjQZSkVBz1pIVJx=)u#_gJ)wOo1>@FJ=|`@ zgU$wW0O`-Cfu=Oui6`YgJMw4jGo6A6XG%@W;fqi0?bG+sjKVQ~ud37<`Mfu5*wIBJ z7!5-J`bW?BWK+Auw3m$sVY>Tf3>oakq;`q0-zLbF{=5bBQ@}HT)aygglw!>nh`6F< z|7Z=ikH!Oe!^vJBqEj`pHNWLUdzN8uB6aHlcc$3weu*|&gb*c5g&v_E*mDCp)UFNy zJsOw*NIjNSl zs|ok}HL~3=zLTNH4^F1Cdxt5h_QYH8SUr@MNjdB`~9_;6k*X99{Ug&yO3 zhTFw+K+gjf08)>Ypee;_7qRE4VwG%Fs>Y)88Etny*n{{Nvop_y!z8M`tOWAp^SQl! zN;%}nZ3JKGC+~ya3w#Yox$Zn6cfGUE@A!VNta91%6-(`{#wGJnGQ)sOyL51LsL@0d z%;Sw5H=Q6#R5RRayx9Q(320B8eHNkzCYgruaZXp*TqW!=9dbj+FZso9Rq$L|}oLzDv!DMVtKuqn( zEe78Z@CEp0AB?Vtqz^WJks{4(vudv`e}>%xn25-*gHAAaoTgRlfP zfcFj#z-OY13>B}IyE`Qhc6H@hE=%u{YHKn8!xD>7{I9gXp_yF;{Ymi;bmehND&9kL zyE+&>ZM8#EZTBf=AKu%tJpFu*+7B|?VADytmeWt%RTM zE8$~B{aBCanw@8(v-F6fHA2r4=pp@cHRyG~20-fhC}>KXKN5C*d{?wT;L<(XlxAyc z@6Tx9uc_NOYv5SJ!1UBH-k>YnJp;Agh!k8}Ki3#M3leZL-MEJ7{dm5f@5!O|x)@Ww zW&BiZJzt7NynHoZwWPMVC*f+LZ?Jz@-(1kcfzg1}_d?K=b~^j8W5yE~R8-fr?D@le z7V0+IOMM-)AN^_Jxl6zz1I3Tdg@05hIhzBFcK_JWUO zs%gn)z}^oul)uffWr2@nX<_|quNC??K|g8luR;F@_!W@)Ck+t#7dr7!WIQk8W~zU! zHUi!&HUehSw)$iIORhZN6|MFdyBc=IWgESCC!akpF&n4$3M1zQ4y_Y_+wL za?o|a&4ASFY0#8n@1vx+0C5`GH9S*N%O13Qlj}u4xQi<W3tE8 z5^yLvp6oT77x72!H9(SAyxuAIQ^NHr7xZx83_y<8t^)mMpvsxwmF?E%R^v6&^ZXT+ zH5KJyHJjK*F*1HhJo<~EVmi(|{mR&4j=Kr=LvKI#rT8`XN1kqY z%uG-dDX{Iqv5kADU1CFd5=+CSO!H8j95|IHp#CJVK1xHK$mcHPLAHzk1pPn2Qy9)? z9_WEUfwRsa{eR3$cOSfzzm{#DlikwV)64;2iMv3>)N>W5^)xPu zdkpPU@AYi2Hx7psm@M%DGJut{TF zug+NodA%|3F*@(of8W6%DR%J=cT2WteRWp z8fm6tb>_0%?%mQ0dkwsq<@M;9K2dNOer9}1kK{l?A;!>&m?ID2HlPsW)Z8zi2xUB< zjqNVO`CxvG@rRhF+D|j5{k6d?7wg)kd@MG~470zb*q_-LVyF13{inJn@;4ZtiKQ6K z1WmxK0hp|$WuxKzM~0tnLG(lSaV)_9Ih~&|q@RCqLBR-!-G)_8bq2Prz^X`xHjDCI zh_aL8u?s=312zD%{ksn|rI52!2MVhF_B7T|ei|?RAp@Q7Wl`DeT zn9Rt;w!!)Q6x_Vffh^DidrwE<2h?j6Kj5?jkW&abW@1;hJz+dq8wrz* zuy1(5Q6rwaKk=f)%MwGjuzc`|N1W5titWRSQHuly5s!5$X(3G1{6{-%}Jn?v}J zd(60d%{Uf!H}yG%`~xu^trYx4=rJ8~WIMbB^m1S&AoaKqG^ObAQN%rYl(fhu)&eH1N@}C-Jrh$z6GSbA3#%T^M1InwB+Lc$okos2fG*Z(F!&U zVVkCw!;+ABrQ~6ezrtZ*d1r#24x9@}d8ME!{Z9Vm1TR&m;>#w}y?pmTB!Kzm(~wQ7 zE0ls;h1>@4mHB)X^n1WZfRwujG^G>fvz64b$m|$9vzTww0HspP6qyB|Mn`TgrhlZ| zVW7tV696f9B4|p#li%gbOD~|QfHq6C=&vH5o4`-X+Y0(A;2A*5YXnW{g!v3h8-+}^ z^#&`OPqQP}RTOR~dVwwg`U8}xFOF`95S8NgzMA~+#^iI3j_g5l&_PNSFyCJvbwZ-b&JF|9f=`FUNLyfamX^z=L0JuqY-4+tXP2fEVCDyTRVAe2XWg5{LgP@RD}A z3G^+%Z4vz2V<%_RxFg}PEuqTczYDx%JvsvVKfr$@_(!kD$I`zg44#WD%taR)hs$G< zv?LSm+~mk98Wk>wNubXJrU8^rRBxtE9z7ZVBNd!el}7<59dh{AgNL-wF3d0Xv`Qx)O@ zq&Yl`U!o48c78B_kI}dzi-LBfrUp@O3r2_I^a-G60&@YW&t;$~9eGpek@!JteX6P} zt4bGO!K_6o=MD(g$R1-f#I98vRa|A4!#f#0a3xcm%V&($Qp~}6Zf1@r#jAI>XD#|+ z8sl7SQ%mGC_((O8I$=B2Ju38Uf*v9KgyMj2K>rgs?C3`2F}n@F#a`QrWi>)MR6-c7 zk&#MFxfjP2x!>|k4F)_xH4ewBX}z=fF(GgKn6SKaK`#N$2c%v81e#L$E5aV5o%Lr~ zPSq7lD=(-RwQ$iA`&e`xTegAr_l~5+@LKhKro7;sJx}7Mk%}2WT7ej3;to5Mz19sE z)Q#YA2#5+E7y9gS{SPn>eSAnL~@Q}!V$y2TUBDV*EYIvz=_(X%0Ts0T* z^+e1~*Q#$ZWj)q*aU=kfE^dz7k|^f`wC>nX+z+K+^n_FHkR$8+x1j$G`~pZlT;qfu z-#dD2a-K5Zt@IELS90-6^qv6(C$;KB3^z06Lk+km3sQ7)Dz2{!;q;&5fQKACrbCX@ zV+H8TfHi>BV?Ag}GG37TV`A#j(g5Lti7V|3CTdj#!&_mH6;xSQ;Si!Dzy3+5{J}p2 z{#5?|2JIb>{gHr_KLRwRmz?^kq*dA9W6BprLk&m+|C5+|yc=_mn1alt8OU1oUz)OA zABbIA>AVBhs^WO6Yqr*1?dnSAaou=cN1kg20zNI5ifs@~j;^**sF_qZxoXBS}_=lhmmD>`~D}jpvDgQ3el={CY z%I(OG=yo8S-xjw^uDTcv0WDJ1s#oGRCEVHP!MqpUH-n4uG!t$X?{ee#v76_)ds0;# zqoGb>ERMTpM9pYy6#5;7{36IF{XD1Rd?3&TpfaF)kVk@^1U%!cbEG)!lxyJe{w3p% z_fl)u|HF{E5Ixb)0CO^ z?1VB5^EW~D0Jab_EIA_;zaaFjhc2=_p8@>}@CG35xf3)c*^V4vo)^&FC$|5D%d?q1 zg@cS#o*y&ib*TA}J$!wDq0-vbP$_s($PY~n`|S|WV}a8FDSrlNN_A1^(!>4~mfvEp zk~x?lJp&V@wd&irrv&ojjbXS$C7pzyt@UH}6-zc>RoAN1m7Rbx((cnr9C;~cg#CCR=yAYAK+2mBn$i*H9I2~! zYyXIfb6SLE9pb;SgPa}WXCAbh&R@8)RvV~w(bDz7Jfwwm-1vm?=NP7uF~;Hc#}U-O zV3MsLH)vK%q~@1}T^b!d$S$9N{u1~aka~XS{9f8aJ|pcS+sPIs!`IK^7%`N?hnv2uy zIft2_;Y8A>Ea@|L+NWqzwV99e;b-^YIlEc!ue7B7THMDhjwMb@e2j)=g}l*jcTp5| zJDl=|T-mRD4*CG_PeAJRBWOy|>)%qZR`HH>1Tsm50N0U(AQY*=k-G(agZOT@1E609 zUUOto8(!3&epG~)9g(??iq?_XD@_i6*O}q=HXC#oAQzxS{M#NchWjlMHl~7os-ig~ zx^FY|{R?mmkaF1+Ay@XBa-U2rxuQH1ipCCi6_MB~MMGmh*mliB zj=b^Uho;gl*K*KHfoed?y8tw$?asc5Xn8HQA#&Cyq2yerK3s$P0AM5QAd%PFH=X(q zzEbYTp!Wh_15)mHpefZoBI2yJ<%Yd!jw5s}gaXP$EvLo6!MB|HKQ(OM63~l)rGS)M z1)5UZ_AQS!W7xfA%Fq`q#8qZVF!yXlo2@8gHM@+f9QoV9U;5Qv(BA3(GGDy%abfkn(Fl|1tRyQ;RV*u-PiXx1I8b zoK^S{wI{nke*x?Vq#oabrnJjhPm3;p*_z~si@)3{{_9cv0Iuo_7r#>P$SpiOT>jHQ z&jv~XDYpVNrRegHSl^IUO;&K~b&8e_r!{~-K{TKgU^9hS11NY$iIZJgZC=gab4_}OMy@5J&{jkMp$k~ z&|QHZfRvjLno`^EmpV>r+b@{{pC(7{D)5#0T?6`h;3h!IeE>A2om+){r*09?<(1Vn z`BUf>!pI+1!au+oxJS7{{SQ;Rx0bp2`bCUybX`&@}%)B7UdN5MaY z@8nP3nK%y)bOfaQ?w~0}&y(8n7cEe%6+|e9`=x(YRZZMAorK#1#nV z(-i3%^#!hs$K|$3xd{Obx)Y3{JQK^bi7Y^4rb+x;XMI-r(8)jKgdm6VZ_dKp7?1== zJ-UOY6f^$|D@v>0T=xam<@(h~>JbFl%b3*955rqCJcRs2pV8~j2a3HhtQ zU)o_k=uN<#fRz6fXi5c9<7(RuODoD3l`fk+f9gW#j_~5uXuuw0Xu;N~Z*%1qmV=w~ z#FfD*t|1&3jqqN+T$-{PN1JGS$4{W^af2ScDbx9tvai8 znSB>&Lh&4os@JHi@ouLq92zKK$uw0wRU9T$4mt8xfnNdmk^Qd*eJgMWAmwT23VG4{ znC<-I2=t;0D#`P*>iA*9zMtx8eFKI_Yt#?CxZe~vPw|fav_yA8e4?h!z`>F;vhn+Xrn~!TR-l8YCk|lv zy83#i;x$`Y7>@TL+>N6f@*?+;!+!^ONqg@By%*RI$o%{Sno>-AS65(XZP)@)dpFN7&DPeVE;fLnbw6WJV9p zTzc$3#7CXOzaG3~J$VZB3&5*@%-5TsDMjDM97B%CTgh_Fz0t)iYt&76$B2dxWg#Lw zlpCdjFGYE!l!Wcs8}wjcI3VSY22Ck?ym*}4DQFvz!Q|it2&S_GB=>2i?9%X|Y{5mu zj^IO%+&b`;{o;e5w*ijdmn*uagj!a18MQ~3DxcBjnPRP*U4T{l zL_U?$uslELB%mW8mCg5238ns+`9rw`o5ffy+(I~aN!KdUak*{6gC++wZ=!3u!K*~#+C*(!PHMSj> zOL^#JAI42t9=HjRdVB?%Qp|d}eD%^ZD#R7nXy~0w2eE)dmlIye?Z*fBMn1L2#H)oy zx;l6}V@bFNPt+_cpW)!1H|WjP+_>Tb7n!RG{(LkYxZ)gp6zPRn7GBYW7=iaSEYwMyf?Go^kM5+_pQiRVOcm|V?a*=rT{WuOF_4puji;S9 zXoQ>)QCuZ8L7iJ8f~$XN zRLibb@9`)%ir~tdhNIuO0hOPQ;A*&b4sLMj%-w-_+%z5R;?t&RlkgJ_!4+;94#cP6 zf+O4s)hom5+*#{m4T(46e6AuZ)y&l_cf2P=0ak`DwN-#c%clsizSgkD{g;;bs`lR^ zpWBfS*{-|=`ZM55K<3l4-~@JWiLYc%v99g}S$8<)f0d@(7#U>2?oN=EfFLUcS2d!Q z$uhe2gq9-6I-89PM?Fg2e}tYTjvnNni$PxiTnI=#FL8b^*9+v+Zik&kg9Q6l|1JS~ zPx359n?<|mF>0~>>X0L62l&YTgc^}!WS%lFEhVj-4t!~d)kC|wfOfm^IfeQ z=Fu5m&=ErX$|s=Wn)n|g)&3&vQgmLp{AYq*2rLJro|k~W3WzTMjVI8vB~-kg!9uwK z%bxxnyBDWsZ57Av)GlZ5lXi^^<6CGqmY;*JJrmkh{a5JK1er4K*$etR;2o90a z(es10-NNGlipdiSVo#CTf8XrLD_R^buPLBs10{fzR|c9=^m*@A@>(iE>q)YSvJ&9$ zi+>gQ+X8;Fo<9fr1>hA&2H8G({cE{B)L4#pPScGh^sZ)6!@DYL)viikx_JRt?V-FK z{;nlq{vptvfo=e$_VJ&x=t2rr0}v2U#s}=b#CXQxUj<%;_!;^4TF{$-I{|60M?q8C z7xiAzL5q@?IWO{23`YXeQE~%HE>*gGM##VTseyyQ{){x1&eWGN=|PN^cna8 z>+>N?`+)gBWS!BU)BEJym-V@VrCrYaSL3yJ_LV6kwS^R840Ntc=`7S$njC!#mxcS^ zsh}4CO8{xNwV){-H$FU0Pbx=w4!n2?ig6k+xTQEB;L2vG80XTkSH{J06qkE=T7rxB zGwk=*V*6E1_;r+!h?N?oX2_TJJO(ju}wlV+XINXmZ8j58GYfH(Xy&Z#6@PgFn=(`rW6yQ76i~B%74Ll1- zd+r5I>EfvSGLH8{`(5l)F`>uH?Y?uEtCw%Lrk{oxX+mJZ#!P)9bIs!CnH{Ye?(yUl@B>5Sw+{J{aqVA0KMrgMWPV=)P3gGtL`1z3*`=Ef zZHg?7Bd-b+X?JPVYISU2>{mrxch%ey}>c?$ZbKU|={P=Il*%t`!S6!?q8?g>Q}DDTLt~Wkbx~& zxG^h;osFDdggxIljO*{ji?F=n#ctIBxKjl8u-o5Ud;?Zj+ACe#5je7?1petFw#?`M;QXl;NEu-com?*nfG*FUoHh>`?^!QGM~( zU>+aH17y3m1oQsx`iJdHBwZ zW^7`zt$7VDejsyR!LdiP6tA@$hS`}M7dN}$RqshY)gSQV1q8Sa%a6}Q-201{8thO# zud28K3%l5@o_&8%XMU|FXns@AMdoRM^()t^MN1UH6`7cenPFrKO82#D!8wjqRAr@o{qd)2;p+X**3 z%%$SIHiybQ4lf8Eh%KBR%uah<(=-!@Y*X>hhcvfk;HDwkk$Nh>j`O`tHmJo3LhoAW zCH;Fd=*NMl0jc-PpeaSae^eGiZjaKcs)}Xh_7KCaa40GJ3H761_PI{Qt4O!t9KnT{ z)Ue+-S{?BkQd^8tn<(^3xggvhjRbuba1J2#Dg#X^`u(H7uUAWh5KFtq+tRL~gV3u1 za;3fA1HA`m2Bcm`K~rjuy5~{qC7!}i!cJj*YS|i^j9aHZz!Y4$$6Ze2WZ~Hf$cJNN zzyAQ@m3Ks6i%;N>{x7uW(*8#{af?TQ>-B)2BD=-m| z?ZH;iF9JuLa{!y0M7?{CL0;L4kH&gMhS$ivi0O@@;7MM+0!!?;kSrYhG)Pgp!jf3~YRZ)S+>89wy5Jw6KLZW{il5{QB|r0=_0RNoI*xDf zZPE!h?bis1R``r{Cq*kfPdqazWZ|{?&+sQ}4zqlL9Nyc%91(rs^kEZYwXOu~1o++< zk7yQf-Az*#jdHV$yBWWgv2%@|$t+?TpT;t2@vAjOWjR)Y&vJaH_INkw=YSUh)gG-s zV4V(ZaqI%-Id=G;9Mv8>FHeU?NglpG*MDQIp683_T=6{hH_?gyYig^k{QH>~VG-{a z!4dDrd3RD1JkIpUfSU)nfu~k>9G-4i?H4EXGiX^*@EV)E6Q06Fc_(sMfYk9189xuL zDnKI0Z);Vh>=pyT=V=?FHFcBauS3~XJ>CHN&%gtKs>eN`DRsTRn}gtKsx`H*Kdkl- z$aQ|ISoGVp+P_xc%CWZW3C}t*G0&i0|S&sjbKKko@lle@f23flj&@ z_j-Whe*$Pq3!Hgkud@#7$bZMa+d}UNj1z1ZH&%j|J?H3GflU;6^h?i*^h@We@ ztqSP&leJ2U%Lg;4Qe4KHf%1&>L@e=opakm}wjl6qDBYuIl|_>OM(|e-{-~e43i>nP z5TN===_T+*2h7|m`}q%!-;C`?^%JUx_;SS6Ml0Jc%aSX~a-n$6l_h%9)ZVmnf92jI z-1RFr#WRDaUaogDdcX*AH0meW1FucE`Y%c`qj~-U+srf#8i#vs(rhf zWBJN2qJBcPmD|=&`m-at>L;ZoPWe$b>Nr&XCqTaf><3i&qn9F%HSmiwpDKSu6|Row zAz~aBdx3G}W>aheTiL^=C}K4gajpI)XKp@-jpgrfZB8yW!Y*qw3vg@#d^Q5w!7d~N zc8>pgHzm@ZWPHqLvlurY}0NbhKEy)4B7zkRf)r=wb=3P#8xZF5#iCsn`+d#Q;U$tI6q&Cqned<3$ZDr z>9~pQ(YKLrqe0uy9M5*GhkR~h(Q-Z zsMr*^)pQ9Jn9}|-pFQpJc^CAjz~_LH2ftj(BmTTg$-~L-q?+?YMV%v>&l>%F?ZPlN zuZW+86V+JO;V|9?m(QpVC;tg}ziP*4f?f0S1%5 z-hjP?DrFUXQ$njP$z$UnFvkryQm&wx<}FUJQy_l~pOd(-f!#Gg%40wBQ~VqR{a@f) zK=I?g;@JF*fnSSi+>?WsNYxY^o~+T&MoWzOVWm@xe1?})2R6E9x+ng{q@9tbdVwr zKWJt=4KalHUGjKCYaAlwyA$Pzq8wsg1pOKC1E9vM^ebVr1H{WWF>YQEWmSi{^{k2< z%2v>00zIPi=!3oB8vSXgw%Sjy(T}sh6YKxOU1%IfPT@S4{gkbM%X5;AJy4 z+><7@>lmNI&!!dC(+o#Lqj4Z~f)*;1{I3LWs-Erz{VLE5DE_spa8?bp#`y;^I^%!T zVmKgCJs2ke%jVYBPODiidfek;dz~A4!A+JL|BYd z4EZ{(#mRp^-ai5Fr*?7>w0$*f-~pBY1kjW!96uHD>sRc?r`0W#j{Tb0*K&ezJXl7z z(QMI8&K94U+I}6!h9as}z*Wvu5Ys7u6#q|xrnEdx|6a*YFn=PA zUXAR6J8|r~1}D$(VSxuM?+3N5_v^}Key-KAbCnd(QJ?@&`4xkvG(0Yjc8C0Ab}M9d zIOToQz=I5W+p>et9j71QeX1X<2E7ru9Z>mw3Yt<^_ebMuYZlI<(K)4V4|#4q11J_V z#aD(_Zw^N6EGUZd2sGc#ked(0NiGiS;iWGL2ld>TVBi!VzoeVC&+GRjn0y3=({O>= zZ?reywGoTZCiPhaK)71xr-1#2F_Q1nYhvq;3eeMmS%BjE2GEqYJ8>qqJNDyBPLl6& zQspYI-t)fso14{p&ioAr5^MC&E$xumFOcC+OkK#k`MBH0kq+)GtuqiBu^ag0;k*ED z5_u2TM4TwsT7}_B*iHn-fY*0%UBfQqGx<*xfh<4=9F)dOz7K$}A^1w|={wLl*J7Lm z6yFO#Q(ErCm)^a*{Ztoli^TzkN`YDaH?J_Mv(7aLFi4Ei}>mx@p2*x%*Hji)CF zEmaJbSGvT=m?NIA!r28C<|F<%3qHYKHy>x7Cm5c7@l0w*yR8^EpnjKX%yN;NUkuyxfhWO8WAi$BP=FEukmP*&sT^A4R4L!+n%Fqr z7xY-*ctEwA<)A5bHI7eTGI`1Qa@$pRA^PYYw5*E&a#{B#*VelGz_Shx)I;1(${UjA zvIgQz9WJ72Pl-zr+bD}9hD2LfVwAJle1sTHrb+&GA%9i>Z-V|5I0z{I`1O*%&~36k zD}TkRKTcm-yJ&LF{N+xMOsP5-Dl%cA8$=Zk-*?S$0!_zrwBSpGd(*y9dlUDgV~m+? z>I7Po!%rphQ~aC-dMR)|p!m5NG^Jzlb5iYD3)&c}TMS{%5+mE^2!GIlnJkxXWV?I9 zM2`D#2uE@m1Cu><$3XcsPIvl0@>P8OMEtC^H49LDC4;6kvy1y>l9MB&NYy#BX+D9* z)Dcf?L3}(d2Fl@oGSC+SmjEi?wV)~O>|%c_)@f}SSBQo9 zZ0%ZaEMK7sH_}Mc#fuu8eD~wMs=WUJ{R8kTpz`&vlljK4vsAmF!-AEnQPi`uX+c=( zEC{tN-fp;y%fJFKTSnzL6DOf4G*aaZS?-y5zsi3J=u3br0G0nOpec2=9$%=|hM5o&$>9f zc_jxrKN&S`%*2UUS7Q7>6ZL+k_HS<*H$2_k2+xU53X>=NdncdDhS+|00q9l0H9%Xr zK~qxxhYjcaynTLSRxDpu)7Al+*+=qre$GA$bSR$*`^0wRU0u5hzN1q-EBL9dx#79g z114YvJB^>JKPisWD`z?FANi{Dg71i*8_@m%#aAL|N|kYb%@tqN{%N&QRf4hMB+>ri zq>?;=Q(Rk*RY61Q=>}9OsP!YA>a>5nSLM4D^u@sCfXcT4G^JzZOXJhgdGG8xZ@jO` z$-f2fkK#M^zpp|61RMcW{+{(R|1QUGlv_pbiBwGz{cpbZF3j6#OdLQP;Nh6e3Ho||w!FrK;me$RB@ay}I|6JgfJd)#oj z497yl7Dur+k&9&hzJWWnRm|*R6{AjDX3O#v{xQ~{hk>36oB^ov+zgsh(_OMW@%xFf z=dP$;IBtpZ?gqb8w7;Gup0CL-g>no1x}m-6ABZ?5exB#?@stF^lk7@Bl&=WBaqeRw zD-|wcB3@UPI|Xjv5Q@6*^giP;{?kd+&&)WNk*bN)49n*@?H~N9@d&FFEfdHE6#p|o zQ|f9w664`X)pKeWPpV#uBUU;j*vAF?@?hXhL1)S`Ty1DCA_lbq8^rEVdy@wMK6q}k zp}a-W46k9d_jg57Ci6%D6@Z~jXmbtV42-eLt|x`HjXcr7x{M zRex>sUze{n==oZqm-`Gq{(iml-XHJ|B@g>Xtl@z(0VR+7K~w5V9%5c1F*LD1%gtfZ zHrf>?i|2*nDSsIvX!(@C3~TqNW$oxp+EF&>f5%9zj!-NkWCShC$U-2L?1V}vH5xcn znSenj(@0Lq^cO>Mt3*#O%osVeV!)&f9Hrp$)D7eD$#xk3nPS=0z|o%h#SB8<%EjUd zrTF|+yY3|4{>V2{IZB)po~~{3!CA&2 zG7Ay!X>syB;JlaQ{T=1E(bh~risV?HE zE=?0ZQQ7O+B3gOdmwM_Mx!zIE!KWJoq_5o4MN$sU$VZLmKY_Mx!}$iF`t=gfD}i`> zwAII9GDDibu=*@0$arlZbX1BKQX4vJa7&iBe#{ zS10Asg0iZ15!eL(20$91JS{l5tCxE~;Mc$fPes;lV+7 znzn~|Zef92L22>_$ykfS*8=3J#=omTUjtkZP$J&q$GxNZn7EAc9EbYCzp#+6rR`peeNxbE~LIk|Lf*ut@xFKDAL%|=v_0&GZ<>E2Of*zDvN`ctf& zC7}BN{Q*jpU;Mb)X@07FDaa}XE5j7T!*Slf67N#wSr7Ua;C4XC@j=j(x~NAHye=k4 zS&?<8ETI8nsn)2=4l5$Z(hxP&=;sVkbt_~&{($$Z@hNFD_JcqaQ2FPBrqo3}#^tXH z8mXHqSXihvLGuJ7W829&Z5<$1E)t$4pGci=AElLKjh%0CMndCEuR^+%W9X8T8PF)bMg|L$gU^rvS+qndhSp%d zbNr{`4+n=7WWU&$Y8!>YCBPcwbADv@#gOgbj z9%3?L9qM79lOi0x%T#%hEYFa8V*Pj$=sCbyfRg96pedd1=p~jqdU~QhPhKp71fIOC zTDXjYHt1?tjX)c8w0Jf{HI&Nmw59F0y5n*vfOGC79OdO8g5`ivTISG<2lOyTY$n?A zd(3#4@dh2Xl{h}RRPwhU`MZ!m$@_cIM*#lk7=IzqlvEt5QfD0)-`*;hVuesqGrxMp z!sXQcB9+6j7hSKPqHVUba2N+&i9w#hc-JUH_+V*u@}KFvpYmS_dKqv&pyYFz^XF=x ztv*HmM`bEvFsw%mhE=Y(7!0NLvb@cBpDM3)FZ|d58GveEV?b8|yBt5D4fo4&W}fl_@Kh*NJdDDXr|h!=wfK96K!P>}_1=k(;fXb^opUa5!c6{7DaN z)cGxX#vQr~@tM!RO%H5BEK0Pf#i-I5xUI;dFa2-{IR!fi4(0zV$hZjo{S-vLl zJ_NszJl_TV3Gg|f%ICfh{TrAUcaOCDiw^slw(`*)Vn#Le>qOBO*PJhZfU9)bxycjB zdL1r^*SdSWXY===b4M4X%3h5=J#fDR#?L{;bRcPVw9`p zoxvK6%k6arF}ByEJ>x4gK4sA8wi4aeWQf(Lk3iV#2iR+N^1HVAwjFrKHue5!D?6G0 z3YLIl%c-Q~cRXz55R~R*gdoHn=ll4d^Qll<${|JYJtjtfD7dqK8KT`pSIc@h0G?Gn z{02IBKl~m8s$AuuCjrBq@u}I-r#3q7gWKB8{Oa0;^J(yHW{2dpRO&v_@L{KX1UE9I zwQjaU+SRV)YhB0d@L0xs==^F|V6_W|wiG*J3C6Wi)by8vb==bjaKfQgUL*P52%c1b z-Uj*!;2A)TAFqI>q{c7hUn9P!u5iZKNVFh_MZGz+>Yb!D`126%GN^lXyrq|sLLV|U zI{BwQ5Sy?1fxZ&B7Et*g0Zr+E! z%TjIx{>dJh8t!5u6!_dZnh5eoxm1A$@g{8luDfYB&D|y zFJEymMeVWjF)}I&135UdT(4itwPylCb3t6gqF>n@^!m@NfE!;}@7`}u=OKI0eDc4r#{ggj%LYaXS zK#hZ?ppOGoJ5%e={PyEu$AF`l`(MSZkI6q>&iz+&?Fm;dxBse#ck8zymI?Q~pa-7U zeN@3qjWf8Z=NZBQM*68Hl zfcLBY`8}W?0v-ia{*QsC6u&=jcYh>u9w*O-Q_8PlBgvyU7DR|QMV1=Vg-7wqKgsfH zkH+##1f2_X2ULE=pec2Ef6^hh%A2VYZX-v$n;F6q8vwMx;Yxf7^#P=&%`)GWc&{qw z2GF+wcLFNk&7dj8pEI>9=V|@^FaECYlKHmcy((YNcAS3z>43^N8#JXZ@5zqN_1ONd zoqQMIy(-^&(CdH=fXeqzpee=ID_O6R_oC4-Z6fbQa?wkTzV3X?DcR1va+Cfn(=LKC zj%%KtBh~X38gR{^HEfaPZo&IQct7>CZ$bY6{Nm(EV@r9Q{!@Iuj$btGCOrb@6%nn; zdGCb3#NK-W=+(gWfEuqJ1pOBv-apvtL2~?x&u98ls0JfEA|~UwlAlxqr6?+R=>&L9 z$pZ@dc)-si^0wUryBMAo%r@boGf4N(+{p6yY(1L{ps}HXy%OCE2U!&HcT2g< z0dH!&{Q>mPz;6I0DnntMTzERNOxIq-T3h77sREH2ocGP#5v%70&<_HS07@Q5K>HrU z+9xjl{Dk?P%j2x2OU^%97R#4jFdly}`T__=`9g1CYxz1-s(DC$B#AG>*P-Lxq(5xp z-lqF0-ZMQt1>1p4o*Z?#GCf|;s6-b$3njq4OByDxGhhhF?X(owJm3y412=QF9bsla zvTw${XV@;X6ClXX7~jkIbBy<=8JEJ5c?|dwHSaVm>0zq!UMb%ylvTC6^FUt)Tm`6h zzY#R0`1TQB`&3*SJq?k~XHe-o{wcHzL@19c!c@q$Hxa5FOyu6;yZi`Qx`4j-+^ zX9#|x_HXaBwFr<3sCwxSdL&SCgWNBx{lqt)$?x&}i2GVJ5CCAjjm&e6N;rpvyP*%v}gxB%^g%d-Hr#A2uo{0WkFhDELQJ}Iw_;Gxvv^Dm&E z16~9apPztk1>*0M^A8+@&)A?5$L*KI?TrlVLia1i@9oT9PmCRl;rk`O<&VesJr#5v zumVu^dpl@Kdz^K=vNMjCCn-COTe?K(7&gPD{65lktQF6}`$QAorE42--E8251X2Ic zPy_HE1I1r#Ec@C+d7c-WAlMy?)7~-sJKA$(Q{$9r*8`H@R`3(WPt*?B6Sn3D5&*?- zHfWLJ?nNcPqMf}3y)pc1PKe}Vw_Fb7%kz1Rcn1nmSf11G5Jjc zeI_s$Q02G+^!0#R$E$v19IJhf#!ycZEuZ5o>~GSc-@6{ZP>jc+bDr=7+9pm*c!HUy zbC>-bw|BrSLBr}2-c@C9>JH5T>P$`BB%dwdp%C(?dj1)-_bH4+fa0?ZbOjJ^Uz2z& zK9#*(-FsB?rvgb!sNWyv+CxSG54nu@VEd4aa~W<~r{c&q#YQ|q+s`vXIII1X+y5lC zpCD%m1BvaS@L=-290Z~dOTIUPCpAvJ0D3?09-#O(pT-#u5bqzbu#0v={p#rXL&Vq? zqt|Q_K>9Cdt2~C%mHbbvn%#?)AC}XK6j*gDHeo2bRX!rivjDtC@tx}7a?tC54S*`oBcOKz@$F^8G0NjK7wKhisL*%2 zNnb;eX~Q=dfei*if6(;LlRg*B8|VQBdi9m?whn(u*n*UxQTHM)HLb|`@U~x zyk`d9p|N+aF@@UsOvmRR$QFm+dhnw7-30o6;7LHq`wh_V0`dI5eoTJVK!ONq?fISF zf#0hg-XO(4^T2kAJJN7*Liq?GM%q=C{{1U@b z5eM1{c#TXuW%*WvcQx+a0{R}{en83hQP7k+mv4JlY!GlET?8C=DXc2>dW4C#dhnAN z{`n%q*LKib@8qjJAImokItR!HRK6vkkC|_q&k0;WT+S$C@1-QPZA{x?_2d^qg4*Q_ ziU9aTDt%m*cO~Ad%DV>iCg4wi%J*r|lqwzn4eDGW0qma=tZbfU4hTfTVimgrr{~I&Y1dOy9!V^+jtg-!w8bQ`o2|O8L%OidmDNr-6 z<7dld7c$!QwB)P&g;+gJ2Ym`~8bFE0sCfG-DIZ!-cd)M72w+ z=8YFYe*}C6sPcagnv&XIEBmTgele|iS^#xzUA0k%b=5A|8y>^D3K{K^d`);UcF#5o zbTu#^P<&kono@I|ePOJfivA-fh?Sz9-o&)496P^Mrz4k9J1s>!EmiHb(aC=g-mlul z+n_%LJ_S_%--4zTA15c4f18z4J)12is0(q08k?X-&;@b%!-izOc-|tv1h$De=y_9H>l@4a;9{#7c0lO~ zZcmmgf*>r(ZB{{W++ZYo5icYqpP%8+%?H@;*(D+;mS(0=e0;XcY`m_SiG(;zHH z9Md3p(n+y0QWo*#_J%>@`G2Hgkl+UO_@d;0C-{rvH(Fo61o{==?+(w@@8aVxNx8T8 zuCoyeTTT8h-0NsfPCn6>r5q@q-k|#e1D)R}A9W6{K4m^_7gPD#t?jLlG_A#XZ#~|j z#`o(%w*a34O8)&`IhOp}tdN@7<;FfbGDs57WbwQ~o+8MfP8L7Or~KuNcK_h`c6274 zH{7Z};MRr|Ii6g|3@HI-NZpMgFhe@WF+)11%?znOcGG3T3~5Hi)JfUya+o1yyT^1i zL)yd1)dkw&cE*2Hc1R7c%6hCvIYUl8-Uxalu*oSq$+xTXS!pB^^J>3IFVF_Gd9_Eo zb>837?)~3^{t@`~|M31culAdum~wnjYj)mS{%WlLW`Ld#oCB!(s|QUfe!nW)N6ag~ z+^6C=?H)Q#Q{L=1>Ax|pQhKwW+0mQ*^~|VNYZ$!0d9RdXGxCe#JGIk;puY!x1{6R3 zy^^2!{bpzUjF!g|?Y-G=(pN%@q-%HfTIJs)A63Xl%~KbFz8bh0pt>Y|w{4(z0P*{q z0Ug%sG5K`i&3=YP$989rIJ%Nw*WY6M zi#*T+fighJZ3bvc@%xL;QFj{xy^JFs+R3pH-lnhudXn{hhGjg> z0?*?p{Fq+sVdvH?`K|nWY#y!!eJQXCP;$H%G^O}+zIZuyINuw)j?VSh$@9H|bh5We ze*lVRIK71zCLGLUo%c0M{)Xj!jpk>ZJaZTyHY@qmFbki8 z+=uX2)pfsC_qyam`==}~@sSL=02l};J}R6)SNW^Yn#FUM%!5baKClR{UV1_A4ji2g zhQgAeU)ZppS@;(g{#h`zmkoQBh4-@XtJFP)$m0Q$cj+6Fp9bWo#=8eWKMp(tD1JT! zE&hJo{b7us>SZ;92J}V`9qX`26;!#0gftvHHR{mRn@Lluho^edp(fT17pEpmwcv-6 zK`AaH+ZGpT^I-2Zmlrq-=BhU(f2FU%_8-iUyk>x&1DpjY{{8@(QibD3`)GMd{uFb) zPpMtLpc0V@AWLGj^je0|WH?5XMpEu+VAVKW@*+|ptmxg@xTJvCO86sf^;r3qoLCOf~GXQq2v8tyxalD0>KCW)p__Y+XuJFt^~+8&5H6o_^k3_ADx|JggCBMeLMnRNA4c( zN?Z)s*jL;5H1U~)Px_CBvb_eyI&;!HvYb0nj#B(Y^7p*~yA>c8P~*x_&|`s+qerjy zThkB8a{ur0PG6#~3;*}uohQ`-;K}|Lx$7B18=Xe|YjF|!5KG~G9%RSyp?vy7toOrA z=+R%s_~~$sT}=(EJ0HgopSL$@e#%t;FImowD1)lcCqRD$dv>*Q~>&w^b#c-Nmz~c#ap(;=`g8x4E@%FsY__a;S%JLr*|IF>uYK zd-8dqHJw*m`PqGvJlGtR8Vg`vf_*{2EI}v?JAt~C3sH&DFnCt~5~xd+g-yHriFA*S z>g|SS7y{VBp}E$?+1b36bMm(lZIR_~METS>@I2^$0&fATp1%ieyoI(9Hx8`ovYy-I zFlOPBW#YQ6f%RQS3yY7TFhI4oLx(HB?uN^g0naw4a94f;?_F>jsQ?uBFY=*%f?+Ht zu4Zhd+(^Uhpq#DX{aKdQ@}cCr5 zk9p#^TJfwF&z0giPCQSdfRc^+20v~N`xq`g55Dc(i8v5|6|@194=c-vdg&Sw_d#6u zdJ=tD+qo#-j^#@9;Igq)XW4KU2Q?H|FP@(6!H|>4YndAny$57@;GZ+qLI8BT)^C9} z4Zk}WE`sMSGo{vEkYZYM{BwG_5&fu!dC_W3_i?tlm0XYd(J*tM=HZ8;hg+!nUSk;B zbY8*M3bpO%=Tg4qZ^zEN)`Q**{25T~^LfzwfR&D&h4ODx(PjIL$+<$v`S*-M@^3n$ z5FGfw&hI1#{=#*CqkgNdeQ6HfucsL4Z|lQI4f%w3b=L=Q$|9Qb#R!&A$(M0))=F`{ zHqZ>{Xk_j>D9agr2X-S)JE{P^7+40VcC-^TrNmEVd!F~;{~l*0*VKUO^^Jyb8u+0u zJ`PJqf<45SVd5#=2{!82d$l`kxF`*b;J8D<;Vh!y;6R8EgT8mW9}0racD zCvo%Wyx&o;vj6nQ3O3fuV|kY#c`9Ozm=47!jyUBhQt?U}(cLELcQXp2yK&+&is+I{=@S`0sYh-fp3dQ_?Vn z8{IUm-CMM}|2p;lZcGkKL2m-?1C$(o1+Bk#v>cZIZaEAZ@cZRJe;0B%h|(S6=jCY=24gmv_~esXIQ@fTAq;iKuk_jT6W+smVHRcOG=I8 z_JMAU#QG$bi`MY9l-t?p^J@H`0QpP;rT~;kcJcb0dIC>|1Gin&jx)ya1o&LuLn)(cbB_; z?og;^m20I|^{ddT2DHC1qdPm1TBJyIKT1CKBcCDoh5Ae4hqjgn^Z?YjH4F57;6Pm5 zl6=R0piTT|FI%#>_sNSF!G38$^}=>TmH30gVmX*kqd@LOZM)xk_IFMW|le+>E?;735o+x?N0x8~Rp?|vJ8Q)YXW7 z7VB;>HDAkxsrfectWG65plfSjap&g;8S`6r!6~t(odOQ|6jp8YA%@F;mHf>_{))e= zK;I5*1{8mff~FMT9y`jvuz2F)^Qsrt&TC^cjz!o&KPB}xE|VYG%KePuIt>bKgqPX94wqYA;WL-Un=V;wr6j;wn|$TPOIB z=eI+%SkZO!SvI$NG2-hL^>umIH4(v_KA{Q#rhiqa{FYIp4%r}+7sad zPeoY4bZtK`3Hkj63572+V=wdYlv^V(@b1jH)syZ{7sb><@L^A> z@RQiN=~&PcfXM(Ql3DzDX-D~-xMI0=~gLz>3W5j|OclcmThEM!SJHGqdG@;?jn*Q22S z3hV)toIV0gY589ye`;TO%=(hScsMqQ4RV8c8pU?oqTi@%Yt6w>beV(W(2xfk22Yt; z5b1;11Q-%9Ml8X9xnhIZWJ~@^55($mCg{1q0zmP1IcQ49?jLdOi3Y<{7St}3O3-Iw zjn{J|@dr(%r_5ZayN6s9J39wa!GcLC+;7-4WX*t=6Qv%cRkO+)s>WU@HYoI%g!}E)<{Mtw>z%BY?T-yu%QOPwT+$Q(P$kpvodeBZDY$RrY=l<}x z>jb4mJv93ypLO7)%Bh#XfPM}57Etvv=Ra680=tzzV8>s7i77*i9J75x4W)Kz&0JVV zEv=cq5Cmpb`H5k8MNRK9)r*BUKMqeL|1mxwPa{Lb^B+un?9<8N$QHc>Q*9YQpLzWQ z175N~+&~j>6>zfli&gTrX?$d+`=Vc%#+Rli>3)|kXW z;i{p$+{;ggalue~guRw!R&+yn-*6f4bJ#S#!YdNJ`6)a#Yf9oGK5mm#qQuQPnM$RHD-OF|U7UM05YiSJB zOW5POtDk+QXNr4}ub8i3$>tPu2(JiK^I@j^J|~c650+ulAET8M$|X}{mXv=LWUJ(V zCFmD{_W>pU8HcfE2bwAF1k&(`Z0Dcs{2lUNGUsg3+Ie29`>&D1Zr18<@QRP04DoTF z{PvV7zJ12T2Wo}>CTfK~Mju8fjV<~UtiNx-Z3e1lDu{>jF@W6|)SBF7N7vC^F5eE9 zC(+YAobDf8fGeC?xC}^gt;GJt#374|4=9ZG&g2e&Rh*@xJhuFsgUiU%g7;O;)b)sv68oe$uM0zx`&c)g!b#=64G zkK=*U&;Sx=ar0f~V~OU7DbuY?-h`vBvbp^yngJKCRVMR(UVkVZA-n^K%U8_LaW$|U zchD?;o$*|jm^8`xEogfFA%5w9{$XYuV4235|DjJaA^IaTeqv@?l{q8mXGuN%rO7_i zja4~rlPCEj;~p~g`%TM&C535Ej1--bd8R+yJtx-M3VPwbBsqCW~KCs><*!PrRSLJFMtHlul9Du0GiB$RXc zMP|7^$~Ozf%!|C;T=NjG5WC3%{3MLMn;Dy~_d}4pYri+JuwO ztC!?P&nDgcEqW`{_WQcS(R(I_iUdDa%7OW03`v(u!}$jI>y>N2#$l4bACUhL`#Rcy`Dp@$t%q0&VXl;adgZ*pAV)0 zIBeRKT)g5f35zZoIRw;#NhJLS{Ag0BSNBtVt#Z(rj+{Ttk2-yz4Dy))#vv*DB9 zG443^Fm3sgrL*a4k~`t?Lr*4upAPF3-0DSQ3Tc)jn6x^oJ2H zC<(q;{>ih4au22g8p->e!Y5e#9q#d)V^XbjtDk$4o*uZAlZnZLoaLDA?|sGwzsK<4 zuzLfu_-1ajFn9;K*f_-8DM7^DsmuDFA$F3*@8+HvKl_a%e$N1mBqI~9bCpgp2X*{mq&Yn>IDtZdAqG_zE;-S2lUdZ7-N!#; zw)&@eY>2DhY`@)o(o`P4-*3F@_hfjWh;Ukt-`K(QWFu;v?6U7R-B-8+tKI3F&7tsq zH~pDKFr&?Ryyd{rPmrD}TYf#|L{aX94=U0RHBj-!VwZ zzmS?zoPKV>*uuViVo|A&=)J6j{%970COLnnuowM4bvTB#3|@oR7w{1njK}e1lV*<_ zJGNk4`)@-E2lOaEap)-eCzFdO78QHOW(#*H7_yWgLfJ+i1!@v2L#HPtk8<>+2Ih*8pb&YCO9fv`Ef5TjL#ayg251RjjXZI8n27e)U|j z>8WRT2|I*dbb8p69u+V~*rLOJbwdct?T|;e^dMY1_BKlVxjdWJhyAgN8Ny50jbvHW zGEef`41S_c|Nj-V|2x?C0*c=Oped!^EBTB%`^aPRE7p4*_-$otbg==tL~eZG)Z~#+ zE}DDT=q=Z9#(XOUYqtbG&?-z?<~Kr+Z+yyH8vY=VCy>f$eBM3?Y#)c_SK(hz}*? z+)^vcw*dUBecH{Sp9FRRs(inIrZjJ_Q@%HTNBNxbxP1X}C;yGSe_t&>5EGnk=og7+ zfNtHl=xZ$P#qeNEnmL#>Q`}zP03+zaMWG+Zg?wmY&^j5zLqEN@JusM$JNPQSG;COY zJp<-1BFM-Iq^&U=`i6t8Gk7@rnKd~7q;yQF=MhkoGWM1QTGU=O0F%aY|+J%kD16v ztuO8a{ULA|Q1h?$GtMM{ElOFDU zv=umqJ4-kV>G($#LV>_h^3B=BUofBLY#0Bp{OB#d+{MMm0VY1ii|17Fyb?cAEBO!H zsp+%eIrs^;wl`rgA8L)l{Ndr*QYpje2Yap3G(FpLjpkKwzXtQDgaZ6IEK99W!15bV ztnlNT?sZ$7_2E9#Ku~S*O9W0wZA;P_?rewZW_EX|o@Q@{>TeE8z!uSOx$lek9*B7P ziFZcAIabunvZA5JNRl-HyM$iQkGpi1XM*YOGpf)0L>w0Ras99V!M}?22YKGr%&Z%J zeiUBI$|oDrVbW$sGyj^KJSncS`g|VaGDEMwD!r1Kk?fIfIJ<$ ziSu_D|JZ{iIFh-(y%R`<`RTY(6;K!B0Un#h@LnqVkdgwIwThk;V43n z31o238?48>%={PA-({J4!CTC3rj-Hi4JcTTP#9Upd%zA$XQPCt0jGQ`W%(+9!I~03 zQU6;6`WoOiK$Y*Wp#K59o+#Iu-#F{*#AB6@%v)r1nO63cJZUQxvyOb)H1}-Pe`JxK zFu>IluV$iT`>_WjH;mn&0+f!`hUZ(>^B3m&nd!f<0==)h?-$HIKxHd4M&Xa&MCqvV ze#90E|4L^#4rp^rqLp4K%UAeoZ2UeM^clb$K#ebFgQoPq&OJ|Fylh2X9sD`h%{i#8YEly>Y((2PvNkM`HXe0et~*384778nj5xI!U$fj^kZnvD30^ zmc}uHle=cj*d!YmXg1(yMS9IDQ;U9J^X#v!T`(BzJ%1^;5bvGarC)Hc^$&tjwS=s|eF3xp*pJ5t> z|Ahlkf6TWjm=$`_6@uHzJQ2DBltLFvKI_4Qnz!x&{Rr?Fpyc)vXi8h|lk-JrRp;vh zAxFtx5rQK*m)5uyxtrlyBsiM{_ZHKhF^ZBsk=*2|JT*mJ1&%W^u@vv6mSbA0!&fS# zr`p$W&|`q{fZ}TkXiBI5k9~XxzS{1MN_+LO!O(c^ecT&m(|yrUL#X^}<(EjgG~)eH zyr1gtDbODP2LM%nsSJM({1WGH;6SJQ^x9=(7u7AlK(uhGy~+tV(H;c!15R=1(fAw+ zkpIlBdeKm$?4P>!Z=>k1y78h8)kMRSkQf}S_qIGngqQ36f);Fd`suK_-yk3@P0eDsSO@9P^D{v>E^^P~25q{VgD+-cungNSU)zAv;_w&ZF?pAO9t?~Gl)R^aMu^&@hy1m-c=Y!?wpF2v6Pl66c;YD!Uar{JS^pp{ml!*U*|u;S8QNYcO>FOA;@diWP|d^Cb_ZN~jN~~u zOUyz1`pIc}`XsE3^IZe5PjL0oONVj9*9-SZ3#Yr%%>2w;(aBH1K$HtDD#&*=AC*Hl^}$=w4JNwZn1k=t-b^ zI^Rb*pY&ZQ)X+Z?L=J9tw&Dn1JAz_oqNSu--EHpj`i5G0X*}KQ>%r0Z4Nq}$k7U$V zGJMEdVWZgQJyP&32xq!3E7$1lKGrUvzB;AztJc)n7 z;dz(M;HLxA+S+0BYAL4%$U*g!M?pUUJOd~>?Ey{c*!TanQfoxcXl=rZ)D2lebJ;Yl z#md8`%|kcT$4S5KrPs*(Q_WcZLqJafW&)}oTnze;K*cuM&h|R{XjiA}cV{5RY}UpE zYz6L-M$tR@vyAOx)z6AqtpwxEqlR|CDtW;)_LxD}2?(s32os8I{suF9dZRq(?@vtA zRCf}Gzp{Lor;IfRSUt>PR*(j8x*NhPL~6WFmZt^0DtTf-t|bAeuQque2b$6+&&%@U zce<~}1^3d}%p5CAEBg{RpRgp@h1D4~qJJ1#gDsa|r2k*Y3tW?+m+f}t!eO`B!w>$6 z)A5K<-Ur(&+=$QTqwK-1Ag#beS}XZ(1Ye5p-Jst9-Un1Y{0cf`yR=VsNxpYKAwLT{ ztp~c5?~MNz_IE5Qa2jxs%e4j7!u>eQuuIli#(LaHOvEzMW99Rn=0WBkq~t#nUY$=A z6>yq83|3x_@bNFJ8YKTS!JFd09`p^sO@M00kAtRE;f!0WI@Ql2xliw$cWm?@;9^t% zG(Jf78%%94RHT&$aw+?6*gEC&zUCJUEht2?KUv5gT2a$cfcd=2OcINyKT5tst{C4v zK@S3k0gCUFK~q|Fr?Jg~{=~Ecb|LQTdh!A{PYClA zv%t>-wmXT0ILVlSJqF_G($Y?*4U(^Wk*|{H^Pv9;yagz}egsXaVvpp@=(HWzE?(Y_ zt!DOww2+^$PYnE9IN~dG7s1e#5RZpbFWZW`xi8G~?HrQS45NrwLv+ca$(G(I`J3R5 z@i!OrGGHa3_`4PK|K^XvK^>dHTmO#?R^24|YeoKQof+}Cw0z)1K=r5lK|f2sJLeKg zeodX~xry*U4x_zm#CU*Z74%CQ%{$2e;XSCCP;FOz!F;VOe3D?C?H2m}@q=U}ywGI<)xn$$uE`czf`hISWuP zsNy-`$TFFQtGq*)-Q2ip04EK%N_nMvWA!-@^a;R8fT~ZN9gF(h?dS#0`P{Md-fbIcJYlYs&HLFJ--pfj| zimV(SGGD?W1+~4CaTzd}Ph)+JGCtDmYvkaLda$chKgn9h=we%>$~$Cv4uD_Pe_TG7 z76DQLRi0ANA|10|qj}0R>sXOe>gJ+z*TM_rR-6cH&*0uyDT1Y9xC|PnaX4AUX&DX@ zO85vk+ZU{r-zoX3N4|=$dq8go9tRX(e*;ZP&9~bfdzy}NUJ*MHj_1(_BMevr1^S=BTY%y-1zz_lHSb+b2Wh}#(P7Wiry8C7MR)T+3 z4>y9|4Ez~T<$D@5rA>|=)B_K8Hol-9PG~D2ZEWlQ%g`IIXQDg)N!LDs|EAtN5;_CR zZ95pm_?b*Y!yxSW`=C3XZ%%b)+USFluhdYiKTZQZ54aFe?f!Yt?*jQBNPf1wEkEz= zbl)v%qlOM89j~!%)iXz$rJSe^R%n}u>+&acaZ$blx8^jUyusXMo|l-r*b{~_@`>&q zp21qZx1?>2lLL(r&a!dE>ND)?ZTEA!d$(S=29EsUDhXO3{@d;1)wbzFq_0!&wFmOF z`|KWT>?jv;5{^d;97MP3ee`5&Cclse+^1OZtE6dfFkS{d176I+#;N*=1}-{8W#CcX zB;_Z6|f&nzkg_{iOkbOCB{hc|9 z@~zzN^n*xDj)Osu0VV*7&*`8k{m=e6ige}L$+4=54&<_D(^wDXl_OwLbWV~}e}g*Z zOj@6m|3&iAhYF%2sx+Xl38yR8_<; zk}ebF+&wqe%1Zb|1Zo0jGL`R;{FNuhXVfWQZ6BDj%D?|l$$9C~H zraj{8{;h5NVB36>F_LQU9HWv%MV%IZEYeQNXB~J@{c}C&JAk_YC9iFuDJeUtqwM*_ zxPkr&UGw$~lF-Vprob?yI*s1Rv=@E3xWqo4B~sHW0a*i{S{y!pKt76(gk-D%fMP)L zF&Z?bczeYfT3WTOZyh^_>D6aZ{`H9ILTjx)^azN1jO#cwfZ-nB>SyFL3sf+en;Ogz z9qte03rsbr*2krMHX`2%$d}H^wu9ac{2fsBcnI|OK)&N&W2a-swWrhhXMSzX!g-@F zXy+!)v9ZY|B0#8A%Ayn zU+**4`YbG_;8Wc?)nni3GdBAIaA!D!elcfYDQdzxCkB!%fRQ{|i_b!wvieIR`dpT%)Q7r1k=r(E(oO7Y z_cl5z9x2a;54g2=P#R1s;5-{X2jGw0uX{3Ka6K44vMiq~f`ilSY%DDX7MZT|jC1X35VR?Dj4ETy{(#OC#{=>}3#QS&cmHg~Seo7u+fyRnY zvjN3V3usE)PnF}}o-;eMGof)=)HiXHS6{rkrdz#Dm*pbh zpmmm2V+}R@uBRBzhfQO$H6L2(xDAFT8IYQ8n8tC?A2N;6yeAy!4B@?uDDN3KDK!tO zD20Ji#7zwihbjh?G8U$t58ag0OK)bp?nV~42|LnO&MatyPfUj~AsnADf3U>J_qv(C zXOu_H2;yq`?R;BzrKc6y1C3sW`3Sp#^-kn|PYo2qkApX+r73AvHMB3Y0@pDM8V>;| zhr-Y}m7idghcUXC_EdX{eGXdjbIh2+YxoY%_b|SXLBoaL$FK-H!1yoBeMI+-^A-ha z%%v{yH=V!8B5$$ealAaZke!@3H02GJehcH*bN)St&L2Xj!MDgnel5MA+feG5(T`<4 z)n~i3)%Z^R;&#x_0=ofKPlrHL8t|5Euk$|ctliFAvIvee7B5$QGp9*^oNv=vlU^mB zmEt);Jfqt%k8jnF7+Pbb#+3`lMIJcVLKF~vifuyUY^ukyCh1c!dSlGZ731s&h9Qop z!AIk#lJD}ISo^91eIBp@Q1k6)L`PwB>X+@SaE|<3(CIp5ZuQ&+QXwSP+IATqTF)A6 zm$5=Tqt7CK>Q=q%ZawcF{WW&Co_3G^rg66(zDGalZawiHxFtOl>Bn8$A|ameP$Um0 z5Mf^d)Ut51`)UMUFkgw_9)RwRmK$|s8qJ5B@WsT;=OQ*N?98Vkrk(9CHqE=mcUNOX zc&kD{e#;T%=phPqR1w0AYgsxEx-p^R%E0AD96snT`r+HhuT>qC z`8FeuAx^$uf{x~5Z40ROv;Z`vcz?zn$HAI&S5z+?2PTwLYOHNHinVQk*0xf$DqSvf z@jaWUNZVIZw|YqbSl2G<2SK|LY5{6yP=xb9p*stDa;<_8eEMBXdzZly88zU+k+cW4KL|VH!Rjq5U}5atBqEDQ2EUN} z%|!l+zl%Yy1=a(Kzb&9C9lIWu)h?=ASTnh1IgXt>vN=7D#f#vWKysMO!Ixj~wZZ^% zGSxeL{eXNGU%_rJtvfInQ2ll@=TNmn9 zv@X=GYNpfDp~Ot}yJvS*gG*xtrA0m6yh~WUDBx&lk#4=MBR$R> zI}_9{S3MzT-EMW=F;Zh?j8@{$@tUH3!kefS)AXsyuW0{d|J@t90_+QHeocjz@Odzg zY5&{~^U|eUjw-CPu-}q3I|UiH0(So-Sp(>N6w9Civ9A zN7{}1pq~b>1Diin2SlBD;PdxPKd>sWi<;JM{v-_ux4VBf*;A~u2j>dO+?f~qCQR<& zkIXI4iszMF=GyFuUFuFEmr7_Ym7gCT7|+YW9-6~zSO8(bS{jKBFC7-^QiwHGEU!?_ z$`AF7s&L+bL9vQ4^w(trqTLGz^knD$0Ny1+UFLQp=ll9)-N`eVCy_@u!~SK6P3Dti zKyNZ=p7%|d4B|chRKGNOX(7#3fnJ`6eh2&sSiMBcqfQ~%onenPvR(TedYc6&V;!-? zobP>F{Hu%v1)vi1C%P8pj4c1g?M^wxl1PQWbt`xzIA+yN_4Ipu#6FI8>FKbB~HDEI1le10(*cA?Jwlx0B-k(H%@KhB+DL$5cf8K=o9$Q8`jE!9OnAjn_k4BuQ_H z@FeL5UkFLjL!=sd>(?ed75gOT+0&tCf;m8fq-pQ#B^3kboW6Wj-I`3}MigGkwUVXy zZ3y^mBF;GRNj-QN`g!m&u=Vk;&=RVH`e^l*-j7ubZ1Xcx-=ME8udZi_=n`2cD%8k^ zwOqzTN0l4qHUYU$E?nfT2^B?(FcwA$GZe>Sd76;;kI_SQMN$uELvH{-0ybaofqnpF z+QV*aH(ytZ8=Z;uCoWm8b9d$nZLXK;bZ5y*dq+cQa1EkKMS>NtJ6Ikt_v2-8Cl7bx zmHU0Nin0@O?fq1Lg(QSCc5Z!8Je^%ZI--@ybksoK1a1R19bE=8egKc&YuX#T53}hc zGoDM=cSbrg6OfV}jjLDU_LaNQ+bl|3+>`Z6L$!XLq+h4$*Wvp06#e>uu~nO_-Sh!~iuzQRq2nzI|4`~4?oHFq z3I<_Jah`|o{yC=n zqYGrwvNVy%_pT&;+d9H$&e6GUZ;?DY>O1t)0hy!8A|^Dvy`k{f45B z1$5|QHX)2C(s(qHo{G?F>%JJq3CVI2%~G{{tP` zcTc&ubzJUoT^O{@>6Ie2)HgJy7y8=cNYo54A4~=Z0ZFi288;eC59mss<8iHOE?n|DMhWv`fpOJ^g-NQ_a@~J^@=zrbDkS6 z4;6)nhw9kHiFi^>oOsmedojAS<@8jN23woa0Km;V&Hp+cY$(l!;Um)B!a@3$8)q_B)WUq^#_aYOlZzB`dKG3@sZU3yP$sswgM~P zE@%mz(2tdG%E|>=#5sX@r|`_vMd&HzaQmRlz*v`wn^w*9R3vY7ZkAc8;g&WJKNLYC z#5keZ6_259a_@>6xvPgJ<*tKX3Qhr5?(?C)zufb*;8Gus(mLgG>m3Men(I8bBsN+^ zV%nvB@JakF*+!o2@UwdS6#73vRVC#qhW;Pq8MdcDa_wQq0yX9sd1~QjB z`uQ>R|00h#MlIDXMw^D#;+LjFfvR$iJiFj$QB@%NR^xfrs<-?9`n7(VXI?Xk1q}q@S$i6P-~vi zPkeY%o^t46U^KAuOoi^GJW^(gswdOcjyOmf2970c!|vKj&_^sSR$2j?@(uqD#BcR+ z2lPYWm%#FW4Z4&3nJ&@YPk?_l7^7wQqwBn#qK!Z+ZYqmpvWgq{z60IVD*L3dUT$(5q&N)$2RAV!PcNzO~?A&Mgm zmY-$!Iq7EB*%0vGLi|<_FG0Tr-T{{X$IzYRKUeEOS`DLvdtK)pbYSu!D3ur6no(UG zq)nk)#906Si76B{AsnDI2g9tN)*wLX7@ot9yR^qpM z_&xOd;4i@P{}Q^h{M)GpA9p0c)_{NYxFr9hpcjC}!17-M-D&>ql!GSBwcD$QjonT9 zw-CQg|0~e1gSP^nGMDY}o{hjhpLHj_7>DjDW1 z0|wHvR&GMiAl>k_>HZz`KftHJ$`#q)$hG(MpCUdUCoQhiEpUtbwpl|e(~C>yHDcD2 zFs8gWi>pz>(byPv0ke9CdK-J^gV|&dL2G&$xoY4WM^c%`H9(&M&H+}g>!2m<{4TrL z1%ZF$)yo&6SuRGJ&b>$@InHs1cbn_HK(WYWV-1(NOx9yuyq&{g34J>fzKq&-%V1Py zlI_acvZ-s7JCn3wms*M*Ue_(C7_6mF0Q zUnRd&*_ZmoSNNQ-j;JGZ@b`z|>94)wjehKHRrK%hf(VxpBqIGNb`#WlO8wepPg-io z4^)9Wlic^P7R&Q*alHe=JwqJKc87SyoZ>5r+$hCRhuS`-TtpdhCHO@0X)yGm;7DNe z>F3bTg8pxq`u+5q=J{X;cB5^oT~S|Wm%|j!3%=%nA?FNN=+`fULx(&>Z$q<}=iC|2 z?v+#EJm|7ve8vC{mRGSM9638XhL2m-jjiDvj1=}&BeAp|%l2Ss%#ee*l&L4z-E`+J zEfy>CRnB44s&eAJS)h#MkLCD53~Q-w;ex6hui#|uw&w!n|6GZyqW$G)kzU#ys+PNV zhB-5$7pu@i?Es^fuGPufxiBYF7C=TqgRt4ul z7q`348r;q%e&eUKow{pLPx#tMYd`&Zx3Spjt>5H{-PQx%Q*Mt0yLMfAmh~v^d3=u{ zJ@4>(>%9F`FE)KftGwcpM^xf*g#*4WkF$7M5ax^?hD+k~?ofI6vKsQ5nxG0< zdSx#ekC4ZDT}u;Li5pbjCV1dw`v7%|C%$4Z6B3V5&Qr1%=;QUS%rEwi$4u%DFH9pT zy#>o@gN%OGk#^fIZ-M?Dcmr7d-9YBL-_G&h(N5~7t!71iW8I4SsSPV^vx(W> zel%G3xIydnQ$u8+NC}|=K4k6xm1?seN8$WNkf8kOSxPReKWWl*mS-G{U*q~ zmv{4bwKI+N^*Bsmq2n0lkFvQJVNc@$Z%TGvP9nR1&K&3YNV#~>Rg8{7-m_*2tfr?*S1>Q0>5xN1qm@|8odqhD3GWVxOJG`nBAx43Sz z%PkVT=IPhSEtJ>?y_b|TrW~uI9<-`?YJ@*c^@^xCrtEpz*XT0;6m`70N=xfuYn73= z7I{P>$@eRuZw9vmEARc#5^4jxOly~&E^mgv^tO8?+HPd!cuv)NIh}I_7TMywtCfW= zyip9J2ROphC%gwL90s~m%-vs3^DrZyGc_sSVCen91YqTx2Q6XY&y60pJ=C5)Gwg)} zw+Bh-THGo@sYSI$;nr0a{X&f`NklQXB#MaHS_LR^dKQVHK(!;PGGAx8!8 zMUT%xZwIdfE9aNc5*`fn*uHkP)^_#OFUx<#B>Gk zDKf+u;va$|vzXH~!pK#9aI*b633@d+16aAvftIlMad>;@6q5qht_&*4-5zUX&&POi z7Sqj3Lz)@eB_h> z|FsNWWsV=*T13AP@LNpWtaqAz5c(=`O$xuif8TUXUD2=%eyM2_*_#4>ZxVM!!0%gV zby(C10|}D8k>6oIla^ni$H1%NK+-qR@dxUNcxegvO(SlJUGi-ybOTtK!mr}{@iVio z0+=EyP(7=y50X zC*U(+`;9N5C47e;wNwWtl|w4hTQyVXEB9R_4NFmDZG&-uxHjudmPm}dD5rM3DX-Nt zlk%JaeJ;2FSa~jn?u0x8SEjmC_%4a&H;6>5of~5;*&eSYY7OMs4nM1(NDXJ4Kq0X5 zbb;=SJgI&Y_O2c)%vVWaU{Jfi(N8V>tUT92H-pW<%5xWVXXHsgC*L`V-pp=OkJB2+ zvkQJ!p2}I2Suhec z?wmB6Q>0;h6UY;vos?%f^c-*`u<{%O-5GiII6vJvp`K3@3P!aD8a>?wU)$gP0s4LL zXJF;}E3|~nbpjdD4jHnzZsp=3rivxbOwf|yx+KAS4l<8V=p#45yTsX2<*R40;>WG1 zT!hL<2~*+Z2JH4go-uQh@+^T~1x^Q6p0lAP*mK<0Uf#%4e@f@2DXp2sxOSo**FMDk zo4`5EFLS%-0riH1jDEJk&+6wR=ug3yz{>MAw1mCrC%qAzlJucd^QyW1^IvcWxN*NZ zxc!rMw%YKYHaE$CG4yJ12C)2p2rZ#QeRRxyi&&@MZf^hl54V2;=N%Uf$T7?K#322| zZ`1!z=-uEOVEKOwEuqutPr8e} z8({f6M;iXSGv*g<^)X!mncT%+Y=y3ZS5OInvz&!Z=7=o;|7pZ;`LBjP8=MC${|lkN zSNhv-Je^AmX16FyYwj~u5l2=&pemkj?%{2k668O8tQ=oMM~}h}2C#AzKuhRkIqX1+ zyQE6qVyfg{sgl5XNvh;ZGs|cGFxALY3qLE*2IyHD_ zZsN6iD4oxqBp3x`t|P7$4uU=e*n5NRIq|1ESch)opFA@DAF}~5hpmSeC9|$$*Krc~ zBE@w1*p~R^>Su9g&5y_d@{&+LY^l}#u3MrGW;#uXA8Pco2^kW+7yUc}{WN$ESpB>R zEg^HgJiQuM3~ZAxI8t8JSZDSt8|4b|ACX1CInM9xG3h0=1pK=mlho5>=)=HFVENC6 zmeA>PyN5%KJzBN4GAr>`9cJ{<3?G|c&qKcs-Ue2Vcc3M7vfQ>O#a_#7YamC(u}L}3 zgT5GC4y+s-pe5`@A8q5W^gKFMu4qiGJbn3sp>?Y`$Gu>Pu2JI?=|5YxTK{Iq;j3}x zYKCbY^$8+J?R2BRR^+n!8*?1?n_wESa!-er&|$yu|61zOnwhi^gLMnRJ+(e?&Nh9C z7Ub|C-;pc92U7k^e-L$sf`!1=)2+v|PX;~@_FXp@HtPR=Y>!j)v$1Z~;-T!gvj4Se z@sLSN>+6=&2&8>jF>q5785Z!2O&bbN7oD>7qmnm( z<4B<%p&Q&XPA0zRdOKYXyZ?fSFnBF6uem}$;6{6de(VlW*<7dfh|9eYS9DMQ zRrZB$=$r}agtJ1WKbXm8YBrFg9$Ass+{iOxgOU}=%Xlr~{e5z=NhorG`NgsHMw{5+ z&E~-Ixt{l=8y?Dzr5r%L+r?*O*gw$gfnU^p@V9efte^6^0;w!Zyh-Nd9fY5g@ddes zV=;NT!*$2zhvGa2=7#d_aC38t{h}~G>(%9;lCE4w8ty)>TTb_}-9p{T!LcQwF88=a zp4*dO$TcE`Jr6|Hy~dOc?xlKG_6YU7%q<@9S@kfXJzVz~G(sWNww z$LE{$Z6e+Z;+6V;FZ9pBBf#?g4fJ>OJ+xs7)joygW-jrt?pZ5@?YQ7FkEVcc*AtR@ z9SnUSI1Jc!=S=8xL1w?Z^AOYiq^El#ULN7^$8T{NmK1^kKr}v{D&7ll(MfB#fPK}T zzX^NW!uWBd_EI)p4|{KL>>U#qTs)Nd-Evj8vYy<>lZ(uMbo~;?8PCsp`JP;rLTEb1 z=I zVejQ?WlFi?#Qj0yf@0=5+0GX4e%CpW6M|}(f0)$k(f%oB2pT`m@ZU}RmVeGde8Pj? z!15mq{oVXeGUW@_4{8M!Xx=+rXKoeOoX6Bz;X?6NhDqMxhCMb~LHdLEC7&*Xz7ezl z%m1n1d%N#vpXvFNw*PmxOiKFdj&=SfE@K;iwJO-ig>(hi%I4qv#Q3lL@z;e4t`8Ob z+b`&iSYy<0+fFvek2i94txxU;90z?8SPpFYKOcG>$n;xL{E;a?3s#)oxT<03%GD>V zT3SB@;{r?vm#><;WLf+I6Xpg__jR zD0e-VR@GyGIbdiEfjA*>)F9mEgvBp{$``|@Y;Ajawm%@q=jvLc&&BYo3go#G`d07& zu=;!n`fV`nMk7yEuz$bsuW9;Ru%vNu{fZ&t_i*B*HWdb+E?iC9BX(t%o2&gMi&@>{ z-b6+LQS}4NY`G*g<_zZQzPZ^)N9R|mA+xS_-NQrO!~3ZC?9ee%Kh#RhH{R1$gc<)& ztIMfA!KA0^#H4;_LLUzn0$XlZLQ7cKzJ3FVXXtcHS+2ESuiKbLZHY9G$w^s*NY5F? zqsp<5*bkqQv$C{yN8nL-V{is>!vZ7E7Wl>CC;9yz^ao&PAcN>Qb3Z!B=Rl5%feTJp z&?ZLZkcmqh7Mwh1$r;jU=OaYEvov2)gB?@AuWE5J{l`F`3>tw=|E&dF;+PGh;65YCEL`YJvyKg&N=9md^WBUE-2XTDen zVH+qT95<3%h8Iq)E$(Y&gm{Lu#f0ibMqj&-FTs1!SIH7+&>vX&heJ!qyoY7)@^icV zAxEIIqUwoQV3i%j9lP9^#cn%Smo#j^5cC$kPNrTVHR1{uy`>Sb3g? zme85r#%3vBwsCmY@)UpD1w@^8(vo%~4Qn_ix{Dq~Azz1)I%kbXUWJsra1-nm)M z`yBl~5Q{z>Q7SLInwy>KqTTV)h(&Sl_`^6h_uHk6m@Vm_3@%vef9a7Wor=B_P8GU46r7+pKs^GM&EPWZI7iLn>*VyzMG6u^RG=Ce7?5r zebPhWOK~FS#?)kIavxe`aW5RjRpNYq-)KcFR53|a?lXbwv<}B9OKG&w+sBWW$A;ItirlNwyZJP`n{(Ov`WN4>q+kl-`VIM#`*SacT6@;&%@k{UWIXeFS#MZSXF=M zs!NozUhY_jTV>=-EKl~|qoEH36M>a;2DF6g@9OUko`mBV#eIUup2KRMcbc=A)={P+ zQ)C)4*56MbpKvw=e4B~a>ZhFT?ulRyu;sM05x*>8Yj9sh#SNyMzV>@F4@qwyD5vlj zXSOpMmM^F`JzV-vxO#RT*ISGpnK`;xQO}+3E9)mNSw-KJ@qZR9o7}Magr&(rT~Llr zT(E4yLe^7cQ1Wj0U9tRMrC(3buX!>+dD>eaxl#?gN)5hJN-qEv12vzSl#s<(HX)kiYs}eTm=H-K;L}K)O}v-(=_k;?1Wy24p8pG7 zx+3b_HNceLk%51+$?dkg0pB_Gb!~}`s23YlK99MRpb?JNsYX# z${5R_z+=>@wBfVWf8|mSH8*Q|&PcqU@dX|tC%X9ktf0k@x-`{4a@`0M7Y@1VP<6J+ z-zL(!A<)MS&`*G;fz?O;O8i%YildD_*5(I#*_%FQvWiI_^ltWk9lphLo4LAKKQ8BF z0`Dg4*AcgnfTz9dvz=#ALa%5nJTh7mHVVkXuiG_l(XeKtm-TA$2Gwsp9(F?EDWR@8 z)BX9o-0|x4pK|Zolr5r=TUDe;D`c5E!Kj0EMos`6p;qDVwABrbkRicNAEiuISb!`1 zy}9`8$#aJqeQZC^=wlsejR*R;4fQh1Apvx+`o7~lW*(o`2CVehaUIW{?)_Mxsl@lPkUc; z3!Bd&sA%6v*4vzK!gCu1%JU1`L7p4^lN(k=Z@4(9S&C53&w({=l_*iJ0?0?fpbK+cLnz)#G>qylx^FE6^*{YCIOgWjL zoosFh_|_0_b-;He^jdH+uzc@0R zi*!-Tvms|=s1Hhs#r9F7vd5}fSe`Fd`COa`r55Mvb8myWjZA$c&W;zWg5bnh?IlJ} z(bJOoHwAhQI11Quy$bpqaAV-N-;Nun?X6rdtY5L@R2F=+^qCEG4gg3b5@eqQ~l{|QIt!zKkv#|nx+4Itxl)r z(jebOem;_X{|wq&LpcC8J!e5*3|c1)M{2ld2 z5hTxxvVLxmk7w{`I254J@20x=MSiTj6t7#!zmj2H`xlc!`&X!n_8qTcgVQRa%Wg($ zHFYE6J$iv0GrP-E=SZpl+T|`Lx2u1r>rJ6{j*;5QPSq7gAFZUdCeVj_dekWZU4Si* zL!l-3FPd^_&)=liPcyU@^KTZRC6U zNHky7vs|H9hBd#Y^+vuX_*?mIguWa63|RSEp(RY;WaP8!py~20s$02=Nr0>$N<-?$ zzmk?;)(;cTHt&Ar^v7Kqr}(m>C4PP|lH@{LMvl0l#VxqUb1Z&KySgEoTRGe8+{kPI zzFRjKIV;Xc%2^G4D3}SXoToxdSQyL~Z9Pesb4|kvDq|3FLF72K=5SN$E?uwtRn-wC>{ z+vY82;*`TeHg1m@4jY9HhMPh|I}IH8M0KNq@K14{*Hx+*CD0bkM2=g{6+-2DfvTz#P>SiRV1 zdcLKtv)8lCUZ9uRYi?8HZ&d}ise)S>@cK26tMQMig2z?CV>137qgI=`DDhWcZRBZ$ zUsv9XJl8_s3~mEfo*zR?*oz%Ox@f6YlcL{|?Pg2Be;4sv{v~I#HUkC#%fAv@LWlMg zd*%LJR(iBc8;u^;z{k#SZ-o9Cco0}Qwm?f5eC6KC3;tyFq~Ekml_^crHPkJxEs>^) zi5p9iuVZTfxS#w0FTr`79~n8EA13ut20Z{&0xQR0XbGLp4?1qihK_7Awg-II5U

    jN(Pa^(si+yQ}qUQ^xicd$ww600wZJU264z>yPR%RwR@_U;Q^!{oSE}<jV=1^>H$3*k56Y17$b zp)h>zwj5zF_2rRwo*GYt$m5!izX^S{pMd=>lj0ColeECv=fLq7^00xcjyZXX z8D}6^`J~5%W9?ui%OKP30wcfui}Twb(J94HmFARf_&`t$k0l4sb}AjY37-D0`e`1V zK44jW+qQkCTVyS_*PmB&w_2|yJ%CP;aH}j5S7sdaUbM7mA%6yZGy2J{mOXBI6D40( zAfL6YFg$wC%Kr!OKAwg5G^0yCya)A$_pV>=7T$wql(D6I(K`MNSUmp_AT)~qU)7{yG%Yb~b$&(n}=`qQLe*Xqc)`n9OpXIc&y z#AyG)IU5HBjm%>EA#TfJ@ZnC|afVyB=7YG~pcZf~lw?%R{`v3mWxKNU;K|ST#@F(n z8@~GD$Is6g1)FnH_DP#S1m~i%Fr1?et9P~xJtxuJS$s}nI>OE^L#*aK8GVi4r?jT( z)#k1~c;LV9&-az<)T2Mez5Dat-Mj2h@&B*>MCT+Of93d7Lg?^zJf0YuldXVHHFsXt zB^kq&kO9@>znt#k8pAo(3Dzq{R}Hj-xe|58R^5c@B@>t=t^;MGf^|7%O!Fn`>;rup zdPhO}E*R@`p}UbU4^vJ<764)rDhU4vcBY9OSZ)2gHQUz7XJi6hK2~7r(>6|!4{o9I z^gUT_?WsTiMg1oTTY2^WPfcF^pZpi~Uk&_u{+q&voFc)=Th;5E4^(gmxL+L6xiuEO z|KR8%&ZcfQx7PV$u>=FSuI9htj#j*1UZ5WG^S1|vtFcaSF^0Rz|4h$uz06a-Jj(KO zvX=7zY_rNgDTvNt80ua89v3Q3`YU5;C4Kpgd{F|hL2)~p00)oL$4j(|s|~-aqh0Ya zrg>uG^>I>1d^+Uzr;oIdaL0HHpK(fLVsFBm>`&(tpJ0q>nP7i7t&tr0#>qzj%Sld! z#*$iZ1?!atm%rzYwp_XLSb|la%{SXbB0rFLt>JGTz(8h2eGLtFwH!a9bHo}J;1Nx< zz?_d#%?lSo`fhSm1-)FZlgrez_@>{%_66zHKEkA;48%IQzySGW6tewfJ8S;F4%4b% z!j~~$(*ZsVW*%{veBKjr+8$eoLut!NF+H9fa`hjDxEG@x{q%Y%=ME?KpI4ucxQSWB zaVix1{QUaUA=VT|NZOuUiX|WYZf~r8(y%5oFr0c%P#E3;PQKk;gVd%y<+a7%eJ`6C z!e=Shkd2wz{9dMuh&85 z>H`ajNEOMak`YZU=aIepiJ4mWE~ayLX^d_TXg?{=d!f|3{kkn)P;Ibi1cw zv##*JyGC|wazWnU@3VJ6Uvq!v`(p}<6D5a^8q3$yib;CuSZwoW^D9cFGj$v>;oz;* z=Jzxgj*=G?w=)>DBjF@HEbaaf={cX0Zjuy4j8orYawVX!wrEI>zW7P8!_H{OVb+9g zO218TW}@WbB3r)!baK#7P7*W73sI_eaQg+q_56h%93RVWSO3SeX3`%8hz z&D}O-Ui6ZC?O-d&`9$$(*moLof9G1yzDHWE{i91SEJp565K-W9zvr@_CJ-AFNuyQ2 z=o_qY z43J=NRz0&;h!s!rB9e!Rgge)kgrJTDFUnbu;yuDxF(@>aEl z7TA~Epy`*o%=88~!OXSrX}wn?A$gZr(^>M~ZTEib?!=`uZS)=Tz==W`!J1^4ovC5( zap5Q@2U{K5nqT-iK`WOOCC%+>tG^GsI#2h>$a~LuF?egH6N7PXkZ%D?X8EOi<9j3` z`_Mf$5-lbp%I$9+M|UM7&+ZFDh&I2p;;al5HHRl6FIO2lz9@8{A^HiFo>+Zhgu3Ri zYTy}G?>9x_vAW1rV^|$dHK`${C(tUvFePX1>u(!^L%21FI&LSsjnv0FfDbLJ<2O{DX@rmr6S(B_CB9)*>v|63(#Fssz`dH z7-VAV4n1Ni66lqB3JxGg6C|V>cpgmQe1Oyz9Mv5Ez~bxeB7U!Yx8Zh{=b*+jYfwsS zn?I|*I0*m&;7vULMTVB)VB$z&!WTN$6>51BXPe>~$4|F5z$mxaPLH?2v$q4`mC!2J zdCT)>fOpDSeZY!;DDV=I`)g^>h@%()9V-a_@Es2%F%r~L#tEH3Yw4e=sjR=G`dNto zHUyreL7K#%)>`kSrtCWtEEe{S+UCTnSv-KrwE9N=-^Roy@p7pj9_6a^h<41k7W^wUUFN^V&bRyXjbN-GWsqukEp;Hr zsZwm$Adtsl1W(S|yTOdFNZt}3VWQeADpeyleA{j(CrN@%p4VPcWiLEW%vvEznPZ>!x2BzavNGtV(qR5y``{p@L#pSWmWn&bx}N3Ig}!T! zOTEjPjC}SPZ=cTjTIi;MbR4Mpo=(MyL0>&_EVc<>Z9}xY_j4oHB62~4!x3z(`#6NWLVEKs}Z_+V*1|&iP za&qb=44E0h!+IORw3)760L=F?Ck}1_0C5bPebiSBbM4|kmusq_$%-#>!i9@D9E$Hk zq@Y0B!Zl1vgo9B(rrB^Uj+%n zDLmB-v{GXH0y=1$`7WmpO;hWG;5+0{YOw(P5lel_^vizB$XgzjHOKpyF2)zj*@7a4 za;UidN_)ytTah=8k~T%;ZE%zE*G_vyc)I&IL;`e{X^e5Ol?l&w5tQUr03GL}ZI-9D zRi4_`V5B(C&PR*H!@8-W+#5zq8kHg$%y=oiZw%y2RQti(eyBWAOFY^a8!Bv^D*?0w z50e`t9C*zIgq$z%nY5ACSUxBc!3?JEMpNcqJ@c0w>+!&` z#vL}ok@ZNCI&Ji?3eJ8MV!IP_JlSTg5H)cTrb{qa2S@1(wz$)Y9QdQ%1X7gc4q4$z z(FP#KrN-H#{3?P=zeUj}EO>%Q<;l~OulM0^qwCW9sMEtW0~}uuWm|C9pk=6*2+ti= zT?4*^@KX~R71g{3iQ=FJnAr^iaN7S_#fQ~hB1lzq5o8bF1&_0zhwbZ_C-8ajMdz#+ zYv;+kn-hy!d~a*?{{1Y-$^mKmFzE-g!xIM+Hhe$+fz~$cSs!1gT$6Hb7rwtX&mmq5 zNkLoLnD~oruSb-d-L7!jnCS1e>=B*)Gk(^_pB&S+rtpL1xY-5GMPry=tZ9G0xqtL` zuNU0N?V2J^a%qmLL}9e;7!_{Y@=;y<@%W~#wbA?c9ur;Eb!PjTmVSwYZAq4^h)vn4 z?mV&LOZ;HhF@r3Yyrjs6{=B$#kDzkUN9MKeC-+GwG+VZgB!*aX^ml*WWAdT#jc1P7 z5MQZI7HLd z?E70^YiV+DYCg;kl~R|8>FHds-v%;9ywp;Gq*f@iTKcG=ELB2D`5XHadp;3=XaC>| zs<4u7PbeXrgF(S;kMgOzktbRx>2EoIU>c2y)g_ZvjuEE%>c0yXta0$x>mPRG+)uEtn2(1Jr3-@x zDX4C`=}x_)KGguxL=S2zwVEOqT20_4SmJ78`oZR6_vl`iUb-;2Hm|0I!KFR!&&j(F z((q+!uU++D2TMWUM)kiz{l|w^>{S}!2EF6X8LrRz;Q(ez&KVA~)jw4#4R#K94U?iGuf`HE zYb@ckak26=g-uWO;juVWze77wI3#c8%>%BZ0jPMySW*ixZhEvofzNZ?mCm+4bjs9wTg^ zU7svEXiPgBVAUQ}DMMaUucoSPGmd&FPF#rdFq*H}!cxn8pFpW}B5G=}v&_9p$)g8i7&u6egqoAEAeuyFGIhob#3k!E8L_; z>5;xyY%~^!v5v{mJO5>{WiGP0AXk|9o!5SJ&JgF{O%x1`f}v4f<}|7-2-dFwm}KO_ z!w?tYbqlTu_haoo*BC@TpO!HY;a`EF(4`%B!8hc?WP8(;?M-y{b>b?%XAK(bynd(- z_%#y2{QF%z3o;1#$&wH6^M2%%aaDb>~h+|;2&=|^VJBRC!)j$wJY|J7}8>wkrTMoC(qDX zIPC9|{4C5m=u*8(j(RmQC-tt10yrtABJC?}ACR zNf<24K6I`uuX787;=KEy`bA^j6W!$p9q{nVaQM=be{AU6_BObm1Xkf6P+Kz2fT|a# z4jN^@2~)5x_;_$#XZsdTC4Gn`J1z!zvP&@P$LVcD$B-Jasz@#}_^lsWT$>oQW60Qo zGZk@s*!ZM&s3~i9!yH=1VPr!~>yzV$mY#>fIUCj;>c{-GL(5f1ZKC86E54>>U%i#f zQIMKuBw=H@*T5V4Fh;_q?KJ#a>T-KUkU~@_Go?_EK0vVytf<2pYgJHj@ZIK|z#qL- zLKR`l1&gT9kPlB41CD%K7Y-_IyG@@a2d}J6L^cf;hB{j+L7gkt)j5KU44y^YW26 zr{%BC#|>V8Pwh`aGTM}RG?1#&kM}HpRFCp#k#hPUeC{ykWc$J|uq$Eu3Dbo6?T^YY zpBd+s;p>kn?e6U8oNm6HtA~ui0fw7{SP7o~YtX7{@3m?(fAZ^}k+0vE!3uN=&E@J} z-O)MYQ*GP2TeMX5j>B@i`@_|Xn*aH*JHN=lZi={!CT{_fXf(*>#ukSOu0M~ak;j^U zm0l6N#%2MjYq`yU*8~4o<@aAYMEPK%|9k9wvJ5CX1+T+La-r_E*<(Rxb4mPhbz)%Q zy3paxAju#K-YqgDT?P#4cm{wx{6yz`kGg=NQu?D@`lDQJ)|k>W9BKGpgDehYu~0$H zj2Kz7!<+-)iQ#&FR3x+uY$i-E$fc9o{Ng6o(@uXT7ROHR|E_SaX4=^J1cdJ#l!Nec zst=waQl2TCUKIR@7*9&ekTc-t<1aeLrn~aSi^5^0aM%^I0U?PYRE_$Vn!vBvhznEB z8Z$D~y7trVEG#$cdaE1-H(v^_ z>=9TE28A&=a)2j)IT#oC$tJUTl^yT5yrdrY9BOuKNdJ=mcacoPz;rb+CYu=sCHp?( zq@SM~-#G@TWz!F4SQg!fM_ZrHyuCB?_QOB>w;Qr=r)J*1VsC@bF$a?Bk|UHy|0yTr z%ZG3WZtx-%>H_cGfuamqhbJhZqVywKa^%++oulv$byA7C4L_NqP>EF`&+daR8=+r` z4Q7=fTgxZ<%XW69%8BBi9!s9fR~+WLNy&qL@Xn3^%+tn_XF0(iN)nWSEOnW3Eol7S z=#3@M0j=w35lx$n{O*q#tS$Ikh|?#wn1Vd*X7Ey-%V2rkpPF^buLFbISqQ z^*T-suwLiLXI10MNE0s$gD*`*)h8o2|He;@v~a9qBJ%44ape$NEMS`Q0nE7mQ%M9SXWH<1(I(T#BS?Gf8-OvahhSo)0 zv&6x@e{k-ZQHiexgyV;=xaZ(mV%*kMnt5l1D`_UUAyXJOMP-Dd9R$;X@{1129{Bua zpYT=Lc*f*2acOZZabhgNdb6F)pg3;+H?xBw>Pl4(!c{{t>ZPp{ z9P=}E?pwL)>8W1t4`m0k9C_*WexH9){^hsx%J;zMUUHxF;=^#=#F$B4sgK&4B)tkh~=j;Mp>7_z{ zl|1YkQ7o3elk&IN>yib!aC(Yh(?4Z!IQaZ-*cteOr=Bv!`@}Se)d;cj=wtIS(0vkY zi|v3>jEx*8HwsXIHl&&f$nO1Tfi7_;pHv3LX0tNU0^qI@M6Cu{h-;5YAdBIUj9VU@ zD3Gqp5p|Q=Jout>wyKVv^42iH4J3mFpZ7ky2n>%AkbATgmG9GQZJ=%ZWVy9AXUF^% z@Wo>BfrzVLwp`49k+oZ8s$~1!5mA_o;iw6uI4ZNf zNk%Xekq3^1NQpte;iAQbL^b^!C=8hSObK=fZ1B($4OLd#LWZCWW0rc)Nmd>{rc4JH zJ!A}uZ8+CY{CEyIYZXq){{s`Q$9up-?ooQ%4XRjbEkzBcou{$ zJqwcG+jr4RT+vB#K@j*>^%!l_VTZsooho0G^k|Er)|AFZ7w|Dn0pl(-+@5YIFiPmnIIm7WY9^C@e$mqjs=;n*fcsq;ywoGASahQZG z!n7&KLzBqq0Ox|hse7xeL?Af%+N^SNvlGmM#=FwL5F`eKwO>P8Y}hAl+^CsgTobtv)$7=$EZcberBr|T z5RJH~9H0{=9lG!|qNiLxGLb45bJF!OG^BiFVIk29PPyAY?{O$0%D@xE zDz#}A?-GC`Ls?#R1~E(!Ru|GYd$@_KE?B?PRR7w^NbSXBN%f^)HTvwKU%@ggiJt6O zbMpNM@nS&ckb(B?{ z3;3Vtb!Waa6JIZeip&}cEfXb^bwP7Y1VoUW(X|=n8En0Qo*kR7k0@X5%AexPm%H-P zEmShR#{#Dw`fHWRf4+{LPVW-u({m0EW~WlyLQESQjm1Oe=^^B)eBv#%O!ceLj#DY$ zLOvO*=(T2p^;hvLVf@dRCQ6RzZ?Pl}*Xx)5MX=)g3^49s9>rB62hA_Pp_I*lX=xXT zh6kF3*^me5g%QZCuiP5Sp&TU3i6N&A0cY$8*RHS_(9YDuVfJuS%So{~mVz&7p=7Wg zf{)VRoC#TBXG^(}m!_mK>2#{liCAhdpF&OrkeiPab*WWS9$G!TBPlDfq$xEh)H zcHaXttq%H`suE8J&weS}D*lhukG4Oc#szUK z5sf82Pc0jwb1cO$IcU<~W!Lvh47sCNj=>GZxOx*=a5BChw{ek3ls&mVads)QFYK9T zQP*xC2r*x!;OcQ;(R2iQI6g@Ln=m7o5FTz2l$I z?9e^G2fBmT9yf`f=q~HYZc7cOt{ijS(?7TQ!2J2)WaPG{(A=8P*+@Z1-+W>ibb_4Y z1bVqx$hZNvloOF0a+wvD%PW$L!}JFBmiL5hE6=cZrGCNQOg{x3m*L4JBUk*R>g<+EdE%TT0htq-_sR;fQR&b)BQQE4^;8L zZ*zUm0Kd+Pzf|OazmIQdeYq>%(X03aJ&Vt>;y zyYa1GZaGx|;Rtn-_?(EO20_Y1$xFH*-^1xRq?P`5oj%TQezxW(v`PG!#fP!#Q(M>@ z?a1`fPzPt*v;6NLsE%Iw-whI1rWX~kU`j1ky>a^I@am_2S#~#O``bRB+23}pOkY*3 za7QdYup%~$xlxO;HB0eoD0_~YpdaPBZDjgjBDGG!8*1Zx0Cl9150slck>X*Z#I0 zw!46RPRS|F?%Rj^__l}*Dg1YPPC3)QbNRG2>O!W<;+E6G&-zU{$UgIVw>jSh)sI+L zPjr`K-KD}V=%w`1asWW3GavARj0~DRcz>-G`RX-b=dI9`^spynp!)rNzogWvUGMMP zX=w2WqcDyz#m2ZwzWIpvwZ-E)erZU!+OBTJZu)SNKhZ4AX4Jfu}Lc=8lT{;u<*F z@D!Ic*yjSi0QZD4vHw~xvA@c~umnd|N9PtkAyqn}n2ao919*wKCLpup?ZnMslwc+|(?7CmrV*9a=`eX|UST?x!;Mo}KWA*QU zrT5vtzokDrsqHgi^d~>r{9u@0;#Hwkk-V_rx-ZIw^E;*bLn12$X}RL9#uwFppJ}*U zC|2m&TtvZs#fd>*{Adg*3Pt@$^dNa?a6g@hDsHLkUaNWkrn=;1=#`uva9mwoe0x0! z-MGN&O^Or`2(it!ZG?3<1&<}=4!@B8jex_sTU^mfjYQ+7{H7c>M4cf928YvW79O$D z5UdbfFid?RElSN|Dw@%P{`3~nU-XHo0@ay1QDd3-suY=D=1`$x{lIxxm%_W7`AGFN zNeTkH3771K>x(_sc)!iRH+*sL@;dT2WEPh1(|5ezY~TN1R!&yUsn(-)wj3sSW2q^m zSHFNl`Wh*7p}Owr@7p?xJbyp<2DUp9Y5#Bx{U1;vw{Vnm%znFf4UZzwT(<+5lcNq{-ghJne~6xn zml=F6XNbnp7!b5ZnTFMm&uCP`7b8vkWnOIrq=@I@`4PQoy8%TC@9!c zjyu2T5spN#)~}E+*E70WoKB#FHJ-~1H-SH1y39){_+z*a8oPB=zKhRIuFcogtln{bf@FMTx(bt^k zhfTMD4;!pR+vgi0O2*06O$@p~7Y;*hdrXg|Q4%&2Q%It$G-DUO+>FyX0=j?ehof8G z(F1Hk_IQxP89o=;8j5l9ZEU4j;lg0-V=iTFI1WVB@;o#x4365}%i_G33xjQc*iB6@ z=e-OD{Km-GawTM}fs8%q_nM>MG|{g~^m9RfKQPUmvPnkn{~$xjo0o@l7`5JLb<{TZ zE*SMEyB}otd9?fU<6)VGhaBxLRO5-rmIJ|evgE{j%b^?QS7T8yZ$vB&4m~m)#KXSu zu%(O+xl?5lBY&m~a@&B->Tgoiy-FIq`UAJ8eSKoj`oy`#WS>RbAEZjo^Cl;7!^|pW zZj&okTuf3MNo+$#(zi45p!XtzU7UU>CPScnFjk-hYvx))n1UdSr757Qi5UR`&EqvH z=d6ZE!VSMt2YN*k+_~Bp`EH>6C7E=iO2Ft2rLR~6_5dYM^>QB?HEmdvx)`CaBRAX5 zRz)$l8d}2em5a$Q3<7*#NplmNHEsFAU{l_G@U_dKeUTU8Ed7(2^>NqBANUvR<0QdY zh|LCo370oJU;z0Fw;DmjbhFKW2EDws;WN74?$_d*{cHDY*=?ZHZp#k5-fqvVHU~HD zeqpPHaOT_URuP~f=rZ<^=LTlxsYP%$F%$_9EywZ z?JYRtcwZf_Sj|-G?R7G1w>#}s7$_H(QGN8%AhDN*Z3LuD5)yoMx_foEJ`s>R8{7j2 zWV>5d4=^>VL?0#c7rznsov7}1XkiqSz8}7e%>!v#6tNJTU}c*15u6>ZzJ_{4%QQ=aGj38}{IJrzsRrxa1(>ZNQ+`|y ztP))tH^}S1W2nD%sdQpY@{!)bZ!b;};P36P~Z^yByNBLKOFyrw0MA43Vwl*)Z z2dgG;PSq2as*AtKJwu#yTKH(n&d#$vvnp;hKqkX@9MLhYL~u@qEZlsBo8Wt&cZhbM z#cEjKG&nlDMBmL?v)>plVnMM=mFRMe?{g%!~lyTBZv-i16bTta1&h`I~d#9@pOOteTaTv?|xV6_ZM=0e}lt+ zD2%n|MH1E(G_epGB@FYHxCL+D*h@F_90Skyp6fz`iGh%=Y$1;-deBLH@(NUFyT@So zxu2`7-WW~(MvQ=;ZuKRKUKEyY*E2E43I0bZ`p;Ok%vIo(#FKe6>5wD=WSf!(q|ZsPJgwI^kow0 zY$Uv~1aA;Lg zdQuQPZbj9YedU3P#fzR{XYXP4SF_H#UC`j1a%P3pe@dD!FMQ}8mMn^ZYE~GY39fux6w>#FxfW%Dw=wuqHX7% z(;r7h2TK;OfB^hHRKGRP6kS?l=?Y8KFdYiF8tL@+<$N#wFz1UVxb5CHhcoituIPhP z{Ri4}LM(BgYM@J}`kJi9P#Bi!p$P+R+Lzpv1wU`$aUM^FIKEwbWl-CfDCqkQ#X=0< z(5oDx$?|bephgvDI4wC%9cXxG6NFGzmI@XTecy}R567fKc3L;J|e7JPlB%Ip8d>&_dZ)W)}!vTjLV!8BTO8ws$Fm)PcFZ-`?@bu-4u618v2nY z=DpTGKwOHILo!%j2f=b z7R;gScW-o!XSs3S7P|rz<;j1A-toJqV+&Ss{JuhMwrj1LqN|%XK_eDIt~f zeHcGdCH!G|%o`>F{tz)5`mq`Uk?X9%TuNNktEoOI@l9KP=#|8&YCoeBph5sx)xh|IEhd3`V zkor=Pr5CA9{{`jBf^A=QQ2Yy)@1G0B2Hnv0zQy)uzD5&xs?GSSIVxizHGrOr)G^Zp z&X#H$XRnT~Qy;)tF<1NHM7*vSxWwYKlKFWpo1{*&6UTZm!E=c99KF0`tWeTgf#nNM@q5Ep5Om8K35AH3K`Ivz z!-1h7_yuetB38+`(6~cM>SZlIN@5zRD;CF8ijiz!zz=g}gN5o0B@L-8@Fu8qrIi}A zbiEDkTSnV-o!9?hOYrKShndp(FbCKD$ij0I>=KLH!1>G9X9v!|KO-DCFE6lx^C(x~ z&T|<*cXAkacKmGfv-0$q-^_`}3g8;+kn64xgabV;*Rf~Yi=UpH)3-_)LpJu%u5m+N zx(*PkUt+l|E1cSPe8R1_ZxE^*6?Jm)%-uEm2B6YdT zG3S7KB~A65KSeFcfLZ)Py9N`#C>J^6_c;HV_=TKINlv9bhspTuTxT=op3&&L(_GO{ zUkQ_eYxE z#=VXO6`B32HfRBq_NxN^d4dfX?=~21ZZ(`$4ma%%lSOUX%}wN~q_s^+vz-pmaQn_M z2sz&ck5Ed~&VW5TCO5@i+D}h~as3Fcv;FjKHwMeF^#MTb3Yc74jHTH0X+oF*cjELfq#j8vG|cUWtxPBJ#9s3y;>i7I+>O z@+PRS%GKkEVzX9Z(GVjrr}|2G6;^^`)hFEdU5}4e&#k42Zd z90$hd?SE0r^bG<~VKVZII@hqPH=>4@o!Q5f$avYZ-t07Lq-#6FPR*YY5$;nfaLh7Y zp&MmE&|_nD7rqVWf&H+bQh|N#F*|F85YFBUVd+^`T8hk=lkYd{ds^wU9DN+;`*`PB zxqU36RPbzVuRf*@l6s{&SM8!cs|^yhaLV&UR@{_w9>4hWATEYF@QYI(_xM1fzta09 zf;xXkleVxNr(;6%H1h8GI*AHySU$7ZW~r$;(5>IdnT- zE~eq&Ry*gzJ4H28txE(?;?jx4qML|#Pm`#ZDjbDK*zy3+?tzT}0VBg<(RP=?5^CCA z^(m(-pFY%e#ju3aVYxikmC8Q4!WcxND6zck{9avI>rY|vVwvsAIJ$x^{d!|=SEf@< zJnYH|HX6<8it~zviqr=pBs{%4ItBZVh56zc=7R;Z{Ad2zSH({GYod~oZRO>V3n0KE z(L79y=@I_0Un5%v=y|1j3}K{=ctPisqzolu#KZU1k*a)D!`b2WB=ulvNN!>Sj~|MN z5N^2JyU0AYfjD;K4=$ET*Q?^-d!COB`DLoOTn1~nsv(`>y=dD5R8yOXl)gkt4G_fY zlA~T!I{B$}aYE|ygKv^(qVT5irStPch3_2%6#H!g28WS!2X>?gCSOY?!{eNZcjNhq zArHOC{Bd&ByG+5J$N=J9Rioa)cJnJ*?Z(YCc@Z?(&D7<#&p4b4wSC5_;Gjk3u$8*Y z*O>QCHG79Gj~-K4mD;zjOjokbKQt={+6W$H-QA#qO4ASYqVHV-bvJct0B8n=Ye8^= z)hR0z8U}ph4J{WaHzCHF=9*YZ0ph8*kk)&}QjcPW(qQXoz4Po^F1A3SnroKv%8%-1 zz@PquP{}(5(?FW@*n_K12QQ-_TqgM@k6)7vi8KCeTGKMK-YygS#_w?fV@zx*_nso1 z0*fI}D_8vkgNg|OV7s5{A%E{SRf7=4R8JySW4trf9)=Mfm(xeXHr!lI4fdN_oHH#k zY0pdv7Y8pNtg5_%Eq7v}8O?uSD%I3B4}&wdu5^`k!!&2RbK?x3<1D(H8Q&oY$bk3U zn0=vAn~I@QV`VsVt14%DX^C&d_X|mq!^p02A{w|y+LW~Sj)i!0>0OnPG$@a2_*bYa zs5e=~q3n1!9#yu^8qym0Q|$XOe6N+ri@h;?)KFWWAl>bJOMB>81Iw|^XFZi}R^epi zlIMM{#==KHGGy-5^Ejx<<9du_L2&!u`2_5OSZQ5}dWU`8?q~A7dktt-OUH&8+AHP# z=X?{tQWJ26JXHM??FtP0p(7Yp-fgR-6Ifb5*Wx`-A~_`$!?3g40MCEsnOo zr4NY~DYBvgx?7+H)b=1#cerL#rh0ruv)Pj{>=In%CDSEqQo>og=(+>y`mmNK88 znD@EHHW(_#^T|OCm&;FjToDMJ2w2qoP*0X}P-R&vWU)r;RS%X*M*4LUu1S^zw;ofF zI$D|r$XX3G-uF#L{_+@~7@(m$4AO&p|2JoGL0Rh08u%H~MA+ZkUD!v*^IkbN^aTf4 zT&6~ok*PV2*&}$UI2dD%)ys8+TT}DUPFi2eLM*n2uJJziAIHG(5OL0!wMP{m!LsAIFYER5nYVOVpLSb1W-8=CV`Bh z1zlW^WfjjwMHgKRsHh1bhbOomc&wo7(PPj>StSWb{?GGP^-RwZ5_J9U@1M^Hs=KGV z>b>i&x8AC9MpfWnLW%^3X;#1quyPp#(jXa{de^k5yQ@ozuN{3R{BLv!;?bOIV)m$M*o28i*ap_%thb0 z9qwS1zkv1PL_V+$edz?Kyv6^(gkq5tT$Hf?P2(fzyx1EV$ceF$VYIe16|4p?WZQGK z%Ly~%tgNGPsNoAB5Q)t{s`K4aI-WV34sc(Bdrt(YOcaxDJO&utTUeVm~;-FrB!vt;+Wv1G(7Q68j2@9_@qa0QV*lbjS5P%oA|BZ!kF>R5=5AQ%U3jUUKg~27t>cZcmozo^InrNx68mR%LA7 z%Qr30ku6#H0cgL}+u6`UcWC3+C3!(Pi9o{ju`(7uLpv%S5cI(wc(?+=$9Ke^sP4)- zVPDwavr_Rwh!h|CC89H*A)4G{gf`RdVqFiOOH9y@kHUqK1d!i~IlOWm4ydA|M4?M!{u3R1a-`U3Jg4!Ww6 z_tI&h5~&k<3X82&N4G`InQz~psJ1o%Ygiry*yB-vjoGKFCP!CwWmHvN6IAsa=@dd@ za+`!hPb%gBLjy&sRr3>(O3QI+B;>PD57f&zSX`+orynxaT2i1@jxx2i4b`&`gHfeL zG$~n7Gv;km%@%>um`3s%bI;@z-av-hDr3$)q6D(R0&Tz52a|bvF%9AnNCMem%vlGd zoh&wa@O$}4rL{>OxM`(gBW!>Lo-g9tN_pYO*q4d$JCFGay=P>lOkyH^ zgc=<)BlYmDP_fcmtSHIXE>q__8GUx2A82wI zh^f^phs5p_5wxkaDU|HczxN^tmM8PsC_!z$)vZBK+?D{iHe??7E19a&GIiZA`FPMT z`S?FpJlON?PZB(B%d&*oG*=_@K!T6$VY9^P7@~?}k44X20GBNsGKu&XR({q-)p@U? z5LIpy%a6`m4fJ#gxvZyLq6-jDAG}|Wd)ZA48O4YC2W<2Y!1Bm<^mopNzSE(MEo4ash9wccDps%d@oRC=B&C;N**ugFYHL=ySg{uXy0EmCuHqz0fcR~MigyBu*bp@{d zT0a?D;BWrm!=iJ3*?4)oG4Dw{gd+bLYb>^4jm4%{)EbM^{JQ`12YYP6xN!>xEzPpu z?G6)tmiU#CiNb$hq`J8R7>U`RK+Z$w0Tmh{EDhx#95xA_xaZvS)h1gqJTff>qUyGr z4p3eS?3v7U0ZrPkJhe3&6bVZ%F2>e7Slz+tEQ}9zT`EPCp&JQ&vpt`E>vz;ht&Fe^ z&`rO^qaE3+gd3pMD8>HASVo9l1;k2k1UdMp$+{Vreu#%HrIX^J#iVi#rDrwR)u|w` zb$7wgdSl+fsK;+zw!JX;Wx>vm3mSG0F9>|@EwuXdCk1D|;z{Mf&HJ9fAG z2N4~L~nvrT)6%_kH^TZeap+XBt_ zV>LD7bEEnQzG5uzkAK?=03PUQvBA9STVGA=J|-Ad&cJnv-;sbf4>xe za6&&Xww~^niG8s9aS74)tCV=}4>9SNhE+z!Y@SpVIz}`NyIDKyiEcVquP55lh=l<% zEL8mpYtA}d2_dvnR1-pu1%mkHimZIJ$)QmhwA4!PG=}m{_mnxvN=DId`SG*Q{_@*s z8TC^}nI()`MKUS2q6AYxD>O<;ok%Sx!abY9Xa!BJcU)DqK^1JnBFGE>v=~u*sP`+R zbmm;6r^c`eyD<;b{Se-9y9=@8d*??54Z9$`|4J>ihIKEriXh{k;g=?n;~lVEkmC?m ztcegWLe&&vkyMx(Du!;Itx||6H+1*RHTpY0#rDmeu&(_MbJLgRfbU>ze3Mo;mZBT=-H7uY8gM*( zYEFa-=2otWkF1REzuvU+@d7Y`nlT`T|1#}&G&vw*oYTjzr6d-dv+xAh?O521rB1i1 zV#ndYnumIXU57;Rnq3Nike2#~_ypW%4$RR=F}Bv0H5ynPJOZmvdscl^zMY&Z#WzYL z=u2Ck0Z%C5s$gA~=a~w1D@r12&9D(HNW)~GvLMkjj*o|EJHjq7kU}RXo4Ssn7s?^` z&<|z+Lg{>!A6-n`K^{(Ww4BclTYe-_a3#b8Wf(ulS5vk23VacOg0D3`VZV_DD%sF{ zhe}cMF?l9rBhMAPL6xQ%Bn%>FV392=&~Pi#jqXL(i*hy-9(*5+Kqg~bG4#}0tU%eY z_=1$hAepE@iL%1sAMG^=Z-SWv2_L7$62o_1OsoyMwGb~8Jb+CJ!WAF}c!U^braks> zG>N;2BndSIGCfnb{4h*5-We}1lP91(R5t;&Lss%A#ZG&|AZZWP2|09tClhUz;)%~* zbg*g}Ty-;fqV@*03k4eFA#P=^wsQbRh%>zo@+hPEGXwCT;jrww;1MVU9?(|9Q_3sw zh;mDacr}$*+4eFWn1Jk|^CBBTK*y<@tDQuhz!R1s`?f;?;Z<%3qv1Qhh)E(C+eq@~r2Ny9-z4KV4c)4s)C+SuJ4B14XN zfsWQ)pX>(22jNsJn7gANrMaUpS)P|~QP=5{asmyVjJl#; z6)kz?o!92|O2P(#fqF0D&4lRsGzGKGTC^HileYRf2zpZE>q_Wx2~zt|fG(a7AJ#;~ z_3WF~HDp77nCOeet}py?U)VQIqAArjMDqhUQ$Sj0P8myv^hBI6ZG6xKAIJiqvE20H zHVcc`dexXmpxD30JknuIZ!jiXF(xgBF__QVJ7ab~6k*KLn>3~oad}V^ z_Nz5hgQiyi>m4PVJ=~3H{G#lEF?$;a1Mz(ru?;k*7;~>|#%JZ%fbIu; zt9Ott{7Fqf!Z$EeD6r^u!RQnmT7j~-lbQS>c8`Ro06n_cn_6>m&onOU#K;JQu{=-R zt1wgsCB6^TPY{0d{OdvWY6-6IpQ^4)UA-mZS7&OVR_s(Huk%#4}Jm+wL1&4X_t|6iq9A!aXFVGrJYf0kpeetDapciD|bdnniPHy(p#j?9^aUYHb0uBMsFK zX}{WMDs{D8b+vn!A!M)w&rWkBDGid;L*YT&XL+jb-n%5(ovs&$X*Z%4p`9G5sK1Cl zpetIe;$;)a|H^Hf!2l)~ZDeUV<+Q9kPzk3UZ>L|eoqo=C`!u8jbM6CXYVbt9j-ioy8=SNeuaME`m*gWlrT_VROy73xmoq{y-sV#=yoaZVgFG%U^wAG zh0}U@s^3PaP==3sQVHq)H`2F6r36MqDFTmzV?jbV>?;ofQ?Si4m=eX0MT#E}D}HQc z`X_`6UOH_XJYXAUG zh6S1@8gpbO8@1$-Q>YJAS|n>K#lJ|*DKK=I-iyRZJDRH~0#0#&%eaEfJAzY!Uga8M zEu0e0A>u7O!29+1f$u9GIMOmVLvc#pMqE>I%vqt}Y>F4=R1+%EoKhT`tKnFX7!J#G z$dx`cOEP+L5Z@I-+DE7`!2Jh;k0-fCOELW1toZqFLSDITu^_M{YY|KEQHv_2(<0jLI7LL>5pS4$S%SV;hz(TGM~Y}M ztcxoE;|!qeIl^=qu!IE`uauG&6P0sZ>kKRHmJIYZHHq8jex`Y}YdRMJO^9f-t+@8- z{(@SV^+(HTxUer-qD)mb6Gnw6B{eb~9d3L&8?SX5M;VR(KDY06+J_&LWN&$*z4m|V zz1Q}y1O9+}0wO4|>u^W40ptbfqUkTz!)uSAwZjk2mWO4?O{vEwh9DJo11*L##3}-M zm(U^r$X!B5D_I3iW=x6yd-duP~IM)As3y7zoYZQ(L)L3 zh&(IEMLk@V+G&KGr<}*b`?P{LPUcUk#t%lo;?LNAoSUv$8F>qagL!?h2|<2J8uQS8 zZw9fXqHCj)15MFL{BprT?)W9rN>EogetDXq{Kp*C$>0Y;vzWwCc{vRE#6N3jywyIj z7ZBo(jIXQl0LYtK-faaskR+r5dAS>GW_cI6$2n7hrc&qTQ`}tX+`NOE?#|6R++1fY zsBe6UT#fvZ{!EeT9#g-(`~B;$yM`w6QH(siNTd_k6l8JCT`0db`3x(X%pc51NahDa zip<&+N67qrA2*qis01>Lw8OKqKTdbK=@3hiCLJtkhs->&quPGW3tG2vKKjqK*B9&$ z7(rO!y-#_65P(ve>WPGLYD5a`Q2?MVd;K%}i!SbDO#mU$ROv6IeVLSWq|koVXuJIz z;_YRgb6OS*h;!xwP^8>rfq!pmKt!muc?2n-#V}59`V?XG2MOM_PX;)l$zd}TC2y1e z+wlCZf4lHJv0oeTz=Hj3e`m+gef4(^SAhOff9IdvhhJ149D_mo+5XOgbdaT8e~0HW zK~9`_F?uVB52DOXr5*zk2#e|k#H>U4oxDJH5fVGhS)m!2T zY0W}^#Q5>{9)PjU^O#Vn9uLaCkZq3#OXB_2uYU~QEit%*C~43Wg6 zbJh&deBm|alCviSFeStgeu-?50r$!tq*(1$w8!*ufzkP1P1}{0ZHEKnNz#$KijVONEe>XTCU*_b5w~2EYI!4@yFy7%R%1O^|gS z9(q_45`al30`JI|&{yOOc3At@VvNy@o(AyIdSyeNa_qs;#0QbZ^#M`u7T}yF>{=v0 zwAp`L9WDQCs1$9>R@NO6e0ttg6#JFmC~eVl4=@Gvsq9Czw5I@&#)>F=Y0O?gVB_<# z(cyP1?{3tkkGX#YcBCyI=@1FZs-0kf2O`|h^ld=_Oa>*H52BS)5Ni@Q%}D^5t>HP05c#55FR<(kQodFiGSRZA!^L+ z2FpII3j}6dj5TrF6TsP|;tx+NrYWi}$*N%8mM%d`QQ)9r-6H-*k+(a2mY8+9(X4Ya ztg(3Rww}ViWntb-Wv+}cw!3DmvKgAO_&M6_!2gf1^PwZ+*!iFaPO-DJ`~=W*Nl&5j zlPti_dU+)hG}_2}1eYpUR<0ol!W^xvr5Z+Y^sIVvRGa`|D>=G2%u%0et3L`H&EjzM zVDgip4ien9_|G+-4 zF~F2z)wniM&>_{h{aGi__sMqX+h5TaqB;Rog|VCHwog!8M}6q8fOMyj3@$RI5e}z+ zb*!X#JKDjC2>dgL@l#Sn;HUk%hqZx7O5iUm&jCqS??(b;EMo!6E|OQAb%4%Nf5I8S zUeu29`jbR1qeT7k7nSkS;(&&W8lQ4RJ!6Qpl70dTEcDc(o^hOdn!~5Fc--x)p{WpY z`>qs_a+Q!WMm|>)yeOZSRO-a1Y*Co4Ex6atIaEDX5>+XmLZU|FEbdy*>U3fJ8Wtc) zvFdQa&OC8$`HZr(WKNtc-Lz6oA8A>_tTsmXl%*n7<=H4`x3w&dQcut1(>sae`o`Pr zXR+OA$Ol|w@cUBX2Sn%qiN6N?OpPCa)CyF>E3~PFA=A$9uWLSev<`$f?~6?hUut~CLFIz=`ZFNXGgHllg8~^UWhemxsA&lKBpI|`p-hq zc%Q@P^fS~`lTT{~z0KnaD(z>IKmwkV8TL(h5krstl)eCQreT2|MZ|d`O~h?ND_{$C zpn`%<9|#iSI59RSa*yAfJ90mp6MrbsA zF0m21#n9_bLK~+azvI)ee(*{p$r}!D+COMFG@+{8-HjAUzlQ}VSwf^?s$x~8vMNG@ zTqP`LJ=cb+9ImQ70)hhgRB6W5N-M% zb3Rc06>O9CuCO2qdzSrEc$?4uO7f8yT7ej)uu^<2c2+E|7#6R~4rki`=&N2*6pQJu z#&;EpUCE-|?y5kNN0sbox*f10if)na>YFsF_*)dN?&>S`)aFy^uJQ=J$?nSOD2KHVP5&P5B7}Sdg-ieLQ%~>b(`fyB{g00Rwd~r9{_PvRAZL4_*9|<{r-%2+SEf zI`0d;-jyU$C3Biy4?ep$dX=&I+VpZ1E_z+3o?g$V(ezq)heNMdaV}t+_KLe#!(PE0 zx$V0so>+7xQQEf=RfMiadHMDzo%QG<)1O!?UQ=fMl5%WSkp2%35y*Il1%85Mn4480 z?`hi(dlqfepPm^fQ!|#4Ms9yTxAEz4=U1efI2%RdpTnKsDE0JAKCPC{PjW8pXPQBm zZ(V2{~h+2b|aOEIgyrw|sgW=2g$Mf%!$M%8OCBFh5T{J)cj* znAc;^sZe*PCsQUjir7C4U-r^*0~n_Vzkltc-Wjr z`%{VPAD^)PFC<}wwmPQ%-9PT7eq(lGdHt>CTHEqkjXh}Fr4c}<=c z$F(i)@lWA$K_$#gzEYns#|o6>Evr^#UD@OX!JwoFs_; zlSSAWhzy)dAT_1%VwK##EXkd!SI`W(tN>&pdOS2ZdWx>C@z9H{zk}Rmyu<=EfN^^r z58ZcDM8p(B>}#GPfug&F$av@!RsZi$xW+>#s;9Yp8XgZlxC3NpZ#*O$%Lldr&Izzy zkhfBI{6Inm*_t>?_T2I$<3*tq9N|dtAQCc|spnO5DW@vr>3C@Fkiq;tLbOU2kg2;x ziWg)pl5(yJ*TEu{LbfJ`Lk5>i&Z&|u#Wy?WNs=xcL4s(zLk20*N_r<0E{|jPPi#B= zClqdv!@lBsQ17kS-ZXAJ*)e^+;EkWJug<)i5|2dsdQVTct&15s9Ha0X$f8|+HKs(w zQS0l+`Xpp!YFvS?zwZ{pEkohb*C*A}r}(s^`r5p`ZGDw9wG+h;rI*qMQ3hGqy9A7M z53(Yj9qb_o>=V7}72n`H`CRA!}w=&-}{7ta`qdhICl>K38iG8UkoQsQ>we`OKsX=T3rvArqt5NRd-1QZeK zWgMrT=J2U&_+a1lEvT0;{gfr58o_^CyZHA~{#H!?=cr7vTN6Zo zu=%#g!&IUJ<#FP9!YC&;qT}ZxGd?o0gl}haG?jzzlk6+85`@puCB{!p+`Ln0b_$@&9IaWN-`^0SoLD*RFaBs)aR8OeVkfJLQ&6}p_O2hLx!oul=c#aVjXk~*l-tDK zFUH<@68NVPw8g>1R{nwCXl9 zOnZJ;MI&W;tM~zD_|7Rm9Fr%<3ykT5S%5N-K^>ogfH-j(HA*>1@?I5Daurd&d@#!T zycC|2d2xpb$V(_V@v5g}maC^L`1B5?L$&sy_J5Tg$G1<93XEeYGYRQ&n1V5j#op=B z_1cKSXnMT&KpXUU@_V7jQz%^Y_^W!lm`}s>==D_x=y4J4OQQS@(Q(ew4CEWgGg3BM z!Yz7M5uR8ne_26F;YJMhKp~ssz3EvTNSQN>L-Vs(J`i2g-Fi03SVB7G*w16c%v+b= zlPGWFweLuYjFl{4lj^0;*eUb`c^iMeCPHnf1&8;gi^Aqf5~nzhiR5jZsv0^Tg)47k zn0h)8h2(9h+0RJ`4q>wAlIaMZaxi0CUw{cUE~^z|uZ~jo9R!LS50dz;nwk}Y9Z3v& zFVZ(+{g2@dOcwM_6B}f76I&T;O>99p+r@$$`%Hx7NbZDv}eue)oqd8`U?afAeov?D+&m#PFworJio)(|LpHnSfjaa(btMoV0ZI z?>+}PpL3Bj*8U%)=n13FZb{-fh{3>a365gz#I}K4+J&ePoWzBQbgaJUUJ?Xz$e3dv zj1gjtd?p%XA1%0K^kETpE8_ifr|QOv12mMn*M{d`miJ{0W82 zFTYEkrr*t{Zojuwdtez%ZBnyyt)k|skNRj%10z&d5P1kX`S*8p4;yu8M5(H-2G1K-Dt1n zgF5@Ttw8XoFmLG(+PmK7Ms(8{t1VNxO}>J4tAJ)w!Mb`?G_at!rWqddlw_RRHQ7go z^1MUjWa&|ZY|n#k$iDEsU0B%<_GL57o5L4!S%aO&AK0kt&%PzTeQxHI%^l8ixWgIx zwYZk^oR&=ijT-~OrrKNH)h&Z|3^1eRB58Roe~?!99o0kHMl}(ZF$l)Aw^!7prNpR7 zOEFkUORD~LYlRLD-`Zl|h>H!+h%uUly@*$)5K__4CyhjQpOyNf^nda>uywwO>|+Bo z1ol5FKb0)X#$d4wIX6jWkon)QxnXXtnqJQ35m2Hwb6uX_bRsQWxK^}m#dn3Ijfp7&Dvws-Vk^mUfuL1Zo;dZKEO?Q zb<^v(39oK?88@ub9;BdVCt1Kj}hs?Y1{Q%bd z*#~_L2K-ew6J7tMZPrh{1XE>-&g*6Ut1$0v)Ip@G>dP>|0RT9rS*%=+QCHy2ZNO?V ztTxM|1gMq=)i-`?|M?@d9tnb*wm|v&H^Gk~X2&W{2@*ws1!hF2&E1D^G zH&(ycAz*|bgdbBJZOB`cJfMqDvVR+fUm^s723Ua}=-G+7=g3j&SP+rsjnNjj!ALv%%Y= z{kzFrUz}LK9DME9RyRcgp*h%(%^Qv8bwu-sgWKTcUpAxFHrF>Bvlrs)co<+s1?Le7wt353v-<|46E32bnT6|+aJFVm*NccB3fYhV_FsZ02CqP^zd^>o}zx=V#fU* zEpKC^amNsc4nZRp?Q;OaRkm2QlVc`t7QPZz`{Y&Rhorsnoz{9&*5*!oov65sk9{a0 zZ=4_1o-zAYMQ^AI*IdJBY_(U&tM*yx0pS42G$jhHWZqQ^B45 zT<~Lad4IO)Z0-ClxI>-VxKDF}tQ6`k<~~MxAMx9M`=_`Qmn{Q}QmT zbCH`mG4M|Q8T8rpay)&y#M9^VcYY>)y8JTwT#Q-sj?yO&Fz%H;#_YN{e(EtQwA@ov zfl&#ZtF9FHKvQe^#oWYF^dJ9GCGg{^Sm?gIxSt$wGuo^j0afUVWRG$g4JoO{9=Sd- z(e%p2aET`iLz$Y@x~cI!Y>vC3@ijE~)l3e9Xkwr#zQ#W(t>!nDXaBDK#j1Gi4YS2> zyzC#qZeTR`WBA_=eiPYTNAP?9g7)ys?ht-m_JZH>X%2p&YQb;T+rJdQ`CJ&^5&U+Z z-yVMGX}Ei4JN!G64Yt9*bGtbBbyfI1xG52SFlexo@a-)8Lti2eWTvwR7f+kmg~=&w zAL_-Haf6L{bqvP^cI6oJwlby?*fr3oK8GO&Yit+n^EnL%0Dfr9Ih~V$LtiuIoPvwm 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≧wJcyfOB)bHjfYqHR9S={Lk(8# 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%0D}omx zaZf{XSrH+1jKe*6My0JbSeMuOUCsU8`zbHZ9gj-N(T-@d{+s-B*Sd|*`#opp@nnvJ z;z&)zoy>#u6p3dxlc-{qT zR08$xX7dR@aUZw2j~e$e%6)ueD7Hl-*n#}(&(&eko>3B+TI-xI1ZfzPaF0rXjlk#48P{%;c-KM7qPYKc9^@{onfs z>x*@LOI8iK6C1KG2^qlo56Sc(;trl?WAlIM zZBgKW*7_-6qR*wd@KT`N{l|&M^In~ z74vR47k2Jo+ba`xYP5(Yi#VrttZytN{kj&l&7DtxrOSHH8L({|aELh7;ZK%t#GnV(loG!eAh=g`}jcUbCk;ipAuK1xY)PPCQ5crf4WS6P=E(O~P ziu(00bpoH81x0&M`j&}k)Vowul&B29Lm&~w9+CzKWHEq`U7)>>_^QG~cXE*l1hUDE z=y0R_UK~=BpyN?#4@WIl{NnRIFg-phaQRsp-hXNizQ|( zGF+l+>?naaaJS)_bIq(h={|bh$71*K$DObNWf;GK?AcQiosQS%T4&QB1Vb$Tl$Gt4 z50ac+@IjJkw-IsGUj_`4YP>Ku3E4(=)FaPxSS|sSIzC8UT`q~MrC?m2bt)VOeP|#f z!KMuuHl)re;9Ifz2U~+vWgBH+eb}JWjFU0}9DSq=A|ZxP@r+_Uuit)zO;EUL(h%vt z-!zUDDANBuy#Cka^#6Bur9l6GtPAv9>)=bB0~eR%RX^X?Ca=sEdDz&2iLuoZB`-VR zS0%n<5iLw;7li^n&}cD@pKTyZivV&aETB86^%CTab|RsX!YGF3EQ;x}l6$oDSH{ff zoULm|_vkl%qa7)o%XcUoopg1rg``sL9&QvrmF}i zLGaf)T-T3bU3skYXS^|C!O+s|?@fSY{waHM!%MkRV{v6TX0S|*N2XfLhMp#H<{RnJ z`jb7aqhgRgj)__+H0+At=j_mb9Mz&nri-(2#!>8?C(s2BH_Y}%H^TkTHu|LoLAW(h zdZ9nPN~Dba^1a@199J@zu}=CSQ8Zog<0;+@Iy^Oa{^n9Q;H*;j&BC}^z{RClHC`8@ zMbvH|qOpA$*_)FW4Bxe(Z*c>wlJ*$iWmBb^v>Q&oc=P3d%baZ*YQ`hlQ7RgfaKM4n zqMQXr(9B>bQBLyHM&?3oYI4dM>ozUoz5xo15oE10QfmcsplO)vej~9U-{=gZW=xrB zy3Xpr=( z#Z32csrzUtMMPe9y46pg%=&NRd?G&}#mqT^tRDN`*goa}`j$)>vXu1h?9p9H{0|;` zdU|mDv{a&pT|EZ(FyA{q_U)e5b(7LlcJ9lrB*7Z%`mPCC*$HR*Km^T#u#98FL;vE0 z41t;;<601khO1b*aer>Ca9R?aL0rI}1N&D$HeCM?*WY1D?~qmh$PAy(-MCf%|( zO5U5K`p5-lKT)5FUDr*+0<0xLjjCnCg zzMmV@eV};Ij3l#Z&W57uM!FRO+yWwFGH6+RwN4>TF>pQ}%E{u`RT|m8m3=x_!S!8HrO1hl~EJLqW)JQVeE7us7k#-xcK-eykv5a-&K1$?oHX4-xQ#iv+x%eD9&r zZn3>gm(`pUjjtkSWwC;M=;R)!gVhqDCNT>`r}3*K+^h(PaD~g1ZQuaV^Vj=qLmoBC zP%9SPMCO61@w253;5pa0M*_k|-QTGy*JV?Z?^N?WHR5bu2-3Gz@@iV2-QI z5H+kwB!^=s$pZBzu+XYTyaUkOG*eG({>!LT1N$_MAzv1iW+X=S1f{)`spvmsY!B-; z5rg@HDMnZzmYS=mAGgZH27!u!HpFl;dtGja?IyVW6Kn zb={QfS~T!WET}LFO07s5Ay-&uRoMtS$f-((IxvC+?~_>Z9qV+Z*3KLde(ov&;(JvT)GccrqgHSUNf9WK`lgX9J%RlV#;i!xKRM$|4avdpXAYBE>OtE( zTB#IMhn)UML6fMd?Vi*U{(XNO6@?kewV8h+@RpZyrZZe-w|XODW^R(A+?y~(x!Zkw zVzT|Z&HXBOze+cwJ%5b`u6{}cWkJ>swFP}S-8X9nametvNm*u#m&`tdg0R^Kai*MY z8B@P>MosL#amOZD0o^d>E#@s}R8e#{c!vpfOIxWKkrm z{~`XBUa_)FL}$+n`W|oS>m^>9Rjti4I=dXvhwrDY%C4fXk);#so^4&HC*q0J4WfG@ zb&I$#xqjV@GfqzpMls%<5x}Y8`<<4WvZ8Ww{ljxA6Q!#sCwsXwd*o#H`uxG<o_n*8~tbfO!3S#|0uhpojxRe6hh4hnBw4oK`YsrpaV!sr% zSKWDXc>=lO4QRvwa5Ag!6D%i5yMiwj7sIP&84sX4lAxO8UiiD~`Yj4+v25Nx=7jYQ zebpIP2AK`;bpwgfK|?aJXL&<<+@2FsBQCujJ2&RBhP*0{vfL%rXDcUCk#t%^a`>Ld z{im;_r0wX2r4#ln$9iKP>v)a3mAHuq-W!F98op=d5HTWMb{D_H-u@%aeb!$$P9=%uRM;IbDS2eM znBJ~He=dD1)LNiV)UpxLZ6f&Mzqi8AS(odwD_KGoyZ*E0u6wO|Fg&KggyIPIvCw^d z``_r=1}QEyH#V2!AlGBluv?d`Cr?VH_qbuDAK1!(hi8SB$Ni(O+t!D%dsb1!GiR6B zA2*cDcr$j-W7*eaxnTK7w=bbr->vkC?07(@m|fS~WqrBcc2;k1BW<&G0*lLE&K~ix zI<2Ntgg4TGQv;zJb>DwH`>Key)&4(C;1cWlwh4{TG^3Ku~%uY`eU58V&?T( zR=Y^YdAeCVu7$^SHinM}NvWuLFrtHS!nYz7)qtkx@$mjrjN`w47ao6zDCCI2mm+&G za|*OTzorRG{h@u_jq8XW6^2AzA|y&&86H<07UALcf^3T2Y9i^Yzw78Yd$a4cxIgB0 z3(wzBlXUO;qhtExN}NyD6Dm^T7vJ%1 zOmLH)L&h75Fc!~#B9T73Z{j7(q#nu+)lDpYh9$5;{aTiD)^EIgL*``q2CdOZMfG@8 zwEH4;SN~3I{(*u@8?&uxz!*k3%{7VAB@M(9UC&4;`ySJ<`LXfR4uT|0K`?Jh+`#a} zbvvH8t8zl=@n* z^=Q;;W+|!+dk}^U5@2IR6SMCYAF*M}f#5uv`_&TKIwOcF31+>?=#lxXxg`XusIf86E2|fsQzU133+Q9_m9XSJQWYoHO@>lXSARa>^!qei1Q8|ALxbIdk5+1r5$X*fIp8zsi!CzZ#$?AxUF}oEPK5=Z8D9YFuiT5IM-g z3*Ug;xAiloMfMaM6}tJ=2B~z%>o$T-y1LdN?LQgR-w!R#AeHGkMih7ILg(i4*!9)0 zYwW6w_Rwso?{PV3jX5;lmNJ))?|6SM-)C2o$C^;Trj1pUH;wM$N|5p$bUdnl8FYc0 zXk@8@aN@5v^-VxySyExcifHKWJLgVZ1B^wy3bWYdVV0)oT*uj)75mpeHv1Ci;{0&a2Akfv&H)XLsG9(8f86v57IzhNo`kafNFGz&@Y4_d#~yN zdT7~+M=@rinCM~LGbw1_n_p>p*|g0L=ZZgH-do)KDoaNsd)#c)W7Fjv-jZ{8D_rcK zU?llJg2`Ax2aD){As#aVgy;{?{uEj;EcrrDwk&qv`qb2gjj!ONZz+`MdnaZW~}m|1>+&&DV6R(QielHlmdeK7yNFA$#LXg(G%HbB*Uz?5CWR2 z@VbM9pEQOs+}EQKErB0-Glc@0gkB_M5$syQRmYa3vCes1YQR~ur?zHs7;{WHTw{*I zQzJgSM(d2IbeNnTtu3qf5XQ|6Ar5b-e=aspCue8k)*{w1oI~v=BZ=(GqEM|KWl+Pq zr9F(mk44*Mx2S*2+0|LyIVy0{9j^RBrSQ zTi$l#4g@kv)=HHeG*K=&pJn#YU=s9%{`px913L$9xOkj7%}MU#x9(${`?$k>{2)Y^ z_Kb8%3RNWUGv^@djWQ1u@#+s0z&AUW10B7XfQxtXCNSXIv5R&1&2AF?Fa3R22)E9|VifY(|A&(O?FH59HEV}V%dAXs( zCMO?n*toJ`)Z2;DC&?Zr*q5{Z;aN}2{a|jabG}4BU3TPWqNyOO^-)F5s9!jnVq%4x z@ivjpTj{({rqQxv={lOw#MAMKbj6{r&%vb=32xaNnbj(oePtxbqosccw6V@B-SZ=l z2e^@YPV8FWMk)OHrP*iLdN?+J3U^sekr=bIA^D-tVKU z)u$yd99E8*8a5$y;J@aKE1B5+_qHQWOAa13ndDAx#psAwr^;ZoKy*j>{9zL*zk}CdeZ&QMzvS@v-^$@m6BYBMlsi;X?X`QB0zZWX&mHXv0ni zLtZmrl7bMJN?K3HEg>wEfk^tXr>4%gL#SqpcQk8q105w4v7H9H<*%k&&xSEMfCW^v zS?-vtHlO6bAysS-dC>Im{g9_5^KU|@SskAJzrE!pF+vrTe0hR)(>qskQ{z2uO4e&CCCvyT~T%T zR`EvJPosDPD9kp1o2HH+gLtQjzy*AYm!hLa_2mtnJ(ZK$N3?-WR;N!+RZeCLjmdKP zFM>n^Dc|{P_%eA6>DuQSHm+}A@8HR!o^2?7pUQ<;=WlfnLq=*3#UE0R()V4Zqbd#^ zBE{eFwB+z1*@X?s&57ij%pRl3;q{bnYHFIg&Q5uWMS={kai@J!#G_9FeG_Mjd-$mm zwBDUuwW&A=F|dV-cHkvS817=2=W0w;;Ud9BG^_?s$Y*|O%DlrMblE}1ar`t&2?aFV*!_+I zZ%{3yVY@G7WRxdoB;7G%U zb-Kk`YCr4SxuH_AqP14q%e*7KPtQ(D(A@%Sgn^`chVN&V@=vH8CfU4gtsGdZp!-x|~b9alEizzh)T zJC_!iG|Md(Sfx^Np*y+sZwcfr)YtlO&eaLnD-f8tGYmHHU1A0Xs$MwEFtGH7&r_H7 z%0^JFNz}Qwfuy@`Hfye49`i^p|3seC*9Dh;U@?9|xoj;LXh`;E9^!Ly@-LYyiH>sR zP!LgI8VE8d?fM4cqCiVY*K?jPQ2iQV{+7LR?dVPV1U(bfjz@d=iCJHs*;(p98@+a4 zE6?a*`>*+k)LQP}V&|qEVqHH}Tb%YA>)zEu{Q}22^&S5x5{9K?&G5WmYagBN_iC{6z!UqN(csUJn$$0+0DQ4mqOS<2}MxH&fe%W7uKlbUgk*5ud&2A7`I zAW@qZ*cM3$oo>kdsRe90X{e~u83Jp98^YN$^-D2mW_1NJW7GvE>o(|QYCt1~*!Ygk zbGaHz|40uK)Qd|Kk_4mu+2jZ@f0~{%8T5phyJHlt1vDfCQBMoG!;p4t0KZd%l& z1A&YuJ@p33%`Uqo7S}&J`$~r_oV3Sa+x(-|GTeugg-B?kF~0@cV?imABxaO7%X!TC z0O@qNY^MBx51`{Zd%*#swmdX84&&i*$lk$+c-dP?LdpUFiNx?96j;3~!H8w?1r6ja zkT(l5X(JG*M3L*}oFwxg$_7Tu$XOxoYPd3NBs>8WvV$g5dMk>d^j4Gy7nT$rJBXQouqOuP zpX;?pgx7RW6NVUV$qvWpZIq zupe}6UcF>$tNGr*$YvAXQHJ;PxPW1{bLAdg>sxnnyW_pwx#S_P?HRlI5p5zkVy9y@ z$W;WG%VkZY=bWaUlyCEnF{DztHJbEbI9iOMJcc{D^qEks)m8Q3-VKK)8LrnXT`gF-v&GH9tmTYQ{({9sr5+9h^XnwT@&!2-FyM z%cE_0sPxwUxHv5Wjq>pCUnx-d8Y>D=H|imKr|Z(be>Z&glZNG&+{a&6gRBZoJd29( zojHA*yg_>f6udDHpz+5j3wtf9v}jVc$f%Kf;+}p_7*}MU@;n$Pc&^wMJPrQ^Jd%~t zaHJS!vSKoj?`ZWZ3IJ~JFOQ2Hf5A;NcWM4a5n!!|h@0!3J>rdFc6tRL%>5ctWgWq_#fd@ zu1TY&x|MA|())$7S~xH3l7Qhw2b#>CzY@SF<(UioUJa{a!>oN9ePMz~pNz@Pm(5y8 z!CY_h?eXSv$FF{A!jLC}G#QHIxF0kquf#%+7<#lbdUW|R_+D4?i2jyRO4N@&w%Vlg z^%n8BS^NcXMfc9PBU&3%7v?3%-6`PrX!=15HT;L+hpzfx_i#WH4|RoEu& zgF*zLfEelnqh?Z32vBD>=@=uVR)0V$iOmhY6;qrT;PSX{; z4Fe!;Z@Rff6EyAR)M4A^lud!(-gK^*kC-$wNtfH+v?;ujx<~@g>~pkyYt(XULCayK zwJh{OC164E&HcInRkwrcfL%=I{NsEV$3$HWE9hdxR$UzNUv}}^O}>k8&nJRzcv5sq?-40I6u|HIt7 zfLB#q{r?GYBqH$y3mU0tXrm@x+Tb+^NP?&*Hq>}&iD+wj(^zSXkRVpnz)679!%@7{ zYHO9+R;{(www8K(D-p^?tb+Dcyi`%E-N#@>eN`?h|Ic^L>~l*%+V}lG&o7U%&)$3X z%$jwZHEY(ap`0~jZM4XcU=iB&qLG~`sk@~EK|+(pHH+ua_mk*xm)5|Pxb(_OeuO^2 z#?jA2=f8}#(@?#YHS~->kbE0xN!F6~GN{$(;K*;}7%c2b1uJKUYX$O=FO<<#&3;%S z)0Ms>^b?u-p{&|$jw$3Eb77&fms#oRgslr+^jwtSK9R2F$-&J}vFgVs( zC@xvr@7a8zLN?I5uu5THo=2NmQmKxYlywb2d2Ywqs9gCRolDl-j?L&NxgDGA`T}RO zCbpo2(|e;5vH*jwUxU9-Mwezi&W!-8*v9$b2+Q{Bm5>nVqSTa1V1kHK{dTN+Q)ZgD zi7jOUumb`%;v|{BzqPx0Qlh)zgY^w$&TJfM`>SVZpY`a~ms{cia3o!bzglgU1y^qC z14ng+qm@*gnMFWK*h!)U)(|1ZLhQ9FlZSLw?Z*$U6CY&}&FVS4`Py3mN^!u^m;=KLBVlfn;S-o=cz)mfsQ5SbSrJXJcgjp{75vkd!X{7Loy+X0* zk{Zo0qwz^RX5#R^CFXo0oDo=J&Q+ooWTTPjl07=MPa7f?HPG)^y6(^ zY(GuuSR16@yey2Jgo*gbtjhS7`q>A>w@kTWc)YuUqMfJ1z!+E4P=`|ygg9ZCkhdy9 zvXW_6eJKAy>Bv=F};L2NHlirM|6x6J5 zdLB=_n|M6&Z2D|k21sH(WiZR)dh4sXHYYYQ7hoByBN|#-qN*zzupjo^x`jMk6wUy_(ols zyf!}&*|-iSY-3O3c5Q1V0QuD76E9e*0A!p5L&uzmwn(62pW$>_3qV$uO_<6DATtKO zCwXUin^*_!mWrkn6qK!E@TX2JMgeo=E}?(#MB|6?Jr#e7wYmE0wGFA$itAbK?$Smh zSIT0Gag7yCN<7+7y-q8iA3WR8y@hS6>l%s)mDtw)!-+sp<+jB`{~C)?1pRc^#y|NO zH@=#Y@b;XbUt33}yP|ySM82uA?eXdH@RXPlrq3f%L*mKwXZ4QBOkvRR=yxt=rG27j z#7z5Q$+BQ-PWvNymx*=G!MWN$%oe1qditCrOu=#G#stguvCCoZ?vL(n|K+d*zV<9j za7fw0bH^4jalp+Ox%2F?MdPWC2))S7{62u+J@4#(A)4=vB8$vn7X(r4@N!uR6;#-IluOm3!M8Rtcj^hU?I8#!OZql}~vr^(;82 z^7G=#8pnADh)rvh+KQwfZDLsEw-QNaNus9duz=KW#XRv3s8?>_IZ~FDT;FlA)H!?Tra%7f=#_Pzd%z1zrWUqay*9T!auAC>i+SkPiXKc8vz6)B zEd44EjztIPR@Nnvmtcg3Cl=#Q@P;d@7SmhXb%`@kPNMw%(PsA}gWGN(t=SYyACmq)}M14Pn zq6ll~0HtzJ0TCP)MiHUou+Y0FJN+=oOvieExC1ycvv+Js(~(A!;I}Vjn4xX&uxFs# z{TnXh$+>+j9<()-|N0+7vvtFGXups*Lwb5%d{FW_ako%z5 z_&M_=ny-?tphCW&3Mz8|BtVQhLpN%;mIbdp?vN4gCaTTfP4xPIF^m00@A|brD$_kw z^{Z#}K2P%dM$;9M6};m-$)>H_gZcA6+#Y{c+o|qgHpWZX<=c(wC9NX!Nt~Xg{S8I;C7g z&2^$(PV*4)U;Ixrx*#?a3U^zu`FTmLEeKj$G}Lo@@XkZ9+gH$&InWl!%gj&4m*J#D zIN9st5GNjS5Y{6un0b4MRJbJv;NUv|v15GAJg+Z$<=_g0j0YKD=X4OrIcavt-x_aJ z<}_q7=ms_E^w*#BdaP$X`1)J$`h$Sc*_%Hvp?$=5s>U1rssJ@rqI8X3w20$cHPTEI3;CTekN(fQI>hq~KyvBq@s`GP;N}l> z;AU4IwF>AJoo9}gUiys)W6YG)Ut}hvs`PJHIsb~onI_@St!W>rJWX0XBo=W2JMZQ3 z1H@dtCLOtt6(7~Uhl*RG^B%UK@&b1^^_1$yYd&{`);+dnBt=P;&?wz{YI(AB3FH)TfR}U`zuHc2C&5~Xr89A)>9zV>X8k>nxv0i?p|`6a@9b$?wDa#gO~0*I`nqSW z?@6dgQo}C$lRB<=Bb17WQ53xWY&gDmExm%217a~MPM>Pkgm)LJl};tb;pKqKCbdtr zx|2iZY(4YzFP#|e{JH~ZK>J?yY&uE_#U2@uhj;++Kqe!g8r|sp}rp{W2mH%u*JggHz6U-)WavB8#LyK9Gwft^Ws)t?vs-11#Z=p)7rzNF?}kYpPt5 zTa%%CZl5(3r=RoQlvw&FASPJzC%EEzvn3>YY6D)^gkm2U=TksvfeB9J5u0)%Mk6a8 z}wC)oA<&6(Bzfq`fJ)T-$c&ak8cD#n)t-_-FV*nO_^6rxz< z6E*FE7$Z-6cr9Zy?~H=kvIJ!}-vf}}{y5sNkiILIzGIxRMJE^)VSZ$-YX)J&o{)wx zC5BQ|$@ub$Wx*|~`8Q$L?3!Qyf7HKfVnRG5yVSpZcig{T_Kb~()<5C1WRUQA|KmBH z*D`gqR(Q-AO@bwVq@#V4Hq@0)(R)W2sR`^5e|eeeHa{}LDfd;L30 zjsGwDw`I*I_V4{a^xZ$LpTpXRd2`#?ZMNoLIy>fPjY{+5oO9(IUEr5y5j)Du@D`Jn z2Z#Kfx?c^hRTDpR`T_$E^8_}NSztOMBP03paSrXnY*P^}OPYhANFZIAX}S;j)OmFU?NeP@5mgST zM0J&%Z~6xfYn~scf6lr+kG}K|n9YBgX?fo7X}OQ{>Q1A*8ud3D+fowiVAl{p(XpiC66zh2jrzp}&-=w1$_3YEi}WxOczF@_)y{*&M35AAL_08Y~^*{Ex% zH4M<{IxVBmf(c`(D>ev+el`6;B6_u&PU5O38nif%H<$%AYgM5z_L)3CWx*|b{Lgmm z-@P@3oF%*m-`UeGs5g5Dk2apl$PM#0?H)^>1}k&XDvwUYx1N_m)#l?gNu4@#O)gl#`5mDN*vqj2yFwkdQHC|xqO5HHV#M`b?|U%cFbR= zCcq2=6x`SrE|hS~@FOV&Ge}EzA<%qfJuLsT7bzBBS%#0wmh)g6f`SMP{aCN)!M4lV z{R&>2tnib7gQ(qMKa2@;IAU1pbeIbr(t@Ep`0qm;p5R4DC}Ww%Yw%~!_)>DjtQaON z&bk&B5g%upD61C(9#6|n8kAz=rO%W25OKW87{tfP<`x1(VPJZO9v_lqulmGtw`drzA87qhysq7*v$k zCm?eap@gDqgn7SGURGDh#~N4xejTAO*rIZ1}KM40{;TACX0hHwyjR8s7v274}Ey{b{_9X&p zBeoAzXIpy~6gJ5h#+LfDM))iVDwg)bL;788bmg7wPA`zPKH@G&t7Egm0U(dxqVp=u zXTNcpWS~_t(5m`pIS)%yIZ25KSY1Xsy=dwc#EH3#!4DA73X<&iI?qVw;eg>jRv9RK-f*Uf4y zReC}#Vntc4GP<}f_h|_8*MCbEu#-_TIar+6h zUzP)Mv{ONwR;2xYT081k!M3*jH`yxhD{-wIa38H*rs`Fp^|@!wxC?%i-q0SCe#xmd z4_M8Q0d~Q!`CLK&VYuX^Y`G*58sos>2-Jcp1Z8S z10h=Gro4IbGqaxY1J;`gVE)DR0XfH_fQ==!-?tzqm5$3pdMTCn z{3;aBg7Kh=`uS`sI*a;CaQh6HB!3U1fyNK2@#OG;PA6Q1`1!J zz|wj40t+icsd|&c`hO9CQ>E8^_P`>Nizj2vv_1h zYQ)3u%i}$v&4B(Ey{=GSAIqjp;Tfpa08cW2?$ERPa~(*ihWc{oF=3)BPiK()GqQN&&LEDnCm z7VGqvLa?*&raCKUiHB|f{J|06p0lw;?8+3uEWeb$!d}ih8>>**U4@kik4P#LFfrlW zkUI zY_?<3z>{lKWtpn?hhU5QM~;)t!feHuhHjPzH-9#hc6y;JpE|8du}LmLE9WC)kkOzH zO4b;Yio7sZl}JE3eMe0daPJ5ml(t^NoK&{PuKH6>qD_~LBPa?{SpjK51c@R|Hu zoYn)C!!n_&qn}RI=|?b#(7ad@CKr=cc>!7Mm2q@1!p>8V=jDL26{g zE&HQJzG{!MJ=0L0Wk?sz=6kk*SJ5GU=WnXMBqZXW-gaFL9zUzFclt!z&umhbillr= zA;lUpr2NQ#h9FD-P<)ep<~QZ0B46E@gOp)<2U1+sAyVL0hZOw?-utqUV)y_vmNy}r zt#?*%3>D@#7D%UF=9$ct}NZMO6rcT{xni|J~}5j;1)3T zTz2p-#MjKD!4>i#E6Ukdh5$6ulWnZQ**2EY!ZL_%<^;o@o?zw8sJ}l7{WeaGl;Vc!=gF|-6PPrP ze4ag`?u=;7@SuDf<2jttVz!|UtUlQWwA8q=V>FhHg^y6(Dh%mxaRm$ZbMjK5MSV0h z5i2C07s?U0Cj1KnqFuHz6NLrqvig(UZ_u1=t>2nDt)04YG>IJIxEIak6FDFTBPC1A zxUA@`ED>I%Ps*%VXJxsrNl(o=%SB{d0xW{=u4GajTUy&}>5i@}^kzq=*$!R@)fqEH zUg^oozB5kfRj~04*B9i_t7&}fbp3msO&QW6E1Wgh?7G_q#v?! zih{pd46}C=*6ecUGKfnL)mRQRraa6G)KtMp*Z!VJBU?pt2iTx2*o%=^1~CL_lv+8n zvO<>1KQWO+r<0Xu=K`~rCdz6yjigEs zcta#)#+33+sP{qj>4hZJ=R(>I_E{uIXDPo_kcouBJEs+Xrq)c`=?a_PV`aJed#AIp zApCvE#&E`0j>_eXk@^tMaBzg20q#xpR_RCZ2fz2GR^<9OIKwk!65~7tD=-X@x3I3l zv1KZ9&Jkh^MzExx;4s?QI0_WO69=iwY|5AAdHNA%d45hkbwkrY&!5Gf3MPMra_372 z%N{`|KQ5ALa0mvxBCGV{QRuFuS*1g=f*z|#pJgVgPyd2d+Qrvlf%I5=Y4Cb0$bsBx zR+a~5li@V7Uy!Bc20b!b9@JDwODhfwY*v{Zl>@ErADBxka*Gx(DYDt%mluxOf zn2bDF0}6f0=J=~D91Ph1L^JXe69}kYMXadpvP_S+O59)&9McUkUX~tUvKac`>JeS0 zZEK|zEXmk=C?nn2QH*yO6Kn1(?tuqe%;@n_D;FBt*2bztgcW03jW!qqV}V=qFj(Eub>DBz%tDd8gP zidVuV-1JF~X}l0QI#inZ-#@bWvJhOpA_p{+i<1uc=3Uf#sNI`oh+A=ZJ z&puCo&v3HlYH;#?W=@qi|D1UdxTw{9iW!amNk+yxQ+k|Th8?d9i)Yj8nXZjKh8x+8 znrUR#bi@S3YrXkUj{umVN27zF$yk_u>5j-;)u^o-_;i&^25ONq68viH9 ztvLF)B5aM)*Q?D5%IPDK&u)~Av+72HxPn$vkun|yGai7m(!mRhxZJq|`p+DhU;nV% zt{x3dZQkgs3x1*sR%a^6gD*O7jpLsR;mpUFr6RGX4*(>lBip~{B)G&ghql@u3g~_} zKM6rJ-?6Rs!V-5NKNiC>{nj8YHNi{|WvXEPr38*sMu2}-W$Lhu0A;QY7W8ZZSD?g+ zU(?PM_>J|+`=yDLjVd_Der_RB(Y>q+PO&Ge(sJeozqtx(lxL`sJ3lsgdBgP=t3XQx z@W?cHq~<6X!B!#avN#0uvg~U3K)FREO_B)w_I_}i^Cn( zesz+=njxfI4Ai26t?CPvs>r z^KgRjaP%w2oHt(yI<{nl1un?aKQ*!P2Inj|FallXYz%~(#9fsebj4X&60%n9IG)qHa8F3I#%R?<+ zp&!BE6G8_N_-gVDXDbR}yavtQ{<0eij88#3lX6i7jFVJVb9vO&>gZMf!1i!NfK$O8 z^YW{HsAriZTrwkQhhZS{{iGX^va{Hr;s-9!rN)C{m_JJu?Y;h5=F zYS`*)RV!0bJ*=|jOn%frvhBg|9?lui>M}r4=QLL*zl__;1S36c#6h+&krR9~O@P%n zuEf|j6FxZwaHrQg-xt0OJ_chye9`H6)Vm`l8^>yx9(O7~Zw`)V5`%b36Ru`N1J})J zy{7{$st_jb)62P(LT0$Ca4ItEc_$gMR9G532Xjv-g}_Pzx|qbDtYU3 zk0MGm?nDVtOq9IS-smTkhn7)=4Mf)>IC7e7P~~%$i`lh2_>WPNoDuB(6@dKdLVT-xc#N=Tzir7Up|_ z@5=NI{@LUI1MpYO%LU&}fWwZ%<{6>2$1b2Bz>V$nWolJ|w((+sdzg>Vnz2CdOZA{JTQyX9QMQP>RW9*_jet+9V zH7IN3v=0o9d`TL5MWlk4#lbIkr}nx}vzO`%$FY~{^_3rO4~8`J?8B$oRW5}$9F`wnTe|+pH#bpm|P56O&m zwJmjNiObcp`4>6+-(0!$7tp=LR!)=(HW$13aT%_HNBbzf6&?z@yFlz+dEAt1--w@@ z^JS61GzebXLrMne5X&7e3>U9A29c%-&Ndp$_YEP+6(Pnt2;q~wtjh{;Fpve^$PXVWHw>ub@2CROmRFNrziF5iKqfNh{vHYKb4i`Y~IPU zZ%w{_==w*=sQ`sep*zwC^zUe+%8L4yqSUuIq}r79)cz5>y$`bnS{Khr7Wu6}k5{Suau|KX7yV{_4^f z^N9oeu77>h@4Hzr-dH;Mf_xfU@=Trz%#-QMIy607B$%8JjjcS{Lw&M?`eZ>pnS$p+ zuNO&Pq;TY zbrf6ohK?Bpi}>P!Liv&YoA)}ZgA_^R90(H}D1dTr&KtOVlH+sJGzv`o8+#*!i>46A zjvHk;qgP0G^i+&PQ|EupT2;iBt=3G1b>n1sX-upk72yM5SASO!wb@wB!B(Vw(4ip> zsR4Dd1jEWpaGM&TBjR1mg>uyn`lL`VWfio4WAY2-I$v=9$D%g`tWr}ojnz*yR>S`< z#=1WyMvO3^SmbR;v)$N?^F;HUG!b5rqmU=j_IuD6>1ee-zUBTqPnG`nJ z#dS`cy!2IjJlefI!d(t^m&y)cKNYWdj_%RVJpMI*4Gg2P64?a#LJMgf#)u$bIviYg zvvpBVDA34&J$miM#JxDtbnb%So~Hy4ayRgajNCQ863X3P4%*}u0JZ~vO?2Md!b^ca z4VavOOC6HDKCwn(#eM>|D?A>(>UMpS8hnH@n9rBzK+X(XlVGp-g{G?=GN)0_ zRRKOPkbzGzyk9=rv}P*V%_3k0{9c95eY^*gpAW@# zfy-XZfUR$83{;EvhoY-(w?okNq>=7&ce(g-aPp3gqg7HNBCHY z#V+aIF+SSY89u)2F6UpiBYao}_V~tD@obBDwnbn}6Mtan^v7K;1rRe*Xu>Bw8pN!5 z&%M)(dz1T08_ic@ERnQU{65Q#KF~3nuIZ5&hhHF;a2=XN|G-LqK?}2V`_pP3fso#% zg9y*+=)#raG4vQsNslR~jMC2$3cteG^HTIr8$goIFM0IyRVb6uo7xVw)$1`*K1{*Q zj$yJbYf@`eZn-2I@Zwz`b%L$gdTT%?ORrOP8kU1cF3MUedkf4afmtUo;as5WN$Dw7 zxb;>)O|=#wWDATJ0Q4wxF72IWygI`_>1(`^1 zFW_hEN1l(^3zJzN&Gfb?v~W_9d!F*kFTo1y7MYp32c8>yPw&B-jcKzQ@scN2&%G zQ*z}Pvr%rLyhXPfksJQh2EozmulSZ24?eiOJXVZ5mkY@+kL67}TcfckH>H)X4Qh8C zB%%+SrwdqYRa4W{)T|sx-3xP%ne=43kcvcBdn%`vkSG3Xm${dK?Vp;` z+cCaHQ~FLegzK9HcQ$aK|dB^F=RN&LLU-f1XKj*6u& zrO>wM{J*J6%WGvEq+?V#J36s0Tw)vfTzCwGdTOh+P}Zg7@AhZWR(L(3npFWQ{6{}^ z@l1lk0Ip#8^RozPfw02hSz80eh*VdtE}MQU8NZufs>|Y2lC_isd&q9$TdiA$PJcK) z6w=`AHHPss-DQ%yoOCgWzgoOgfN!}^KFNOY@;UmQE56yMT$)lu+kD!<0;)W){D7Z~ z9P(L-Na?3_5&SABF+m+`#ep99qNAU_xLv9M3CGW;^wd$j=TWsgSZxjY_)d!TFG^VNIYQ(u#4-WOIAV*eED!<4u7Em!#TU@RSwef6X~~O#m|a0MK3UG z3||)fXprTNq-{U60MHajL7?Q6@&%`~SR3>(&k}MzfxbB`@@9o0=|wKUR!0wviDLGH znwrE!%~>#mf2=f8PHKact8$cP0sr5kisBm?eKcVX=i3BE#)z(ixXGsSSoF`UQH8Sy zT4qY4Z^+C z8%g0{TRAbo^P7KQD;r@=wtSRaRq$#Vl;i~(79GH1;jHKnc`y|n5$F8#-~=G)nNz6$ z{^;}{ZB3;;Ost{yThxA?Dw`$PW5CY#Sy*1H#i+LM(KwyN z9*rjeihNG^~NCMSF2z| z8mvAvnZT(~WmT#yxFi~4Iv>p3L*1kEz9o2j1HRKH8Q{u;=dO1;937a4g<#Hd6Y1}} z%ZzDo*5`60+i_Sve|@_*f1%6NLn!Am#~Pj;j|e-C{TwFx;5=TS&@)VT<&T_yxu)lj z!7JZ`!8-EVkIvJvt~-HY_P2>X(SbvF2fiWeq1hagFNOhxBbiXl2BzX|u>_87d_qpi z!aahbMJR$i`9N&}fpWRlfXkdnzp zVaGe3kQkev3S=CptoN-_1ABrt4F$!#V(8}5Nc2XGFYCrRpR@ku-kcQGVGo$%b@zpI zeURteKJ-^~-hcP%zhG;U@8e4I4cO7FaslJbi!WAb$6m;4bV*yuc9&;-_IVC`)Xc0{ z0)0;*Iu6GNhemP+AyKm`Az3%isy~+oM2h5@b7?rgtoGSxmo}sqAj#Z_97Fx5zB=9g zXY2GS?(&Ck)Av2|`YsH3tNH)g^J>O!beVR7Ya3i70%$bL)8_jcNo|KJrtpr>tJ!#i zM!4@_gqtRq4POu8v3#9{coICvzjPPR=(}L zn(u@)FOP-YNtL#`nniWEML~407w0!IjmLD{he9DEEzbLePXzXy7Mz#U#GtT=ujMrH zLw1q^d`=Vbf3u1HVH3dxt#DGG=he)-toPW9dKZ6t3$i5W$#vDoOgK!RxPig!BN;;w zxjeYV@A)XuYhc4L6$b8SY|ban2eNPH@%T4mIr&^?ezP}xfZ*V3azYBEj7_qCQ;`E6 za}K`p;6U%9Er5j1nfWFkQ$}+IF~I1V*Qb8@r3ScO`N z)3aM+f@7YaF&FGuRiRL;BlRPb^+Uzk>!#u)IAH_c=8kCm1}tTE=Pk9f5;9H}J1b$G z&SwVt7Hx_HqYx;%WN#f671tmhUGijXI|rI>4G$`b|Fbw&{4wFt^*E+GwPkuDNy1aV zS9^SXn9|tSX(+GN8bhpp&gKqYT~-y}T0i@<@vT#?*gyVAg+A$2G#f$Aa^w~XYfbQS z^D;iKNf3Fq?eN?~7vA)D;HQRcH}#ro#x_nfA~7;J>7epF|k2-gk# zB*ps&&oy*!<;W3^PdKM?RzvEjJ&dHvjDM8DBuplr!uaG#Yx+J7*h0BcKm!95$Qve> zZ_NWhwv9in!BtniTIUM569pPau2!=xjra!oVxLKgb@k++PpnOwGi&tvSjwT_vQUQv z2(G@*#)}`gOZ=P2((%0(=)Q+{GmZM3=ZW( zP*DzkNs+AX(F3^Oo#om0DGtY-=udI@K&LpoG<`!_(@D@c78b76`3s!`ZEE;IZ1juK z)N4SIbAZDUC+YwP4w3m-Z{s=x7hC0s=-qGES8r-aU8DmX+E=&|jXHJa1WJfE>Lej( z2iQy0o26rD*Z~nPQE&3;@EfY%RzVmD*J6eavTemu6*{a&EUz$)s^Bj_@N)*jG^(j| zEO>x}vv@E!xEE*M*QKkG8Z{r&Fkq$#qSK7%v{({-J)s0eGEbSw%rbAi=>(dc7)uO= z$yot3CeKpJCN*th^lSiTRWLFK#>&26bhHwWPfX7jN0XdhaOf`!M=*Mc@zo=Lw9BFH z?p}8{;_GnP9XVX4E`mMqh)4VR9wOkU7hmwa&hfy7HbnC>qAwnq9hl|wfS&j47F)MD zdiRqk$IJJKKCq!^##_<5AMJSq%vV5<%KZ2b!tD0JU%;fhco-c6~ zGjjAda;q^Ies2*LMOV|!$J=WiF_Bi>Fx`LxtD>Ffa~Hkp3-)Z-5E`;rgV#)Wbi_oL zetC_Ocgh3duM-hMr2R#Aw9N}}`QRvPAOtY%qe zn;#Q6VF^uloKu}<;EMARZ#dp2BR4rlg%VZ4Q-ryh0j2$QaS4@p?lPp-KW_(WN1^?(19ZqNVkfpCunt#7YC-7CvK{OyXHD? zh=m!TnHmwe@aT%g2DNA&*U}^0t|y_?`KR>CL^Qv!q`ujZ7Y?X7$ZO1ashA)@;qu@l zqQ``v3b<-v=G8LYG-(`xWtl0c*@k%vDDBb zHR9K?oO5}Dn9ZNyArUN9$FI<1h_6!i+63^&$mwjdi2`Yx}p_71E%vpfW z>%IPzjNClX;JAg$4%eFQ{H;K6vxQ#%G=KgH@-`LbWxO#C#yOlpx7Hf2&>^dP-Rmc< z7aXUlrC(C`96e7)u77t-5i5pT4*C12a7m%~$sH~!+()5c2;rd|^Szz(b^2Px2);H2 zq!pfjQeYnrWjFz)NUs*OfWJx%SDVK_zcu2pKR*m=*0~UlcjABL9RvRnwsv-CxOT>X z_sQ#K?<&~FZww##uEoiq))b~-Mw;aC+_wshYyiuwo53!1D%ndkP%@`zFRk6d81 zI>0rKi`fspZgOk~$GP>k;K93$<0{Vrc~797L&E!O0seHJ82IZ&f2A|%T78-5KK%Ed z?ibbO&|OOu@ZZ}Rx{o<4r2Fn`cS!fWDHQC>5D4A1itE|Tvo^F71I7t+4Zhh7{HID{ z^8X6pk2?A@B2ERH(4S#T!+tLRS_rX7jyidJwykQn3VpuSX==5OR%6Se^Y0Trs#({} zl6H+qs}VAre1phKtXz~y8{k4m1lN3}@a`aFEioL)d{@}s@#k50b!n2@@3psFB9bje#r=Y!R`3X9=%A-pVzI!0v% z0&j=Zvtq$0LNI&&JNWUJ0jE8rWIjBTfrt90f&Mz-T6(Q6U~hm+T;M0S!Cm(o4i2Qzo@-$p8bH?{=GXgo?YyK}zfv8J@BUZk zB}M0Tik}MBL;(Ua!ycU61kuT-jM;hF7cr5C%-Pn#2bT>ec@W$}@N@e=(Cf;j9QvSQ z3ExvOOA`kMiIEeg{Z9+x+vvuhCR~b^tV4l0}Y#(Y3rgLzdNQxwC zG)_d;eK;Bwa`v0XS{JatXB7|l^s^^RlQ2%B@Jf!+r^gn4dYgS(;Xc*Ypr7&}=y*q4 zgAM^84u1-VV0Hp^s9v@PEhenewg#Q+A6%sesbKRN;6{mqK}!KXd^|xuKGH!S_;}Tr zW<_KTFN=fsUIQOx|J=Mi_{lXSDNaR}?48r8YIW-C8w&98@<+nQ7d9F`Kv3y=9;}Fb zp9=H)vy|uR&)V65|6(v&;O`)wz~@8DfnOwG)q;@iuE#}eh@p($%2y>eEEgMgY#S8q z)KX{1w$f;)mdScH(1)@SeqZ+aM}*F0DZiB+b!g#ns!UWDR#VOYoGU_K+g+AU{B zS+ZhcN!@nYHFLHoq-*wD`U2&Fe~t+`hprtpe8D+2oG3`x)tcFxBrA2fOV@p8B6_Y}2$G6s9HVAZ=jb76>yywlt z0-;gUkZHQYz-}m{Pk&mR>G55E3VZy>y%Ip)-k5!RdFJge>}@dOGlsWYX?WHKv;S zHLy>Ej1DAY>(nP_mi3#o`*V{LPc?MEu~$RIS4D{;A%_~xj7lmKk^ zaeuv<`#IEP+VZDqzsNFkhTHZFEfd%Bo%KguQ0fVnyVLbvq;dDP z^u_jD1$)Kf8^)6fZU8P1x}cfQgarfkY|yqW4xH>x501rO9$!!B8FtF%X#4>R)Gufp z#ip%o#qDG3lO|?bhd;O>)zD8aoA?|nGjUWuYUy8}bR0B#^Nerl!~U@(<6c~mYRZuD zHf8$7y5HC>1}fDI8v-`ZXi~|3Ih8+3<^8FA#^>u7OdQp}=YdB2y2pZ%Y;9q+!Kt^} zU>kFndUrX_U5<2@!`$USciG=v_HmaociG)t`nk)tpJfN%-un26o{(fAblgIOU- zUM<;)Z`~g4avR9c)V%nqSobUaW2p%d>5y3Lfh>QMhwseiNIAk7s|_@m0MSs!Wo@vvjx8hlo*sOJ?S490VHv}NP0OzPMhQ)>FKWHbiZ;!4HYp$ z$lnlp)LECY9zoi=p3ldsUv#fQ6M0L*rG#Z#Bv3I@PICHPLt<4d!J@(nQquH~F4SV4 z24%VwO-lxP*s-Ra#M~369Ss>AOG6*J&p&#gD|gH;)&46Vw4$$L4Gm z%{YHSU7_P0hBQ&9*;A*@fl{ItT$&6=WfH96>CMjLawv1xE22#M8Cj~dQ&}V3LGEf5 zJqrbh-gq}UPf;`JL#**L)!pkV7YhP*x7=Y@pN0X+oracHvUrkZ2ivA&)cq3FgYXAL zi}W4TLzGNO-GbTukdvj1ua`w}S}-Hp+<$sHz0_(ur6!gdz>c&|YsKca**vjf1Ga>^ zYjDf}j&!FM)1lmAn&`VqMy}BRS-^^;-cSERpL;JVHPH8)eBZBg$s99%4+h+1L&jAPkyBy-_AT#@EVS2e6uNuwPl*v0#9WbNKXM-eN3N^R&HZ_$-Ak9h z5KA@Hq6t#XRh^hL2*&(zs#M&H4*_mH%Ioc*U1xLXKk-%hYXB| zHnY{Y#yoab(m}Cvl^7LmqaiENFB#eJ5(`DC@0T#e9vVw98x1uJBmR>xo#q%*3Cm<> zW@6D^v6cC>)qw5lOUarm)ybp zb7rseRW)uW{8Vrd9S#mV*M-lOsV_K?22}EtUJSeOpDwG0Q?;MbL#SLX&7J|P^# z4FkLY1C3IjQ^8qW@xB1gil*;I<#RTgzD?X!*@jErcUtJ|hm7}c zOr227DEI{4;Ko69^&MNbw+*pR;xAHi;)2GbDtngTy&TjYiEV$p=hyr!ZF^6nTrFPA z?Guwf5W7v}RQRrwVH-Xzj?Q}?wZgA{Z6)bd{A}31v;mz`9*xJTQ^|^%_zh|cnEkcA z%9}=%ihz!G9<8w<{^hXLL?G_Ek1>gSnZ=qyYRY!mzR~#M>IE7~fVBk%(<|!U!g>np zsMv?8$kc)ArGKEUp?kw#{A#Q`u%Y|q!IO4hWj6*ng!!Q^*TK)2~N*F&lvW*&gBV0t*@m{sk!xB^(Pg-!LFSyFMZN8 z$(-flnPqD6pw1`TuWW=Y^IroMQjAth>dQ!-Ptgn3T`fMleL*dBw|}%t0ltQt1Hi!uY z<>Veg+3c+Qp9uJX_Rl#Oa)9m^ou`%89H9FF+(AX@5eQ{i&Z2Ilp!jxTK(jtx3PFTIHt7_INC7PXzz{)_gqv zhYcs^+W5SAdwVjLx}2OaBq2BhYa=6~IfCv@B9qbr>HIVLrpUCM)i8t_f<@QbV7RZl z?Byg%H zIafhkR>^$+JXdi1YO7H4A2$gOE@$P?{HsQ_3leq*ysTG zw@uRvd8BB_+NDWMub|6dv6VmzWsm`mf!?f)Dqm6*n5*qxH%J4#4bo`grTP&4ohO6P z){r=7xp0c1?y=RK#!ejCkbVjE8T|fgBi*mZL8bFDHclRWmOA=e$mj@tTvKaoulvfV4ZIMQApz>L1*^- zFVNTG&EE7w;09`FsD5Ws;%`2zuwmpojdW2uZBp?Y77Ns^vY2d}&Ccf#YxtU6AaV@(?VvQ7gpvtwG&?bAbQ*E+$5#5(% zP|J{ID^IiVFzzM}Yl+3XVIV(|@r;yyUV|7ITBT+*c2o5|_S*-As562SzVSW_Zs0RN zzH$TSg=rndz0_y_@e=AzgW z8I*b=U*`~p!WRC6xb+(Aieve=(Fys-rRc>SU zoqbYRNO6?q@FdNcR81)0q<%~(H*Vu-XnK(GiHnBJ6)_=YgOF4Gt}+{CVi9CQNthe8 z{|Hr!D$s-g8o}-vTJWSo%CbrmMMc z6W;R6ATIk3l&&F0lEsPsb#u09$%X@C_*Z$Gqw|#8B)Vie(V}g;)sd0eUeDp*?pKF* zzdm$#9fXP{tGo@-B~zGZWNK+^>V9?4-QSfCN!D`BzjSC5NzzkXCKgCr~Jk(8#%{Mw{jsBJ%2+iuZ$FY|!fcFV1; z?OeLBx2tJjbl#t=$SDJjjxk5b&$H@N7R!>7Vz$fB(=+yeMbQ745pG&wjPOHuxzb(c zyGw_=T;eX%-Q_}e`KDcb{9k4%iij`#N@aK+>onM{+h8u(?f|oK04pn-Nl1hbhQUmQ zC?E%IcW}IRJ$7%#cG71mkhN%Y?4{01EnGU2X)RR4WHL6wq;1hHCX=oNC`?{$3-XNX z{?(l2D!HtEV9;pHy&`fXMT&#{H(;opwSu+z%DMQFQjsf<%UPDMgP_5K6iG(@@))i$ zB(MxStZTelOO#%)o@Mt`F9(muEr85&Y7Yku3Rh{B6pgc{=K-LKrF+hRRu_sQn5xzz8YRQdPsc&f9n*)CxW`!_7aLi^yk`RQb4KKyMsH zgSYz@^6Q__yMAA7rX@UzWmf-$CKo+ij?*i*`r}mn9bpIZ>W|Jd^|zxwXxIZ$CBgXz zAwV!8QfZ4sLZt65TIuuv993=-8RshocJF5Vrv?wUfuOOb2z1FqD zoFjOFtX;xxFD#x>1GDT8dxbr9*Mk1qWVVm~n%`d@f#h(qks~6tZ19P8%KmcsY+cSW zW!Rg-x;VRGZRdRQ6nZ-ax)Uy%oK-=%aoY^bUVB0GPp4Ex|I}P{-sm;$&7>DOgu&vF z+GnHJb(3}P1Y1l{=JV0d_L0*zz7)K}M5zf}LmrY-KlthwJ&k)FW5s6`;WEGDx-^#1 znu940O_qbooIJNR8jx$#tzd@adS7#wDH6lPSUxggV5%Jap^uMj-FNHfK>?izbMBrwaX_#HL8CNi3=%VC2WU;Q_(8ZP-x#B1!JQvbB@_m$S}Bn_ zt5+-BVP><+r*nFBNBL9Pt9sl@w-#FJ3sG~FxWjTthu3xfCSCbUmJXp{EcGL)UagfH z>#v-zTm4Z~)Yc#SUsqUB8ObU-mn-jet3Q5fN~*tP>4UE525zwUPvV_^>dz2NM_L>a z`PHglPQ#nlwyGJbz1`)1FYO|huav#1&{2~w27a1Y5h5zoK zD?~+2#DX;nuiOav)CBFwABOJns~RH?=WSI;Ttp^I-_*p)#cpt2Aw_eIq@f)fYr_a%IEFDf}bem2LyyBuXgK1zvr0|7YpTNuj#asRr{$vH&VyZ#YgJX9u+<`5wu-A`jHu+# z`L`e#Gd&jqWvo}7<*HKdPlMee&6@m8xb|1vSqGpRG21s_zIuvr2-) z#u9D{ekz1LSXJz(MaB&WI12t!{pUTO+M;x4WrxQIOrR%ZroJ2pd*@s7?3M?0(0Cf+SYOK%bV7Yh*W|GEO9lQVP2__7Hcy-M zbVYqL|5pM2U@#mm0_qp=Xg0$yz=M&3`v*FdPKzZMI3?2IWHh9v3(;B>Y?znZaa4bl z=**rU!i2Xe#a6LmHNQ$<76nW4N(Pe;=FRVMgM|C9)UF_awvak!`jn&JWxs;rji64$ z0lbDp8TjHETLBLhkyh4CMb_~nSpBvXwYmo>;Uh(Tg862()goe;DEa~Bp@Znc53)8H z4ML*BFmCvtO4vSxCwrqYESiCneC_1kr}QAz1i>@;gM8Ki&XJ9F-lo??kCI%jen&qmLDLY^j-kV#k)z7uS&xlQrE( z!wsDAm;3QS&pvkKR(`&MwJJtd!BVTJW_pD0XFj94qYLi=E%x|Z(Jsr-mO2G6GTTDq zFT;1_-xk1S2JnEAv4^&^1UG@kyYrykq#E1C3j{)@asacQ-~=QD1rW+QwhDx;0-e8BpC-d9RzeCleCsI29X>jl?b2?PmCCe-N_03pr{){tV zADC?_ya&I+fTn;Pzrx4jR~|VD4AzNjxrIfg>U!@5S&X7#!nbcFEczqgY+ifOc^#^w zk2aGFOoXY^c0E*q^%_)_AhAJ7iilr80#gSkdq|K;FEMDqxvC)OROzW}@l?vf*|4uA1xh6U6nFj^qxm75@FR=3m zyk8wyg>yFOl9*hVEd7I(nOuvGXKmwTI>;irE!1TAFqYVYRU3>ZkW>ck-`&CXLABjK zqb^$jtSAO487VyfK1?G;>F=2qztI|20O{d&PnUXD24DUR7Ohz5-4%JUmjb+hCoFJ}jz;v&Nx--QV=&5<6Q^bRe;dLTeX zH&kzyo@|okSEm&Mdg#{}-Hb-55;PWd37-tuH*jrC*5jIA--*{1ys3ERLTAo$k&ysy}*ZKBa4M$LJm!lFRPpJ zb%Kue^qXBRde-KWgDV%vl1>iFnO^Y0s;`Fz_*nJ38+ z2i#|dONGS6P7dI_=}TlR)>mZt$fl)^nLdO2Lpv114k$`lmUUvV@mk?)ozK&3L6Q3q z*1cVut>Z5mT#aisOW&Gq3}Z_RDm(7qYpdYvLQwQNrz1`(dO9$jE}VtwwBlrFYI8KW zxJ5Heqfpjn)U^C+3m)cu`seU$1`7$4IwpL{?$9(KYp1b(8P+m($R9*!&dh0>!N0r7 z?-GFOcuyVuwEbZFxuy6g~s_ zJW{U@k@`JDYQ0`D=zB8oGTfQVc~6S8Ohqn!^wWkOtk}rAe}LyfRh^{20-RRae9%>p zj0|0A2#x6CrVAqd^&A@3vt%a?9X$lR{V-D?_|{iw7`RN2FfU%(b^uui=4`$9ob4N; zT^DF*N)4;HkboGnRdt=Ed(%iXnFCmG^QS?c5=CVcWC8w8i5UK-N#9^E>K~YAkuZee z7|zC60%6Cgao6YA6coe>67dWm|k93K`NzJ1@0&6V;+bLORT$ zorz~~ZvUKF+Mi8x^e*Y<7b;#?;pVRBQ!}GF%*sJIx$tES?4?&6BdYkuGIJOnS>MZo z)MnS4unM9$(*JGJp7|;RVz%Lni}EJTsbS|0ag*H~7W&k4p<`OWDTK3%B=qJc&cRjJ zSHucg5c_CskZ;U`m>RaFG;A!R0B(D>kH*@W7dWEWp*-Gku-JGdJkrre8?%D6l;`@3 za$@)@t`e74#AO<0tT!T^Ql({l|s^?5^d@}*smANJKUAE z=ODswl;;b@din4!WY4_843lE)auK6K^Utc_{XIY0p1vDhor8o-9~_hp10n?+=}~|K z(HYJeREP)CxJ;m#ejTA-q>jHsZPgV>%GD4~p(^+s*t2gH(<{VX@`j~Ulm3x6oIHQ_ zLHsx03#Cn5q)+Kq#yzuxYU@-j_FAo=Y7qvS9cUSM$otzr3_)vuDC82tdxr||Eo!D# z05_*sdsR#YPF$(Z<}xZl#pI{WKp5(SuJhsPu+pC2_c~@>4DAeysrvsHhWbEu~L740j<=Fqdy2k;n%u5(d5LXrY+ z%B>XB6PxP>m9_=UW;F((Vcf@r!5#95%d9&dSBp&q_Ql*#Knbj4&%pc2`CIA zW7ts_%7d5QcU4q)vdYs0YF)R`1OieeDGsrNChJ@dfim5m=i`-HeZDWczon!t#=irj zojUMSDxgE4=h3(H^*_s681{@VG~pTxTHlgBa37=>+Sjr@!J|WqxN}Dx3x54kFSOXE z)hwDJYLShayM*RL_sy55ovGF6!J%5EyH3-|GlHI9Wqr38S#6Egysqbpd_wQ2M~+lS zd9{#BDyb0D9!@5FlcuV{l{Lw0zOdc6(%Z-H?f}HpX=c~6pMvfJvwi8qLaZ)4UL!5u z2(m|KIk*kk^pZShxda^JaF@`$e4jithh4MrMarjbqNyR^ELC;Id=Ycn76Hro#W+eV_?2J&KIb2DWg@@4^Q zFPpuKI9s~4;LGU3rCuLrNxH+1kr7iqr1Ic`(y()Ldwsn_sM|J%ZNqQVc2PFRXFm#K zk;cn`yl%6QOJ2WKsLcVFMef7gMj^=Ey=y{0Z&=732;NeCOnoMJHu|A0970gM`HXU} zSNLtP*hStF#~$)#T*8fmR-qF#O`;gcTg)H|Uh*bah16Rp?^U_-UL&77EmR3hYfX@1({jQ(qE6E)UdPf*dJ1{F7@P_vYBV2 z#8;kN!n6wC>-O7}OC|K#m+rZjmh7TJuS2QA3!bM;EH$|tO>&NU>&%st>4q0FWrjS1|Po|pNjl` zuQ16-SVShm;J@U|L>Pxd3x4?lAzi2&GJC6NSM;HQVNPHyrQlHJh<)kol8hDB=?yRI zNT)Zv#2aOMIT)Z#mN&9eml`(yHqRSNdV2B3tG~$Ojd!9M-f$cs-guZYxxC@HW{147 zXl@>FT>a0!cw>xl%uaYijRfxwv$q>4n&H!U$bHWSu3h(58-v|G zNDU2b9JPZS9EsbuoZVxg=U`nMI+=)_{AMe0_fh0f&>%w=%MXaOh( zhbi*xI6)o9ZGT2n;TopG!$d>_gz{=8z1|d2_MuRbUZ#gys(KAqn;_cEQ^MfCwxF@{ ze1h!igf!Q$>9wNECf@77^oNXa+O{ArdErj)EGHQHcv-!~?QlC682pNZ|=ewB8^tOdV~0J_1h zos~5JsogUbcFhGS`1+>IoE+9Nx`bOEyJH8o@Ih=`5&uTJUh*$hiN+6ssETu@BnO&} zWJED_yR%t9b?yutlA3enCIiv94)$`ji~B&Y`r^0{69I-W)hug$kxgYf{g;Bvb=dI> zH||TR;$g3S$c7D;_k`^VVVjL64qfRp{J50uUT!tCSr(i$IDa(hqkG}+J^VgFzB(q!X_d^?T8|c1R_P&bh{b%?$Z)$r&td!yd+uvM5JAno z8Ptdc7VtqseCzJf&hM4lFE*`5_$9~k-v+BvY`5ENsDzQ!1N^+CBx~RuhkH7gd;197 z?Y}!i?)G)jt^@R$%j7|tIyrLyw8a2%=(8S}y$kaLk#P5_pL(L!BtckG0~EpL*{Q;a z4y)Uh?&?Y!fKTVJ(;4(6mO|F8OyBJE*ZX&Yoo2nHfy^6f@y(1kH>paVIJ(h^jA!Gn zSKOc{hfXBg`3)7+d2e0Ht0vOfCoAWO)cQ*f8+4P%eZP?#2lWTS%SsCv(0hK09rc$S z_R>$R=mu`IIK9*r)vf+i`(nF7MP7*=9J%FwLIR98;05E2KB4~?f}9@9t)l!ooA8u35PKaVlEVf3cx z{IB@ISj-ozW{=*zl}q)LQU8M%EnCS*P7oe?ta@>WfPx7ds#l4z@1vXzE7Edh!A-<= z*huHt29Cc&6~R|%N;aVCW9dC$;ern2dby1zZQW+Z4^)YIBy$gfl0~F2H`pZUy>jk>I2Y;Q|hzFEWgI&~LDtMK^@S zo>UJ@V3G1@*Qe}VXpeMO))~Wx)6ve#n7iv_+<@v}{Y7ADj11oPp1B%Pg7L##zIZPMhpaos1E`UD&T$^L>6ro3q(}l*onP(*NYZ=kb!K#jScY(q`WizIr@>(?6QAlCOlp%U={*)_D zmociW87W_wc7v!EO3?;;Lt?xf)H$&<)ZObR7RLm?Qg!4Y3u96bLi*BNU~ zbf#lgKWJot%r#nCUJ$}W3jl!(5X9}#rj%pT1;&|-Vh+n;oO=oJCLiNmX4j$3QQ}Lt zn0lVSGD_oN@H4fTdI%df#la1o2$$DjcZ`VpVCyviv~J zx}};8h>eT^HMkcUXM_%dkaY_=<)39CS;F4ac-W3Kfgp606@=w)J4?1g!M1i9U*>hE zo13R1f18vQyD|epEP3-E`WCx+(Om(+s_7+m-{0GP3&H#}uvSZG#B3#=b?Hx1k&~|1 z#2-)0e?9L2fbY?osxYJu6Sjex@`tEpZU;jybQCZF)!=FrfMtVUY<5%%TYbpY##WVN z=?&Mp9V&CJ^gz|(REB&Am-5p45Ka+V9Va;-!e;y6WayVO^rs@R>GC6pT`feY;Ta90 z1qwOWo1`j(WkfkD>hAX7etxAd*1Rw5E7k7`CobNS!-=zmEaNMXF)Pa+z1i@_zw~0m z53FNuvD$daNLk2+E#}oWf$&1u2OGMvL2P(6j%w*FW5XY+1)*P*QiG{onPf4Tdnq4=<+MG<2pStFHCjH{LJf_r-nJ z59o{g4C{{jd}5o5p!)qCv)+hncEWl^y!W4*`!wkxa`BRbQu-tmgl%ws*r z#tiqtt+^5e#$`b<2hZqyH#(VN;AOtWxW@F`LO&?_ftEp$wL+)x-zc!Q(!aq!bw6xT zbf5l7Lj%MoN5GP$=kIRTPpe%4!+tVPSZ$eP%(pF zOh09vF92aS@8p{P3E9vMkjz}7f;n=#x-18-?e zJkpq0lYV+r7U|I?3yJ}#b2Z+^#3MG3CZSFGMtz^rOr4d@8vMb#8z#ZO-G|FZkbrwX zTdUEl)QGyF5_T-D)V=O&`O|_azjeZHCJHSsthD0j|62Pj@>)!ihcXgkaP(1CSVr8( zQ)v!H3OG+cg3Z6qA92F@b)Jvl=j*aPP7gJ&+jHqX-gFOl!LmAGTezTwE`sNBT_7dW zPYlXuGVhWL?FRxc9I%6Z{mhn+GFlA5ssi@V4z0D{W=t`!_s$-h!k9URgDm)Yk88hG zG_dlpy{m&%q?~NGZq(97Qokm)DPb({B)I9cmdZ1b+}#HxSy4dI2X8*9R!sD1Q~+1> z+*}}?r`=-GIYF05{E+4mGAP zHZC5E&d)44-Je;9gJ;&NIim=Sv`ROrVL{3-E1dh3Sj{gv5o*Db)53*$%L)UxRnVj@ zIay7%qqUVXxyuSxZNixZrVjI$oJM~;Z&~3uj|eN7ar*ybt$Mu^BSDP>HxtY$O|2!T zsaq?Gf|Q~=ziQl?hl4+6;^@FZQ!Wmg?PgKN?)OtR$Dkc-5v{ zpbbJoVK_nSGT(U~@<57|nGF{IA8l^~XVtX-kI$r|DUChRFrj-72GjL4Atnu`L_4NT zbQxDPx*mp-QDRKa{=Jxe_TKB^vpx^+^;v6u_F687aD#Yq6Hb@6@+_#_1{VQSa`F@_ybcuDs9gfby=vgLKMU^tlVAnC1I< z4eE-uEy_|13c^zJjst6*K+_!ugTuIA-zjyplAuIJHAQ^XQ|c#f(D~4lfol;Y>=dXo z{zbx)j1)D`5Ls&7o$Z&aj4nm4`Cj~uPp&B21EmWhMy{*gO_A%4h6K4z_|cQAh8~Vn z-bWh0Ts2&^3rde(nIPB4R{417$@M&uc2ax&BNtYpy5_~@`q2-NYYPswF>;+LJE3r< ztwfC8NXe_=o7K8r{Z_Aa+QNPpgLEguKp~i25-Fw^^SNs@p=(xhtrH4Ra+*7s2>gDe z@r%{DBP2S0*+99x_RWsASPSN8-38GrY~S~6*7WxYd$n837~gH%4*x{uV-E%uNQkNN zLy#^*y)OJR1EO*}HDK@bEhr8J;B=G~1d(!l=7DA*8ubQz)3j}J1wL$=e2E>wq#-sz z$Jd1J7Hn_G`DC2`>4Sab#3>aBGNB|v77D*W`eZZbWE|Wm^)X7qYw_u|db>p0{pMD* zI|m?`)ZX)$dfL`7n~f&du*rZo9iRnAkkDO+d5R_@P2G)9^Yu4T+7E~4r4Nqz&66!{ z-&r{_9w3Ng*`)3yW_1F8K7zs_FP*@*XKCqFXy!6iKvHGD_Pl;$Yi>Ka$4ob7^5@ms zP0V5;W!_NP$^NfcNAk3QCRBJ9r!=S>l{hw=!f0d83DnhbU{-w-56gm}O7vb93Uram^#c8q3ashmfCO)cu;uc2#mFtnzP#r4gp%g^I@TjC8) zJOZ>~f2h51i9DTO!K-7gAS}##uDJ~py_=a|BMC7L$$M~D$#bZwJjVjNxt}ff8ky(G zZ?KC^U0`l<)a~Eu-X_R$3M3!Z#9gl>LGwpA>_8sTcQoy4cTJd_x?pV4y0u45AB%I51Q_#NiK>`;hM93aJ1E zbnmOAM*n1pYFtLJHC)9OTSy@*17s$?6;8;7Zcy`X6#4aHzGfbQhvQW#dkWTw9awd^ zb^Jhl+^jw~=vP7-ia1IDHC$S8<2!KXEHs>7xYoaS7^vqmVK9InAXn3HPU+Xyadb&@4CvWKMX%~Y@d_;a4ZN8if)>4FqEQ6Mx*gtQ%uOjjiwl$nY!PE zOD2iiNExGpRnrW@3|#JZ#2_2sIwUI^xGt=F;^|^bZXBA7541?x728N;P~vO~TMJhM zg@`3#d=Th$ndzJKbm2iu(?}_f5xO`vCr87?Q>>toDsUT~#3lmL!@I^;_i)*?FW4l9 z35Iutth(2MBa1oEK_uLf|HhkF@PNJZ3hE&<)3;12ESR4+&qY5*?J z)a`c{Y^n7=d)iD{!=AR`3ZjnfOnXB2=NQL`^EztCgUP_dY%EFf3c6i;l43lTW93nb z4b1u>jXmiy(%aLU_a{#oh~Q)}OauX0IjX7&1JDt|K@+}-#;zcDna<;;AP(ZBgtg3< zbu{%`7K_Y$SdfOo?^3R0HYq|n6B-{pPdK8c=UOAByS@>!u>dy?tb#RocI}4%kK|#E z;v0d^8B&rgug{nDNT0>kjW*(@Rg%pMlhk9exz}xi0`9qb9Q?KG-0z8cG(vtKq6T7)%n$Pr(=)ye0IphC>Nc2{Ss?r`F7?Jk5S z9Lo|>a#*f7?Z?#M%6K;JOCul_iy9ygU4c4J!nM!^FrT0tWZG`m83wZ{%h{UggEHb> zr>+xPsz%+HEK6piEM<`8lcf~nlckKc;8*@9jVyH;>1Da$-aY6#>t9O+<-yUcfzw*A zx_sP3OGfxO5y9?^6F#uX2)9QJw}!Br+|bB>Bv6s(cGTTRbCOWSz0oKNggqLWS814D zmBjQKKhwFvZ;sj^gU~%?dWB(nm1g=oyL+KN2+?utB-6i|myEB>CUo)YW4aXMV|tA) z_PA|nn6Ar6&-5$r*#oBMECIew2P-|b(;QfjU^P0+!9=x#jz~A)8l|5eY&+N zJ@%F?-D59;+xW$143pR5LGx`4pG<0B(Ha*bL1;CSpOURjMdtmjMU9~S(a6ae{N6#_ z{~cK1)eI5)1J(cv=bNx=Ml#G7+|ct=xY1xD6C8=NWS8N)lNciQ1)T(9s4L(CVMprX zjm{3is^MR_6(;~dToO}jj3lJ8ANCsjwcvx;cZcw$Dk%S!N^7+Pp%_VoRV`it!8qle1E6 zV8GTClSjagl))ir>JVkZU3<`HKJyaT>Ra~K4v6ufG{;!F$1bR^dSZib*;}!n1eXff zi(=*ik<-$1zK>Hg@kQp&?l^xCp#nG%3jrWFxoP@#c7VVlQ*F>3#alCiC%PbMI>8Mkzh_j0-$D8Ne6R`%tTZ*+%_@BL3t1DJS z-idY6Q|^6tvRIi-oN!)!VwGZiVl9$l16O>VB37t^l#w3E@1MN~V*T*{U@}XvD+Vb@ zk1N8F-J4uR_u)y9`l5dk^@#5ByW3=71hCFlcT0@Z5r1vQ(q_Sdu=|}3X_CzGN^kkRL zPS#&Z4h1OE*&f*B)6Wu`wiAy=Pq+BH%h?0{JoyC(_Yk&;6bZLEhnX0zb?1E$Gx!lS zqb^`NF+Neu?RJ%ifBG}3ef|wbwO20EJb;s3r`IA}KyW_&Iyo3rrZ7nsQCVF@Nu@jSTrp@c>Fx?C}l zFWaywC>Aaksg3y69AVSuQF<63X*@s&1+dnBhD_QdxGB(5HDZ-7eu!@2o^hV3q$;Yq zdYe5ujz8~E(hUp#7fJWW`X}`y&+nf4L9Ft6Bk4^qwlC?E0VI1S>6L5Sm-K7bwIk_A z@!}Uqy87G%Nl#h`NpF<^m1Ifp`mZbL|KOLF^y9x!(pNA4)smK~MADDE2T9wc(V2i# zJ9utl7ot+_&Yo61maHJ7v{NKs%W@*cr*YW?4PhUxbs?C(Z`7_s5s2kiJqvz(BB2Q8 z<1Qdpi?rI`-}(Ch&okkqln(QwT}DUH4?OfSI?T85KzEqi*mi<2 z7%dExZs7nk;uD#`{WG6LY2@g5fJ0P78L&UD;7(lur8tp9p?sa4b@>G&j!5-KE?>10 zl)#^KXWh^fyC+T&w9MuRKx-hfI_8el6|Y~=OZ*o*b#;gx$BZ@d{PV*0v18}PJ;e^^ zo%XR~+BNN9MsuXHc*fB4lL!IBqNYErDhFRcVK zI{pnGZrr}dJp@)Lbv3fYmZxT*qlxV+U#t48J(^v06Wp(8?hU+1AIzy)wev}|$7YbC zsI5D&6OYXu)iK?ExzKEJA7H9sG>V@y7E*tpTkh$ym<8sSD4X$`W5%BFY^iOFanG}= zye+{3+)%8x72n*SPZy-NHLtqD8#h6NwKh`c^Hjvh7~m!2BI%hpHJ@Mt?Ly23;%J5m zgo~SuKfO!_4*Ec=E-cMI85sB7Z>Th?i(MX}9Di@Vad`8}c%?(!V^tRW0Q>cEJ zMablOGa6h%rNuhl%Ib2ak{bH2uo|xBz#0arl|-+?`5ZcTC=O#_Dj`*9(C`f1RKw8^ z#^!v@x_p)wx3%4Wg&;%by^z|Za12rRlGx@wws!TWwXX1diW>9{GFMz_6!na!QWSOE z6`rE@f8SHoc%NB{_rCxedk;!b)ZegubGXAm3O4?Edt6apUk63K3lDx)QNMZBZ7WyL z*HXCdU;-T8EW(!A6{CCX!^r#D=1rbDccoS@z=fa(KIEc~!K`gwoxp}(@p*jx3I(b! zrs?hprAZHLhE=N641=UNsGlgqe4{cQ_vBPpr~)K47^?C@BUI%Y6Fit6me39joa~tY z3>fRMXI=M4BlV$Aq)2_z7*FbFu1zEL3-SIJNd2gi1gRH12B|;DPiRx5{>*oAsjplE zsn5rQ=G&}A@p;8D20Pq|sWNl#4#hR%#3!aI%=JiEcZitJE0LJ9OHA| zkzTeF81t|A0AFY#@~A0ctrrlzU=ZdEnH=TYyh3C_(uaE~2KU;wFz={~UHXx40>BN8 z&}C3}Q|BFbPThm0hJJt6m=mVn1Dr(vF%7dB_pzJI#8uT^q>TPz_H`4)6}XHSU>N!t zLh-kcV7YEF;vul_1X|&jlAb;^&H=wX^Ok<*Nqc9SAn3T99>?>fdEiZNyE+W!1!;rA zoOYJh7l2`u$3kIT_PQ@94|uGO|D(gLwT%<&`ZYv&v+aj7d@FpOy{v{xB=Iqc zhW^UxL?*e&^Sn%LndzJV1$p`}0rGtNPrbrd_W*(iV{P*N`@Kxtt636%7Wr(eMd_%kOi)T~0+Bri4rlL1Z&U%!}PifV1 z)8t2J1Kc!uJpS%&)#JluD8gX$_>s=}Y9E#;i6K4=g%VJiwt#b_0!OZLZC^%SH2m5r ziHbIuk#-URISyV$?XnWt23Xg@({Wh`zSGR!^~Zyuj=7q5cE~}MaF?? zmCRZZ`#6QP@>m6GQx`X(-Vea)#P~-!&*^!sFIDmVqgA(VG!&wiG*jl^ap%eW4*&pH z<_O!EEf&r_8BQ`*Q-i%VgmlQtWCU+B)S)J$8+;5obMAr%=HVEx=uLTc+k1BZ7OUX^ z7KG#V8nXEV5-7C$AWSuWLh(}D>4}pj!L&Z$EC+H(l%v8hL@rT-QPMq`C_vBxF>zys zOAU4uLiAk`d!k9lh9du_@WI_0Qml&PGkFmLkKwN^0a0Gf_cNd2QX;gN~&L#siYMug1wK{WkGUNrq0=r6*Qezd0ZJTGfe=e>#% zKGh0!EJpOy0A8=E?vKvr@6El?1RXG5jBuVt9ei^D_T=RrdmMbAcX7+uiXOY+=+I&5=9`4eHEMJ>Z73(bYk^ z$@5qPNL;`xf_uZf8bVkcw4ciE@}2C~ba3AKZ}W8NBzXn?m~a5rCY)z5BS` z?qEJ-7x}1n8Y|ijhPgre={e5Q%2*oII?g`h{;I?xg;2N=#C&{XV?40Rq}f z)v#BT#$^Mn?7C(38y2(KIwj z@+A0+h82bZ)Mc>Rgbwh49Lg2)=8`a`=jxv3WU>?ZT{mNF$hVMft8Lnw@-nuu&(sv( zl+s5zFKQm)1geHnXcF^4e|TOC&fA@JHcN*-6cLnWu-piB%;%!t;k--~`rP)Pv!KHoR-lBp^v+IDEu*c|mMy^JrO0%A=xO{N75WSQ zj;VfK%Ksh>e5-R`?3bj=&xFkIdi>-;_+E=)92j+8ToB(U7MU~85x-wVqI39s4Pl=0#ci>PhCSFYMLl!ADC#|WLL{x4G?T; zCfs70E)Yb#K$tERHcy?*voOW_Y8$(g3qk2=V754NDOK&E@vhp&uuoLmVj4WN`G}dz z$){gM%o8}5lEi=pmgt;>pZZ${y(Dy+eH*C}G%aB5!3cK0z9^yu$9Y!p0T}JJ#DxEdXdF zUZMdlv&D`8(>!TY_e#rrMeiwdOJWCbi1W)pgaD_Cg^Q-cy4Cryr>CDBVIE34i zeI0ThHBWp-C{qYIiQjW!2Q(n~1sp;5Uw=y}iw}eCc7#5k>qLpmMANSO!h>y%&jzez z|K5=tkL&EQD`1S+&k4R{|Ie(3RZ^n+os`*n7Ym$g@Z6v!v@sDafitn^xs$j-a&{<< zrW~RypX=UQe|6JtIsHH6d|_m5EQ6)>|FC%*|1_J2&79T!Wg<|s0^;~J=u3{i+^8=T z^kuBRZ0{^7ztNX}>B}a4S+6f^^<|a5EY+7|boL|k_|!ScrCaN1x>Sj%nKeBo#Yx{tem^Mh&{Pu4@9lR!xL8-5{=P z!Avmh97UMq)DL%K%NH||fsjlNai+lu4E?;fl%|4r=vf9~Cz`0)S((I6G8W#6xYDi# zONTJijNPPiGk`;~LYmU!LNVZ4HQ%VEP@+YJF9Iq^H2z=&jU&IK3#UjC`X%>J6}etV0!*D30!-Vgg^?~FD0ZW*xJqDehz0okMlC9 zvpR`+oc=e6v_ItFi8Mif@;o_ zzQH$4A$2-hJ^T!a8`qJ(O}a8IeH2VdP>UP|2fcxl6F8#>X(FnUre2^)b^Ccr4g@95 z^}?eB{#euh!B*97g~@P|3FEs;DhG@Q{3(m`$lcKdFKD~stH?o%fOb0V7|!_ z&%=vHJ%wfri8mujey_0lg!79HNMf?n49|Th$-mUuJxRVglPAenkEgUt*jD}kkQ3Kp zulW|hMA|{(8Uz4W6+#fWg4iK94$;dnL=W=E2>duyalZ(chS}1_3B z!o9lXNwls{ymd+PnS`O!R_N3?Xc=@9v~V6MzFeuv7VFDW&u0rH9E~EIUrvt)*7PkJ z-wRkKbd7&B2i(IJ_q7@hlQdYlYKRDTTQWms7~J4{kCx7pEQAKx0$o8gDdFr%cQ*y{ zC`X+*%jIHyBV}RB`Q5Cr!))WGn9YxBw`GE#P;)PfQ-+UBb_OO52Qdgp#gu)+^?*P}|aT@??#Xe&ncWL?~ip+gJZ&QX_B`T!=NlZaMx7}i1#? z>8E-hXksoPdmm;*Gu0OV8|bs}1XDe^dhJWSYQ*IjkayRse?`7EYr$vB=61(v82@tA8S*qWDQsKa>=&lrSY4s->V z12uQQkNrjGi@ksaAv=Nwi+VeOj16vQxacBwhML(V8DGGD?7q8C-l-EGg$AF_C8dOa zN&0*(r)1KcR~)r#uwwkxaPTGCdp$1@UzXqi$%N_A1)_yxmj$anTV{5MyHT@6w3mjh z#f)6b0ao3ooGL_?5@tC`=3gX>)OEkEYv#|^^`)3u$908pG_0xTpr23P!)n-~d$#VA zClESA7h*wLHng5}GT>A;vz~MSxV-zn+TFB$-Gvj_oc8HmKc!21MVhCzE!kMWscqRe zbOQeNsJ@3hOX|YZ1>A%U&jrBz^+y9OXH!1ZcwZ+L*pTKa#n4cv+uAc!iP~~QXd#}~ z|0aFcsaE40?DX}f()eC}J87N3%w4J6zzLh7^HF=A(162*IFp*L?Ok|!Qo6P~fstwW znTC5`!oN;iLOiW>DCkGj$|H0a0+f?MrtBNP{ai7HA9xYp6!rj7@EZo#3hL(4UgHJ2 z{trIe}Z!a4lYeNAZE_DE^(M_+X*fGu}jsZ#G0F zDVwHvtqB_-#dBNz6i;qPC&cJtN3u{S@T6o(&`R~-Lja{4QLcwc33xQ=G++_1WgN60 zeJjv}MhsQ~1D(L#4+llf^;i#xlc7Gt!X1?!0T9cImZ~#QeDgD2+5C}EzBT=9qCxG} z3f6%k0snaO8LrCM;;7 zb0K;B{@`RO_nbVos11|w#uK0qk3+U-m*~APrA@kOmsMakTzYY864F*N8-IWr@wwc= z9u!RN|ETL);$0b4H^|&Je2c6wdwd)#^ZHcRdBE#3>F>9mjBZnhag1grbYbl0MYU{v zL~(&*P6uI|2oEvd8vhT$k7IQhc}(8$c{^JHAtwv*TOQj5&Sj3T;(j zp3GxgDz$tW+sWYteDR>VcZ{}(0#;P$1#Ot5P=y%}rKrOD05Bip;_ONk-X{>AG1zK+ z=xZifa}4mrYdA8sh8q%UQ0wMHmmf&(V3YJsVu(`a&t_24BFp#$7MPAbw&Vq!?GMIl zaTZY2kiHRTC6y8CBNGJ)8n;)xVOD+A=x>FqF_4z=(u?>jN6on{Ns0HmJ4K0eF45{D z@(#+B24tQTXld2$@awIaz(O6+6si-KkU=qa<92?v2)LvYP2`= zW}o(!i}oIOlBd06m-Ir8O&50Mkgrm7Evv2sX7_-cg6e^{oVf%t-qRqDs&&T zizm7#pjir@aaRT48IXY!J-{<4h|6Rjo;@r2;KBt##EtQjsVkydZ8%9GzH?F(qOH7r zg^=D7N-X0;GwTan+gN=f2Ma)~G?OKD`G2Cxb4)O@AGt>QYZ=)E{VAmWK%nADa={$K z3Q?!97zrEUs+Ix6+46$wwD&_kb*k{x35cJ&>n5X4&)4|W35J5f&!)bfI$2>{{>QwAgC;3L4V3>QEMO_k}l8iItn>TS)*%a`mDE4pagNuZ}c|)rfwxkl(Dp%dj zlZdNY+JaNW)pJ@BjsQskV$cjq zr29XlHfRQ|Afw-!nxwq_qAAKd=)(4u7v#bQ(kL&)?4Dgs{bjA7JBO5Fexok`IW$r9 zcg_ja->37#Y;$tBSRvCFaR_Boi=hcF_Gv9%z)ZSH?s-mZRmpsx7FUu)@QT4_PHw*% zqs3dReOe5ZhZgrb-qYe6n5n`AMO02uY&}liQ;W~w`!YNhP}KG#iafV_f+A0n1AIAw ziu8qAkpr-+r!Dpn_RB(VP+6OlPt=3wDb{efI*IJWP=_y(0JR3p^;vV zN8<#9Z94UUq0Y})?wXz?w5ZH&+cM+WUo1B1TqvC145(Hxks3YJ6DVpom zz`MaIhV%Hl%>SSGb>)3~%CBdC9ly5kw}<@NnD_JidI@RB!bE=cxT`~c0spt@_(AzN zdfHYE4^L}%&M{XQw}yGB4e);XC>a|#Ii2p|-_(ktqjlbFI>%%i-{(X7`lR%51 z!Wr_VcsXO*FUKR?X?3_-G!V)U@?FTJHtjv#jS|69Y?#$R5eisw6~M7PWWe#gDuN^9 z>5*GgGb9J|C4C5h=VkE|&gJaeK)7xMf&kq%oQF&-4o96wv)_^&JQN*aVv@u4rG@}G zO$;q9$I0HWFH!n(EA^qF|_>Xj&U#;E*@>(uY-%7vBlUoA?rn^r zcWhHrKHtt|*J^$F%mHLDT+D;mIKDcA^H*rRxQA1_)3$1Zds<@x@Is^yYF2<6VmWPX zjr^vypt0-ahIn!I-3k6&H22CP%)4QEr0y}%8vUs?;X-!5Pbk#gI#~L8b2KP=lN{BA zwKJk1ELJ=zS5b`dJAsN%dTGKO_Z7-e*ACVm7F12#RuE2|RO>d9qCH3gj1 z$L9nat1q)1Msvx)hr}RP4mB`O4T<^!$^cv5TQsE6aEAu*Iex>t%u{C{4wgaFg@x0W zk+U*J0zAn~%}Dlw@w{fTK7>Xukt1W-d%C7x61#$GyJtLeW+(6rLelhc>cOQtfztVh zL61j>UC^OtnrPtJlR0Zj8JsrF+h+~36D9X6M7y#JB+@|~=CZW(9RS@kBSERaHfCEvB+c0d`faCTn{*q0 zI1SaA5O<-EXHw6F4tx>SGV!_4$AhBybgi#si53!Faf39}`&TDwo(Z}vNn=mqm2(uv zAD83Dp(h(OoF z$?ddB4>{Gvm0IM;Cr$~5WYZ7zhGh6MkV7alPX*3$yp>(wb~r>RUIX=T@6R-&OjMs9 zWfiJ#5vjKgmz8aS`LljCm&_J0)piVGpNM99*?n) zyjk6Yz#y7O1=Dc}8>Cbq8m{lgzvD?p^P#0+LCsL73}>K&Jwu&xj4F@>VZCmy{;MtL zFxHAuZW+4t{PT!)=uJD(b`<&SOu$OzlKgF=uH)ccV!X0VO<#mYMXy7>CYft$NIFBZ zy_lTk0$-LYk{qG9X6Dz(Z_!ZfBr7*?92g2t#N8Oav7OTYib{xE2q%F9pUo(!4hJxNk1Kts^Keu57H;}(gyV%# zrDnEEp)?5fhmj&aM3TvGkc-LhJoSg(BqN@U5;|3F2Qs-p%cg2cjX+;^agaR@f{s74 zYL~OvXwUDMf-)BELZ?)zdjvf=qc4SD<$RW>&899t!s;bNN#y0wRWlM^s#sz zW9y;mIN~;C{OkDjeRaqBF5EIoqMHMfRoNhNi)%2@1e;RNV_Ql{Y7V7?8P(oToj|kp zCNDWvS~S${zLBro%LiR2NFg7lt$TleEe9copE&vm0+WO+w*a&r{ z73Rh6K)jH zg*_;5>GiJ5?lTIr(BkBtb+sOn8yAIr+;?ZW5yQw(MivAqY1ko`5TLC!eK+zWxiAFV zoKFy^_dC?7%3~h{HD@1Wa!MwA^8<4%#n{rBk7kxehXeXA%qork#zyB<`&+gVDppBl zt187Oij63*)EB_b@=Klk`-ewLx8w|t9=oR3fQ;eJNn4;$TZTJRwq%`E|BY2&fU<{2 z4%sq1GIC2+Y2>7Qm6c2G(OW|!vg8<^VS}2%Zp3rl${HcPJxxa8s{4$HFCQv z>;_G6FO;hZFh7klXb1)z**!iu7>z>Yr@}gYG;mlhj9Ml;;SvPlxQ=G(0`5ue1g_l9 zwCL=Xm^FQL``NSaKx2p+U-c9`$O0aSxde4*C*bOip-dkaRM$SHEq;>}uP(uD^8<|H za!-Mk=5)jl38;GNNX!XDd(Y=ZE37zO{(!3b&na<4d&rhp3Dl^OH$z0!2zMZBuJQ4Z zjAwUtqE>7Tiz1K1a0EjR_-QUM>tTavwpcezeSsteE$X>H`g+JIEGQvgd_Ed-j!zin zs9wW~;d*Tv8VISPJL6(9>C|f+Zq*nBAL4Yw4n!$K6F3xyNLqCXVd2 zrl|cM(RTG`&zsE9Ph!_dlRSkYSDirpO+gTu0BLJ*tYre*)NwVil9+G0Cwcxu{E-wq zgK)IuAZTfo`7S9(Jy7A<1it-=4$ikdjNN`?3PEQWf_y8b@`)X?=^AL$(gu`-y2OQ& z?gm3hI;WNHtj;xhY}$#zM=m0%vdL&280*J?B>R6!<29-q2f@JjOGtDX#t=5m5q177 zSj$deT<6z0g)@fQEcKee0_g_vMbL;T?-6LBYZoBgAR2HisF@4Og)S&VF$l_QzGYhI z!%-$QfuMY|I6ctN^O;pg<_Rblx}aP^7L;J^)W#ez^am4B>K}-F#Mnl!I~S?97zp`5 zdreL5S=R5|1-&ti2vUdhD0i53?w3KBQMC7ma;d7Jjc17u#5T5l=nWwBcCj2v%kkaW zZ%T&Tw|Eg1qTj@l3nZf#Gh6>x4e`H!PlpHl+NN%(hIo%jg7_r)$`_?6=LuKD$1s@NV@;SRa-A{4zu5|{$nM`X^=Oh>!V$%+aRLHj z9PU)iW&uwmh{=K!+K4Lk%S+W#c{vW2R?BmW^Fv@JkE`sszm&zhly7d(VQKfIL`zRA z3s{Mkx$epPZ)=1TO9(=dC#*7-F!Ta<0tAjpUNmrHciH@PG)oC;OL*&RV+p+_Em6(M z{!asJj_!$#41P<1c5;f6C<03;Km!Y1OUP5J5tiv$LQpNiZSw=_h>2)^4p^9^KO4aR zRDZ6_Rh4p2Rlr%Q$^)0QkAI<5{M)VpIgWp(WEVfk0+bBXQ~xZ}%2Z+yQfwZ2WHidQ zG16p8G+f3r7#;jPLLN5(&F<<)$fWlFdU^kIRg%0rx$?evM54SS-BRRzp)2oWC9RhC zwCP6P<;bwd^4^F*NuRvm#x3OC?}qg9eq77Dko^ICX#Rl+%B@#6XH7hp-~d(c!E1?V zHhzHdrelZfg!86vs&M-zS#e1Ew9OPXBI{R|)%?7wszM_M_@$RJ9>ETj)ZZZ6lgIYp zPoU)j&JmzrdG9>-L0!9ooo*il|Av7N)s<{_fgD)Fg$x|Vi;S;-Wz6s%WMl%G;kETf zEKOO7V##sM5IkeWwfw$UcSt#E@Sl8QDNz07_C1zas0wh?JX_s)J(_n+V)K&y6N!mW zvp&Ok`K4%k-<8b>mzN%$vxWVeEaw5T1bsU~8V>0;ZC4n#Q^#U|FktX8lwctmTJ=d# zI3$a1IOUUj<>aU}*s90$Xw^@m&|@Ot;n?GM$-^u}Cd_po{_D8-!!Uf-a@05ux>L(- zSK(5`4ON}ncSjqHSetWd`35YQg(IIc(COM7par%Rff*B{&+7=Uzlk&G`fa> zQPq6B9Wjo(obV_s9cqM(ONg3n$RiHCEUJ+um}i?!zV+W`IZyJ3MpwN8QyT5Od}w5) zIW6IU>PJ{!5lb#1Dgq?Eb#C;MQlko8=mBLl&V3X|kKL~y`H-8)7dw~8CoJMx3~a7| zGkHa^Q@|{4g|Gkw@t>I;5*r5lD!^`pk70sg0bX)~NZw$of)jaUuuh>0t^-G3&>W5P z(;1vULob${n2F@mwzfzqPwT}dM_)B}_592nnZRfsWk-jWQNhG}035rYa=;$6k8V35 z+Tjw-Qds6TTIM!2|9;qn%#D~CI}A59sb+DRa+$9uo%*kzdMnEd3sE!8?*5ttCdwhr z(UZ{p5QYA-9>cGmWuH$G=dX;vL-dc+?3c%F6C$gOM&(ss0*4$> ziH@CWD}DugTdPXxsu7`+ z&0nN1dd`T1qMh8m+?`N$^;FElqw$p`Mj-{P9yDNHnt`R+!g@W5@LJ(qjPC_;0Pu7X zSZx!&8Eg$$4HrsUG!46oMCdBH{sKi#w$9E6_G84#D;SID&nt-xMWofaf{6xf#M4n_k!7j zdrsiX_c&w+6V`RZ`FSUO(}J9=OfWTYfRS3_;qJ%(K^`)auQ;^u+eKbI6=@gQ5>63~QeS+dM|IK& zJ{qsq;!*RWq;yM?(}mO%OgF1IJ5*eJShY-Ic!i8oGyUl)of9!s%Tm>N9Ao%j@u<){ zvA?I%Gt!@r^h{6#ndflifmq*c?UxZdj@iKIBH6|1LvQ=sH*9QLN}+PBsQ$1U4g=sv zn00O9bqeWlPC0^RuIg{2pxS|A71h~-~{hF_f6p4`z_!d46P_O7*+t)z+Ql6 z>JgLs8>XIYH9TN|Oqy@^dEbtF=53?7L6lkuL!VB{a#Yn39Sxgwk|MRGMB}b+ND`dKB0Q(XRvhupQ8WTQG}7*#cQcqPhLo zumx0U=0XbquG||d&eb(cSZQajF?PWg{Ow_+S29lvo*z&ma}3F{s4V?XW*+PzBx-swqHfxK@u zSP0aJ5Spr6zWX-N~RE$!9Zb+@EXkQ{DW4!s}1x>dJ1fm`WX96Pzk+9 z^rfHXPfsWuAW(QM9;ZT~FW*pqJ`IH@GmnA7SGEHR z4=_+z;tgKBZ&HIqUm8#Or zw*M#XNNk*04O`05hj2XqaGTFMLS_4O@4OXxRI>fSO_#Gl!#MU}jFDc717p z1hxn+7|iq<_|bP-Sxz;W2`8A_HSDByp%{pe42SC+-Knx>7wq_4keldtj{kAUgvruFH`EHq@^ZNPNUL`IdJ zxy#Ta8^wYi47gO&CLcW-%l?k=AA+m?nqK|(1p&~dO!Ma*Mu9 z)|btfal9kT!Y;ff&sV%hk`vccFo5N_l>ay;IQs<+G%yA;jF=UdXJun_PYGq+2H2l4&|<7uVG)2C9yrft$(7~^S~ zV8GyWF*$*OC%MASeroq(`mv25&@8`355a05CqA7}rz{FLXggClB=E=_;gabb(utu# zjVNm<%i@GsH2Z)bPt6#H5{En8J7Mjv;+$xAl-Rw~Ic|YqAr{Gf1!lMfqJ0JDL^^k3 z0u16A%O9_HL)7JtY0k7|Y$Z-aAs{({%NB5@kurd_=!uY{hhQqr2@H1MpnTK|;I_dq zkzbDLf;7!fshowPmp6_AzaIralEF|WaNrpD>G+?tQ7N!TD4P0L)U4SCS)-rmRD=Yb zpf#YmZ(H-;cH8n&>>=8J`P8A9!P#Z^e|KWl(8z!6u|Fb;cjO639Xg@J?!RN|ArnUo zjh?h~X#Z`Y)ugJ(nhyb?zS?D3OJPXFC3D9@db0$O!OSaC(yMcxl~$aoFU9)OPcCSW zPhT(%flXJ<6bz&OuuhLLFyobLc!kRFD#o%zqBeYz_+h%1gwmFjDe#b{i6^=34)higr%6vmz{t9?L7ET0PZ>|bg zW?!F`lKpVEb_dD%8g|HRYAlM2cFxD`2P{Qzem>6>$TP!O!D3w5$`a&sTWP0OvKFzj zf+DDdNm&VtPkWYz9d6y3+W(&+9J8Wn4gs8 zAU6wkllj(c+wUN>N$8-L?x5FUR@iTjDtq)hR3Ov+_%1Efn=KQP(P|+XcvS<^WANH& z<0a{foMVb4B0Eo-BHzl$G;@or8wKeC=SzXjSb}&_2c5OSsQ_cQQItVp)6D!lA$N`m zE}L%-#s(WnIXBmq>!L;xXEBy(*@!Gcu9QGYtlfu6>r9ps^v~E~KpHM%70e^9VWu2b z+rsMHDa{P{tv(s7bk!PV<%ml=Gryck>Ki$!@eu6_`}GOyIC3QsLO$xNBJ1|&L?bd6 zG80}FNcr7?paPMB+b#~GK2pLjVL)Mq`uHuqTrE%-#7t*q^$~Jf#j(}x*CV?s(!XK3 z>g-Edo8WJq4l4wz2C140$z$}a=rY~OR`KPq#kO$YOslJrIH8VngZQ$@s(Y4jfksFY zG(zTF!8x79+_S~xu+w|-1Dv-)No^RgigQcV*m95;lv8H{4-HK@9!+qHqzq_BCClPL z5x-;QAa=dbhhY)=%PhO;pL=N~K3G&9k%&wW+N3acA1~+V2ci=oPUr6~9}MP+6c8yX zHP6ov%KiL&CHD)Z2S)?6X5~P_R^4#o4S1lF;1paT$J~Rlx+qL|yJVs*N;H&?rPFV~ zr9m_!WCRUM&rsn}z$)-K$XVB?x&Vl5?(dFEbo z8pdtzMFL1)fP3((5Ep(qLcZa)ucU%*lI#day&N(F=t+&wvcE+HI?+`f^aCwaMn34W zAO&JU6>B=hy0lm{{vk#cDgbc}M1 z9ZL*%vM-l%Jm_|%$GVP0U9pR#m+W_{SDiqgyQHqG`}6=-7hjg-d>?>RS2ssj*Mvbk zm%wONvBNRMWmGde9c)0s==)eJ$CHq%h8(jYCBnx=E8_89wJp6uK`N<>B*sXrMH)|H z&-u#%6(vTgT?4au@8mx56*UjQ3!3Qouq7fhNl!>qd(Zc29!jbtDNgqFk`o+*#C1-Q z(tLATGni(3zX&p)hU<&Stn|6=|~eYmY2RFJxVRzgM^zMCeGC>*`Y# zi3DYN(k2YUF_XC=HfBcxbEPXlB3-%5TntC3OK>hTU?%)WlgYyGRKNUaMDmIo2X$g< z%9|-kiiSeCcjjJ0AtYh$H5At6+veWwbjr-VrV18m?sfS-(36Vd5Vmuw0lg!z3z!Fb zResQ`Nd&zWCI_h%hDrDqTv@gmAFSW;SN?!z2p54SrB3I)21m0)U!9t97KWy$&_QMe zrIF5v=$(=$nv+z?AKgkK7?Esz$6b7q}iGUG3=y(_djcY zj*Tr6TC*p2Ta4N>Vu$kl5N-y#t#4zjCvSef2-&$5E~qc9Uewltcb6o!I>rzNfc2Nv zv3D`-?AwSqzjBU0U2{ZjuG=$@j0Bss+k>xYa(51}Ox`>z5!`RU80FoE2w7Gr6f1p9s$Jx@R7xQxjJz$)?)~~!}3`i zy+(GH9OgZ0nju%z%&QYP;vzoA5J+z8^w<^m1^V^$bKRBTI#UAVqbl~&QA{F!^k*bd zoB~shn8eLL@N;@oB25D&_FdO^V~lJq1)~aa9qLTP%4D3oo5=?>QZsSB>|8-ZE|5Gr z*n*!KufRPAxGZD1bI9KO+H8iTc~n|nijayjR5+~vKc`-A)%E~P4I8_$^1NuMHvr+q z{0j7H=Q*Q}h8g4g9^8~-E;J5T=iaE{ie$=LSS_;*>%Y1>$WPPwbu;Fn*pcjy1#uJH zgo9YzQ5Wf>Csg0WUueO4w#;Cdw2~NBE-zCsY~dEcFsuG^WMcEV5@K*{FTt@jc;KV= zeuSfIs9(>+&(NWON17knYvOzY`BBQRRxd(ktF|-8El>=ymWm-nfsH~aG=M5P6u3Bc zT_uxIBEzCRd+_@{k~7o^(Q{mqpF~QIA%!*aRVjNP-&f z+_n#W*LJ!iLd5m_MBOCt2Pg@%(=~9^5Ok~X=|saMT{ed(VN!uMkRr-@o{X25l|yhHl+%v>J}TvE{T+<`pEjK;j(w@qeXp|+Le!VK%eoSDS1OI$+9pJ! zlLxUg=zc;0x3TRYvP7Vkn9X@o#cu&>qy$pH~b4v2^)#T3_SoZg2> z_Mg#(m-gvc7bJQM6>K*A6k9<>w3XPctO!C81wlImfzb{@WIV5=THtw=TxaIj@ahEq zh)uf$LOF<#SAJPShBEOx zZ5ii*m#V5i$xL$VJh^am-2uP#<2*efrhn~nx0VX`Aw^80`+Gb{rjwpd;pr2d59MIZ^pw!x?N}R1% ziuq6;viUL+mqs(`lEDKUm^C!g3TH1L^YP!6;v@06n$;Ln(dI6fQ}Sruc?feNOK7>16ac01k-!|45-D8r9*6+HI4hPfkk@_)#fxu^6xFFGPN}6>kSa?NN9ohS|4$#D?O8ltP0(`G2 ziZVlp#5{rs)_fZ41orc2DAh~Mu)+8?#5wAXJAE`j%A|quTin+qckX)7u&%nA4XCgq z2ST|AZKwRvCMWRHKiE793M8U^oFY2>C=}-ejxnj!3k!81EOKM~PtuSU)nM>%Zc2D# z%Z;(9Y0GF}vZH8)dZQ9yq74}3eGbFKkaDF=8wHkrPckIh0m>Eo6Q4SPH}BO02sQsV z?9iay7y~rMPUc&5S5m*%*Qc+w@46UvAx7rx3aLT@#IaBW?#71Tg?jjOF#i)@Y?iF= zqE#|JVTBtbpEd8rRe}C*Of5kWXb&8H9iG^y_Nz^UoguFe47c=})J1Q|v;l9Ab+7vrH@)WhZocr|kQzUJN&NO( zWN*Uv7kaw{SS1CENq|ZozTU{Mk0Yx}86+EmMEM!Pg}S9^tMV z4y6rG9C=nzQ|Q2fwVOAc<&>duJ9|w&VPNg&o6ag)QGJlzwsI)8Ei>m8*M6R9XRfuK z3)-6R#(H!Obiw!ag#VVhR5%#1GWY^QzVs9I1C@3J_#hK=c%GyFvCbDs#DK2j!#gjq z8o1#>c;~s*qfh(Yp*SKOQ?W!LESNPc!W#sZv0JVhifd%)&>icCHnp5F^iVtm!kz1M zhdQ(IuuGWT8$%=OnY}RfDLnHes!>_>0jJ#xc7*09y-KM140dLW}x*Sq{W=ofKSTWSEH)zpKGkHfHaVCYp+S4 zBtGXIh&8Da->J4)qrflKcIS`kTh3H&UvvJMHE)$6*TlFJle3QL!4h_??mk-H< zwqa~Gq=46G_7J4Q?oWl>DJq9)mk%kF6bLaZe``ol##=+OusDW~p)8w=EGQj47v_nf zfmqN+QXENaIq%RzkbV$)T0>^+O;b4ozh+8w4x=*bVn{wP+)`}S*D*aJF$Y==+r_yU zNhcI`ghHj$=(CzizGI_oHgM=_JM(*OVhm0Ptmy#E-@T&4vXGVFpMA)HAgJKr$O|_= z@Kq)WtRDnuj%KgKg(i81FUImZ)DL>SaC0e4ZNdkw$hSb}yVK3*##r`Eo9Ri(B;J6X z$t~N?2=Cfr)z{OHaHA)wcS7l#qI_ZYBtV8JUi7E{*eu*o1HlB z%IOF~WWu5uBrA%o;rJ#8ZdzAsri6Lbw(JwSk`IxGenS5hQ@YX*i%mq=X*Jv>oj^*v z5z&woV^|Y!JoHu;h2Y+(Z(bs4D7g7aT?zC`YJz@u&sXotu#t`g>A23&p*vlWGWBe$ zp=%-q#)DxXV?0zFYu@~dD)T$-YV~m`7zGN(f&%eYjgtmktw3NDK0HICg@613z~^vy zUwmc8Tky^S?mbBnTuCWVASkGGt^6X7JCd2u>Ys@1qbNM zLlL>l(sy_2yW91pR$sR2%a{F7LIz4m!oSP{z_7o)fI`ivxc z`|J^3mteT@!i@&6Z|~{h_3Q6wyk18%bh0z~(`X9d+( zJo4oMmJ2?_YhCTn!!g)wQlNFtcfb<+um$o4M$Y+BJsRd5CFFpHPr;sB7BS3YU+jET zR(z>de>d{s6Ru;h(Bbh1LIe$m=#~#jB=R63(nE^`lIELH9lR`3p-BpnBt#(!eN#YE zo5VSbI11E_Fno>t*6opgURW33MpFR!tEg z;n)hchc?jm5=i_7Tx-J_Ngnsy^W(6ih9>fFtVzgy6u;c3^W-Tp6IH99XrLfO5WV^g zA58>)0of;>NdvMAg;xmu;MD_J1Kje`d+0~Y2mYYZatwG1v^*{fw2a_c>?k}?-xlK6 zD+wdEBs}R4{RaLOa9S$J?`gF9)OCqw-?b880f#NXBu@7Gx3>cp*CL$@7EPqyfJNM| zYu=Z3gJ5KY%!qR04%>sQm^z#cfvVsOZh}Dy5cvA*eX3t2FYS28BzQs;24jNg(F)Kh z7w4;+iC3NgVA4O6$;{*cf#Su)d!y4X*8Dx5QxHzz-3a*G2hU{bL)~#aemw~-_2AkU zA1vd~MS@9b`Fp|&&EMOY#L1qBqSHFh-H^`ZuN;@P$NaUh>W8uudF%&TAAbW=UImI~ zS$8-TA@DS`H}9(-GYrhJBf3k3f^^eI|Iv-=R$a#gg{%ZDq?8%oA!3mUG>%`fvz5m70@f(7Se*z!849VSD$Z|U6mGS@+ za46L*%3$t8JpQW6Ea^n}90Z*FKtfE=a3kY3*OTmOm_;Rqu zmmu*40Kh*epa2EnY&C$30&&(NJBz`#D}_)Ln5<|R1M3uXB!y%R?a#&*A`Dm>XLj#! z0#o)idxzY;58WOTySyX|=dWTI+PI7sSA80+?XbTFK|UHGkzpgsY#s{j|?vlibZ&S{F>2&+`Jze7t-$FBr+ zN!Evf+J8k~ISzOMeJEqUUKwr;PTt?D-wEs%kBb4b8*meDg{O8T05aTqtksZ-_J&&z z!=u-laBHED{%@K*26XGF?r&~G-BnUId0Kyp0IA{P<5GxK|1{a=1U^Sv*;r>t z(2kx5w+_2>JELJ96A%IV)~$!z&Y(<8m*?5bJFkUk(BXsS&^JHJf#x>WOlDngBE`jj zg|jL8m?xh^spr1=K`az#00)4M6%=(8`Eo%pn!7)VT32n^ku#AAgF|#8P0h99K&Zcr z02i@+VxS+}H4k?&?pPdd9d9*E2PNUwt9(pa(daShI@7kaT2jWs&SlZilJQpke&T-` zCe_9Zsp+VYOIXO>rjU@2ib3%LF6yX&Q(3^9Wtxhct@@ebUm7a@`#PKAiR#E{doC)l zMT<&g=IIkV-V%uFpVxIDs=c>%B&tdhm0naOYS(#2R5yjuu5WNBq7tQXAx7J2xV3Aw ziKY7qK5Mu&+r9lpZh3J9 zH8RJMe*~Ir;Xxw2CgbZS-Tp%2YXR{UeJAF_h_7G(SLqDCR!{Mew1`Oh=xd&h+<2=8 zVqBdPvo1jIflcZ#AA^_bsNvL3wzJ3wVt4&J=mW9eA*Y&kfM$n)m`zAF1;PGoSNi&q zPx_aknLg=rbHH$`NPjRn(kmaV=xkV#B>#u${U`1JH-)$&I2N>{qw{#QQE4>$g(cG9 zlhCH%Ez)32LIc-|F<}UQN@f5?o3VtTmY;kluyrc<@Y`YF!wSq$=9gf`G&p&%RsSzo zmtk?JUo?A|u7w@c8^~cgsHCRjYUj&6w}?c@1iIy&3xQ~c!lblQNgLz zr^9SM7QKvSfA^{; zK*TYI2;9M?x-L${BU9q-Loc65L_J=rZRfImC}V1Mh-V%&d4OBA_KVK`Up(;>vIvDEum>c(jHmRE!y-I4Jkow0c(exJ)Ulb8mF)W(}X zVYa{d+(J!#zJI&T?_|~g6G^1`km_Vz6{Wi5=6I_S-IYk+LwKono?}{lY4zCT#vZ2& zVq@>u1$m9lN-pds7WNDaLt}q<*=y{zI-@l9GNy?zO+sVWkM=hf&CF2S_eAE@R}1%xc30N4YLop7n}W_GZ9yY1jYV6Q7#t+VZnp&JZZczX>_9PiX|2Y zL*0wJhO)5XP3Pin)#CTtu4irF1Q-k?(!MWvdEZ!ndvn>|&S*vRGWF?i!JDWLLzD1> zF`VCO`Zfy6`2BLq~VSp?%rFkB4Xu9UpoLv86+j@hWuO)IbNx!Y>kAPKa`00#T6W-ZXk12$J+&BU2CU-!<|KX*YcQzU5 zjCd%#Gcak1Gvak#UrgrZwSV{X@-PshzTG!HFV&($&=$toB>NY8O8@Ww&tqV>j_Chp z66jx#AjqGm|H;=<=s&(a`hPt5f24oziyr-hK%(1kgK3E-egx^y+avnFUXnup_1W$4 z|K$Ib{(rpS(f?$12lP95smcfM3IBhWO8>Ln+o6BbLGAGW{q*|p4QfUC^Wwz!3w1zz z9$u>Z&(y@n2jx=62hV#9Xr0(W8K2;#x=6}MHkkSZbVdJ>q5h8Pn{?o#>U*KVDf=@| znhIM761#I>#Lhy$tryVs?h_|}*oc>EA0aT@dZn*`A@KsL75!ox?d2In^B);-poV3l9XvJY_VQ-upDY>2+q(xJ0&Y zd)6bmI!<(|T*^uG#FBQ{`U*a-B9X~#DIKmbhJ+uisLjt zT;(x3sUEm+b$F>>KSR@eY_cklyXk0F|IGz~l|BL!=(DEpsXom8o5$MkuJ_1HqYrqg z@`TJ}eR%PHzdp#E-mU!pBaL&W&L-KZ`Y>r^GCwi*>)2~BR-P<=a5CQ#<{~~f-+(3y zR;}*|w%(&5A&EaYQ74^$0)NTpzScbBF{i#G=2Vh7yH2AFlbN$>fuA|p<|#vs!4zUz z=JWx%v5`imdrEJ$kKPqed-T3Dz5`({#7lK)`>A*r+!gc44RIgt{?>Ha5i=Xu99R`xxb?ypD?|`)Qe)s1TdLJ>9MJe=N)8kk0 zccPEptT?@M$96z(4PL6~scHF}O7C}_+R@*abAAQAe*GDZU4IR|etdZRagW})9no7udXG*^?~(+t7d*R*L+5m0f3fu|`0Ll-mcM%R zetJy@{B6Wbb#qZV{(f_xpT9!y7D9hIdY{<$f27xr)B9Rw2lOt$OSSrxbo8EL<7jMM&CIfnNeQ$I6DaNaU+R2 zz+eHDvZBsk<@^;y!UOlw2@BYoLR5)_@en7t!sc{CBrj1Nw$A ze3(_Ygw1tI^Gi9wXDw-C>~z(__5dLy~C{#!lE zuH6b!$HAe8J_{d$)}j$bb?d6lCkBxbCDGg${wx6wSk=gcpbtTe0~Txpk6lUo%zSHL z5kj??yLMULQgzBn5-5WA^?0ueaNGO|?!LWPe|3bPC*45xp=5SmCj?LI27)j1dE#m4 zopc6hg<0V12?zgU_AQ4?0r-B9#6^c7M5H=b)OCokHfTr9hZgG56G6jQDjT&lKjq^| zl74-}P9t$YQu1)7DyA zX^D^^Dwn{9kabx_OBJuBR$E(brD~~GTeAehO(lTJRS2MPmPH9*A%K$q_xsG8v%9$< zYJYFv|L60f**TXvGtWHp+~%2QW=I2WPGqaqhmS}V41)@d0_fv#obPmU?{F-&8ICQ? zW?qDH{aE`rGY1#N;bGZ@IE*hiEVnoZ>@_N1uT1dwUpFkA)-BX8L!X1Br)T03|AqRk{Vg;8gNwOF7y4_SpL za2e`1O=WfKQbX!JZ~4zuZ8KBBE7Hnhu&a_oBnw_a)PTpV*EXy8N1%kP3v>ZNj|pDG z