github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/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 }