// 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) }
// 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 }
// 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 }
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 }
// 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 }
// 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 }
// 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 }
// 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 }
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 }