Keep directories when moving glob results

Patterns containing multiple globs or a recurisve glob may match
files with the same name in multiple directories.  Keep the relative
directories of matches after the path entry containing a glob.

Bug: 117295826
Test: zip2zip_test.go
Change-Id: I5d663e546953af374175837551d23f484d568377
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index c4fb3d6..491267b 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -148,8 +148,13 @@
 				} else {
 					if pathtools.IsGlob(input) {
 						// If the input is a glob then the output is a directory.
-						_, name := filepath.Split(file.Name)
-						newName = filepath.Join(output, name)
+						rel, err := filepath.Rel(constantPartOfPattern(input), file.Name)
+						if err != nil {
+							return err
+						} else if strings.HasPrefix("../", rel) {
+							return fmt.Errorf("globbed path %q was not in %q", file.Name, constantPartOfPattern(input))
+						}
+						newName = filepath.Join(output, rel)
 					} else {
 						// Otherwise it is a file.
 						newName = output
@@ -277,3 +282,24 @@
 	}
 	return false, nil
 }
+
+func constantPartOfPattern(pattern string) string {
+	ret := ""
+	for pattern != "" {
+		var first string
+		first, pattern = splitFirst(pattern)
+		if pathtools.IsGlob(first) {
+			return ret
+		}
+		ret = filepath.Join(ret, first)
+	}
+	return ret
+}
+
+func splitFirst(path string) (string, string) {
+	i := strings.IndexRune(path, filepath.Separator)
+	if i < 0 {
+		return path, ""
+	}
+	return path[:i], path[i+1:]
+}