github.com/vipernet-xyz/tm@v0.34.24/cmd/tendermint/commands/debug/io.go (about)

     1  package debug
     2  
     3  import (
     4  	"archive/zip"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"path"
    10  	"path/filepath"
    11  	"strings"
    12  )
    13  
    14  // zipDir zips all the contents found in src, including both files and
    15  // directories, into a destination file dest. It returns an error upon failure.
    16  // It assumes src is a directory.
    17  func zipDir(src, dest string) error {
    18  	zipFile, err := os.Create(dest)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	defer zipFile.Close()
    23  
    24  	zipWriter := zip.NewWriter(zipFile)
    25  	defer zipWriter.Close()
    26  
    27  	dirName := filepath.Base(dest)
    28  	baseDir := strings.TrimSuffix(dirName, filepath.Ext(dirName))
    29  
    30  	return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
    31  		if err != nil {
    32  			return err
    33  		}
    34  
    35  		header, err := zip.FileInfoHeader(info)
    36  		if err != nil {
    37  			return err
    38  		}
    39  
    40  		// Each execution of this utility on a Tendermint process will result in a
    41  		// unique file.
    42  		header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, src))
    43  
    44  		// Handle cases where the content to be zipped is a file or a directory,
    45  		// where a directory must have a '/' suffix.
    46  		if info.IsDir() {
    47  			header.Name += "/"
    48  		} else {
    49  			header.Method = zip.Deflate
    50  		}
    51  
    52  		headerWriter, err := zipWriter.CreateHeader(header)
    53  		if err != nil {
    54  			return err
    55  		}
    56  
    57  		if info.IsDir() {
    58  			return nil
    59  		}
    60  
    61  		file, err := os.Open(path)
    62  		if err != nil {
    63  			return err
    64  		}
    65  		defer file.Close()
    66  
    67  		_, err = io.Copy(headerWriter, file)
    68  		return err
    69  	})
    70  }
    71  
    72  // copyFile copies a file from src to dest and returns an error upon failure. The
    73  // copied file retains the source file's permissions.
    74  func copyFile(src, dest string) error {
    75  	if _, err := os.Stat(src); os.IsNotExist(err) {
    76  		return err
    77  	}
    78  
    79  	srcFile, err := os.Open(src)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	defer srcFile.Close()
    84  
    85  	destFile, err := os.Create(dest)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	defer destFile.Close()
    90  
    91  	if _, err = io.Copy(destFile, srcFile); err != nil {
    92  		return err
    93  	}
    94  
    95  	srcInfo, err := os.Stat(src)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	return os.Chmod(dest, srcInfo.Mode())
   101  }
   102  
   103  // writeStateToFile pretty JSON encodes an object and writes it to file composed
   104  // of dir and filename. It returns an error upon failure to encode or write to
   105  // file.
   106  func writeStateJSONToFile(state interface{}, dir, filename string) error {
   107  	stateJSON, err := json.MarshalIndent(state, "", "  ")
   108  	if err != nil {
   109  		return fmt.Errorf("failed to encode state dump: %w", err)
   110  	}
   111  
   112  	return os.WriteFile(path.Join(dir, filename), stateJSON, os.ModePerm)
   113  }