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  }