Expand uncompresses and extracts a chart into the specified directory.
(dir string, r io.Reader)
| 32 | |
| 33 | // Expand uncompresses and extracts a chart into the specified directory. |
| 34 | func Expand(dir string, r io.Reader) error { |
| 35 | files, err := archive.LoadArchiveFiles(r) |
| 36 | if err != nil { |
| 37 | return err |
| 38 | } |
| 39 | |
| 40 | // Get the name of the chart |
| 41 | var chartName string |
| 42 | for _, file := range files { |
| 43 | if file.Name == "Chart.yaml" { |
| 44 | ch := &chart.Metadata{} |
| 45 | if err := yaml.Unmarshal(file.Data, ch); err != nil { |
| 46 | return fmt.Errorf("cannot load Chart.yaml: %w", err) |
| 47 | } |
| 48 | chartName = ch.Name |
| 49 | } |
| 50 | } |
| 51 | if chartName == "" { |
| 52 | return errors.New("chart name not specified") |
| 53 | } |
| 54 | |
| 55 | // Reject chart names that are POSIX path dot-segments or dot-dot segments or contain path separators. |
| 56 | // A dot-segment name (e.g. ".") causes SecureJoin to resolve to the root |
| 57 | // directory and extraction then to write files directly into that extraction root |
| 58 | // instead of a per-chart subdirectory. |
| 59 | if chartName == "." || chartName == ".." { |
| 60 | return fmt.Errorf("chart name %q is not allowed", chartName) |
| 61 | } |
| 62 | if chartName != filepath.Base(chartName) { |
| 63 | return fmt.Errorf("chart name %q must not contain path separators", chartName) |
| 64 | } |
| 65 | |
| 66 | // Find the base directory |
| 67 | // The directory needs to be cleaned prior to passing to SecureJoin or the location may end up |
| 68 | // being wrong or returning an error. This was introduced in v0.4.0. |
| 69 | dir = filepath.Clean(dir) |
| 70 | chartdir, err := securejoin.SecureJoin(dir, chartName) |
| 71 | if err != nil { |
| 72 | return err |
| 73 | } |
| 74 | |
| 75 | // Defense-in-depth: the chart directory must be a subdirectory of dir, |
| 76 | // never dir itself. |
| 77 | if chartdir == dir { |
| 78 | return fmt.Errorf("chart name %q resolves to the extraction root", chartName) |
| 79 | } |
| 80 | |
| 81 | // Copy all files verbatim. We don't parse these files because parsing can remove |
| 82 | // comments. |
| 83 | for _, file := range files { |
| 84 | outpath, err := securejoin.SecureJoin(chartdir, file.Name) |
| 85 | if err != nil { |
| 86 | return err |
| 87 | } |
| 88 | |
| 89 | // Make sure the necessary subdirs get created. |
| 90 | basedir := filepath.Dir(outpath) |
| 91 | if err := os.MkdirAll(basedir, 0755); err != nil { |
searching dependent graphs…