github.com/vipernet-xyz/tm@v0.34.24/libs/os/os.go (about) 1 package os 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "os" 8 "os/signal" 9 "syscall" 10 11 "github.com/vipernet-xyz/tm/libs/log" 12 ) 13 14 type logger interface { 15 Info(msg string, keyvals ...interface{}) 16 } 17 18 // TrapSignal catches the SIGTERM/SIGINT and executes cb function. After that it exits 19 // with code 0. 20 func TrapSignal(logger logger, cb func()) { 21 c := make(chan os.Signal, 1) 22 signal.Notify(c, os.Interrupt, syscall.SIGTERM) 23 go func() { 24 for sig := range c { 25 logger.Info("signal trapped", "msg", log.NewLazySprintf("captured %v, exiting...", sig)) 26 if cb != nil { 27 cb() 28 } 29 os.Exit(0) 30 } 31 }() 32 } 33 34 // Kill the running process by sending itself SIGTERM. 35 func Kill() error { 36 p, err := os.FindProcess(os.Getpid()) 37 if err != nil { 38 return err 39 } 40 return p.Signal(syscall.SIGTERM) 41 } 42 43 func Exit(s string) { 44 fmt.Printf(s + "\n") 45 os.Exit(1) 46 } 47 48 // EnsureDir ensures the given directory exists, creating it if necessary. 49 // Errors if the path already exists as a non-directory. 50 func EnsureDir(dir string, mode os.FileMode) error { 51 err := os.MkdirAll(dir, mode) 52 if err != nil { 53 return fmt.Errorf("could not create directory %q: %w", dir, err) 54 } 55 return nil 56 } 57 58 func FileExists(filePath string) bool { 59 _, err := os.Stat(filePath) 60 return !os.IsNotExist(err) 61 } 62 63 func ReadFile(filePath string) ([]byte, error) { 64 return os.ReadFile(filePath) 65 } 66 67 func MustReadFile(filePath string) []byte { 68 fileBytes, err := os.ReadFile(filePath) 69 if err != nil { 70 Exit(fmt.Sprintf("MustReadFile failed: %v", err)) 71 return nil 72 } 73 return fileBytes 74 } 75 76 func WriteFile(filePath string, contents []byte, mode os.FileMode) error { 77 return os.WriteFile(filePath, contents, mode) 78 } 79 80 func MustWriteFile(filePath string, contents []byte, mode os.FileMode) { 81 err := WriteFile(filePath, contents, mode) 82 if err != nil { 83 Exit(fmt.Sprintf("MustWriteFile failed: %v", err)) 84 } 85 } 86 87 // CopyFile copies a file. It truncates the destination file if it exists. 88 func CopyFile(src, dst string) error { 89 srcfile, err := os.Open(src) 90 if err != nil { 91 return err 92 } 93 defer srcfile.Close() 94 95 info, err := srcfile.Stat() 96 if err != nil { 97 return err 98 } 99 if info.IsDir() { 100 return errors.New("cannot read from directories") 101 } 102 103 // create new file, truncate if exists and apply same permissions as the original one 104 dstfile, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, info.Mode().Perm()) 105 if err != nil { 106 return err 107 } 108 defer dstfile.Close() 109 110 _, err = io.Copy(dstfile, srcfile) 111 return err 112 }