blob: 88f4cc3d6f8fb50458ce676da4bc6c1ef8ed28cf [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
Lorenz Brun30167f52021-03-17 17:49:01 +01002// SPDX-License-Identifier: Apache-2.0
Lorenz Brun30167f52021-03-17 17:49:01 +01003
4package main
5
6import (
7 "archive/tar"
8 "flag"
9 "io"
Lorenz Brun30167f52021-03-17 17:49:01 +010010 "log"
11 "os"
12 "path"
13 "strings"
14
15 "google.golang.org/protobuf/encoding/prototext"
Serge Bazanski96043bc2021-10-05 12:10:13 +020016
Jan Schär06341a62025-07-09 08:02:35 +000017 "source.monogon.dev/build/binary_tarball/spec"
Lorenz Brun30167f52021-03-17 17:49:01 +010018)
19
20var (
21 specPath = flag.String("spec", "", "Path to the layer specification (spec.Spec)")
22 outPath = flag.String("out", "", "Output file path")
23)
24
25func main() {
26 flag.Parse()
27 var spec spec.Spec
Lorenz Brun764a2de2021-11-22 16:26:36 +010028 specRaw, err := os.ReadFile(*specPath)
Lorenz Brun30167f52021-03-17 17:49:01 +010029 if err != nil {
30 log.Fatalf("failed to open spec file: %v", err)
31 }
32 if err := prototext.Unmarshal(specRaw, &spec); err != nil {
33 log.Fatalf("failed to unmarshal spec: %v", err)
34 }
35 outFile, err := os.Create(*outPath)
36 if err != nil {
37 log.Fatalf("failed to open output: %v", err)
38 }
39 defer outFile.Close()
40 outTar := tar.NewWriter(outFile)
41 defer outTar.Close()
42 createdDirs := make(map[string]bool)
43 for _, file := range spec.File {
44 srcFile, err := os.Open(file.Src)
45 if err != nil {
46 log.Fatalf("failed to open input file: %v", err)
47 }
48 info, err := srcFile.Stat()
49 if err != nil {
50 log.Fatalf("cannot stat input file: %v", err)
51 }
52 var mode int64 = 0644
53 if info.Mode()&0111 != 0 {
54 mode = 0755
55 }
56 targetPath := path.Join("app", file.Path)
57 targetDirParts := strings.Split(path.Dir(targetPath), "/")
58 var partialDir string
59 for _, part := range targetDirParts {
60 partialDir = path.Join(partialDir, part)
61 if !createdDirs[partialDir] {
62 if err := outTar.WriteHeader(&tar.Header{
63 Typeflag: tar.TypeDir,
64 Name: partialDir,
65 Mode: 0755,
66 }); err != nil {
67 log.Fatalf("failed to write directory: %v", err)
68 }
69 createdDirs[partialDir] = true
70 }
71 }
72 if err := outTar.WriteHeader(&tar.Header{
73 Name: targetPath,
74 Size: info.Size(),
75 Mode: mode,
76 }); err != nil {
77 log.Fatalf("failed to write header: %v", err)
78 }
79 if _, err := io.Copy(outTar, srcFile); err != nil {
80 log.Fatalf("failed to copy file into tar: %v", err)
81 }
82 }
83}