github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/installer/lib.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "fmt" 7 "io" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 "syscall" 13 14 "github.com/Cloud-Foundations/Dominator/lib/log" 15 ) 16 17 type writeCloser struct{} 18 19 func create(filename string) (io.WriteCloser, error) { 20 if *dryRun { 21 return &writeCloser{}, nil 22 } 23 return os.Create(filename) 24 } 25 26 func findExecutable(rootDir, file string) error { 27 if d, err := os.Stat(filepath.Join(rootDir, file)); err != nil { 28 return err 29 } else { 30 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 31 return nil 32 } 33 return os.ErrPermission 34 } 35 } 36 37 func lookPath(rootDir, file string) (string, error) { 38 if strings.Contains(file, "/") { 39 if err := findExecutable(rootDir, file); err != nil { 40 return "", err 41 } 42 return file, nil 43 } 44 path := os.Getenv("PATH") 45 for _, dir := range filepath.SplitList(path) { 46 if dir == "" { 47 dir = "." // Unix shell semantics: path element "" means "." 48 } 49 path := filepath.Join(dir, file) 50 if err := findExecutable(rootDir, path); err == nil { 51 return path, nil 52 } 53 } 54 return "", fmt.Errorf("(chroot=%s) %s not found in PATH", rootDir, file) 55 } 56 57 func run(name, chroot string, logger log.DebugLogger, args ...string) error { 58 if *dryRun { 59 logger.Debugf(0, "dry run: skipping: %s %s\n", 60 name, strings.Join(args, " ")) 61 return nil 62 } 63 path, err := lookPath(chroot, name) 64 if err != nil { 65 return err 66 } 67 cmd := exec.Command(path, args...) 68 if chroot != "" { 69 cmd.Dir = "/" 70 cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: chroot} 71 logger.Debugf(0, "running(chroot=%s): %s %s\n", 72 chroot, name, strings.Join(args, " ")) 73 } else { 74 logger.Debugf(0, "running: %s %s\n", name, strings.Join(args, " ")) 75 } 76 if output, err := cmd.CombinedOutput(); err != nil { 77 return fmt.Errorf("error running: %s: %s", name, output) 78 } else { 79 return nil 80 } 81 } 82 83 func (wc *writeCloser) Close() error { 84 return nil 85 } 86 87 func (wc *writeCloser) Write(p []byte) (int, error) { 88 return len(p), nil 89 }