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 }