github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/pkg/archive/tar/tar.go (about) 1 // Package tar implements the Archive interface providing tar archiving. 2 package tar 3 4 import ( 5 "archive/tar" 6 "io" 7 "os" 8 9 "github.com/goreleaser/goreleaser/pkg/config" 10 ) 11 12 // Archive as tar. 13 type Archive struct { 14 tw *tar.Writer 15 } 16 17 // New tar archive. 18 func New(target io.Writer) Archive { 19 return Archive{ 20 tw: tar.NewWriter(target), 21 } 22 } 23 24 // Close all closeables. 25 func (a Archive) Close() error { 26 return a.tw.Close() 27 } 28 29 // Add file to the archive. 30 func (a Archive) Add(f config.File) error { 31 file, err := os.Open(f.Source) // #nosec 32 if err != nil { 33 return err 34 } 35 defer file.Close() 36 info, err := os.Lstat(f.Source) // #nosec 37 if err != nil { 38 return err 39 } 40 var link string 41 if info.Mode()&os.ModeSymlink != 0 { 42 link, err = os.Readlink(f.Source) // #nosec 43 if err != nil { 44 return err 45 } 46 } 47 header, err := tar.FileInfoHeader(info, link) 48 if err != nil { 49 return err 50 } 51 header.Name = f.Destination 52 if !f.Info.MTime.IsZero() { 53 header.ModTime = f.Info.MTime 54 } 55 if f.Info.Mode != 0 { 56 header.Mode = int64(f.Info.Mode) 57 } 58 if f.Info.Owner != "" { 59 header.Uid = 0 60 header.Uname = f.Info.Owner 61 } 62 if f.Info.Group != "" { 63 header.Gid = 0 64 header.Gname = f.Info.Group 65 } 66 if err = a.tw.WriteHeader(header); err != nil { 67 return err 68 } 69 if info.IsDir() || info.Mode()&os.ModeSymlink != 0 { 70 return nil 71 } 72 _, err = io.Copy(a.tw, file) 73 return err 74 }