diff --git a/builder/builder-next/adapters/snapshot/snapshot.go b/builder/builder-next/adapters/snapshot/snapshot.go index 656c79ec20..c77f7ff96f 100644 --- a/builder/builder-next/adapters/snapshot/snapshot.go +++ b/builder/builder-next/adapters/snapshot/snapshot.go @@ -291,7 +291,7 @@ func (s *snapshotter) Mounts(ctx context.Context, key string) (snapshot.Mountabl return nil, nil, err } return []mount.Mount{{ - Source: rootfs.Path(), + Source: rootfs, Type: "bind", Options: []string{"rbind"}, }}, func() error { @@ -312,7 +312,7 @@ func (s *snapshotter) Mounts(ctx context.Context, key string) (snapshot.Mountabl return nil, nil, err } return []mount.Mount{{ - Source: rootfs.Path(), + Source: rootfs, Type: "bind", Options: []string{"rbind"}, }}, func() error { diff --git a/builder/builder.go b/builder/builder.go index f01563812f..86fcd4de91 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -14,7 +14,6 @@ import ( containerpkg "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/pkg/containerfs" ) const ( @@ -26,7 +25,7 @@ const ( // instructions in the builder. type Source interface { // Root returns root path for accessing source - Root() containerfs.ContainerFS + Root() string // Close allows to signal that the filesystem tree won't be used anymore. // For Context implementations using a temporary directory, it is recommended to // delete the temporary directory in Close(). @@ -110,6 +109,6 @@ type ROLayer interface { // RWLayer is active layer that can be read/modified type RWLayer interface { Release() error - Root() containerfs.ContainerFS + Root() string Commit() (ROLayer, error) } diff --git a/builder/dockerfile/copy.go b/builder/dockerfile/copy.go index 8eb79140d8..10a766d3ca 100644 --- a/builder/dockerfile/copy.go +++ b/builder/dockerfile/copy.go @@ -1,7 +1,6 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile" import ( - "archive/tar" "fmt" "io" "mime" @@ -39,14 +38,14 @@ type pathCache interface { // copyInfo is a data object which stores the metadata about each source file in // a copyInstruction type copyInfo struct { - root containerfs.ContainerFS + root string path string hash string noDecompress bool } func (c copyInfo) fullPath() (string, error) { - return c.root.ResolveScopedPath(c.path, true) + return containerfs.ResolveScopedPath(c.root, c.path) } func newCopyInfoFromSource(source builder.Source, path string, hash string) copyInfo { @@ -160,7 +159,7 @@ func (o *copier) getCopyInfoForSourcePath(orig, dest string) ([]copyInfo, error) } path = unnamedFilename } - o.tmpPaths = append(o.tmpPaths, remote.Root().Path()) + o.tmpPaths = append(o.tmpPaths, remote.Root()) hash, err := remote.Hash(path) ci := newCopyInfoFromSource(remote, path, hash) @@ -203,7 +202,7 @@ func (o *copier) calcCopyInfo(origPath string, allowWildcards bool) ([]copyInfo, o.source, err = remotecontext.NewLazySource(rwLayer.Root()) if err != nil { - return nil, errors.Wrapf(err, "failed to create context for copy from %s", rwLayer.Root().Path()) + return nil, errors.Wrapf(err, "failed to create context for copy from %s", rwLayer.Root()) } } @@ -260,7 +259,7 @@ func (o *copier) storeInPathCache(im *imageMount, path string, hash string) { func (o *copier) copyWithWildcards(origPath string) ([]copyInfo, error) { root := o.source.Root() var copyInfos []copyInfo - if err := root.Walk(root.Path(), func(path string, info os.FileInfo, err error) error { + if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -272,7 +271,7 @@ func (o *copier) copyWithWildcards(origPath string) ([]copyInfo, error) { if rel == "." { return nil } - if match, _ := root.Match(origPath, rel); !match { + if match, _ := filepath.Match(origPath, rel); !match { return nil } @@ -318,7 +317,7 @@ func walkSource(source builder.Source, origPath string) ([]string, error) { } // Must be a dir var subfiles []string - err = source.Root().Walk(fp, func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(fp, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -443,19 +442,14 @@ func downloadSource(output io.Writer, stdout io.Writer, srcURL string) (remote b return } - lc, err := remotecontext.NewLazySource(containerfs.NewLocalContainerFS(tmpDir)) + lc, err := remotecontext.NewLazySource(tmpDir) return lc, filename, err } type copyFileOptions struct { decompress bool identity *idtools.Identity - archiver Archiver -} - -type copyEndpoint struct { - driver containerfs.Driver - path string + archiver *archive.Archiver } func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions) error { @@ -471,96 +465,77 @@ func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions) archiver := options.archiver - srcEndpoint := ©Endpoint{driver: source.root, path: srcPath} - destEndpoint := ©Endpoint{driver: dest.root, path: destPath} - - src, err := source.root.Stat(srcPath) + src, err := os.Stat(srcPath) if err != nil { return errors.Wrapf(err, "source path not found") } if src.IsDir() { - return copyDirectory(archiver, srcEndpoint, destEndpoint, options.identity) + return copyDirectory(archiver, srcPath, destPath, options.identity) } - if options.decompress && isArchivePath(source.root, srcPath) && !source.noDecompress { + if options.decompress && archive.IsArchivePath(srcPath) && !source.noDecompress { return archiver.UntarPath(srcPath, destPath) } - destExistsAsDir, err := isExistingDirectory(destEndpoint) + destExistsAsDir, err := isExistingDirectory(destPath) if err != nil { return err } // dest.path must be used because destPath has already been cleaned of any // trailing slash - if endsInSlash(dest.root, dest.path) || destExistsAsDir { + if endsInSlash(dest.path) || destExistsAsDir { // source.path must be used to get the correct filename when the source // is a symlink - destPath = dest.root.Join(destPath, source.root.Base(source.path)) - destEndpoint = ©Endpoint{driver: dest.root, path: destPath} + destPath = filepath.Join(destPath, filepath.Base(source.path)) } - return copyFile(archiver, srcEndpoint, destEndpoint, options.identity) + return copyFile(archiver, srcPath, destPath, options.identity) } -func isArchivePath(driver containerfs.ContainerFS, path string) bool { - file, err := driver.Open(path) - if err != nil { - return false - } - defer file.Close() - rdr, err := archive.DecompressStream(file) - if err != nil { - return false - } - r := tar.NewReader(rdr) - _, err = r.Next() - return err == nil -} - -func copyDirectory(archiver Archiver, source, dest *copyEndpoint, identity *idtools.Identity) error { +func copyDirectory(archiver *archive.Archiver, source, dest string, identity *idtools.Identity) error { destExists, err := isExistingDirectory(dest) if err != nil { return errors.Wrapf(err, "failed to query destination path") } - if err := archiver.CopyWithTar(source.path, dest.path); err != nil { + if err := archiver.CopyWithTar(source, dest); err != nil { return errors.Wrapf(err, "failed to copy directory") } if identity != nil { - return fixPermissions(source.path, dest.path, *identity, !destExists) + return fixPermissions(source, dest, *identity, !destExists) } return nil } -func copyFile(archiver Archiver, source, dest *copyEndpoint, identity *idtools.Identity) error { +func copyFile(archiver *archive.Archiver, source, dest string, identity *idtools.Identity) error { if identity == nil { // Use system.MkdirAll here, which is a custom version of os.MkdirAll // modified for use on Windows to handle volume GUID paths. These paths // are of the form \\?\Volume{}\. An example would be: // \\?\Volume{dae8d3ac-b9a1-11e9-88eb-e8554b2ba1db}\bin\busybox.exe - if err := system.MkdirAll(filepath.Dir(dest.path), 0755); err != nil { + if err := system.MkdirAll(filepath.Dir(dest), 0755); err != nil { return err } } else { - if err := idtools.MkdirAllAndChownNew(filepath.Dir(dest.path), 0755, *identity); err != nil { + if err := idtools.MkdirAllAndChownNew(filepath.Dir(dest), 0755, *identity); err != nil { return errors.Wrapf(err, "failed to create new directory") } } - if err := archiver.CopyFileWithTar(source.path, dest.path); err != nil { + if err := archiver.CopyFileWithTar(source, dest); err != nil { return errors.Wrapf(err, "failed to copy file") } if identity != nil { - return fixPermissions(source.path, dest.path, *identity, false) + return fixPermissions(source, dest, *identity, false) } return nil } -func endsInSlash(driver containerfs.Driver, path string) bool { - return strings.HasSuffix(path, string(driver.Separator())) +func endsInSlash(path string) bool { + return strings.HasSuffix(path, string(filepath.Separator)) } // isExistingDirectory returns true if the path exists and is a directory -func isExistingDirectory(point *copyEndpoint) (bool, error) { - destStat, err := point.driver.Stat(point.path) +func isExistingDirectory(path string) (bool, error) { + destStat, err := os.Stat(path) switch { case errors.Is(err, os.ErrNotExist): return false, nil diff --git a/builder/dockerfile/copy_test.go b/builder/dockerfile/copy_test.go index 84b2a735f7..5fce0bd4eb 100644 --- a/builder/dockerfile/copy_test.go +++ b/builder/dockerfile/copy_test.go @@ -4,7 +4,6 @@ import ( "net/http" "testing" - "github.com/docker/docker/pkg/containerfs" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/fs" @@ -39,7 +38,7 @@ func TestIsExistingDirectory(t *testing.T) { } for _, testcase := range testcases { - result, err := isExistingDirectory(©Endpoint{driver: containerfs.NewLocalDriver(), path: testcase.path}) + result, err := isExistingDirectory(testcase.path) if !assert.Check(t, err) { continue } diff --git a/builder/dockerfile/copy_unix.go b/builder/dockerfile/copy_unix.go index 7c5a574ffb..2099401485 100644 --- a/builder/dockerfile/copy_unix.go +++ b/builder/dockerfile/copy_unix.go @@ -9,7 +9,6 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" ) @@ -19,8 +18,7 @@ func fixPermissions(source, destination string, identity idtools.Identity, overr err error ) if !overrideSkip { - destEndpoint := ©Endpoint{driver: containerfs.NewLocalDriver(), path: destination} - skipChownRoot, err = isExistingDirectory(destEndpoint) + skipChownRoot, err = isExistingDirectory(destination) if err != nil { return err } diff --git a/builder/dockerfile/internals.go b/builder/dockerfile/internals.go index 1bc445d383..e78aa01a04 100644 --- a/builder/dockerfile/internals.go +++ b/builder/dockerfile/internals.go @@ -7,7 +7,6 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "io" "strings" "github.com/docker/docker/api/types" @@ -17,8 +16,6 @@ import ( "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/containerfs" - "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" "github.com/docker/go-connections/nat" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -26,50 +23,8 @@ import ( "github.com/sirupsen/logrus" ) -// Archiver defines an interface for copying files from one destination to -// another using Tar/Untar. -type Archiver interface { - TarUntar(src, dst string) error - UntarPath(src, dst string) error - CopyWithTar(src, dst string) error - CopyFileWithTar(src, dst string) error - IdentityMapping() idtools.IdentityMapping -} - -// The builder will use the following interfaces if the container fs implements -// these for optimized copies to and from the container. -type extractor interface { - ExtractArchive(src io.Reader, dst string, opts *archive.TarOptions) error -} - -type archiver interface { - ArchivePath(src string, opts *archive.TarOptions) (io.ReadCloser, error) -} - -// helper functions to get tar/untar func -func untarFunc(i interface{}) containerfs.UntarFunc { - if ea, ok := i.(extractor); ok { - return ea.ExtractArchive - } - return chrootarchive.Untar -} - -func tarFunc(i interface{}) containerfs.TarFunc { - if ap, ok := i.(archiver); ok { - return ap.ArchivePath - } - return archive.TarWithOptions -} - -func (b *Builder) getArchiver(src, dst containerfs.Driver) Archiver { - t, u := tarFunc(src), untarFunc(dst) - return &containerfs.Archiver{ - SrcDriver: src, - DstDriver: dst, - Tar: t, - Untar: u, - IDMapping: b.idMapping, - } +func (b *Builder) getArchiver() *archive.Archiver { + return chrootarchive.NewArchiver(b.idMapping) } func (b *Builder) commit(dispatchState *dispatchState, comment string) error { @@ -192,7 +147,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error { // translated (if necessary because of user namespaces), and replace // the root pair with the chown pair for copy operations if inst.chownStr != "" { - identity, err = parseChownFlag(b, state, inst.chownStr, destInfo.root.Path(), b.idMapping) + identity, err = parseChownFlag(b, state, inst.chownStr, destInfo.root, b.idMapping) if err != nil { if b.options.Platform != "windows" { return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping") @@ -205,7 +160,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error { for _, info := range inst.infos { opts := copyFileOptions{ decompress: inst.allowLocalDecompression, - archiver: b.getArchiver(info.root, destInfo.root), + archiver: b.getArchiver(), } if !inst.preserveOwnership { opts.identity = &identity diff --git a/builder/dockerfile/internals_test.go b/builder/dockerfile/internals_test.go index 5353167ad6..9668590157 100644 --- a/builder/dockerfile/internals_test.go +++ b/builder/dockerfile/internals_test.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/go-connections/nat" "github.com/opencontainers/go-digest" "gotest.tools/v3/assert" @@ -183,8 +182,8 @@ func TestDeepCopyRunConfig(t *testing.T) { type MockRWLayer struct{} -func (l *MockRWLayer) Release() error { return nil } -func (l *MockRWLayer) Root() containerfs.ContainerFS { return nil } +func (l *MockRWLayer) Release() error { return nil } +func (l *MockRWLayer) Root() string { return "" } func (l *MockRWLayer) Commit() (builder.ROLayer, error) { return &MockROLayer{ diffID: layer.DiffID(digest.Digest("sha256:1234")), diff --git a/builder/dockerfile/mockbackend_test.go b/builder/dockerfile/mockbackend_test.go index 0310374a69..ad5b3b120d 100644 --- a/builder/dockerfile/mockbackend_test.go +++ b/builder/dockerfile/mockbackend_test.go @@ -13,7 +13,6 @@ import ( containerpkg "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/pkg/containerfs" ) // MockBackend implements the builder.Backend interface for unit testing @@ -143,6 +142,6 @@ func (l *mockRWLayer) Commit() (builder.ROLayer, error) { return nil, nil } -func (l *mockRWLayer) Root() containerfs.ContainerFS { - return nil +func (l *mockRWLayer) Root() string { + return "" } diff --git a/builder/remotecontext/archive.go b/builder/remotecontext/archive.go index 6d247f945d..9d89329040 100644 --- a/builder/remotecontext/archive.go +++ b/builder/remotecontext/archive.go @@ -15,12 +15,12 @@ import ( ) type archiveContext struct { - root containerfs.ContainerFS + root string sums tarsum.FileInfoSums } func (c *archiveContext) Close() error { - return c.root.RemoveAll(c.root.Path()) + return os.RemoveAll(c.root) } func convertPathError(err error, cleanpath string) error { @@ -53,7 +53,7 @@ func FromArchive(tarStream io.Reader) (builder.Source, error) { } // Assume local file system. Since it's coming from a tar file. - tsc := &archiveContext{root: containerfs.NewLocalContainerFS(root)} + tsc := &archiveContext{root: root} // Make sure we clean-up upon error. In the happy case the caller // is expected to manage the clean-up @@ -82,7 +82,7 @@ func FromArchive(tarStream io.Reader) (builder.Source, error) { return tsc, nil } -func (c *archiveContext) Root() containerfs.ContainerFS { +func (c *archiveContext) Root() string { return c.root } @@ -91,7 +91,7 @@ func (c *archiveContext) Remove(path string) error { if err != nil { return err } - return c.root.RemoveAll(fullpath) + return os.RemoveAll(fullpath) } func (c *archiveContext) Hash(path string) (string, error) { @@ -100,7 +100,7 @@ func (c *archiveContext) Hash(path string) (string, error) { return "", err } - rel, err := c.root.Rel(c.root.Path(), fullpath) + rel, err := filepath.Rel(c.root, fullpath) if err != nil { return "", convertPathError(err, cleanpath) } @@ -115,9 +115,9 @@ func (c *archiveContext) Hash(path string) (string, error) { return path, nil // backwards compat TODO: see if really needed } -func normalize(path string, root containerfs.ContainerFS) (cleanPath, fullPath string, err error) { - cleanPath = root.Clean(string(root.Separator()) + path)[1:] - fullPath, err = root.ResolveScopedPath(path, true) +func normalize(path string, root string) (cleanPath, fullPath string, err error) { + cleanPath = filepath.Clean(string(filepath.Separator) + path)[1:] + fullPath, err = containerfs.ResolveScopedPath(root, path) if err != nil { return "", "", errors.Wrapf(err, "forbidden path outside the build context: %s (%s)", path, cleanPath) } diff --git a/builder/remotecontext/detect.go b/builder/remotecontext/detect.go index 3dae780275..6fd18fbd9e 100644 --- a/builder/remotecontext/detect.go +++ b/builder/remotecontext/detect.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/builder" "github.com/docker/docker/builder/remotecontext/urlutil" "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/fileutils" "github.com/moby/buildkit/frontend/dockerfile/dockerignore" "github.com/moby/buildkit/frontend/dockerfile/parser" @@ -161,7 +162,7 @@ func openAt(remote builder.Source, path string) (driver.File, error) { if err != nil { return nil, err } - return remote.Root().Open(fullPath) + return os.Open(fullPath) } // StatAt is a helper for calling Stat on a path from a source @@ -170,12 +171,12 @@ func StatAt(remote builder.Source, path string) (os.FileInfo, error) { if err != nil { return nil, err } - return remote.Root().Stat(fullPath) + return os.Stat(fullPath) } // FullPath is a helper for getting a full path for a path from a source func FullPath(remote builder.Source, path string) (string, error) { - fullPath, err := remote.Root().ResolveScopedPath(path, true) + fullPath, err := containerfs.ResolveScopedPath(remote.Root(), path) if err != nil { if runtime.GOOS == "windows" { return "", fmt.Errorf("failed to resolve scoped path %s (%s): %s. Possible cause is a forbidden path outside the build context", path, fullPath, err) diff --git a/builder/remotecontext/detect_test.go b/builder/remotecontext/detect_test.go index 71dfd7bbb9..aa73e565c7 100644 --- a/builder/remotecontext/detect_test.go +++ b/builder/remotecontext/detect_test.go @@ -4,11 +4,11 @@ import ( "errors" "log" "os" + "path/filepath" "sort" "testing" "github.com/docker/docker/builder" - "github.com/docker/docker/pkg/containerfs" ) const ( @@ -52,7 +52,7 @@ func checkDirectory(t *testing.T, dir string, expectedFiles []string) { } func executeProcess(t *testing.T, contextDir string) { - modifiableCtx := &stubRemote{root: containerfs.NewLocalContainerFS(contextDir)} + modifiableCtx := &stubRemote{root: contextDir} err := removeDockerfile(modifiableCtx, builder.DefaultDockerfileName) @@ -104,19 +104,19 @@ func TestProcessShouldLeaveAllFiles(t *testing.T) { // TODO: remove after moving to a separate pkg type stubRemote struct { - root containerfs.ContainerFS + root string } func (r *stubRemote) Hash(path string) (string, error) { return "", errors.New("not implemented") } -func (r *stubRemote) Root() containerfs.ContainerFS { +func (r *stubRemote) Root() string { return r.root } func (r *stubRemote) Close() error { return errors.New("not implemented") } func (r *stubRemote) Remove(p string) error { - return r.root.Remove(r.root.Join(r.root.Path(), p)) + return os.Remove(filepath.Join(r.root, p)) } diff --git a/builder/remotecontext/lazycontext.go b/builder/remotecontext/lazycontext.go index 96435f2585..d7234d6656 100644 --- a/builder/remotecontext/lazycontext.go +++ b/builder/remotecontext/lazycontext.go @@ -3,10 +3,11 @@ package remotecontext // import "github.com/docker/docker/builder/remotecontext" import ( "encoding/hex" "os" + "path/filepath" + "runtime" "strings" "github.com/docker/docker/builder" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/pools" "github.com/pkg/errors" ) @@ -14,7 +15,7 @@ import ( // NewLazySource creates a new LazyContext. LazyContext defines a hashed build // context based on a root directory. Individual files are hashed first time // they are asked. It is not safe to call methods of LazyContext concurrently. -func NewLazySource(root containerfs.ContainerFS) (builder.Source, error) { +func NewLazySource(root string) (builder.Source, error) { return &lazySource{ root: root, sums: make(map[string]string), @@ -22,11 +23,11 @@ func NewLazySource(root containerfs.ContainerFS) (builder.Source, error) { } type lazySource struct { - root containerfs.ContainerFS + root string sums map[string]string } -func (c *lazySource) Root() containerfs.ContainerFS { +func (c *lazySource) Root() string { return c.root } @@ -45,7 +46,7 @@ func (c *lazySource) Hash(path string) (string, error) { return "", errors.WithStack(convertPathError(err, cleanPath)) } - fi, err := c.root.Lstat(fullPath) + fi, err := os.Lstat(fullPath) if err != nil { // Backwards compatibility: a missing file returns a path as hash. // This is reached in the case of a broken symlink. @@ -64,13 +65,13 @@ func (c *lazySource) Hash(path string) (string, error) { } func (c *lazySource) prepareHash(relPath string, fi os.FileInfo) (string, error) { - p := c.root.Join(c.root.Path(), relPath) + p := filepath.Join(c.root, relPath) h, err := NewFileHash(p, relPath, fi) if err != nil { return "", errors.Wrapf(err, "failed to create hash for %s", relPath) } if fi.Mode().IsRegular() && fi.Size() > 0 { - f, err := c.root.Open(p) + f, err := os.Open(p) if err != nil { return "", errors.Wrapf(err, "failed to open %s", relPath) } @@ -86,10 +87,10 @@ func (c *lazySource) prepareHash(relPath string, fi os.FileInfo) (string, error) // Rel makes a path relative to base path. Same as `filepath.Rel` but can also // handle UUID paths in windows. -func Rel(basepath containerfs.ContainerFS, targpath string) (string, error) { +func Rel(basepath string, targpath string) (string, error) { // filepath.Rel can't handle UUID paths in windows - if basepath.OS() == "windows" { - pfx := basepath.Path() + `\` + if runtime.GOOS == "windows" { + pfx := basepath + `\` if strings.HasPrefix(targpath, pfx) { p := strings.TrimPrefix(targpath, pfx) if p == "" { @@ -98,5 +99,5 @@ func Rel(basepath containerfs.ContainerFS, targpath string) (string, error) { return p, nil } } - return basepath.Rel(basepath.Path(), targpath) + return filepath.Rel(basepath, targpath) } diff --git a/builder/remotecontext/tarsum.go b/builder/remotecontext/tarsum.go index b809cfb78b..e6486e9736 100644 --- a/builder/remotecontext/tarsum.go +++ b/builder/remotecontext/tarsum.go @@ -2,9 +2,9 @@ package remotecontext // import "github.com/docker/docker/builder/remotecontext" import ( "os" + "path/filepath" "sync" - "github.com/docker/docker/pkg/containerfs" iradix "github.com/hashicorp/go-immutable-radix" "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -18,7 +18,7 @@ type hashed interface { // CachableSource is a source that contains cache records for its contents type CachableSource struct { mu sync.Mutex - root containerfs.ContainerFS + root string tree *iradix.Tree txn *iradix.Txn } @@ -27,7 +27,7 @@ type CachableSource struct { func NewCachableSource(root string) *CachableSource { ts := &CachableSource{ tree: iradix.New(), - root: containerfs.NewLocalContainerFS(root), + root: root, } return ts } @@ -66,7 +66,7 @@ func (cs *CachableSource) Scan() error { return err } txn := iradix.New().Txn() - err = cs.root.Walk(cs.root.Path(), func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(cs.root, func(path string, info os.FileInfo, err error) error { if err != nil { return errors.Wrapf(err, "failed to walk %s", path) } @@ -144,7 +144,7 @@ func (cs *CachableSource) Hash(path string) (string, error) { } // Root returns a root directory for the source -func (cs *CachableSource) Root() containerfs.ContainerFS { +func (cs *CachableSource) Root() string { return cs.root } diff --git a/builder/remotecontext/tarsum_test.go b/builder/remotecontext/tarsum_test.go index 64b7f1d5f2..a398839ab3 100644 --- a/builder/remotecontext/tarsum_test.go +++ b/builder/remotecontext/tarsum_test.go @@ -35,7 +35,7 @@ func TestCloseRootDirectory(t *testing.T) { t.Fatalf("Error while executing Close: %s", err) } - _, err = os.Stat(src.Root().Path()) + _, err = os.Stat(src.Root()) if !errors.Is(err, os.ErrNotExist) { t.Fatal("Directory should not exist at this point") @@ -118,7 +118,7 @@ func TestRemoveDirectory(t *testing.T) { src := makeTestArchiveContext(t, contextDir) - _, err = src.Root().Stat(src.Root().Join(src.Root().Path(), relativePath)) + _, err = os.Stat(filepath.Join(src.Root(), relativePath)) if err != nil { t.Fatalf("Statting %s shouldn't fail: %+v", relativePath, err) } @@ -129,7 +129,7 @@ func TestRemoveDirectory(t *testing.T) { t.Fatalf("Error when executing Remove: %s", err) } - _, err = src.Root().Stat(src.Root().Join(src.Root().Path(), relativePath)) + _, err = os.Stat(filepath.Join(src.Root(), relativePath)) if !errors.Is(err, os.ErrNotExist) { t.Fatalf("Directory should not exist at this point: %+v ", err) } diff --git a/container/archive.go b/container/archive.go index ed72c4a405..c96ea1b868 100644 --- a/container/archive.go +++ b/container/archive.go @@ -2,6 +2,7 @@ package container // import "github.com/docker/docker/container" import ( "os" + "path/filepath" "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/archive" @@ -14,24 +15,21 @@ import ( // the absolute path to the resource relative to the container's rootfs, and // an error if the path points to outside the container's rootfs. func (container *Container) ResolvePath(path string) (resolvedPath, absPath string, err error) { - if container.BaseFS == nil { - return "", "", errors.New("ResolvePath: BaseFS of container " + container.ID + " is unexpectedly nil") + if container.BaseFS == "" { + return "", "", errors.New("ResolvePath: BaseFS of container " + container.ID + " is unexpectedly empty") } // Check if a drive letter supplied, it must be the system drive. No-op except on Windows - path, err = system.CheckSystemDriveAndRemoveDriveLetter(path, container.BaseFS) + path, err = system.CheckSystemDriveAndRemoveDriveLetter(path) if err != nil { return "", "", err } // Consider the given path as an absolute path in the container. - absPath = archive.PreserveTrailingDotOrSeparator( - container.BaseFS.Join(string(container.BaseFS.Separator()), path), - path, - container.BaseFS.Separator()) + absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path) // Split the absPath into its Directory and Base components. We will // resolve the dir in the scope of the container then append the base. - dirPath, basePath := container.BaseFS.Split(absPath) + dirPath, basePath := filepath.Split(absPath) resolvedDirPath, err := container.GetResourcePath(dirPath) if err != nil { @@ -40,7 +38,7 @@ func (container *Container) ResolvePath(path string) (resolvedPath, absPath stri // resolvedDirPath will have been cleaned (no trailing path separators) so // we can manually join it with the base path element. - resolvedPath = resolvedDirPath + string(container.BaseFS.Separator()) + basePath + resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath return resolvedPath, absPath, nil } @@ -49,12 +47,11 @@ func (container *Container) ResolvePath(path string) (resolvedPath, absPath stri // resolved to a path on the host corresponding to the given absolute path // inside the container. func (container *Container) StatPath(resolvedPath, absPath string) (stat *types.ContainerPathStat, err error) { - if container.BaseFS == nil { - return nil, errors.New("StatPath: BaseFS of container " + container.ID + " is unexpectedly nil") + if container.BaseFS == "" { + return nil, errors.New("StatPath: BaseFS of container " + container.ID + " is unexpectedly empty") } - driver := container.BaseFS - lstat, err := driver.Lstat(resolvedPath) + lstat, err := os.Lstat(resolvedPath) if err != nil { return nil, err } @@ -67,17 +64,17 @@ func (container *Container) StatPath(resolvedPath, absPath string) (stat *types. return nil, err } - linkTarget, err = driver.Rel(driver.Path(), hostPath) + linkTarget, err = filepath.Rel(container.BaseFS, hostPath) if err != nil { return nil, err } // Make it an absolute path. - linkTarget = driver.Join(string(driver.Separator()), linkTarget) + linkTarget = filepath.Join(string(filepath.Separator), linkTarget) } return &types.ContainerPathStat{ - Name: driver.Base(absPath), + Name: filepath.Base(absPath), Size: lstat.Size(), Mode: lstat.Mode(), Mtime: lstat.ModTime(), diff --git a/container/container.go b/container/container.go index ead7960f4f..d09a130968 100644 --- a/container/container.go +++ b/container/container.go @@ -61,10 +61,10 @@ type ExitStatus struct { type Container struct { StreamConfig *stream.Config // embed for Container to support states directly. - *State `json:"State"` // Needed for Engine API version <= 1.11 - Root string `json:"-"` // Path to the "home" of the container, including metadata. - BaseFS containerfs.ContainerFS `json:"-"` // interface containing graphdriver mount - RWLayer layer.RWLayer `json:"-"` + *State `json:"State"` // Needed for Engine API version <= 1.11 + Root string `json:"-"` // Path to the "home" of the container, including metadata. + BaseFS string `json:"-"` // Path to the graphdriver mountpoint + RWLayer layer.RWLayer `json:"-"` ID string Created time.Time Managed bool @@ -299,18 +299,18 @@ func (container *Container) SetupWorkingDirectory(rootIdentity idtools.Identity) // symlinking to a different path) between using this method and using the // path. See symlink.FollowSymlinkInScope for more details. func (container *Container) GetResourcePath(path string) (string, error) { - if container.BaseFS == nil { - return "", errors.New("GetResourcePath: BaseFS of container " + container.ID + " is unexpectedly nil") + if container.BaseFS == "" { + return "", errors.New("GetResourcePath: BaseFS of container " + container.ID + " is unexpectedly empty") } // IMPORTANT - These are paths on the OS where the daemon is running, hence // any filepath operations must be done in an OS agnostic way. - r, e := container.BaseFS.ResolveScopedPath(path, false) + r, e := containerfs.ResolveScopedPath(container.BaseFS, containerfs.CleanScopedPath(path)) // Log this here on the daemon side as there's otherwise no indication apart // from the error being propagated all the way back to the client. This makes // debugging significantly easier and clearly indicates the error comes from the daemon. if e != nil { - logrus.Errorf("Failed to ResolveScopedPath BaseFS %s path %s %s\n", container.BaseFS.Path(), path, e) + logrus.Errorf("Failed to ResolveScopedPath BaseFS %s path %s %s\n", container.BaseFS, path, e) } return r, e } diff --git a/daemon/archive.go b/daemon/archive.go index f443d12117..6d6d01c180 100644 --- a/daemon/archive.go +++ b/daemon/archive.go @@ -3,6 +3,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( "io" "os" + "path/filepath" "strings" "github.com/docker/docker/api/types" @@ -20,32 +21,6 @@ import ( // path does not refer to a directory. var ErrExtractPointNotDirectory = errors.New("extraction point is not a directory") -// The daemon will use the following interfaces if the container fs implements -// these for optimized copies to and from the container. -type extractor interface { - ExtractArchive(src io.Reader, dst string, opts *archive.TarOptions) error -} - -type archiver interface { - ArchivePath(src string, opts *archive.TarOptions) (io.ReadCloser, error) -} - -// helper functions to extract or archive -func extractArchive(i interface{}, src io.Reader, dst string, opts *archive.TarOptions, root string) error { - if ea, ok := i.(extractor); ok { - return ea.ExtractArchive(src, dst, opts) - } - - return chrootarchive.UntarWithRoot(src, dst, opts, root) -} - -func archivePath(i interface{}, src string, opts *archive.TarOptions, root string) (io.ReadCloser, error) { - if ap, ok := i.(archiver); ok { - return ap.ArchivePath(src, opts) - } - return chrootarchive.Tar(src, opts, root) -} - // ContainerCopy performs a deprecated operation of archiving the resource at // the specified path in the container identified by the given name. func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, error) { @@ -165,7 +140,7 @@ func (daemon *Daemon) containerStatPath(container *container.Container, path str } // Normalize path before sending to rootfs - path = container.BaseFS.FromSlash(path) + path = filepath.FromSlash(path) resolvedPath, absPath, err := container.ResolvePath(path) if err != nil { @@ -208,7 +183,7 @@ func (daemon *Daemon) containerArchivePath(container *container.Container, path } // Normalize path before sending to rootfs - path = container.BaseFS.FromSlash(path) + path = filepath.FromSlash(path) resolvedPath, absPath, err := container.ResolvePath(path) if err != nil { @@ -228,24 +203,23 @@ func (daemon *Daemon) containerArchivePath(container *container.Container, path // also catches the case when the root directory of the container is // requested: we want the archive entries to start with "/" and not the // container ID. - driver := container.BaseFS // Get the source and the base paths of the container resolved path in order // to get the proper tar options for the rebase tar. - resolvedPath = driver.Clean(resolvedPath) - if driver.Base(resolvedPath) == "." { - resolvedPath += string(driver.Separator()) + "." + resolvedPath = filepath.Clean(resolvedPath) + if filepath.Base(resolvedPath) == "." { + resolvedPath += string(filepath.Separator) + "." } sourceDir := resolvedPath sourceBase := "." if stat.Mode&os.ModeDir == 0 { // not dir - sourceDir, sourceBase = driver.Split(resolvedPath) + sourceDir, sourceBase = filepath.Split(resolvedPath) } - opts := archive.TarResourceRebaseOpts(sourceBase, driver.Base(absPath)) + opts := archive.TarResourceRebaseOpts(sourceBase, filepath.Base(absPath)) - data, err := archivePath(driver, sourceDir, opts, container.BaseFS.Path()) + data, err := chrootarchive.Tar(sourceDir, opts, container.BaseFS) if err != nil { return nil, nil, err } @@ -285,11 +259,10 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path } // Normalize path before sending to rootfs' - path = container.BaseFS.FromSlash(path) - driver := container.BaseFS + path = filepath.FromSlash(path) // Check if a drive letter supplied, it must be the system drive. No-op except on Windows - path, err = system.CheckSystemDriveAndRemoveDriveLetter(path, driver) + path, err = system.CheckSystemDriveAndRemoveDriveLetter(path) if err != nil { return err } @@ -301,10 +274,7 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path // that you can extract an archive to a symlink that points to a directory. // Consider the given path as an absolute path in the container. - absPath := archive.PreserveTrailingDotOrSeparator( - driver.Join(string(driver.Separator()), path), - path, - driver.Separator()) + absPath := archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path) // This will evaluate the last path element if it is a symlink. resolvedPath, err := container.GetResourcePath(absPath) @@ -312,7 +282,7 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path return err } - stat, err := driver.Lstat(resolvedPath) + stat, err := os.Lstat(resolvedPath) if err != nil { return err } @@ -335,24 +305,21 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path // a volume file path. var baseRel string if strings.HasPrefix(resolvedPath, `\\?\Volume{`) { - if strings.HasPrefix(resolvedPath, driver.Path()) { - baseRel = resolvedPath[len(driver.Path()):] + if strings.HasPrefix(resolvedPath, container.BaseFS) { + baseRel = resolvedPath[len(container.BaseFS):] if baseRel[:1] == `\` { baseRel = baseRel[1:] } } } else { - baseRel, err = driver.Rel(driver.Path(), resolvedPath) + baseRel, err = filepath.Rel(container.BaseFS, resolvedPath) } if err != nil { return err } // Make it an absolute path. - absPath = driver.Join(string(driver.Separator()), baseRel) + absPath = filepath.Join(string(filepath.Separator), baseRel) - // @ TODO: gupta-ak: Technically, this works since it no-ops - // on Windows and the file system is local anyway on linux. - // But eventually, it should be made driver aware. toVolume, err := checkIfPathIsInAVolume(container, absPath) if err != nil { return err @@ -374,7 +341,7 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path } } - if err := extractArchive(driver, content, resolvedPath, options, container.BaseFS.Path()); err != nil { + if err := chrootarchive.UntarWithRoot(content, resolvedPath, options, container.BaseFS); err != nil { return err } @@ -416,27 +383,26 @@ func (daemon *Daemon) containerCopy(container *container.Container, resource str } // Normalize path before sending to rootfs - resource = container.BaseFS.FromSlash(resource) - driver := container.BaseFS + resource = filepath.FromSlash(resource) basePath, err := container.GetResourcePath(resource) if err != nil { return nil, err } - stat, err := driver.Stat(basePath) + stat, err := os.Stat(basePath) if err != nil { return nil, err } var filter []string if !stat.IsDir() { - d, f := driver.Split(basePath) + d, f := filepath.Split(basePath) basePath = d filter = []string{f} } - archv, err := archivePath(driver, basePath, &archive.TarOptions{ + archv, err := chrootarchive.Tar(basePath, &archive.TarOptions{ Compression: archive.Uncompressed, IncludeFiles: filter, - }, container.BaseFS.Path()) + }, container.BaseFS) if err != nil { return nil, err } diff --git a/daemon/daemon.go b/daemon/daemon.go index bb38689fc1..398637f3b8 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -1270,7 +1270,7 @@ func (daemon *Daemon) Mount(container *container.Container) error { } logrus.WithField("container", container.ID).Debugf("container mounted via layerStore: %v", dir) - if container.BaseFS != nil && container.BaseFS.Path() != dir.Path() { + if container.BaseFS != "" && container.BaseFS != dir { // The mount path reported by the graph driver should always be trusted on Windows, since the // volume path for a given mounted layer may change over time. This should only be an error // on non-Windows operating systems. diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index acc2e85ba6..3becb30199 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -38,7 +38,6 @@ import ( "github.com/docker/docker/libnetwork/options" lntypes "github.com/docker/docker/libnetwork/types" "github.com/docker/docker/opts" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/kernel" @@ -1072,8 +1071,8 @@ func removeDefaultBridgeInterface() { } } -func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error { - return func(initPath containerfs.ContainerFS) error { +func setupInitLayer(idMapping idtools.IdentityMapping) func(string) error { + return func(initPath string) error { return initlayer.Setup(initPath, idMapping.RootPair()) } } diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 12f014c890..c64e4570ba 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -23,7 +23,6 @@ import ( winlibnetwork "github.com/docker/docker/libnetwork/drivers/windows" "github.com/docker/docker/libnetwork/netlabel" "github.com/docker/docker/libnetwork/options" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/operatingsystem" @@ -64,7 +63,7 @@ func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfi return nil } -func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error { +func setupInitLayer(idMapping idtools.IdentityMapping) func(string) error { return nil } diff --git a/daemon/export.go b/daemon/export.go index b248def224..8a14430840 100644 --- a/daemon/export.go +++ b/daemon/export.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/ioutils" ) @@ -61,10 +62,10 @@ func (daemon *Daemon) containerExport(container *container.Container) (arch io.R return nil, err } - archv, err := archivePath(basefs, basefs.Path(), &archive.TarOptions{ + archv, err := chrootarchive.Tar(basefs, &archive.TarOptions{ Compression: archive.Uncompressed, IDMap: daemon.idMapping, - }, basefs.Path()) + }, basefs) if err != nil { rwlayer.Unmount() return nil, err diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index a8e5ff9609..6e33590698 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -351,12 +351,12 @@ func atomicRemove(source string) error { // Get returns the rootfs path for the id. // This will mount the dir at its given path -func (a *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +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 nil, err + return "", err } a.pathCacheLock.Lock() @@ -370,21 +370,21 @@ func (a *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { } } if count := a.ctr.Increment(m); count > 1 { - return containerfs.NewLocalContainerFS(m), nil + 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 nil, err + return "", err } } a.pathCacheLock.Lock() a.pathCache[id] = m a.pathCacheLock.Unlock() - return containerfs.NewLocalContainerFS(m), nil + return m, nil } // Put unmounts and updates list of active mounts. diff --git a/daemon/graphdriver/aufs/aufs_test.go b/daemon/graphdriver/aufs/aufs_test.go index 377c050e29..26142acfc5 100644 --- a/daemon/graphdriver/aufs/aufs_test.go +++ b/daemon/graphdriver/aufs/aufs_test.go @@ -43,14 +43,6 @@ func testInit(dir string, t testing.TB) graphdriver.Driver { return d } -func driverGet(d *Driver, id string, mntLabel string) (string, error) { - mnt, err := d.Get(id, mntLabel) - if err != nil { - return "", err - } - return mnt.Path(), nil -} - func newDriver(t testing.TB) *Driver { if err := os.MkdirAll(tmp, 0755); err != nil { t.Fatal(err) @@ -180,7 +172,7 @@ func TestGetWithoutParent(t *testing.T) { t.Fatal(err) } expected := path.Join(tmp, "diff", "1") - if diffPath.Path() != expected { + if diffPath != expected { t.Fatalf("Expected path %s got %s", expected, diffPath) } } @@ -257,13 +249,13 @@ func TestMountWithParent(t *testing.T) { if err != nil { t.Fatal(err) } - if mntPath == nil { - t.Fatal("mntPath should not be nil") + if mntPath == "" { + t.Fatal("mntPath should not be empty") } expected := path.Join(tmp, "mnt", "2") - if mntPath.Path() != expected { - t.Fatalf("Expected %s got %s", expected, mntPath.Path()) + if mntPath != expected { + t.Fatalf("Expected %s got %s", expected, mntPath) } } @@ -288,8 +280,8 @@ func TestRemoveMountedDir(t *testing.T) { if err != nil { t.Fatal(err) } - if mntPath == nil { - t.Fatal("mntPath should not be nil") + if mntPath == "" { + t.Fatal("mntPath should not be empty") } mounted, err := d.mounted(d.pathCache["2"]) @@ -323,7 +315,7 @@ func TestGetDiff(t *testing.T) { t.Fatal(err) } - diffPath, err := driverGet(d, "1", "") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -367,7 +359,7 @@ func TestChanges(t *testing.T) { } }() - mntPoint, err := driverGet(d, "2", "") + mntPoint, err := d.Get("2", "") if err != nil { t.Fatal(err) } @@ -406,7 +398,7 @@ func TestChanges(t *testing.T) { if err := d.CreateReadWrite("3", "2", nil); err != nil { t.Fatal(err) } - mntPoint, err = driverGet(d, "3", "") + mntPoint, err = d.Get("3", "") if err != nil { t.Fatal(err) } @@ -452,7 +444,7 @@ func TestDiffSize(t *testing.T) { t.Fatal(err) } - diffPath, err := driverGet(d, "1", "") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -494,7 +486,7 @@ func TestChildDiffSize(t *testing.T) { t.Fatal(err) } - diffPath, err := driverGet(d, "1", "") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -595,7 +587,7 @@ func TestApplyDiff(t *testing.T) { t.Fatal(err) } - diffPath, err := driverGet(d, "1", "") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -630,7 +622,7 @@ func TestApplyDiff(t *testing.T) { // Ensure that the file is in the mount point for id 3 - mountPoint, err := driverGet(d, "3", "") + mountPoint, err := d.Get("3", "") if err != nil { t.Fatal(err) } @@ -673,7 +665,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) { err := d.CreateReadWrite(current, parent, nil) assert.NilError(t, err, "current layer %d", i) - point, err := driverGet(d, current, "") + point, err := d.Get(current, "") assert.NilError(t, err, "current layer %d", i) f, err := os.Create(path.Join(point, current)) @@ -689,7 +681,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) { } // Perform the actual mount for the top most image - point, err := driverGet(d, last, "") + point, err := d.Get(last, "") assert.NilError(t, err) files, err := os.ReadDir(point) assert.NilError(t, err) diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go index d51f04709e..ac920c88a2 100644 --- a/daemon/graphdriver/btrfs/btrfs.go +++ b/daemon/graphdriver/btrfs/btrfs.go @@ -627,29 +627,29 @@ func (d *Driver) Remove(id string) error { } // Get the requested filesystem id. -func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { dir := d.subvolumesDirID(id) st, err := os.Stat(dir) if err != nil { - return nil, err + return "", err } if !st.IsDir() { - return nil, fmt.Errorf("%s: not a directory", dir) + return "", fmt.Errorf("%s: not a directory", dir) } if quota, err := os.ReadFile(d.quotasDirID(id)); err == nil { if size, err := strconv.ParseUint(string(quota), 10, 64); err == nil && size >= d.options.minSpace { if err := d.enableQuota(); err != nil { - return nil, err + return "", err } if err := subvolLimitQgroup(dir, size); err != nil { - return nil, err + return "", err } } } - return containerfs.NewLocalContainerFS(dir), nil + return dir, nil } // Put is not implemented for BTRFS as there is no cleanup required for the id. diff --git a/daemon/graphdriver/btrfs/btrfs_test.go b/daemon/graphdriver/btrfs/btrfs_test.go index 63c3adbe1c..511f29af7d 100644 --- a/daemon/graphdriver/btrfs/btrfs_test.go +++ b/daemon/graphdriver/btrfs/btrfs_test.go @@ -36,14 +36,12 @@ func TestBtrfsSubvolDelete(t *testing.T) { } defer graphtest.PutDriver(t) - dirFS, err := d.Get("test", "") + dir, err := d.Get("test", "") if err != nil { t.Fatal(err) } defer d.Put("test") - dir := dirFS.Path() - if err := subvolCreate(dir, "subvoltest"); err != nil { t.Fatal(err) } diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 6c2a80b6cb..15465e439d 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -10,7 +10,6 @@ import ( "strconv" "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/devicemapper" "github.com/docker/docker/pkg/idtools" units "github.com/docker/go-units" @@ -175,13 +174,13 @@ func (d *Driver) Remove(id string) error { } // Get mounts a device with given id into the root filesystem -func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +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 containerfs.NewLocalContainerFS(rootFs), nil + return rootFs, nil } root := d.idMap.RootPair() @@ -189,23 +188,23 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { // Create the target directories if they don't exist if err := idtools.MkdirAllAndChown(path.Join(d.home, "mnt"), 0755, root); err != nil { d.ctr.Decrement(mp) - return nil, err + return "", err } if err := idtools.MkdirAndChown(mp, 0755, root); err != nil && !os.IsExist(err) { d.ctr.Decrement(mp) - return nil, err + return "", err } // Mount the device if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil { d.ctr.Decrement(mp) - return nil, err + return "", err } if err := idtools.MkdirAllAndChown(rootFs, 0755, root); err != nil { d.ctr.Decrement(mp) d.DeviceSet.UnmountDevice(id, mp) - return nil, err + return "", err } idFile := path.Join(mp, "id") @@ -215,11 +214,11 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { if err := os.WriteFile(idFile, []byte(id), 0600); err != nil { d.ctr.Decrement(mp) d.DeviceSet.UnmountDevice(id, mp) - return nil, err + return "", err } } - return containerfs.NewLocalContainerFS(rootFs), nil + return rootFs, nil } // Put unmounts a device and removes it. diff --git a/daemon/graphdriver/driver.go b/daemon/graphdriver/driver.go index 06f088fa73..34a2ec4fe7 100644 --- a/daemon/graphdriver/driver.go +++ b/daemon/graphdriver/driver.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/plugingetter" "github.com/pkg/errors" @@ -60,7 +59,7 @@ type ProtoDriver interface { // 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) (fs containerfs.ContainerFS, err error) + Get(id, mountLabel string) (fs string, err error) // Put releases the system resources for the specified id, // e.g, unmounting layered filesystem. Put(id string) error diff --git a/daemon/graphdriver/fsdiff.go b/daemon/graphdriver/fsdiff.go index c61369535d..2a201dc2f5 100644 --- a/daemon/graphdriver/fsdiff.go +++ b/daemon/graphdriver/fsdiff.go @@ -50,7 +50,7 @@ func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch io.ReadCloser, err err if err != nil { return nil, err } - layerFs := layerRootFs.Path() + layerFs := layerRootFs defer func() { if err != nil { @@ -70,14 +70,12 @@ func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch io.ReadCloser, err err }), nil } - parentRootFs, err := driver.Get(parent, "") + parentFs, err := driver.Get(parent, "") if err != nil { return nil, err } defer driver.Put(parent) - parentFs := parentRootFs.Path() - changes, err := archive.ChangesDirs(layerFs, parentFs) if err != nil { return nil, err @@ -106,22 +104,20 @@ func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch io.ReadCloser, err err func (gdw *NaiveDiffDriver) Changes(id, parent string) ([]archive.Change, error) { driver := gdw.ProtoDriver - layerRootFs, err := driver.Get(id, "") + layerFs, err := driver.Get(id, "") if err != nil { return nil, err } defer driver.Put(id) - layerFs := layerRootFs.Path() parentFs := "" if parent != "" { - parentRootFs, err := driver.Get(parent, "") + parentFs, err = driver.Get(parent, "") if err != nil { return nil, err } defer driver.Put(parent) - parentFs = parentRootFs.Path() } return archive.ChangesDirs(layerFs, parentFs) @@ -140,7 +136,7 @@ func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, diff io.Reader) (size i } defer driver.Put(id) - layerFs := layerRootFs.Path() + layerFs := layerRootFs options := &archive.TarOptions{IDMap: gdw.idMap} start := time.Now().UTC() logrus.WithField("id", id).Debug("Start untar layer") @@ -169,5 +165,5 @@ func (gdw *NaiveDiffDriver) DiffSize(id, parent string) (size int64, err error) } defer driver.Put(id) - return archive.ChangesSize(layerFs.Path(), changes), nil + return archive.ChangesSize(layerFs, changes), nil } diff --git a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go index baaa24b291..0607b8054b 100644 --- a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go +++ b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go @@ -303,12 +303,12 @@ func (d *Driver) Remove(id string) error { } // Get creates and mounts the required file system for the given id and returns the mount path. -func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr error) { +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 nil, err + return "", err } diffDir := path.Join(dir, diffDirName) @@ -316,14 +316,14 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if err != nil { // If no lower, just return diff directory if os.IsNotExist(err) { - return containerfs.NewLocalContainerFS(diffDir), nil + return diffDir, nil } - return nil, err + return "", err } mergedDir := path.Join(dir, mergedDirName) if count := d.ctr.Increment(mergedDir); count > 1 { - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } defer func() { if retErr != nil { @@ -351,7 +351,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if _, err := os.Stat(path.Join(dir, "committed")); err == nil { readonly = true } else if !os.IsNotExist(err) { - return nil, err + return "", err } var opts string @@ -365,7 +365,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e mountTarget := mergedDir if err := idtools.MkdirAndChown(mergedDir, 0700, d.idMap.RootPair()); err != nil { - return nil, err + return "", err } mountProgram := exec.Command(binary, "-o", mountData, mountTarget) @@ -377,10 +377,10 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if output == "" { output = "" } - return nil, errors.Wrapf(err, "using mount program %s: %s", binary, output) + return "", errors.Wrapf(err, "using mount program %s: %s", binary, output) } - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } // Put unmounts the mount path created for the give id. diff --git a/daemon/graphdriver/graphtest/graphbench_unix.go b/daemon/graphdriver/graphtest/graphbench_unix.go index 378794a531..422c3ec23d 100644 --- a/daemon/graphdriver/graphtest/graphbench_unix.go +++ b/daemon/graphdriver/graphtest/graphbench_unix.go @@ -5,9 +5,10 @@ package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphte import ( "io" + "os" + "path/filepath" "testing" - contdriver "github.com/containerd/continuity/driver" "github.com/docker/docker/pkg/stringid" "gotest.tools/v3/assert" ) @@ -249,7 +250,7 @@ func DriverBenchDeepLayerRead(b *testing.B, layerCount int, drivername string, d for i := 0; i < b.N; i++ { // Read content - c, err := contdriver.ReadFile(root, root.Join(root.Path(), "testfile.txt")) + c, err := os.ReadFile(filepath.Join(root, "testfile.txt")) if err != nil { b.Fatal(err) } diff --git a/daemon/graphdriver/graphtest/graphtest_unix.go b/daemon/graphdriver/graphtest/graphtest_unix.go index 8b6a6bf971..b0b93d281d 100644 --- a/daemon/graphdriver/graphtest/graphtest_unix.go +++ b/daemon/graphdriver/graphtest/graphtest_unix.go @@ -96,10 +96,10 @@ func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...str dir, err := driver.Get("empty", "") assert.NilError(t, err) - verifyFile(t, dir.Path(), 0755|os.ModeDir, 0, 0) + verifyFile(t, dir, 0755|os.ModeDir, 0, 0) // Verify that the directory is empty - fis, err := readDir(dir, dir.Path()) + fis, err := readDir(dir) assert.NilError(t, err) assert.Check(t, is.Len(fis, 0)) @@ -324,19 +324,19 @@ func DriverTestSetQuota(t *testing.T, drivername string, required bool) { quota := uint64(50 * units.MiB) // Try to write a file smaller than quota, and ensure it works - err = writeRandomFile(path.Join(mountPath.Path(), "smallfile"), quota/2) + err = writeRandomFile(path.Join(mountPath, "smallfile"), quota/2) if err != nil { t.Fatal(err) } - defer os.Remove(path.Join(mountPath.Path(), "smallfile")) + defer os.Remove(path.Join(mountPath, "smallfile")) // Try to write a file bigger than quota. We've already filled up half the quota, so hitting the limit should be easy - err = writeRandomFile(path.Join(mountPath.Path(), "bigfile"), quota) + err = writeRandomFile(path.Join(mountPath, "bigfile"), quota) if err == nil { t.Fatalf("expected write to fail(), instead had success") } if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT && pathError.Err != unix.ENOSPC { - os.Remove(path.Join(mountPath.Path(), "bigfile")) + os.Remove(path.Join(mountPath, "bigfile")) t.Fatalf("expect write() to fail with %v or %v, got %v", unix.EDQUOT, unix.ENOSPC, pathError.Err) } } diff --git a/daemon/graphdriver/graphtest/testutil.go b/daemon/graphdriver/graphtest/testutil.go index 258aba7002..20a0da8b31 100644 --- a/daemon/graphdriver/graphtest/testutil.go +++ b/daemon/graphdriver/graphtest/testutil.go @@ -3,11 +3,12 @@ package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphte import ( "bytes" "fmt" + "io/fs" "math/rand" "os" + "path/filepath" "sort" - "github.com/containerd/continuity/driver" "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/stringid" @@ -35,17 +36,17 @@ func addFiles(drv graphdriver.Driver, layer string, seed int64) error { } defer drv.Put(layer) - if err := driver.WriteFile(root, root.Join(root.Path(), "file-a"), randomContent(64, seed), 0755); err != nil { + if err := os.WriteFile(filepath.Join(root, "file-a"), randomContent(64, seed), 0755); err != nil { return err } - if err := root.MkdirAll(root.Join(root.Path(), "dir-b"), 0755); err != nil { + if err := os.MkdirAll(filepath.Join(root, "dir-b"), 0755); err != nil { return err } - if err := driver.WriteFile(root, root.Join(root.Path(), "dir-b", "file-b"), randomContent(128, seed+1), 0755); err != nil { + if err := os.WriteFile(filepath.Join(root, "dir-b", "file-b"), randomContent(128, seed+1), 0755); err != nil { return err } - return driver.WriteFile(root, root.Join(root.Path(), "file-c"), randomContent(128*128, seed+2), 0755) + return os.WriteFile(filepath.Join(root, "file-c"), randomContent(128*128, seed+2), 0755) } func checkFile(drv graphdriver.Driver, layer, filename string, content []byte) error { @@ -55,7 +56,7 @@ func checkFile(drv graphdriver.Driver, layer, filename string, content []byte) e } defer drv.Put(layer) - fileContent, err := driver.ReadFile(root, root.Join(root.Path(), filename)) + fileContent, err := os.ReadFile(filepath.Join(root, filename)) if err != nil { return err } @@ -74,7 +75,7 @@ func addFile(drv graphdriver.Driver, layer, filename string, content []byte) err } defer drv.Put(layer) - return driver.WriteFile(root, root.Join(root.Path(), filename), content, 0755) + return os.WriteFile(filepath.Join(root, filename), content, 0755) } func addDirectory(drv graphdriver.Driver, layer, dir string) error { @@ -84,7 +85,7 @@ func addDirectory(drv graphdriver.Driver, layer, dir string) error { } defer drv.Put(layer) - return root.MkdirAll(root.Join(root.Path(), dir), 0755) + return os.MkdirAll(filepath.Join(root, dir), 0755) } func removeAll(drv graphdriver.Driver, layer string, names ...string) error { @@ -95,7 +96,7 @@ func removeAll(drv graphdriver.Driver, layer string, names ...string) error { defer drv.Put(layer) for _, filename := range names { - if err := root.RemoveAll(root.Join(root.Path(), filename)); err != nil { + if err := os.RemoveAll(filepath.Join(root, filename)); err != nil { return err } } @@ -109,8 +110,8 @@ func checkFileRemoved(drv graphdriver.Driver, layer, filename string) error { } defer drv.Put(layer) - if _, err := root.Stat(root.Join(root.Path(), filename)); err == nil { - return fmt.Errorf("file still exists: %s", root.Join(root.Path(), filename)) + if _, err := os.Stat(filepath.Join(root, filename)); err == nil { + return fmt.Errorf("file still exists: %s", filepath.Join(root, filename)) } else if !os.IsNotExist(err) { return err } @@ -126,13 +127,13 @@ func addManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) e defer drv.Put(layer) for i := 0; i < count; i += 100 { - dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i)) - if err := root.MkdirAll(dir, 0755); err != nil { + dir := filepath.Join(root, fmt.Sprintf("directory-%d", i)) + if err := os.MkdirAll(dir, 0755); err != nil { return err } for j := 0; i+j < count && j < 100; j++ { - file := root.Join(dir, fmt.Sprintf("file-%d", i+j)) - if err := driver.WriteFile(root, file, randomContent(64, seed+int64(i+j)), 0755); err != nil { + file := filepath.Join(dir, fmt.Sprintf("file-%d", i+j)) + if err := os.WriteFile(file, randomContent(64, seed+int64(i+j)), 0755); err != nil { return err } } @@ -151,7 +152,7 @@ func changeManyFiles(drv graphdriver.Driver, layer string, count int, seed int64 var changes []archive.Change for i := 0; i < count; i += 100 { archiveRoot := fmt.Sprintf("/directory-%d", i) - if err := root.MkdirAll(root.Join(root.Path(), archiveRoot), 0755); err != nil { + if err := os.MkdirAll(filepath.Join(root, archiveRoot), 0755); err != nil { return nil, err } for j := 0; i+j < count && j < 100; j++ { @@ -165,23 +166,23 @@ func changeManyFiles(drv graphdriver.Driver, layer string, count int, seed int64 switch j % 3 { // Update file case 0: - change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j)) + change.Path = filepath.Join(archiveRoot, fmt.Sprintf("file-%d", i+j)) change.Kind = archive.ChangeModify - if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil { + if err := os.WriteFile(filepath.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil { return nil, err } // Add file case 1: - change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j)) + change.Path = filepath.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j)) change.Kind = archive.ChangeAdd - if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil { + if err := os.WriteFile(filepath.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil { return nil, err } // Remove file case 2: - change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j)) + change.Path = filepath.Join(archiveRoot, fmt.Sprintf("file-%d", i+j)) change.Kind = archive.ChangeDelete - if err := root.Remove(root.Join(root.Path(), change.Path)); err != nil { + if err := os.Remove(filepath.Join(root, change.Path)); err != nil { return nil, err } } @@ -200,10 +201,10 @@ func checkManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) defer drv.Put(layer) for i := 0; i < count; i += 100 { - dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i)) + dir := filepath.Join(root, fmt.Sprintf("directory-%d", i)) for j := 0; i+j < count && j < 100; j++ { - file := root.Join(dir, fmt.Sprintf("file-%d", i+j)) - fileContent, err := driver.ReadFile(root, file) + file := filepath.Join(dir, fmt.Sprintf("file-%d", i+j)) + fileContent, err := os.ReadFile(file) if err != nil { return err } @@ -253,17 +254,17 @@ func addLayerFiles(drv graphdriver.Driver, layer, parent string, i int) error { } defer drv.Put(layer) - if err := driver.WriteFile(root, root.Join(root.Path(), "top-id"), []byte(layer), 0755); err != nil { + if err := os.WriteFile(filepath.Join(root, "top-id"), []byte(layer), 0755); err != nil { return err } - layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i)) - if err := root.MkdirAll(layerDir, 0755); err != nil { + layerDir := filepath.Join(root, fmt.Sprintf("layer-%d", i)) + if err := os.MkdirAll(layerDir, 0755); err != nil { return err } - if err := driver.WriteFile(root, root.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil { + if err := os.WriteFile(filepath.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil { return err } - return driver.WriteFile(root, root.Join(layerDir, "parent-id"), []byte(parent), 0755) + return os.WriteFile(filepath.Join(layerDir, "parent-id"), []byte(parent), 0755) } func addManyLayers(drv graphdriver.Driver, baseLayer string, count int) (string, error) { @@ -290,7 +291,7 @@ func checkManyLayers(drv graphdriver.Driver, layer string, count int) error { } defer drv.Put(layer) - layerIDBytes, err := driver.ReadFile(root, root.Join(root.Path(), "top-id")) + layerIDBytes, err := os.ReadFile(filepath.Join(root, "top-id")) if err != nil { return err } @@ -300,16 +301,16 @@ func checkManyLayers(drv graphdriver.Driver, layer string, count int) error { } for i := count; i > 0; i-- { - layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i)) + layerDir := filepath.Join(root, fmt.Sprintf("layer-%d", i)) - thisLayerIDBytes, err := driver.ReadFile(root, root.Join(layerDir, "layer-id")) + thisLayerIDBytes, err := os.ReadFile(filepath.Join(layerDir, "layer-id")) if err != nil { return err } if !bytes.Equal(thisLayerIDBytes, layerIDBytes) { return fmt.Errorf("mismatched file content %v, expecting %v", thisLayerIDBytes, layerIDBytes) } - layerIDBytes, err = driver.ReadFile(root, root.Join(layerDir, "parent-id")) + layerIDBytes, err = os.ReadFile(filepath.Join(layerDir, "parent-id")) if err != nil { return err } @@ -317,11 +318,11 @@ func checkManyLayers(drv graphdriver.Driver, layer string, count int) error { return nil } -// readDir reads a directory just like driver.ReadDir() +// readDir reads a directory just like os.ReadDir() // then hides specific files (currently "lost+found") // so the tests don't "see" it -func readDir(r driver.Driver, dir string) ([]os.FileInfo, error) { - a, err := driver.ReadDir(r, dir) +func readDir(dir string) ([]fs.DirEntry, error) { + a, err := os.ReadDir(dir) if err != nil { return nil, err } diff --git a/daemon/graphdriver/graphtest/testutil_unix.go b/daemon/graphdriver/graphtest/testutil_unix.go index 1c3037c8aa..d42682203e 100644 --- a/daemon/graphdriver/graphtest/testutil_unix.go +++ b/daemon/graphdriver/graphtest/testutil_unix.go @@ -5,6 +5,7 @@ package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphte import ( "os" + "path/filepath" "syscall" "testing" @@ -44,12 +45,12 @@ func createBase(t testing.TB, driver graphdriver.Driver, name string) { assert.NilError(t, err) defer driver.Put(name) - subdir := dirFS.Join(dirFS.Path(), "a subdir") - assert.NilError(t, dirFS.Mkdir(subdir, 0705|os.ModeSticky)) - assert.NilError(t, dirFS.Lchown(subdir, 1, 2)) + subdir := filepath.Join(dirFS, "a subdir") + assert.NilError(t, os.Mkdir(subdir, 0705|os.ModeSticky)) + assert.NilError(t, contdriver.LocalDriver.Lchown(subdir, 1, 2)) - file := dirFS.Join(dirFS.Path(), "a file") - err = contdriver.WriteFile(dirFS, file, []byte("Some data"), 0222|os.ModeSetuid) + file := filepath.Join(dirFS, "a file") + err = os.WriteFile(file, []byte("Some data"), 0222|os.ModeSetuid) assert.NilError(t, err) } @@ -58,13 +59,13 @@ func verifyBase(t testing.TB, driver graphdriver.Driver, name string) { assert.NilError(t, err) defer driver.Put(name) - subdir := dirFS.Join(dirFS.Path(), "a subdir") + subdir := filepath.Join(dirFS, "a subdir") verifyFile(t, subdir, 0705|os.ModeDir|os.ModeSticky, 1, 2) - file := dirFS.Join(dirFS.Path(), "a file") + file := filepath.Join(dirFS, "a file") verifyFile(t, file, 0222|os.ModeSetuid, 0, 0) - files, err := readDir(dirFS, dirFS.Path()) + files, err := readDir(dirFS) assert.NilError(t, err) assert.Check(t, is.Len(files, 2)) } diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go index 540daf1077..8346ff1cd0 100644 --- a/daemon/graphdriver/overlay/overlay.go +++ b/daemon/graphdriver/overlay/overlay.go @@ -339,22 +339,22 @@ func (d *Driver) Remove(id string) error { } // Get creates and mounts the required file system for the given id and returns the mount path. -func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err error) { +func (d *Driver) Get(id, mountLabel string) (_ string, err error) { d.locker.Lock(id) defer d.locker.Unlock(id) dir := d.dir(id) if _, err := os.Stat(dir); err != nil { - return nil, err + return "", err } // If id has a root, just return it rootDir := path.Join(dir, "root") if _, err := os.Stat(rootDir); err == nil { - return containerfs.NewLocalContainerFS(rootDir), nil + return rootDir, nil } mergedDir := path.Join(dir, "merged") if count := d.ctr.Increment(mergedDir); count > 1 { - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } defer func() { if err != nil { @@ -371,11 +371,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro }() lowerID, err := os.ReadFile(path.Join(dir, "lower-id")) if err != nil { - return nil, err + return "", err } root := d.idMap.RootPair() if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil { - return nil, err + return "", err } var ( lowerDir = path.Join(d.dir(string(lowerID)), "root") @@ -384,14 +384,14 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir) ) if err := unix.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil { - return nil, fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) + return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, 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. if err := root.Chown(path.Join(workDir, "work")); err != nil { - return nil, err + return "", err } - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } // Put unmounts the mount path created for the give id. diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index ef243163c8..f373cfb7b8 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -513,12 +513,12 @@ func (d *Driver) Remove(id string) error { } // Get creates and mounts the required file system for the given id and returns the mount path. -func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr error) { +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 nil, err + return "", err } diffDir := path.Join(dir, diffDirName) @@ -526,14 +526,14 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if err != nil { // If no lower, just return diff directory if os.IsNotExist(err) { - return containerfs.NewLocalContainerFS(diffDir), nil + return diffDir, nil } - return nil, err + return "", err } mergedDir := path.Join(dir, mergedDirName) if count := d.ctr.Increment(mergedDir); count > 1 { - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } defer func() { if retErr != nil { @@ -559,7 +559,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if _, err := os.Stat(path.Join(dir, "committed")); err == nil { readonly = true } else if !os.IsNotExist(err) { - return nil, err + return "", err } var opts string @@ -575,7 +575,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e root := d.idMap.RootPair() if err := idtools.MkdirAndChown(mergedDir, 0700, root); err != nil { - return nil, err + return "", err } pageSize := unix.Getpagesize() @@ -592,7 +592,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e } mountData = label.FormatMountLabel(opts, mountLabel) if len(mountData) > pageSize-1 { - return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData)) + 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 { @@ -602,18 +602,18 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e } if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil { - return nil, fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) + return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) } if !readonly { // 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. if err := root.Chown(path.Join(workDir, workDirName)); err != nil { - return nil, err + return "", err } } - return containerfs.NewLocalContainerFS(mergedDir), nil + return mergedDir, nil } // Put unmounts the mount path created for the give id. diff --git a/daemon/graphdriver/proxy.go b/daemon/graphdriver/proxy.go index 022808de34..024c32092e 100644 --- a/daemon/graphdriver/proxy.go +++ b/daemon/graphdriver/proxy.go @@ -6,7 +6,6 @@ import ( "io" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/plugins" @@ -128,20 +127,20 @@ func (d *graphDriverProxy) Remove(id string) error { return nil } -func (d *graphDriverProxy) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +func (d *graphDriverProxy) Get(id, mountLabel string) (string, error) { args := &graphDriverRequest{ ID: id, MountLabel: mountLabel, } var ret graphDriverResponse if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil { - return nil, err + return "", err } var err error if ret.Err != "" { err = errors.New(ret.Err) } - return containerfs.NewLocalContainerFS(d.p.ScopedPath(ret.Dir)), err + return d.p.ScopedPath(ret.Dir), err } func (d *graphDriverProxy) Put(id string) error { diff --git a/daemon/graphdriver/vfs/driver.go b/daemon/graphdriver/vfs/driver.go index 2c6c720eab..f762ed7ec2 100644 --- a/daemon/graphdriver/vfs/driver.go +++ b/daemon/graphdriver/vfs/driver.go @@ -172,7 +172,7 @@ func (d *Driver) create(id, parent string, size uint64) error { if err != nil { return fmt.Errorf("%s: %s", parent, err) } - return CopyDir(parentDir.Path(), dir) + return CopyDir(parentDir, dir) } func (d *Driver) dir(id string) string { @@ -185,14 +185,14 @@ func (d *Driver) Remove(id string) error { } // Get returns the directory for the given id. -func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { dir := d.dir(id) if st, err := os.Stat(dir); err != nil { - return nil, err + return "", err } else if !st.IsDir() { - return nil, fmt.Errorf("%s: not a directory", dir) + return "", fmt.Errorf("%s: not a directory", dir) } - return containerfs.NewLocalContainerFS(dir), nil + 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. diff --git a/daemon/graphdriver/windows/windows.go b/daemon/graphdriver/windows/windows.go index 1e3b9343ee..75e6035a87 100644 --- a/daemon/graphdriver/windows/windows.go +++ b/daemon/graphdriver/windows/windows.go @@ -27,7 +27,6 @@ import ( "github.com/Microsoft/hcsshim/osversion" "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/longpath" @@ -393,35 +392,35 @@ func (d *Driver) GetLayerPath(id string) (string, error) { } // Get returns the rootfs path for the id. This will mount the dir at its given path. -func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel) var dir string rID, err := d.resolveID(id) if err != nil { - return nil, err + return "", err } if count := d.ctr.Increment(rID); count > 1 { - return containerfs.NewLocalContainerFS(d.cache[rID]), nil + 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 nil, err + return "", err } if err := hcsshim.ActivateLayer(d.info, rID); err != nil { d.ctr.Decrement(rID) - return nil, err + 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 nil, err + return "", err } mountPath, err := hcsshim.GetLayerMountPath(d.info, rID) @@ -433,7 +432,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { logrus.Warnf("Failed to Deactivate %s: %s", id, err) } - return nil, err + return "", err } d.cacheMu.Lock() d.cache[rID] = mountPath @@ -447,7 +446,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { dir = d.dir(id) } - return containerfs.NewLocalContainerFS(dir), nil + return dir, nil } // Put adds a new layer to the driver. @@ -651,7 +650,7 @@ func (d *Driver) DiffSize(id, parent string) (size int64, err error) { } defer d.Put(id) - return archive.ChangesSize(layerFs.Path(), changes), nil + return archive.ChangesSize(layerFs, changes), nil } // GetMetadata returns custom driver information. diff --git a/daemon/graphdriver/zfs/zfs.go b/daemon/graphdriver/zfs/zfs.go index e438ab0ab1..cafb77fd5d 100644 --- a/daemon/graphdriver/zfs/zfs.go +++ b/daemon/graphdriver/zfs/zfs.go @@ -14,7 +14,6 @@ import ( "time" "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/parsers" zfs "github.com/mistifyio/go-zfs" @@ -363,12 +362,12 @@ func (d *Driver) Remove(id string) error { } // Get returns the mountpoint for the given id after creating the target directories if necessary. -func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr error) { +func (d *Driver) Get(id, mountLabel string) (_ string, retErr error) { d.locker.Lock(id) defer d.locker.Unlock(id) mountpoint := d.mountPath(id) if count := d.ctr.Increment(mountpoint); count > 1 { - return containerfs.NewLocalContainerFS(mountpoint), nil + return mountpoint, nil } defer func() { if retErr != nil { @@ -391,20 +390,20 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e root := d.idMap.RootPair() // Create the target directories if they don't exist if err := idtools.MkdirAllAndChown(mountpoint, 0755, root); err != nil { - return nil, err + return "", err } if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil { - return nil, errors.Wrap(err, "error creating zfs mount") + return "", errors.Wrap(err, "error creating zfs mount") } // 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 := root.Chown(mountpoint); err != nil { - return nil, fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) + return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) } - return containerfs.NewLocalContainerFS(mountpoint), nil + return mountpoint, nil } // Put removes the existing mountpoint for the given id if it exists. diff --git a/daemon/images/image_builder.go b/daemon/images/image_builder.go index 10980c6561..af2d4073cc 100644 --- a/daemon/images/image_builder.go +++ b/daemon/images/image_builder.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" @@ -83,10 +82,10 @@ type rwLayer struct { released bool layerStore layer.Store rwLayer layer.RWLayer - fs containerfs.ContainerFS + fs string } -func (l *rwLayer) Root() containerfs.ContainerFS { +func (l *rwLayer) Root() string { return l.fs } @@ -115,11 +114,11 @@ func (l *rwLayer) Release() error { return nil } - if l.fs != nil { + if l.fs != "" { if err := l.rwLayer.Unmount(); err != nil { return errors.Wrap(err, "failed to unmount RWLayer") } - l.fs = nil + l.fs = "" } metadata, err := l.layerStore.ReleaseRWLayer(l.rwLayer) diff --git a/daemon/initlayer/setup_unix.go b/daemon/initlayer/setup_unix.go index 1a971897b4..4d2c84cafb 100644 --- a/daemon/initlayer/setup_unix.go +++ b/daemon/initlayer/setup_unix.go @@ -8,7 +8,6 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "golang.org/x/sys/unix" ) @@ -18,9 +17,9 @@ import ( // // This extra layer is used by all containers as the top-most ro layer. It protects // the container from unwanted side-effects on the rw layer. -func Setup(initLayerFs containerfs.ContainerFS, rootIdentity idtools.Identity) error { +func Setup(initLayerFs string, rootIdentity idtools.Identity) error { // Since all paths are local to the container, we can just extract initLayerFs.Path() - initLayer := initLayerFs.Path() + initLayer := initLayerFs for pth, typ := range map[string]string{ "/dev/pts": "dir", diff --git a/daemon/list_windows.go b/daemon/list_windows.go index 7c7b5fa856..62daa36fc8 100644 --- a/daemon/list_windows.go +++ b/daemon/list_windows.go @@ -9,7 +9,7 @@ import ( // excludeByIsolation is a platform specific helper function to support PS // filtering by Isolation. This is a Windows-only concept, so is a no-op on Unix. func excludeByIsolation(container *container.Snapshot, ctx *listContext) iterationAction { - i := strings.ToLower(string(container.HostConfig.Isolation)) + i := strings.ToLower(container.HostConfig.Isolation) if i == "" { i = "default" } diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index e30ea08e8c..b0ca314fd8 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -721,8 +721,8 @@ func sysctlExists(s string) bool { // WithCommonOptions sets common docker options func WithCommonOptions(daemon *Daemon, c *container.Container) coci.SpecOpts { return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error { - if c.BaseFS == nil && !daemon.UsesSnapshotter() { - return errors.New("populateCommonSpec: BaseFS of container " + c.ID + " is unexpectedly nil") + if c.BaseFS == "" && !daemon.UsesSnapshotter() { + return errors.New("populateCommonSpec: BaseFS of container " + c.ID + " is unexpectedly empty") } linkedEnv, err := daemon.setupLinkedContainers(c) if err != nil { @@ -730,7 +730,7 @@ func WithCommonOptions(daemon *Daemon, c *container.Container) coci.SpecOpts { } if !daemon.UsesSnapshotter() { s.Root = &specs.Root{ - Path: c.BaseFS.Path(), + Path: c.BaseFS, Readonly: c.HostConfig.ReadonlyRootfs, } } diff --git a/daemon/oci_linux_test.go b/daemon/oci_linux_test.go index 42084c900d..d7a68b88bf 100644 --- a/daemon/oci_linux_test.go +++ b/daemon/oci_linux_test.go @@ -10,7 +10,6 @@ import ( "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/network" "github.com/docker/docker/libnetwork" - "github.com/docker/docker/pkg/containerfs" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/skip" @@ -36,7 +35,7 @@ func setupFakeDaemon(t *testing.T, c *container.Container) *Daemon { } c.Root = root - c.BaseFS = containerfs.NewLocalContainerFS(rootfs) + c.BaseFS = rootfs if c.Config == nil { c.Config = new(containertypes.Config) diff --git a/daemon/oci_windows.go b/daemon/oci_windows.go index 502ce10102..e2205b8ca2 100644 --- a/daemon/oci_windows.go +++ b/daemon/oci_windows.go @@ -236,11 +236,11 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S } s.Root.Readonly = false // Windows does not support a read-only root filesystem if !isHyperV { - if c.BaseFS == nil { - return errors.New("createSpecWindowsFields: BaseFS of container " + c.ID + " is unexpectedly nil") + if c.BaseFS == "" { + return errors.New("createSpecWindowsFields: BaseFS of container " + c.ID + " is unexpectedly empty") } - s.Root.Path = c.BaseFS.Path() // This is not set for Hyper-V containers + s.Root.Path = c.BaseFS // This is not set for Hyper-V containers if !strings.HasSuffix(s.Root.Path, `\`) { s.Root.Path = s.Root.Path + `\` // Ensure a correctly formatted volume GUID path \\?\Volume{GUID}\ } diff --git a/daemon/start.go b/daemon/start.go index bbdefb0173..bee566e5cf 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -251,7 +251,7 @@ func (daemon *Daemon) Cleanup(container *container.Container) { daemon.unregisterExecCommand(container, eConfig) } - if container.BaseFS != nil && container.BaseFS.Path() != "" { + if container.BaseFS != "" { if err := container.UnmountVolumes(daemon.LogVolumeEvent); err != nil { logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err) } diff --git a/integration/plugin/graphdriver/external_test.go b/integration/plugin/graphdriver/external_test.go index cb261774b8..7eaec7a861 100644 --- a/integration/plugin/graphdriver/external_test.go +++ b/integration/plugin/graphdriver/external_test.go @@ -213,13 +213,12 @@ func setupPlugin(t *testing.T, ec map[string]*graphEventsCounter, ext string, mu return } - // TODO @gupta-ak: Figure out what to do here. dir, err := driver.Get(req.ID, req.MountLabel) if err != nil { respond(w, err) return } - respond(w, &graphDriverResponse{Dir: dir.Path()}) + respond(w, &graphDriverResponse{Dir: dir}) }) mux.HandleFunc("/GraphDriver.Put", func(w http.ResponseWriter, r *http.Request) { diff --git a/layer/layer.go b/layer/layer.go index f5a4792498..330f359632 100644 --- a/layer/layer.go +++ b/layer/layer.go @@ -15,7 +15,6 @@ import ( "github.com/docker/distribution" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" ) @@ -114,7 +113,7 @@ type RWLayer interface { // Mount mounts the RWLayer and returns the filesystem path // to the writable layer. - Mount(mountLabel string) (containerfs.ContainerFS, error) + Mount(mountLabel string) (string, error) // Unmount unmounts the RWLayer. This should be called // for every mount. If there are multiple mount calls @@ -158,7 +157,7 @@ type Metadata struct { // writable mount. Changes made here will // not be included in the Tar stream of the // RWLayer. -type MountInit func(root containerfs.ContainerFS) error +type MountInit func(root string) error // CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer type CreateRWLayerOpts struct { diff --git a/layer/layer_store.go b/layer/layer_store.go index 51fa656652..623d494012 100644 --- a/layer/layer_store.go +++ b/layer/layer_store.go @@ -786,5 +786,5 @@ func (n *naiveDiffPathDriver) DiffGetter(id string) (graphdriver.FileGetCloser, if err != nil { return nil, err } - return &fileGetPutter{storage.NewPathFileGetter(p.Path()), n.Driver, id}, nil + return &fileGetPutter{storage.NewPathFileGetter(p), n.Driver, id}, nil } diff --git a/layer/layer_test.go b/layer/layer_test.go index 710f7423ad..afda53a871 100644 --- a/layer/layer_test.go +++ b/layer/layer_test.go @@ -13,7 +13,6 @@ import ( "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver/vfs" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" "github.com/opencontainers/go-digest" @@ -80,7 +79,7 @@ func newTestStore(t *testing.T) (Store, string, func()) { } } -type layerInit func(root containerfs.ContainerFS) error +type layerInit func(root string) error func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) { containerID := stringid.GenerateRandomID() @@ -121,7 +120,7 @@ func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) { } type FileApplier interface { - ApplyFile(root containerfs.ContainerFS) error + ApplyFile(root string) error } type testFile struct { @@ -138,22 +137,22 @@ func newTestFile(name string, content []byte, perm os.FileMode) FileApplier { } } -func (tf *testFile) ApplyFile(root containerfs.ContainerFS) error { - fullPath := root.Join(root.Path(), tf.name) - if err := root.MkdirAll(root.Dir(fullPath), 0755); err != nil { +func (tf *testFile) ApplyFile(root string) error { + fullPath := filepath.Join(root, tf.name) + if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { return err } // Check if already exists - if stat, err := root.Stat(fullPath); err == nil && stat.Mode().Perm() != tf.permission { - if err := root.Lchmod(fullPath, tf.permission); err != nil { + if stat, err := os.Stat(fullPath); err == nil && stat.Mode().Perm() != tf.permission { + if err := driver.LocalDriver.Lchmod(fullPath, tf.permission); err != nil { return err } } - return driver.WriteFile(root, fullPath, tf.content, tf.permission) + return os.WriteFile(fullPath, tf.content, tf.permission) } func initWithFiles(files ...FileApplier) layerInit { - return func(root containerfs.ContainerFS) error { + return func(root string) error { for _, f := range files { if err := f.ApplyFile(root); err != nil { return err @@ -267,7 +266,7 @@ func TestMountAndRegister(t *testing.T) { t.Fatal(err) } - b, err := driver.ReadFile(path2, path2.Join(path2.Path(), "testfile.txt")) + b, err := os.ReadFile(filepath.Join(path2, "testfile.txt")) if err != nil { t.Fatal(err) } @@ -375,7 +374,7 @@ func TestStoreRestore(t *testing.T) { t.Fatal(err) } - if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile.txt"), []byte("nothing here"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(pathFS, "testfile.txt"), []byte("nothing here"), 0644); err != nil { t.Fatal(err) } @@ -409,20 +408,20 @@ func TestStoreRestore(t *testing.T) { if mountPath, err := m2.Mount(""); err != nil { t.Fatal(err) - } else if pathFS.Path() != mountPath.Path() { - t.Fatalf("Unexpected path %s, expected %s", mountPath.Path(), pathFS.Path()) + } else if pathFS != mountPath { + t.Fatalf("Unexpected path %s, expected %s", mountPath, pathFS) } if mountPath, err := m2.Mount(""); err != nil { t.Fatal(err) - } else if pathFS.Path() != mountPath.Path() { - t.Fatalf("Unexpected path %s, expected %s", mountPath.Path(), pathFS.Path()) + } else if pathFS != mountPath { + t.Fatalf("Unexpected path %s, expected %s", mountPath, pathFS) } if err := m2.Unmount(); err != nil { t.Fatal(err) } - b, err := driver.ReadFile(pathFS, pathFS.Join(pathFS.Path(), "testfile.txt")) + b, err := os.ReadFile(filepath.Join(pathFS, "testfile.txt")) if err != nil { t.Fatal(err) } @@ -597,7 +596,7 @@ func tarFromFiles(files ...FileApplier) ([]byte, error) { defer os.RemoveAll(td) for _, f := range files { - if err := f.ApplyFile(containerfs.NewLocalContainerFS(td)); err != nil { + if err := f.ApplyFile(td); err != nil { return nil, err } } diff --git a/layer/layer_windows.go b/layer/layer_windows.go index 3d079a9af6..350a671124 100644 --- a/layer/layer_windows.go +++ b/layer/layer_windows.go @@ -37,7 +37,7 @@ func GetLayerPath(s Store, layer ChainID) (string, error) { return "", err } - return path.Path(), nil + return path, nil } func (ls *layerStore) mountID(name string) string { diff --git a/layer/mount_test.go b/layer/mount_test.go index 20de6e0c7c..643a52c524 100644 --- a/layer/mount_test.go +++ b/layer/mount_test.go @@ -2,13 +2,14 @@ package layer // import "github.com/docker/docker/layer" import ( "io" + "os" + "path/filepath" "runtime" "sort" "testing" "github.com/containerd/continuity/driver" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" ) func TestMountInit(t *testing.T) { @@ -28,7 +29,7 @@ func TestMountInit(t *testing.T) { t.Fatal(err) } - mountInit := func(root containerfs.ContainerFS) error { + mountInit := func(root string) error { return initfile.ApplyFile(root) } @@ -45,12 +46,12 @@ func TestMountInit(t *testing.T) { t.Fatal(err) } - fi, err := pathFS.Stat(pathFS.Join(pathFS.Path(), "testfile.txt")) + fi, err := os.Stat(filepath.Join(pathFS, "testfile.txt")) if err != nil { t.Fatal(err) } - f, err := pathFS.Open(pathFS.Join(pathFS.Path(), "testfile.txt")) + f, err := os.Open(filepath.Join(pathFS, "testfile.txt")) if err != nil { t.Fatal(err) } @@ -88,7 +89,7 @@ func TestMountSize(t *testing.T) { t.Fatal(err) } - mountInit := func(root containerfs.ContainerFS) error { + mountInit := func(root string) error { return newTestFile("file-init", contentInit, 0777).ApplyFile(root) } rwLayerOpts := &CreateRWLayerOpts{ @@ -105,7 +106,7 @@ func TestMountSize(t *testing.T) { t.Fatal(err) } - if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "file2"), content2, 0755); err != nil { + if err := os.WriteFile(filepath.Join(pathFS, "file2"), content2, 0755); err != nil { t.Fatal(err) } @@ -140,7 +141,7 @@ func TestMountChanges(t *testing.T) { t.Fatal(err) } - mountInit := func(root containerfs.ContainerFS) error { + mountInit := func(root string) error { return initfile.ApplyFile(root) } rwLayerOpts := &CreateRWLayerOpts{ @@ -157,23 +158,23 @@ func TestMountChanges(t *testing.T) { t.Fatal(err) } - if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile1.txt"), 0755); err != nil { + if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile1.txt"), 0755); err != nil { t.Fatal(err) } - if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile1.txt"), []byte("mount data!"), 0755); err != nil { + if err := os.WriteFile(filepath.Join(pathFS, "testfile1.txt"), []byte("mount data!"), 0755); err != nil { t.Fatal(err) } - if err := pathFS.Remove(pathFS.Join(pathFS.Path(), "testfile2.txt")); err != nil { + if err := os.Remove(filepath.Join(pathFS, "testfile2.txt")); err != nil { t.Fatal(err) } - if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile3.txt"), 0755); err != nil { + if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile3.txt"), 0755); err != nil { t.Fatal(err) } - if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile4.txt"), []byte("mount data!"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(pathFS, "testfile4.txt"), []byte("mount data!"), 0644); err != nil { t.Fatal(err) } @@ -248,7 +249,7 @@ func TestMountApply(t *testing.T) { t.Fatal(err) } - f, err := pathFS.Open(pathFS.Join(pathFS.Path(), "newfile.txt")) + f, err := os.Open(filepath.Join(pathFS, "newfile.txt")) if err != nil { t.Fatal(err) } diff --git a/layer/mounted_layer.go b/layer/mounted_layer.go index f614fd571d..05f98f5f3d 100644 --- a/layer/mounted_layer.go +++ b/layer/mounted_layer.go @@ -5,7 +5,6 @@ import ( "sync" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/containerfs" ) type mountedLayer struct { @@ -100,7 +99,7 @@ type referencedRWLayer struct { *mountedLayer } -func (rl *referencedRWLayer) Mount(mountLabel string) (containerfs.ContainerFS, error) { +func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) { return rl.layerStore.driver.Get(rl.mountedLayer.mountID, mountLabel) } diff --git a/libnetwork/ipam/structures.go b/libnetwork/ipam/structures.go index de4130f83d..dd5edf13e1 100644 --- a/libnetwork/ipam/structures.go +++ b/libnetwork/ipam/structures.go @@ -186,7 +186,7 @@ func (aSpace *addrSpace) UnmarshalJSON(data []byte) error { aSpace.scope = datastore.LocalScope s := m["Scope"].(string) - if s == string(datastore.GlobalScope) { + if s == datastore.GlobalScope { aSpace.scope = datastore.GlobalScope } diff --git a/pkg/archive/copy.go b/pkg/archive/copy.go index 43a9b1417d..90d23cdc08 100644 --- a/pkg/archive/copy.go +++ b/pkg/archive/copy.go @@ -26,23 +26,23 @@ var ( // 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 the separator, then another is not added. -func PreserveTrailingDotOrSeparator(cleanedPath string, originalPath string, sep byte) string { +// clean path already ends in a path separator, then another is not added. +func PreserveTrailingDotOrSeparator(cleanedPath string, originalPath string) string { // Ensure paths are in platform semantics - cleanedPath = strings.ReplaceAll(cleanedPath, "/", string(sep)) - originalPath = strings.ReplaceAll(originalPath, "/", string(sep)) + cleanedPath = normalizePath(cleanedPath) + originalPath = normalizePath(originalPath) if !specifiesCurrentDir(cleanedPath) && specifiesCurrentDir(originalPath) { - if !hasTrailingPathSeparator(cleanedPath, sep) { + 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(sep) + cleanedPath += string(filepath.Separator) } cleanedPath += "." } - if !hasTrailingPathSeparator(cleanedPath, sep) && hasTrailingPathSeparator(originalPath, sep) { - cleanedPath += string(sep) + if !hasTrailingPathSeparator(cleanedPath) && hasTrailingPathSeparator(originalPath) { + cleanedPath += string(filepath.Separator) } return cleanedPath @@ -51,14 +51,14 @@ func PreserveTrailingDotOrSeparator(cleanedPath string, originalPath string, sep // 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, sep byte) bool { - return hasTrailingPathSeparator(path, sep) || specifiesCurrentDir(path) +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, sep byte) bool { - return len(path) > 0 && path[len(path)-1] == sep +func hasTrailingPathSeparator(path string) bool { + return len(path) > 0 && path[len(path)-1] == filepath.Separator } // specifiesCurrentDir returns whether the given path specifies @@ -285,7 +285,7 @@ func PrepareArchiveCopy(srcContent io.Reader, srcInfo, dstInfo CopyInfo) (dstDir srcBase = srcInfo.RebaseName } return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - case assertsDirectory(dstInfo.Path, os.PathSeparator): + 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 @@ -387,8 +387,8 @@ func CopyResource(srcPath, dstPath string, followLink bool) error { dstPath = normalizePath(dstPath) // Clean the source and destination paths. - srcPath = PreserveTrailingDotOrSeparator(filepath.Clean(srcPath), srcPath, os.PathSeparator) - dstPath = PreserveTrailingDotOrSeparator(filepath.Clean(dstPath), dstPath, os.PathSeparator) + srcPath = PreserveTrailingDotOrSeparator(filepath.Clean(srcPath), srcPath) + dstPath = PreserveTrailingDotOrSeparator(filepath.Clean(dstPath), dstPath) if srcInfo, err = CopyInfoSourcePath(srcPath, followLink); err != nil { return err @@ -451,7 +451,7 @@ func ResolveHostSourcePath(path string, followLink bool) (resolvedPath, rebaseNa // 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, os.PathSeparator) && + if hasTrailingPathSeparator(path) && filepath.Base(path) != filepath.Base(resolvedPath) { rebaseName = filepath.Base(path) } @@ -470,8 +470,8 @@ func GetRebaseName(path, resolvedPath string) (string, string) { resolvedPath += string(filepath.Separator) + "." } - if hasTrailingPathSeparator(path, os.PathSeparator) && - !hasTrailingPathSeparator(resolvedPath, os.PathSeparator) { + if hasTrailingPathSeparator(path) && + !hasTrailingPathSeparator(resolvedPath) { resolvedPath += string(filepath.Separator) } diff --git a/pkg/containerfs/archiver.go b/pkg/containerfs/archiver.go deleted file mode 100644 index d5f153b373..0000000000 --- a/pkg/containerfs/archiver.go +++ /dev/null @@ -1,203 +0,0 @@ -package containerfs // import "github.com/docker/docker/pkg/containerfs" - -import ( - "archive/tar" - "errors" - "io" - "os" - "path/filepath" - "time" - - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -// TarFunc provides a function definition for a custom Tar function -type TarFunc func(string, *archive.TarOptions) (io.ReadCloser, error) - -// UntarFunc provides a function definition for a custom Untar function -type UntarFunc func(io.Reader, string, *archive.TarOptions) error - -// Archiver provides a similar implementation of the archive.Archiver package with the rootfs abstraction -type Archiver struct { - SrcDriver Driver - DstDriver Driver - Tar TarFunc - Untar UntarFunc - IDMapping idtools.IdentityMapping -} - -// 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) - tarArchive, err := archiver.Tar(src, &archive.TarOptions{Compression: archive.Uncompressed}) - if err != nil { - return err - } - defer tarArchive.Close() - options := &archive.TarOptions{ - IDMap: archiver.IDMapping, - } - return archiver.Untar(tarArchive, 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 { - tarArchive, err := archiver.SrcDriver.Open(src) - if err != nil { - return err - } - defer tarArchive.Close() - options := &archive.TarOptions{ - IDMap: archiver.IDMapping, - } - return archiver.Untar(tarArchive, 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 := archiver.SrcDriver.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 - - identity := idtools.Identity{UID: archiver.IDMapping.RootPair().UID, GID: archiver.IDMapping.RootPair().GID} - - // Create dst, copy src's content into it - if err := idtools.MkdirAllAndChownNew(dst, 0755, identity); 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) (retErr error) { - logrus.Debugf("CopyFileWithTar(%s, %s)", src, dst) - srcDriver := archiver.SrcDriver - dstDriver := archiver.DstDriver - - srcSt, retErr := srcDriver.Stat(src) - if retErr != nil { - return retErr - } - - if srcSt.IsDir() { - return errors.New("cannot copy a directory") - } - - // Clean up the trailing slash. This must be done in an operating - // system specific manner. - if dst[len(dst)-1] == dstDriver.Separator() { - dst = dstDriver.Join(dst, srcDriver.Base(src)) - } - - // The original call was system.MkdirAll, which is just - // os.MkdirAll on not-Windows and changed for Windows. - if dstDriver.OS() == "windows" { - // Now we are WCOW - if err := system.MkdirAll(filepath.Dir(dst), 0700); err != nil { - return err - } - } else { - // We can just use the driver.MkdirAll function - if err := dstDriver.MkdirAll(dstDriver.Dir(dst), 0700); err != nil { - return err - } - } - - r, w := io.Pipe() - errC := make(chan error, 1) - - go func() { - defer close(errC) - errC <- func() error { - defer w.Close() - - srcF, err := srcDriver.Open(src) - if err != nil { - return err - } - defer srcF.Close() - - hdr, err := archive.FileInfoHeaderNoLookups(srcSt, "") - if err != nil { - return err - } - hdr.Format = tar.FormatPAX - hdr.ModTime = hdr.ModTime.Truncate(time.Second) - hdr.AccessTime = time.Time{} - hdr.ChangeTime = time.Time{} - hdr.Name = dstDriver.Base(dst) - if dstDriver.OS() == "windows" { - hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode))) - } else { - hdr.Mode = int64(os.FileMode(hdr.Mode)) - } - - if err := remapIDs(archiver.IDMapping, 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 err := <-errC; retErr == nil && err != nil { - retErr = err - } - }() - - retErr = archiver.Untar(r, dstDriver.Dir(dst), nil) - if retErr != nil { - r.CloseWithError(retErr) - } - return retErr -} - -// IdentityMapping returns the IdentityMapping of the archiver. -func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping { - return archiver.IDMapping -} - -func remapIDs(idMapping idtools.IdentityMapping, hdr *tar.Header) error { - ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid}) - hdr.Uid, hdr.Gid = ids.UID, ids.GID - return err -} - -// 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 -} diff --git a/pkg/containerfs/containerfs.go b/pkg/containerfs/containerfs.go index cf2d39c82e..e65f783a23 100644 --- a/pkg/containerfs/containerfs.go +++ b/pkg/containerfs/containerfs.go @@ -2,85 +2,12 @@ package containerfs // import "github.com/docker/docker/pkg/containerfs" import ( "path/filepath" - "runtime" - "github.com/containerd/continuity/driver" - "github.com/containerd/continuity/pathdriver" "github.com/moby/sys/symlink" ) -// ContainerFS is that represents a root file system -type ContainerFS interface { - // Path returns the path to the root. Note that this may not exist - // on the local system, so the continuity operations must be used - Path() string - - // ResolveScopedPath evaluates the given path scoped to the root. - // For example, if root=/a, and path=/b/c, then this function would return /a/b/c. - // If rawPath is true, then the function will not preform any modifications - // before path resolution. Otherwise, the function will clean the given path - // by making it an absolute path. - ResolveScopedPath(path string, rawPath bool) (string, error) - - Driver -} - -// Driver combines both continuity's Driver and PathDriver interfaces with a Platform -// field to determine the OS. -type Driver interface { - // OS returns the OS where the rootfs is located. Essentially, runtime.GOOS. - OS() string - - // Architecture returns the hardware architecture where the - // container is located. - Architecture() string - - // Driver & PathDriver provide methods to manipulate files & paths - driver.Driver - pathdriver.PathDriver -} - -// NewLocalContainerFS is a helper function to implement daemon's Mount interface -// when the graphdriver mount point is a local path on the machine. -func NewLocalContainerFS(path string) ContainerFS { - return &local{ - path: path, - Driver: driver.LocalDriver, - PathDriver: pathdriver.LocalPathDriver, - } -} - -// NewLocalDriver provides file and path drivers for a local file system. They are -// essentially a wrapper around the `os` and `filepath` functions. -func NewLocalDriver() Driver { - return &local{ - Driver: driver.LocalDriver, - PathDriver: pathdriver.LocalPathDriver, - } -} - -type local struct { - path string - driver.Driver - pathdriver.PathDriver -} - -func (l *local) Path() string { - return l.path -} - -func (l *local) ResolveScopedPath(path string, rawPath bool) (string, error) { - cleanedPath := path - if !rawPath { - cleanedPath = cleanScopedPath(path) - } - return symlink.FollowSymlinkInScope(filepath.Join(l.path, cleanedPath), l.path) -} - -func (l *local) OS() string { - return runtime.GOOS -} - -func (l *local) Architecture() string { - return runtime.GOARCH +// ResolveScopedPath evaluates the given path scoped to the root. +// For example, if root=/a, and path=/b/c, then this function would return /a/b/c. +func ResolveScopedPath(root, path string) (string, error) { + return symlink.FollowSymlinkInScope(filepath.Join(root, path), root) } diff --git a/pkg/containerfs/containerfs_unix.go b/pkg/containerfs/containerfs_unix.go index 5a7ab97e58..3e18599989 100644 --- a/pkg/containerfs/containerfs_unix.go +++ b/pkg/containerfs/containerfs_unix.go @@ -5,7 +5,7 @@ package containerfs // import "github.com/docker/docker/pkg/containerfs" import "path/filepath" -// cleanScopedPath preappends a to combine with a mnt path. -func cleanScopedPath(path string) string { +// CleanScopedPath preappends a to combine with a mnt path. +func CleanScopedPath(path string) string { return filepath.Join(string(filepath.Separator), path) } diff --git a/pkg/containerfs/containerfs_windows.go b/pkg/containerfs/containerfs_windows.go index 9fb7084628..f4011d1203 100644 --- a/pkg/containerfs/containerfs_windows.go +++ b/pkg/containerfs/containerfs_windows.go @@ -2,9 +2,9 @@ package containerfs // import "github.com/docker/docker/pkg/containerfs" import "path/filepath" -// cleanScopedPath removes the C:\ syntax, and prepares to combine +// CleanScopedPath removes the C:\ syntax, and prepares to combine // with a volume path -func cleanScopedPath(path string) string { +func CleanScopedPath(path string) string { if len(path) >= 2 { c := path[0] if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { diff --git a/pkg/system/path.go b/pkg/system/path.go index 4d81906b9d..7561361d54 100644 --- a/pkg/system/path.go +++ b/pkg/system/path.go @@ -16,12 +16,6 @@ func DefaultPathEnv(os string) string { } -// PathVerifier defines the subset of a PathDriver that CheckSystemDriveAndRemoveDriveLetter -// actually uses in order to avoid system depending on containerd/continuity. -type PathVerifier interface { - IsAbs(string) bool -} - // CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter, // is the system drive. // On Linux: this is a no-op. @@ -37,6 +31,6 @@ type PathVerifier interface { // a --> a // /a --> \a // d:\ --> Fail -func CheckSystemDriveAndRemoveDriveLetter(path string, driver PathVerifier) (string, error) { - return checkSystemDriveAndRemoveDriveLetter(path, driver) +func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) { + return checkSystemDriveAndRemoveDriveLetter(path) } diff --git a/pkg/system/path_unix.go b/pkg/system/path_unix.go index 197a37a219..3778cf06d8 100644 --- a/pkg/system/path_unix.go +++ b/pkg/system/path_unix.go @@ -12,6 +12,6 @@ func GetLongPathName(path string) (string, error) { // checkSystemDriveAndRemoveDriveLetter is the non-Windows implementation // of CheckSystemDriveAndRemoveDriveLetter -func checkSystemDriveAndRemoveDriveLetter(path string, driver PathVerifier) (string, error) { +func checkSystemDriveAndRemoveDriveLetter(path string) (string, error) { return path, nil } diff --git a/pkg/system/path_windows.go b/pkg/system/path_windows.go index 7d375b0ddc..708702ee1c 100644 --- a/pkg/system/path_windows.go +++ b/pkg/system/path_windows.go @@ -34,11 +34,11 @@ func GetLongPathName(path string) (string, error) { // checkSystemDriveAndRemoveDriveLetter is the Windows implementation // of CheckSystemDriveAndRemoveDriveLetter -func checkSystemDriveAndRemoveDriveLetter(path string, driver PathVerifier) (string, error) { +func checkSystemDriveAndRemoveDriveLetter(path string) (string, error) { if len(path) == 2 && string(path[1]) == ":" { return "", fmt.Errorf("No relative path specified in %q", path) } - if !driver.IsAbs(path) || len(path) < 2 { + if !filepath.IsAbs(path) || len(path) < 2 { return filepath.FromSlash(path), nil } if string(path[1]) == ":" && !strings.EqualFold(string(path[0]), "c") { diff --git a/pkg/system/path_windows_test.go b/pkg/system/path_windows_test.go index 5ba2c84e39..c7cc902065 100644 --- a/pkg/system/path_windows_test.go +++ b/pkg/system/path_windows_test.go @@ -5,21 +5,19 @@ package system // import "github.com/docker/docker/pkg/system" import ( "testing" - - "github.com/containerd/continuity/pathdriver" ) // TestCheckSystemDriveAndRemoveDriveLetter tests CheckSystemDriveAndRemoveDriveLetter func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { // Fails if not C drive. - _, err := CheckSystemDriveAndRemoveDriveLetter(`d:\`, pathdriver.LocalPathDriver) + _, err := CheckSystemDriveAndRemoveDriveLetter(`d:\`) if err == nil || err.Error() != "The specified path is not on the system drive (C:)" { t.Fatalf("Expected error for d:") } // Single character is unchanged var path string - if path, err = CheckSystemDriveAndRemoveDriveLetter("z", pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter("z"); err != nil { t.Fatalf("Single character should pass") } if path != "z" { @@ -27,7 +25,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Two characters without colon is unchanged - if path, err = CheckSystemDriveAndRemoveDriveLetter("AB", pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter("AB"); err != nil { t.Fatalf("2 characters without colon should pass") } if path != "AB" { @@ -35,7 +33,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Abs path without drive letter - if path, err = CheckSystemDriveAndRemoveDriveLetter(`\l`, pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`\l`); err != nil { t.Fatalf("abs path no drive letter should pass") } if path != `\l` { @@ -43,7 +41,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Abs path without drive letter, linux style - if path, err = CheckSystemDriveAndRemoveDriveLetter(`/l`, pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`/l`); err != nil { t.Fatalf("abs path no drive letter linux style should pass") } if path != `\l` { @@ -51,7 +49,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Drive-colon should be stripped - if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:\`, pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:\`); err != nil { t.Fatalf("An absolute path should pass") } if path != `\` { @@ -59,7 +57,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Verify with a linux-style path - if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:/`, pathdriver.LocalPathDriver); err != nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:/`); err != nil { t.Fatalf("An absolute path should pass") } if path != `\` { @@ -67,7 +65,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Failure on c: - if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:`, pathdriver.LocalPathDriver); err == nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:`); err == nil { t.Fatalf("c: should fail") } if err.Error() != `No relative path specified in "c:"` { @@ -75,7 +73,7 @@ func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) { } // Failure on d: - if path, err = CheckSystemDriveAndRemoveDriveLetter(`d:`, pathdriver.LocalPathDriver); err == nil { + if path, err = CheckSystemDriveAndRemoveDriveLetter(`d:`); err == nil { t.Fatalf("c: should fail") } if err.Error() != `No relative path specified in "d:"` { diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go index 7daaf6af40..0bd7f18c39 100644 --- a/plugin/manager_linux.go +++ b/plugin/manager_linux.go @@ -12,7 +12,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/daemon/initlayer" "github.com/docker/docker/errdefs" - "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/stringid" @@ -55,7 +54,7 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error { } } - rootFS := containerfs.NewLocalContainerFS(filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName)) + rootFS := filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName) if err := initlayer.Setup(rootFS, idtools.Identity{UID: 0, GID: 0}); err != nil { return errors.WithStack(err) } diff --git a/vendor/github.com/containerd/continuity/pathdriver/path_driver.go b/vendor/github.com/containerd/continuity/pathdriver/path_driver.go deleted file mode 100644 index b0d5a6b567..0000000000 --- a/vendor/github.com/containerd/continuity/pathdriver/path_driver.go +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright The containerd 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 pathdriver - -import ( - "path/filepath" -) - -// PathDriver provides all of the path manipulation functions in a common -// interface. The context should call these and never use the `filepath` -// package or any other package to manipulate paths. -type PathDriver interface { - Join(paths ...string) string - IsAbs(path string) bool - Rel(base, target string) (string, error) - Base(path string) string - Dir(path string) string - Clean(path string) string - Split(path string) (dir, file string) - Separator() byte - Abs(path string) (string, error) - Walk(string, filepath.WalkFunc) error - FromSlash(path string) string - ToSlash(path string) string - Match(pattern, name string) (matched bool, err error) -} - -// pathDriver is a simple default implementation calls the filepath package. -type pathDriver struct{} - -// LocalPathDriver is the exported pathDriver struct for convenience. -var LocalPathDriver PathDriver = &pathDriver{} - -func (*pathDriver) Join(paths ...string) string { - return filepath.Join(paths...) -} - -func (*pathDriver) IsAbs(path string) bool { - return filepath.IsAbs(path) -} - -func (*pathDriver) Rel(base, target string) (string, error) { - return filepath.Rel(base, target) -} - -func (*pathDriver) Base(path string) string { - return filepath.Base(path) -} - -func (*pathDriver) Dir(path string) string { - return filepath.Dir(path) -} - -func (*pathDriver) Clean(path string) string { - return filepath.Clean(path) -} - -func (*pathDriver) Split(path string) (dir, file string) { - return filepath.Split(path) -} - -func (*pathDriver) Separator() byte { - return filepath.Separator -} - -func (*pathDriver) Abs(path string) (string, error) { - return filepath.Abs(path) -} - -// Note that filepath.Walk calls os.Stat, so if the context wants to -// to call Driver.Stat() for Walk, they need to create a new struct that -// overrides this method. -func (*pathDriver) Walk(root string, walkFn filepath.WalkFunc) error { - return filepath.Walk(root, walkFn) -} - -func (*pathDriver) FromSlash(path string) string { - return filepath.FromSlash(path) -} - -func (*pathDriver) ToSlash(path string) string { - return filepath.ToSlash(path) -} - -func (*pathDriver) Match(pattern, name string) (bool, error) { - return filepath.Match(pattern, name) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 90fcaeec6a..c7078e217f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -236,7 +236,6 @@ github.com/containerd/containerd/version github.com/containerd/continuity/devices github.com/containerd/continuity/driver github.com/containerd/continuity/fs -github.com/containerd/continuity/pathdriver github.com/containerd/continuity/sysx # github.com/containerd/fifo v1.0.0 ## explicit; go 1.13