github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/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  	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  	return nil
    73  }
    74  
    75  // copyFile copies a file from src to dest and returns an error upon failure. The
    76  // copied file retains the source file's permissions.
    77  func copyFile(src, dest string) error {
    78  	if _, err := os.Stat(src); os.IsNotExist(err) {
    79  		return err
    80  	}
    81  
    82  	srcFile, err := os.Open(src)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	defer srcFile.Close()
    87  
    88  	destFile, err := os.Create(dest)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	defer destFile.Close()
    93  
    94  	if _, err = io.Copy(destFile, srcFile); err != nil {
    95  		return err
    96  	}
    97  
    98  	srcInfo, err := os.Stat(src)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	return os.Chmod(dest, srcInfo.Mode())
   104  }
   105  
   106  // writeStateToFile pretty JSON encodes an object and writes it to file composed
   107  // of dir and filename. It returns an error upon failure to encode or write to
   108  // file.
   109  func writeStateJSONToFile(state interface{}, dir, filename string) error {
   110  	stateJSON, err := json.MarshalIndent(state, "", "  ")
   111  	if err != nil {
   112  		return fmt.Errorf("failed to encode state dump: %w", err)
   113  	}
   114  
   115  	return ioutil.WriteFile(path.Join(dir, filename), stateJSON, os.ModePerm)
   116  }