github.com/kubearmor/cilium@v1.6.12/bugtool/cmd/helper.go (about) 1 // Copyright 2017-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "archive/tar" 19 "compress/gzip" 20 "fmt" 21 "io" 22 "os" 23 "path/filepath" 24 "strings" 25 ) 26 27 type tarWriter interface { 28 io.Writer 29 WriteHeader(hdr *tar.Header) error 30 } 31 32 type walker struct { 33 baseDir, dbgDir string 34 output tarWriter 35 log io.Writer 36 } 37 38 func newWalker(baseDir, dbgDir string, output tarWriter, logger io.Writer) *walker { 39 return &walker{ 40 baseDir: baseDir, 41 dbgDir: dbgDir, 42 output: output, 43 log: logger, 44 } 45 } 46 47 func (w *walker) walkPath(path string, info os.FileInfo, err error) error { 48 if err != nil { 49 fmt.Fprintf(w.log, "Error while walking path %s: %s", path, err) 50 return nil 51 } 52 if info == nil { 53 fmt.Fprintf(w.log, "No file info available") 54 return nil 55 } 56 57 file, err := os.Open(path) 58 if err != nil { 59 fmt.Fprintf(w.log, "Failed to open %s: %s\n", path, err) 60 // TODO: Write an empty file here, just to hint that this file 61 // existed by there was some problem attempting to add it. 62 return nil 63 } 64 defer file.Close() 65 66 if info.IsDir() { 67 fmt.Fprintf(w.log, "Skipping directory %s\n", info.Name()) 68 return nil 69 } 70 71 // Just get the latest fileInfo to make sure that the size is correctly 72 // when the file is write to tar file 73 fpInfo, err := file.Stat() 74 if err != nil { 75 fpInfo, err = os.Lstat(file.Name()) 76 if err != nil { 77 fmt.Fprintf(w.log, "Failed to retrieve file information: %s\n", err) 78 return nil 79 } 80 } 81 82 header, err := tar.FileInfoHeader(fpInfo, fpInfo.Name()) 83 if err != nil { 84 fmt.Fprintf(w.log, "Failed to prepare file info %s: %s\n", fpInfo.Name(), err) 85 return nil 86 } 87 88 if w.baseDir != "" { 89 header.Name = filepath.Join(w.baseDir, strings.TrimPrefix(path, w.dbgDir)) 90 } 91 92 if err := w.output.WriteHeader(header); err != nil { 93 fmt.Fprintf(w.log, "Failed to write header: %s\n", err) 94 return nil 95 } 96 97 _, err = io.Copy(w.output, file) 98 return err 99 } 100 101 func createArchive(dbgDir string) (string, error) { 102 // Based on http://blog.ralch.com/tutorial/golang-working-with-tar-and-gzip/ 103 archivePath := fmt.Sprintf("%s.tar", dbgDir) 104 file, err := os.Create(archivePath) 105 if err != nil { 106 return "", err 107 } 108 defer file.Close() 109 110 writer := tar.NewWriter(file) 111 defer writer.Close() 112 113 var baseDir string 114 if info, err := os.Stat(dbgDir); os.IsNotExist(err) { 115 fmt.Fprintf(os.Stderr, "Debug directory does not exist %s\n", err) 116 return "", err 117 } else if err == nil && info.IsDir() { 118 baseDir = filepath.Base(dbgDir) 119 } 120 121 walker := newWalker(baseDir, dbgDir, writer, os.Stderr) 122 return archivePath, filepath.Walk(dbgDir, walker.walkPath) 123 } 124 125 func createGzip(dbgDir string) (string, error) { 126 // Based on http://blog.ralch.com/tutorial/golang-working-with-tar-and-gzip/ 127 source, err := createArchive(dbgDir) 128 if err != nil { 129 return "", err 130 } 131 132 reader, err := os.Open(source) 133 if err != nil { 134 return "", err 135 } 136 137 filename := filepath.Base(source) 138 target := fmt.Sprintf("%s.gz", source) 139 writer, err := os.Create(target) 140 if err != nil { 141 return "", err 142 } 143 defer writer.Close() 144 145 archiver := gzip.NewWriter(writer) 146 archiver.Name = filename 147 defer archiver.Close() 148 149 _, err = io.Copy(archiver, reader) 150 if err != nil { 151 return "", err 152 } 153 154 return target, nil 155 }