mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
Where the candidate command line is based on the current internal edition of the asset. Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2020 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package bootloader
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/snapcore/snapd/bootloader/assets"
|
|
)
|
|
|
|
var errNoEdition = errors.New("no edition")
|
|
|
|
// editionFromDiskConfigAsset extracts the edition information from a boot
|
|
// config asset on disk.
|
|
func editionFromDiskConfigAsset(p string) (uint, error) {
|
|
f, err := os.Open(p)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return 0, errNoEdition
|
|
}
|
|
return 0, fmt.Errorf("cannot load existing config asset: %v", err)
|
|
}
|
|
defer f.Close()
|
|
return editionFromConfigAsset(f)
|
|
}
|
|
|
|
const editionHeader = "# Snapd-Boot-Config-Edition: "
|
|
|
|
// editionFromConfigAsset extracts edition information from boot config asset.
|
|
func editionFromConfigAsset(asset io.Reader) (uint, error) {
|
|
scanner := bufio.NewScanner(asset)
|
|
if !scanner.Scan() {
|
|
err := fmt.Errorf("cannot read config asset: unexpected EOF")
|
|
if sErr := scanner.Err(); sErr != nil {
|
|
err = fmt.Errorf("cannot read config asset: %v", err)
|
|
}
|
|
return 0, err
|
|
}
|
|
|
|
line := scanner.Text()
|
|
if !strings.HasPrefix(line, editionHeader) {
|
|
return 0, errNoEdition
|
|
}
|
|
|
|
editionStr := line[len(editionHeader):]
|
|
editionStr = strings.TrimSpace(editionStr)
|
|
edition, err := strconv.ParseUint(editionStr, 10, 32)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("cannot parse asset edition: %v", err)
|
|
}
|
|
return uint(edition), nil
|
|
}
|
|
|
|
// editionFromInternalConfigAsset extracts edition information from a named
|
|
// internal boot config asset.
|
|
func editionFromInternalConfigAsset(assetName string) (uint, error) {
|
|
data := assets.Internal(assetName)
|
|
if data == nil {
|
|
return 0, fmt.Errorf("internal error: no boot asset for %q", assetName)
|
|
}
|
|
return editionFromConfigAsset(bytes.NewReader(data))
|
|
}
|
|
|
|
// configAsset is a boot config asset, such as text script, used by grub or
|
|
// u-boot.
|
|
type configAsset struct {
|
|
body []byte
|
|
parsedEdition uint
|
|
}
|
|
|
|
func (g *configAsset) Edition() uint {
|
|
return g.parsedEdition
|
|
}
|
|
|
|
func (g *configAsset) Raw() []byte {
|
|
return g.body
|
|
}
|
|
|
|
func configAssetFrom(data []byte) (*configAsset, error) {
|
|
edition, err := editionFromConfigAsset(bytes.NewReader(data))
|
|
if err != nil && err != errNoEdition {
|
|
return nil, err
|
|
}
|
|
gbs := &configAsset{
|
|
body: data,
|
|
parsedEdition: edition,
|
|
}
|
|
return gbs, nil
|
|
}
|