blob: 72ee5d0a477761dd469303898142b0237dfc1f18 [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"
23 "io/ioutil"
24 "log"
25 "os"
26 "path"
27 "strings"
28
29 "google.golang.org/protobuf/encoding/prototext"
Serge Bazanski96043bc2021-10-05 12:10:13 +020030
Lorenz Brun30167f52021-03-17 17:49:01 +010031 "source.monogon.dev/build/static_binary_tarball/spec"
32)
33
34var (
35 specPath = flag.String("spec", "", "Path to the layer specification (spec.Spec)")
36 outPath = flag.String("out", "", "Output file path")
37)
38
39func main() {
40 flag.Parse()
41 var spec spec.Spec
42 specRaw, err := ioutil.ReadFile(*specPath)
43 if err != nil {
44 log.Fatalf("failed to open spec file: %v", err)
45 }
46 if err := prototext.Unmarshal(specRaw, &spec); err != nil {
47 log.Fatalf("failed to unmarshal spec: %v", err)
48 }
49 outFile, err := os.Create(*outPath)
50 if err != nil {
51 log.Fatalf("failed to open output: %v", err)
52 }
53 defer outFile.Close()
54 outTar := tar.NewWriter(outFile)
55 defer outTar.Close()
56 createdDirs := make(map[string]bool)
57 for _, file := range spec.File {
58 srcFile, err := os.Open(file.Src)
59 if err != nil {
60 log.Fatalf("failed to open input file: %v", err)
61 }
62 info, err := srcFile.Stat()
63 if err != nil {
64 log.Fatalf("cannot stat input file: %v", err)
65 }
66 var mode int64 = 0644
67 if info.Mode()&0111 != 0 {
68 mode = 0755
69 }
70 targetPath := path.Join("app", file.Path)
71 targetDirParts := strings.Split(path.Dir(targetPath), "/")
72 var partialDir string
73 for _, part := range targetDirParts {
74 partialDir = path.Join(partialDir, part)
75 if !createdDirs[partialDir] {
76 if err := outTar.WriteHeader(&tar.Header{
77 Typeflag: tar.TypeDir,
78 Name: partialDir,
79 Mode: 0755,
80 }); err != nil {
81 log.Fatalf("failed to write directory: %v", err)
82 }
83 createdDirs[partialDir] = true
84 }
85 }
86 if err := outTar.WriteHeader(&tar.Header{
87 Name: targetPath,
88 Size: info.Size(),
89 Mode: mode,
90 }); err != nil {
91 log.Fatalf("failed to write header: %v", err)
92 }
93 if _, err := io.Copy(outTar, srcFile); err != nil {
94 log.Fatalf("failed to copy file into tar: %v", err)
95 }
96 }
97}