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  }