blob: b7b36123bc932b5abde5cacc9390a64bd2c4e6f5 [file] [log] [blame]
Lorenz Brun30167f52021-03-17 17:49:01 +01001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package main
18
19import (
20 "archive/tar"
21 "flag"
22 "io"
Lorenz Brun30167f52021-03-17 17:49:01 +010023 "log"
24 "os"
25 "path"
26 "strings"
27
28 "google.golang.org/protobuf/encoding/prototext"
Serge Bazanski96043bc2021-10-05 12:10:13 +020029
Lorenz Brun30167f52021-03-17 17:49:01 +010030 "source.monogon.dev/build/static_binary_tarball/spec"
31)
32
33var (
34 specPath = flag.String("spec", "", "Path to the layer specification (spec.Spec)")
35 outPath = flag.String("out", "", "Output file path")
36)
37
38func main() {
39 flag.Parse()
40 var spec spec.Spec
Lorenz Brun764a2de2021-11-22 16:26:36 +010041 specRaw, err := os.ReadFile(*specPath)
Lorenz Brun30167f52021-03-17 17:49:01 +010042 if err != nil {
43 log.Fatalf("failed to open spec file: %v", err)
44 }
45 if err := prototext.Unmarshal(specRaw, &spec); err != nil {
46 log.Fatalf("failed to unmarshal spec: %v", err)
47 }
48 outFile, err := os.Create(*outPath)
49 if err != nil {
50 log.Fatalf("failed to open output: %v", err)
51 }
52 defer outFile.Close()
53 outTar := tar.NewWriter(outFile)
54 defer outTar.Close()
55 createdDirs := make(map[string]bool)
56 for _, file := range spec.File {
57 srcFile, err := os.Open(file.Src)
58 if err != nil {
59 log.Fatalf("failed to open input file: %v", err)
60 }
61 info, err := srcFile.Stat()
62 if err != nil {
63 log.Fatalf("cannot stat input file: %v", err)
64 }
65 var mode int64 = 0644
66 if info.Mode()&0111 != 0 {
67 mode = 0755
68 }
69 targetPath := path.Join("app", file.Path)
70 targetDirParts := strings.Split(path.Dir(targetPath), "/")
71 var partialDir string
72 for _, part := range targetDirParts {
73 partialDir = path.Join(partialDir, part)
74 if !createdDirs[partialDir] {
75 if err := outTar.WriteHeader(&tar.Header{
76 Typeflag: tar.TypeDir,
77 Name: partialDir,
78 Mode: 0755,
79 }); err != nil {
80 log.Fatalf("failed to write directory: %v", err)
81 }
82 createdDirs[partialDir] = true
83 }
84 }
85 if err := outTar.WriteHeader(&tar.Header{
86 Name: targetPath,
87 Size: info.Size(),
88 Mode: mode,
89 }); err != nil {
90 log.Fatalf("failed to write header: %v", err)
91 }
92 if _, err := io.Copy(outTar, srcFile); err != nil {
93 log.Fatalf("failed to copy file into tar: %v", err)
94 }
95 }
96}