diff --git a/txtar.go b/txtar.go index 591dcbf..afd3b53 100644 --- a/txtar.go +++ b/txtar.go @@ -29,6 +29,9 @@ func (fs *fileSet) Data(filename string) []byte { return fs.m[filename] } // Num returns the number of files in the set. func (fs *fileSet) Num() int { return len(fs.m) } +// Files returns the filenames in user-provided order. +func (fs *fileSet) Files() []string { return fs.files } + // Contains reports whether fs contains the given filename. func (fs *fileSet) Contains(filename string) bool { _, ok := fs.m[filename] @@ -113,6 +116,15 @@ func splitFiles(src []byte) (*fileSet, error) { } fs.AddFile(f.Name, f.Data) } + for _, filename := range fs.Files() { + parts := strings.Split(filename, "/") + for i := 1; i < len(parts); i++ { + dirname := path.Join(parts[:i]...) + if fs.Contains(dirname) { + return nil, fmt.Errorf("conflict file/dir name %q and %q", dirname, filename) + } + } + } return fs, nil } diff --git a/txtar_test.go b/txtar_test.go index 493d140..e895e14 100644 --- a/txtar_test.go +++ b/txtar_test.go @@ -117,6 +117,16 @@ func TestSplitFiles(t *testing.T) { in: strings.Repeat("-- x.go --\n", 50), wantErr: `too many files in txtar archive (50 exceeds limit of 20)`, }, + { + name: "reject file overwritten by dir", + in: "-- a --\n-- a/b --\n", + wantErr: `conflict file/dir name "a" and "a/b"`, + }, + { + name: "reject dir overwritten by file", + in: "-- a/b --\n-- a --\n", + wantErr: `conflict file/dir name "a" and "a/b"`, + }, } { got, err := splitFiles([]byte(tt.in)) var gotErr string