github.com/abdfnx/gh-api@v0.0.0-20210414084727-f5432eec23b8/pkg/cmd/run/download/zip.go (about) 1 package download 2 3 import ( 4 "archive/zip" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "strings" 10 ) 11 12 const ( 13 dirMode os.FileMode = 0755 14 fileMode os.FileMode = 0644 15 execMode os.FileMode = 0755 16 ) 17 18 func extractZip(zr *zip.Reader, destDir string) error { 19 destDirAbs, err := filepath.Abs(destDir) 20 if err != nil { 21 return err 22 } 23 pathPrefix := destDirAbs + string(filepath.Separator) 24 for _, zf := range zr.File { 25 fpath := filepath.Join(destDirAbs, filepath.FromSlash(zf.Name)) 26 if !strings.HasPrefix(fpath, pathPrefix) { 27 continue 28 } 29 if err := extractZipFile(zf, fpath); err != nil { 30 return fmt.Errorf("error extracting %q: %w", zf.Name, err) 31 } 32 } 33 return nil 34 } 35 36 func extractZipFile(zf *zip.File, dest string) error { 37 zm := zf.Mode() 38 if zm.IsDir() { 39 return os.MkdirAll(dest, dirMode) 40 } 41 42 f, err := zf.Open() 43 if err != nil { 44 return err 45 } 46 defer f.Close() 47 48 if dir := filepath.Dir(dest); dir != "." { 49 if err := os.MkdirAll(dir, dirMode); err != nil { 50 return err 51 } 52 } 53 54 df, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_EXCL, getPerm(zm)) 55 if err != nil { 56 return err 57 } 58 defer df.Close() 59 60 _, err = io.Copy(df, f) 61 return err 62 } 63 64 func getPerm(m os.FileMode) os.FileMode { 65 if m&0111 == 0 { 66 return fileMode 67 } 68 return execMode 69 }