pkg/fileutils: move ReadSymlinkedDirectory internal to daemon

It has no external consumers, is written with specific behavior (including
some potentially surprising behavior), making it not a good candidate to
carry in the module.

This moves it internal to the daemon as a non-exported utility, so that
it's only accessible where it's currently used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-07-29 11:03:10 +02:00
parent bae46854c5
commit ae0a3d6918
4 changed files with 61 additions and 54 deletions

View File

@@ -18,7 +18,6 @@ import (
"github.com/docker/docker/daemon/container"
"github.com/docker/docker/daemon/internal/mounttree"
"github.com/docker/docker/daemon/internal/unshare"
"github.com/docker/docker/pkg/fileutils"
containertypes "github.com/moby/moby/api/types/container"
)
@@ -104,7 +103,7 @@ func (daemon *Daemon) openContainerFS(ctr *container.Container) (_ *containerFSV
if err != nil {
return err
}
if err := fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
return err
}
@@ -252,6 +251,27 @@ func (vw *containerFSView) Stat(ctx context.Context, path string) (*containertyp
return stat, err
}
// createIfNotExists creates a file or a directory only if it does not already exist.
func createIfNotExists(dest string, isDir bool) error {
if _, err := os.Stat(dest); err != nil {
// FIXME(thaJeztah): this ignores any other error (which may include "dest" is of the wrong type, or permission errors).
if os.IsNotExist(err) {
if isDir {
return os.MkdirAll(dest, 0o755)
}
if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
return err
}
f, err := os.OpenFile(dest, os.O_CREATE, 0o755)
if err != nil {
return err
}
_ = f.Close()
}
}
return nil
}
// makeMountRRO makes the mount recursively read-only.
func makeMountRRO(dest string) error {
attr := &unix.MountAttr{

View File

@@ -0,0 +1,39 @@
package daemon
import (
"os"
"path/filepath"
"testing"
"gotest.tools/v3/assert"
)
func TestCreateIfNotExists(t *testing.T) {
t.Run("directory", func(t *testing.T) {
toCreate := filepath.Join(t.TempDir(), "tocreate")
err := createIfNotExists(toCreate, true)
assert.NilError(t, err)
fileinfo, err := os.Stat(toCreate)
assert.NilError(t, err, "Did not create destination")
assert.Assert(t, fileinfo.IsDir(), "Should have been a dir, seems it's not")
err = createIfNotExists(toCreate, true)
assert.NilError(t, err, "Should not fail if already exists")
})
t.Run("file", func(t *testing.T) {
toCreate := filepath.Join(t.TempDir(), "file/to/create")
err := createIfNotExists(toCreate, false)
assert.NilError(t, err)
fileinfo, err := os.Stat(toCreate)
assert.NilError(t, err, "Did not create destination")
assert.Assert(t, !fileinfo.IsDir(), "Should have been a file, but created a directory")
err = createIfNotExists(toCreate, true)
assert.NilError(t, err, "Should not fail if already exists")
})
}

View File

@@ -27,23 +27,3 @@ func ReadSymlinkedDirectory(path string) (realPath string, _ error) {
}
return realPath, nil
}
// CreateIfNotExists creates a file or a directory only if it does not already exist.
func CreateIfNotExists(path string, isDir bool) error {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
if isDir {
return os.MkdirAll(path, 0o755)
}
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
f, err := os.OpenFile(path, os.O_CREATE, 0o755)
if err != nil {
return err
}
_ = f.Close()
}
}
return nil
}

View File

@@ -107,35 +107,3 @@ func TestReadSymlinkedDirectoryToFile(t *testing.T) {
t.Errorf("failed to remove symlink: %s", err)
}
}
func TestCreateIfNotExistsDir(t *testing.T) {
folderToCreate := filepath.Join(t.TempDir(), "tocreate")
if err := CreateIfNotExists(folderToCreate, true); err != nil {
t.Fatal(err)
}
fileinfo, err := os.Stat(folderToCreate)
if err != nil {
t.Fatalf("Should have create a folder, got %v", err)
}
if !fileinfo.IsDir() {
t.Errorf("Should have been a dir, seems it's not")
}
}
func TestCreateIfNotExistsFile(t *testing.T) {
fileToCreate := filepath.Join(t.TempDir(), "file/to/create")
if err := CreateIfNotExists(fileToCreate, false); err != nil {
t.Error(err)
}
fileinfo, err := os.Stat(fileToCreate)
if err != nil {
t.Fatalf("Should have create a file, got %v", err)
}
if fileinfo.IsDir() {
t.Errorf("Should have been a file, seems it's not")
}
}