Skip to content

Commit

Permalink
copier.Put: check for is-not-a-directory using lstat, not stat
Browse files Browse the repository at this point in the history
When checking if something that we want to overwrite with a directory is
already a directory or not, use lstat instead of stat.  If it's a
symbolic link, it's not a directory.

This is a subtle behavior change, but it's in line with docker build.

Signed-off-by: Nalin Dahyabhai <[email protected]>
  • Loading branch information
nalind committed Jan 24, 2022
1 parent 867c1bc commit 9091023
Show file tree
Hide file tree
Showing 7 changed files with 14 additions and 2 deletions.
4 changes: 2 additions & 2 deletions copier/copier.go
Original file line number Diff line number Diff line change
Expand Up @@ -1660,7 +1660,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM
// only check the length if there wasn't an error, which we'll
// check along with errors for other types of entries
if err == nil && written != hdr.Size {
return errors.Errorf("copier: put: error creating %q: incorrect length (%d != %d)", path, written, hdr.Size)
return errors.Errorf("copier: put: error creating regular file %q: incorrect length (%d != %d)", path, written, hdr.Size)
}
case tar.TypeLink:
var linkTarget string
Expand Down Expand Up @@ -1733,7 +1733,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM
case tar.TypeDir:
if err = os.Mkdir(path, 0700); err != nil && os.IsExist(err) {
var st os.FileInfo
if st, err = os.Stat(path); err == nil && !st.IsDir() {
if st, err = os.Lstat(path); err == nil && !st.IsDir() {
// it's not a directory, so remove it and mkdir
if err = os.Remove(path); err == nil {
err = os.Mkdir(path, 0700)
Expand Down
3 changes: 3 additions & 0 deletions copier/copier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ func testPut(t *testing.T) {
for _, typeFlag := range []byte{tar.TypeReg, tar.TypeLink, tar.TypeSymlink, tar.TypeChar, tar.TypeBlock, tar.TypeFifo} {
t.Run(fmt.Sprintf("overwrite=%v,type=%c", overwrite, typeFlag), func(t *testing.T) {
archive := makeArchiveSlice([]tar.Header{
{Name: "target", Typeflag: tar.TypeSymlink, Mode: 0755, Linkname: "target", ModTime: testDate},
{Name: "target", Typeflag: tar.TypeDir, Mode: 0755, ModTime: testDate},
{Name: "target", Typeflag: tar.TypeSymlink, Mode: 0755, Linkname: "target", ModTime: testDate},
{Name: "target", Typeflag: tar.TypeReg, Size: 123, Mode: 0755, ModTime: testDate},
{Name: "test", Typeflag: tar.TypeDir, Size: 0, Mode: 0755, ModTime: testDate},
{Name: "test", Typeflag: typeFlag, Size: 0, Mode: 0755, Linkname: "target", ModTime: testDate},
Expand Down
5 changes: 5 additions & 0 deletions tests/conformance/conformance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2870,4 +2870,9 @@ var internalTestCases = []testCase{
contextDir: "dockerignore/exceptions-skip",
fsSkip: []string{"(dir):volume:mtime"},
},

{
name: "replace-symlink-with-directory",
contextDir: "replace/symlink-with-directory",
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM scratch
COPY tree1/ /
COPY tree2/ /
Empty file.

0 comments on commit 9091023

Please sign in to comment.