Skip to content

Commit

Permalink
snapdtool, many: support additional key/value flags in info file
Browse files Browse the repository at this point in the history
Also set a new key, SNAPD_APPARMOR_REEXEC, to 0 for now, since this key will be
used shortly with the new apparmor vendoring inside the snapd snap.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
  • Loading branch information
anonymouse64 committed Dec 1, 2021
1 parent 2cfed25 commit c5f3197
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 25 deletions.
4 changes: 2 additions & 2 deletions cmd/snap-preseed/preseed_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ type targetSnapdInfo struct {
func chooseTargetSnapdVersion() (*targetSnapdInfo, error) {
// read snapd version from the mounted core/snapd snap
infoPath := filepath.Join(snapdMountPath, dirs.CoreLibExecDir, "info")
verFromSnap, err := snapdtool.SnapdVersionFromInfoFile(infoPath)
verFromSnap, _, err := snapdtool.SnapdVersionFromInfoFile(infoPath)
if err != nil {
return nil, err
}

// read snapd version from the main fs under chroot (snapd from the deb);
// assumes running under chroot already.
infoPath = filepath.Join(dirs.GlobalRootDir, dirs.CoreLibExecDir, "info")
verFromDeb, err := snapdtool.SnapdVersionFromInfoFile(infoPath)
verFromDeb, _, err := snapdtool.SnapdVersionFromInfoFile(infoPath)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions mkversion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,5 @@ EOF

cat <<EOF > "$PKG_BUILDDIR/data/info"
VERSION=$v
SNAPD_APPARMOR_REEXEC=0
EOF
55 changes: 37 additions & 18 deletions snapdtool/info_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,53 @@
package snapdtool

import (
"bytes"
"bufio"
"fmt"
"io/ioutil"
"os"
"strings"
)

// SnapdVersionFromInfoFile returns snapd version read for the
// given info" file, pointed by infoPath.
// The format of the "info" file is a single line with "VERSION=..."
// in it. The file is produced by mkversion.sh and normally installed
// along snapd binary in /usr/lib/snapd.
func SnapdVersionFromInfoFile(infoPath string) (string, error) {
content, err := ioutil.ReadFile(infoPath)
// The format of the "info" file are lines with "KEY=VALUE" with the typical key
// being just VERSION. The file is produced by mkversion.sh and normally
// installed along snapd binary in /usr/lib/snapd.
// Other typical keys in this file include SNAPD_APPARMOR_REEXEC, which
// indicates whether or not the snapd-apparmor binary installed via the
// traditional linux package of snapd supports re-exec into the version in the
// snapd or core snaps.
func SnapdVersionFromInfoFile(infoPath string) (version string, flags map[string]string, err error) {
f, err := os.Open(infoPath)
if err != nil {
return "", fmt.Errorf("cannot open snapd info file %q: %s", infoPath, err)
return "", nil, fmt.Errorf("cannot open snapd info file %q: %s", infoPath, err)
}
defer f.Close()

if !bytes.HasPrefix(content, []byte("VERSION=")) {
idx := bytes.Index(content, []byte("\nVERSION="))
if idx < 0 {
return "", fmt.Errorf("cannot find snapd version information in %q", content)
flags = map[string]string{}

scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "VERSION=") {
version = strings.TrimPrefix(line, "VERSION=")
} else {
keyVal := strings.SplitN(line, "=", 2)
if len(keyVal) != 2 {
// potentially malformed line, just skip it
continue
}

flags[keyVal[0]] = keyVal[1]
}
content = content[idx+1:]
}
content = content[8:]
idx := bytes.IndexByte(content, '\n')
if idx > -1 {
content = content[:idx]

if err := scanner.Err(); err != nil {
return "", nil, fmt.Errorf("error reading snapd info file %q: %v", infoPath, err)
}

if version == "" {
return "", nil, fmt.Errorf("cannot find snapd version information in file %q", infoPath)
}

return string(content), nil
return version, flags, nil
}
21 changes: 17 additions & 4 deletions snapdtool/info_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package snapdtool_test

import (
"fmt"
"io/ioutil"
"path/filepath"

Expand All @@ -33,7 +34,7 @@ type infoFileSuite struct{}
var _ = Suite(&infoFileSuite{})

func (s *infoFileSuite) TestNoVersionFile(c *C) {
_, err := snapdtool.SnapdVersionFromInfoFile("/non-existing-file")
_, _, err := snapdtool.SnapdVersionFromInfoFile("/non-existing-file")
c.Assert(err, ErrorMatches, `cannot open snapd info file "/non-existing-file":.*`)
}

Expand All @@ -42,16 +43,28 @@ func (s *infoFileSuite) TestNoVersionData(c *C) {
infoFile := filepath.Join(top, "info")
c.Assert(ioutil.WriteFile(infoFile, []byte("foo"), 0644), IsNil)

_, err := snapdtool.SnapdVersionFromInfoFile(infoFile)
c.Assert(err, ErrorMatches, `cannot find snapd version information in "foo"`)
_, _, err := snapdtool.SnapdVersionFromInfoFile(infoFile)
c.Assert(err, ErrorMatches, fmt.Sprintf(`cannot find snapd version information in file %q`, infoFile))
}

func (s *infoFileSuite) TestVersionHappy(c *C) {
top := c.MkDir()
infoFile := filepath.Join(top, "info")
c.Assert(ioutil.WriteFile(infoFile, []byte("VERSION=1.2.3"), 0644), IsNil)

ver, err := snapdtool.SnapdVersionFromInfoFile(infoFile)
ver, flags, err := snapdtool.SnapdVersionFromInfoFile(infoFile)
c.Assert(err, IsNil)
c.Check(ver, Equals, "1.2.3")
c.Assert(flags, HasLen, 0)
}

func (s *infoFileSuite) TestInfoVersionFlags(c *C) {
top := c.MkDir()
infoFile := filepath.Join(top, "info")
c.Assert(ioutil.WriteFile(infoFile, []byte("VERSION=1.2.3\nFOO=BAR"), 0644), IsNil)

ver, flags, err := snapdtool.SnapdVersionFromInfoFile(infoFile)
c.Assert(err, IsNil)
c.Check(ver, Equals, "1.2.3")
c.Assert(flags, DeepEquals, map[string]string{"FOO": "BAR"})
}
2 changes: 1 addition & 1 deletion snapdtool/tool_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func distroSupportsReExec() bool {
// version of core that do not yet have it.
func coreSupportsReExec(coreOrSnapdPath string) bool {
infoPath := filepath.Join(coreOrSnapdPath, filepath.Join(dirs.CoreLibExecDir, "info"))
ver, err := SnapdVersionFromInfoFile(infoPath)
ver, _, err := SnapdVersionFromInfoFile(infoPath)
if err != nil {
logger.Noticef("%v", err)
return false
Expand Down

0 comments on commit c5f3197

Please sign in to comment.