diff --git a/cli/command/container/create.go b/cli/command/container/create.go index 122d15e2e149..cb67b964b178 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -198,14 +198,21 @@ func newCIDFile(cidPath string) (*cidFile, error) { if cidPath == "" { return &cidFile{}, nil } - if _, err := os.Stat(cidPath); err == nil { - return nil, errors.New("container ID file found, make sure the other container isn't running or delete " + cidPath) + // mktemp (and similar) create an empty file first. Only refuse the path + // when it already holds a container ID from another run. + f, err := os.OpenFile(cidPath, os.O_RDWR|os.O_CREATE, 0o644) + if err != nil { + return nil, fmt.Errorf("failed to create the container ID file: %w", err) } - - f, err := os.Create(cidPath) + st, err := f.Stat() if err != nil { + _ = f.Close() return nil, fmt.Errorf("failed to create the container ID file: %w", err) } + if st.Size() > 0 { + _ = f.Close() + return nil, errors.New("container ID file found, make sure the other container isn't running or delete " + cidPath) + } return &cidFile{path: cidPath, file: f}, nil } diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 1c6ec9264975..67c66f00c2ed 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -37,11 +37,27 @@ func TestCIDFileNoOPWithNoFilename(t *testing.T) { func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) { tempfile := fs.NewFile(t, "test-cid-file") defer tempfile.Remove() + assert.NilError(t, os.WriteFile(tempfile.Path(), []byte("already-running"), 0o644)) _, err := newCIDFile(tempfile.Path()) assert.ErrorContains(t, err, "container ID file found") } +func TestNewCIDFileWhenEmptyFileExists(t *testing.T) { + tempfile := fs.NewFile(t, "test-cid-file") + defer tempfile.Remove() + + file, err := newCIDFile(tempfile.Path()) + assert.NilError(t, err) + + assert.NilError(t, file.Write("id")) + assert.NilError(t, file.Close()) + + actual, err := os.ReadFile(tempfile.Path()) + assert.NilError(t, err) + assert.Check(t, is.Equal("id", string(actual))) +} + func TestCIDFileCloseWithNoWrite(t *testing.T) { // Closing should remove the file if it was not written to. t.Run("closing should remove file", func(t *testing.T) {