9 // Get the first file path component. We can't use filepath.Split because that breaks off the last
10 // one. We could optimize this to avoid allocating a slice down the track.
11 func firstComponent(filePath string) string {
12 return strings.SplitN(filePath, string(filepath.Separator), 2)[0]
15 // Combines file info path components, ensuring the result won't escape into parent directories.
16 func ToSafeFilePath(fileInfoComponents ...string) (string, error) {
17 safeComps := make([]string, 0, len(fileInfoComponents))
18 for _, comp := range fileInfoComponents {
19 safeComps = append(safeComps, filepath.Clean(comp))
21 safeFilePath := filepath.Join(safeComps...)
22 fc := firstComponent(safeFilePath)
25 return "", errors.New("escapes root dir")
27 return safeFilePath, nil