github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/osutil/tar.go (about) 1 // Copyright 2025 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package osutil 5 6 import ( 7 "archive/tar" 8 "compress/gzip" 9 "io" 10 "io/fs" 11 "os" 12 "path/filepath" 13 "strings" 14 ) 15 16 func TarGzDirectory(dir string, writer io.Writer) error { 17 gzw := gzip.NewWriter(writer) 18 defer gzw.Close() 19 return tarDirectory(dir, gzw) 20 } 21 22 func tarDirectory(dir string, writer io.Writer) error { 23 tw := tar.NewWriter(writer) 24 defer tw.Close() 25 26 return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { 27 if err != nil || path == dir { 28 return err 29 } 30 typ := d.Type() 31 if !typ.IsDir() && !typ.IsRegular() { 32 // Only folders and regular files. 33 return nil 34 } 35 relPath, err := filepath.Rel(dir, path) 36 if err != nil { 37 return err 38 } 39 relPath = filepath.ToSlash(relPath) 40 info, err := d.Info() 41 if err != nil { 42 return err 43 } 44 header, err := tar.FileInfoHeader(info, "") 45 if err != nil { 46 return err 47 } 48 header.Name = relPath 49 if typ.IsDir() && !strings.HasSuffix(header.Name, "/") { 50 header.Name += "/" 51 } 52 if err := tw.WriteHeader(header); err != nil { 53 return err 54 } 55 if typ.IsDir() { 56 return nil 57 } 58 // Write the file content. 59 f, err := os.Open(path) 60 if err != nil { 61 return err 62 } 63 _, err = io.Copy(tw, f) 64 f.Close() 65 return err 66 }) 67 }