github.com/516108736/tendermint@v0.36.0/cmd/tendermint/commands/debug/io.go (about)

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