github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/bootloader/assets/genasset/main.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package main
    21  
    22  import (
    23  	"bytes"
    24  	"flag"
    25  	"fmt"
    26  	"io"
    27  	"os"
    28  	"strconv"
    29  	"text/template"
    30  	"time"
    31  
    32  	"github.com/snapcore/snapd/osutil"
    33  )
    34  
    35  var assetTemplateText = `// -*- Mode: Go; indent-tabs-mode: t -*-
    36  
    37  /*
    38   * Copyright (C) {{ .Year }} Canonical Ltd
    39   *
    40   * This program is free software: you can redistribute it and/or modify
    41   * it under the terms of the GNU General Public License version 3 as
    42   * published by the Free Software Foundation.
    43   *
    44   * This program is distributed in the hope that it will be useful,
    45   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    46   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    47   * GNU General Public License for more details.
    48   *
    49   * You should have received a copy of the GNU General Public License
    50   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    51   *
    52   */
    53  
    54  package assets
    55  
    56  // Code generated from {{ .InputFileName }} DO NOT EDIT
    57  
    58  func init() {
    59  	registerInternal("{{ .AssetName }}", []byte{
    60  {{ range .AssetDataLines }}		{{ . }}
    61  {{ end }}	})
    62  }
    63  `
    64  
    65  var inFile = flag.String("in", "", "asset input file")
    66  var outFile = flag.String("out", "", "asset output file")
    67  var assetName = flag.String("name", "", "asset name")
    68  var assetTemplate = template.Must(template.New("asset").Parse(assetTemplateText))
    69  
    70  // formatLines generates a list of strings, each carrying a line containing hex
    71  // encoded data
    72  func formatLines(data []byte) []string {
    73  	const lineBreak = 16
    74  
    75  	l := len(data)
    76  	lines := make([]string, 0, l/lineBreak+1)
    77  	for i := 0; i < l; i = i + lineBreak {
    78  		end := i + lineBreak
    79  		start := i
    80  		if end > l {
    81  			end = l
    82  		}
    83  		var line bytes.Buffer
    84  		forLine := data[start:end]
    85  		for idx, val := range forLine {
    86  			line.WriteString(fmt.Sprintf("0x%02x,", val))
    87  			if idx != len(forLine)-1 {
    88  				line.WriteRune(' ')
    89  			}
    90  		}
    91  		lines = append(lines, line.String())
    92  	}
    93  	return lines
    94  }
    95  
    96  func run(assetName, inputFile, outputFile string) error {
    97  	inf, err := os.Open(inputFile)
    98  	if err != nil {
    99  		return fmt.Errorf("cannot open input file: %v", err)
   100  	}
   101  	defer inf.Close()
   102  
   103  	var inData bytes.Buffer
   104  	if _, err := io.Copy(&inData, inf); err != nil {
   105  		return fmt.Errorf("cannot copy input data: %v", err)
   106  	}
   107  
   108  	outf, err := osutil.NewAtomicFile(outputFile, 0644, 0, osutil.NoChown, osutil.NoChown)
   109  	if err != nil {
   110  		return fmt.Errorf("cannot open output file: %v", err)
   111  	}
   112  	defer outf.Cancel()
   113  
   114  	templateData := struct {
   115  		Comment        string
   116  		InputFileName  string
   117  		AssetName      string
   118  		AssetDataLines []string
   119  		Year           string
   120  	}{
   121  		InputFileName: inputFile,
   122  		// dealing with precise formatting in template is annoying thus
   123  		// we use a preformatted lines carrying asset data
   124  		AssetDataLines: formatLines(inData.Bytes()),
   125  		AssetName:      assetName,
   126  		Year:           strconv.Itoa(time.Now().Year()),
   127  	}
   128  	if err := assetTemplate.Execute(outf, &templateData); err != nil {
   129  		return fmt.Errorf("cannot generate content: %v", err)
   130  	}
   131  	return outf.Commit()
   132  }
   133  
   134  func parseArgs() error {
   135  	flag.Parse()
   136  	if *inFile == "" {
   137  		return fmt.Errorf("input file not provided")
   138  	}
   139  	if *outFile == "" {
   140  		return fmt.Errorf("output file not provided")
   141  	}
   142  	if *assetName == "" {
   143  		return fmt.Errorf("asset name not provided")
   144  	}
   145  	return nil
   146  }
   147  
   148  func main() {
   149  	if err := parseArgs(); err != nil {
   150  		fmt.Fprintln(os.Stderr, err)
   151  		os.Exit(1)
   152  	}
   153  	if err := run(*assetName, *inFile, *outFile); err != nil {
   154  		fmt.Fprintf(os.Stderr, "error: %v\n", err)
   155  		os.Exit(1)
   156  	}
   157  }