Пример #1
0
// isMounted returns true if the given path is a mountpoint
func isMounted(path string) (bool, error) {
	cmd := exec.Command(mountpointCmd, path)
	// mountpoint uses translated messages, ensure we get the
	// english ones
	cmd.Env = []string{"LC_ALL=C"}

	output, err := cmd.CombinedOutput()
	exitCode, err := helpers.ExitCode(err)
	// if we get anything other than "ExitError" er error here
	if err != nil {
		return false, err
	}

	// mountpoint.c from util-linux always returns 0 or 1
	// (unless e.g. signal)
	if exitCode != 0 && exitCode != 1 {
		return false, fmt.Errorf("got unexpected exit code %v from the mountpoint command: %s", exitCode, output)
	}

	// exitCode == 0 means it is a mountpoint, do we are done
	if exitCode == 0 {
		return true, nil
	}

	// exitCode == 1 either means something went wrong *or*
	//               the path is not a mount point
	//               (thanks mountpoint.c :/)
	if strings.Contains(string(output), "is not a mountpoint") {
		return false, nil
	}

	return false, fmt.Errorf("unexpected output from mountpoint: %s (%v)", output, exitCode)
}
Пример #2
0
// RefreshDependentsSecurity refreshes the security policies of dependent snaps
func (s *SnapPart) RefreshDependentsSecurity(oldPart *SnapPart, inter interacter) (err error) {
	oldBaseDir := ""
	if oldPart != nil {
		oldBaseDir = oldPart.basedir
	}
	upPol, upTpl := policy.AppArmorDelta(oldBaseDir, s.basedir, s.Name()+"_")

	deps, err := s.Dependents()
	if err != nil {
		return err
	}

	for _, dep := range deps {
		err := dep.RequestAppArmorUpdate(upPol, upTpl)
		if err != nil {
			return err
		}
	}

	cmd := exec.Command(aaClickHookCmd)
	if output, err := cmd.CombinedOutput(); err != nil {
		if exitCode, err := helpers.ExitCode(err); err == nil {
			return &ErrApparmorGenerate{
				ExitCode: exitCode,
				Output:   output,
			}
		}
		return err
	}

	return nil
}
Пример #3
0
// run calls systemctl with the given args, returning its standard output (and wrapped error)
func run(args ...string) ([]byte, error) {
	bs, err := exec.Command("systemctl", args...).CombinedOutput()
	if err != nil {
		exitCode, _ := helpers.ExitCode(err)
		return nil, &Error{cmd: args, exitCode: exitCode, msg: bs}
	}

	return bs, nil
}
Пример #4
0
func regenerateAppArmorRulesImpl() error {
	if output, err := exec.Command(aaClickHookCmd, "-f").CombinedOutput(); err != nil {
		if exitCode, err := helpers.ExitCode(err); err == nil {
			return &ErrApparmorGenerate{
				ExitCode: exitCode,
				Output:   output,
			}
		}
		return err
	}

	return nil
}
Пример #5
0
// jctl calls journalctl to get the JSON logs of the given services, wrapping the error if any.
func jctl(svcs []string) ([]byte, error) {
	cmd := []string{"journalctl", "-o", "json"}

	for i := range svcs {
		cmd = append(cmd, "-u", svcs[i])
	}

	bs, err := exec.Command(cmd[0], cmd[1:]...).Output() // journalctl can be messy with its stderr
	if err != nil {
		exitCode, _ := helpers.ExitCode(err)
		return nil, &Error{cmd: cmd, exitCode: exitCode, msg: bs}
	}

	return bs, nil
}
Пример #6
0
// Verify is a tiny wrapper around debsig-verify
func Verify(clickFile string, allowUnauthenticated bool) (err error) {
	cmd := exec.Command(VerifyCmd, clickFile)
	if err := cmd.Run(); err != nil {
		exitCode, err := helpers.ExitCode(err)
		if err == nil {
			if allowUnauthenticated && allowUnauthenticatedOkExitCode(exitCode) {
				logger.Noticef("Signature check failed, but installing anyway as requested")
				return nil
			}
			return &ErrSignature{exitCode: exitCode}
		}
		// not a exit code error, something else, pass on
		return &ErrSignature{err: err}
	}
	return nil
}
Пример #7
0
// Execute the hook.Exec command
func execHook(execCmd string) (err error) {
	// the spec says this is passed to the shell
	cmd := exec.Command("sh", "-c", execCmd)
	if output, err := cmd.CombinedOutput(); err != nil {
		if exitCode, err := helpers.ExitCode(err); err == nil {
			return &ErrHookFailed{
				Cmd:      execCmd,
				Output:   string(output),
				ExitCode: exitCode,
			}
		}
		return err
	}

	return nil
}
Пример #8
0
// Lowlevel copy the snap data (but never override existing data)
func copySnapDataDirectory(oldPath, newPath string) (err error) {
	if _, err := os.Stat(oldPath); err == nil {
		if _, err := os.Stat(newPath); err != nil {
			// there is no golang "CopyFile"
			cmd := exec.Command("cp", "-a", oldPath, newPath)
			if err := cmd.Run(); err != nil {
				if exitCode, err := helpers.ExitCode(err); err == nil {
					return &ErrDataCopyFailed{
						OldPath:  oldPath,
						NewPath:  newPath,
						ExitCode: exitCode}
				}
				return err
			}
		}
	}
	return nil
}
Пример #9
0
func systemImageDownloadUpdate(configDir string, pb progress.Meter) (err error) {
	cmd := exec.Command(systemImageCli, "--progress", "json", "-C", configDir)

	// collect progress over stdout pipe if we want progress
	var stdout io.Reader
	stdout, err = cmd.StdoutPipe()
	if err != nil {
		return err
	}

	// collect error message (traceback etc in a separate goroutine)
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	stderrCh := make(chan []byte)
	go func() {
		stderrContent, _ := ioutil.ReadAll(stderr)
		stderrCh <- stderrContent
	}()

	// run it
	if err := cmd.Start(); err != nil {
		return err
	}

	// and parse progress synchronously
	if err := parseSIProgress(pb, stdout); err != nil {
		return err
	}

	// we need to read all of stderr *before* calling cmd.Wait() to avoid
	// a race, see docs for "os/exec:func (*Cmd) StdoutPipe"
	stderrContent := <-stderrCh
	if err := cmd.Wait(); err != nil {
		retCode, _ := helpers.ExitCode(err)
		return fmt.Errorf("%s failed with return code %v: %s", systemImageCli, retCode, string(stderrContent))
	}

	return err
}