Esempio n. 1
0
func snapExecHook(snapName, revision, hookName string) error {
	rev, err := snap.ParseRevision(revision)
	if err != nil {
		return err
	}

	info, err := snap.ReadInfo(snapName, &snap.SideInfo{
		Revision: rev,
	})
	if err != nil {
		return err
	}

	hook := info.Hooks[hookName]
	if hook == nil {
		return fmt.Errorf("cannot find hook %q in %q", hookName, snapName)
	}

	// build the environment
	env := append(os.Environ(), hook.Env()...)

	// run the hook
	hookPath := filepath.Join(hook.Snap.HooksDir(), hook.Name)
	return syscallExec(hookPath, []string{hookPath}, env)
}
Esempio n. 2
0
func nameAndRevnoFromSnap(sn string) (string, snap.Revision, error) {
	l := strings.Split(sn, "_")
	if len(l) < 2 {
		return "", snap.Revision{}, fmt.Errorf("input %q has invalid format (not enough '_')", sn)
	}
	name := l[0]
	revnoNSuffix := l[1]
	rev, err := snap.ParseRevision(strings.Split(revnoNSuffix, ".snap")[0])
	if err != nil {
		return "", snap.Revision{}, err
	}
	return name, rev, nil
}
Esempio n. 3
0
func (x *cmdDownload) Execute(args []string) error {
	if err := x.setChannelFromCommandline(); err != nil {
		return err
	}

	if len(args) > 0 {
		return ErrExtraArgs
	}

	var revision snap.Revision
	if x.Revision == "" {
		revision = snap.R(0)
	} else {
		var err error
		revision, err = snap.ParseRevision(x.Revision)
		if err != nil {
			return err
		}
	}

	snapName := string(x.Positional.Snap)

	// FIXME: set auth context
	var authContext auth.AuthContext
	var user *auth.UserState

	sto := store.New(nil, authContext)
	// we always allow devmode for downloads
	devMode := true

	dlOpts := image.DownloadOptions{
		TargetDir: "", // cwd
		DevMode:   devMode,
		Channel:   x.Channel,
		User:      user,
	}

	fmt.Fprintf(Stderr, i18n.G("Fetching snap %q\n"), snapName)
	snapPath, snapInfo, err := image.DownloadSnap(sto, snapName, revision, &dlOpts)
	if err != nil {
		return err
	}

	fmt.Fprintf(Stderr, i18n.G("Fetching assertions for %q\n"), snapName)
	err = fetchSnapAssertions(sto, snapPath, snapInfo, &dlOpts)
	if err != nil {
		return err
	}

	return nil
}
Esempio n. 4
0
func snapExecApp(snapApp, revision, command string, args []string) error {
	rev, err := snap.ParseRevision(revision)
	if err != nil {
		return fmt.Errorf("cannot parse revision %q: %s", revision, err)
	}

	snapName, appName := snap.SplitSnapApp(snapApp)
	info, err := snap.ReadInfo(snapName, &snap.SideInfo{
		Revision: rev,
	})
	if err != nil {
		return fmt.Errorf("cannot read info for %q: %s", snapName, err)
	}

	app := info.Apps[appName]
	if app == nil {
		return fmt.Errorf("cannot find app %q in %q", appName, snapName)
	}

	cmdAndArgs, err := findCommand(app, command)
	if err != nil {
		return err
	}
	// strings.Split() is ok here because we validate all app fields
	// and the whitelist is pretty strict (see
	// snap/validate.go:appContentWhitelist)
	cmdArgv := strings.Split(cmdAndArgs, " ")
	cmd := cmdArgv[0]
	cmdArgs := cmdArgv[1:]

	// build the environment from the yaml
	env := append(os.Environ(), app.Env()...)

	// run the command
	fullCmd := filepath.Join(app.Snap.MountDir(), cmd)
	if command == "shell" {
		fullCmd = "/bin/bash"
		cmdArgs = nil
	}
	fullCmdArgs := []string{fullCmd}
	fullCmdArgs = append(fullCmdArgs, cmdArgs...)
	fullCmdArgs = append(fullCmdArgs, args...)
	if err := syscallExec(fullCmd, fullCmdArgs, env); err != nil {
		return fmt.Errorf("cannot exec %q: %s", fullCmd, err)
	}
	// this is never reached except in tests
	return nil
}
Esempio n. 5
0
func snapRunHook(snapName, snapRevision, hookName string) error {
	revision, err := snap.ParseRevision(snapRevision)
	if err != nil {
		return err
	}

	info, err := getSnapInfo(snapName, revision)
	if err != nil {
		return err
	}

	hook := info.Hooks[hookName]
	if hook == nil {
		return fmt.Errorf(i18n.G("cannot find hook %q in %q"), hookName, snapName)
	}

	return runSnapConfine(info, hook.SecurityTag(), snapName, "", hook.Name, nil)
}
Esempio n. 6
0
func snapRunHook(snapName, snapRevision, hookName string) error {
	revision, err := snap.ParseRevision(snapRevision)
	if err != nil {
		return err
	}

	info, err := getSnapInfo(snapName, revision)
	if err != nil {
		return err
	}

	hook := info.Hooks[hookName]

	// Make sure this hook is valid for this snap. If not, don't run it. This
	// isn't an error, e.g. it will happen if a snap doesn't ship a system hook.
	if hook == nil {
		return nil
	}

	return runSnapConfine(info, hook.SecurityTag(), snapName, "", hook.Name, nil)
}
Esempio n. 7
0
func (s revisionSuite) ParseRevision(c *C) {
	type testItem struct {
		s string
		n int
		e string
	}

	var tests = []testItem{{
		s: "unset",
		n: 0,
	}, {
		s: "x1",
		n: -1,
	}, {
		s: "1",
		n: 1,
	}, {
		s: "x-1",
		e: `invalid snap revision: "x-1"`,
	}, {
		s: "x0",
		e: `invalid snap revision: "x0"`,
	}, {
		s: "-1",
		e: `invalid snap revision: "-1"`,
	}, {
		s: "0",
		e: `invalid snap revision: "0"`,
	}}

	for _, test := range tests {
		r, err := snap.ParseRevision(test.s)
		if test.e != "" {
			c.Assert(err.Error(), Equals, test.e)
			continue
		}
		c.Assert(r, Equals, snap.R(test.n))
	}
}
Esempio n. 8
0
func getSnapInfo(snapName string, revision snap.Revision) (*snap.Info, error) {
	if revision.Unset() {
		curFn := filepath.Join(dirs.SnapMountDir, snapName, "current")
		realFn, err := os.Readlink(curFn)
		if err != nil {
			return nil, fmt.Errorf("cannot find current revision for snap %s: %s", snapName, err)
		}
		rev := filepath.Base(realFn)
		revision, err = snap.ParseRevision(rev)
		if err != nil {
			return nil, fmt.Errorf("cannot read revision %s: %s", rev, err)
		}
	}

	info, err := snap.ReadInfo(snapName, &snap.SideInfo{
		Revision: revision,
	})
	if err != nil {
		return nil, err
	}

	return info, nil
}
Esempio n. 9
0
func copySnap(snapName, targetDir string) (*info, error) {
	baseDir := filepath.Join(dirs.SnapMountDir, snapName)
	if _, err := os.Stat(baseDir); err != nil {
		return nil, err
	}
	sourceDir := filepath.Join(baseDir, "current")
	files, err := filepath.Glob(filepath.Join(sourceDir, "*"))
	if err != nil {
		return nil, err
	}

	revnoDir, err := filepath.EvalSymlinks(sourceDir)
	if err != nil {
		return nil, err
	}
	origRevision := filepath.Base(revnoDir)

	for _, m := range files {
		if err = exec.Command("sudo", "cp", "-a", m, targetDir).Run(); err != nil {
			return nil, err

		}
	}

	rev, err := snap.ParseRevision(origRevision)
	if err != nil {
		return nil, err
	}

	place := snap.MinimalPlaceInfo(snapName, rev)
	origDigest, origSize, err := asserts.SnapFileSHA3_384(place.MountFile())
	if err != nil {
		return nil, err
	}

	return &info{revision: origRevision, size: origSize, digest: origDigest}, nil
}