github.com/ssube/gitlab-ci-multi-runner@v1.2.1-0.20160607142738-b8d1285632e6/helpers/archives/zip_extract.go (about)

     1  package archives
     2  
     3  import (
     4  	"archive/zip"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/Sirupsen/logrus"
    11  )
    12  
    13  func extractZipDirectoryEntry(file *zip.File) (err error) {
    14  	err = os.Mkdir(file.Name, file.Mode().Perm())
    15  
    16  	// The error that directory does exists is not a error for us
    17  	if os.IsExist(err) {
    18  		err = nil
    19  	}
    20  	return
    21  }
    22  
    23  func extractZipSymlinkEntry(file *zip.File) (err error) {
    24  	var data []byte
    25  	in, err := file.Open()
    26  	if err != nil {
    27  		return err
    28  	}
    29  	defer in.Close()
    30  
    31  	data, err = ioutil.ReadAll(in)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	// Remove symlink before creating a new one, otherwise we can error that file does exist
    37  	os.Remove(file.Name)
    38  	err = os.Symlink(string(data), file.Name)
    39  	return
    40  }
    41  
    42  func extractZipFileEntry(file *zip.File) (err error) {
    43  	var out *os.File
    44  	in, err := file.Open()
    45  	if err != nil {
    46  		return err
    47  	}
    48  	defer in.Close()
    49  
    50  	// Remove file before creating a new one, otherwise we can error that file does exist
    51  	os.Remove(file.Name)
    52  	out, err = os.OpenFile(file.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode().Perm())
    53  	if err != nil {
    54  		return err
    55  	}
    56  	defer out.Close()
    57  	_, err = io.Copy(out, in)
    58  
    59  	return
    60  }
    61  
    62  func extractZipFile(file *zip.File) (err error) {
    63  	// Create all parents to extract the file
    64  	os.MkdirAll(filepath.Dir(file.Name), 0777)
    65  
    66  	switch file.Mode() & os.ModeType {
    67  	case os.ModeDir:
    68  		err = extractZipDirectoryEntry(file)
    69  
    70  	case os.ModeSymlink:
    71  		err = extractZipSymlinkEntry(file)
    72  
    73  	case os.ModeNamedPipe, os.ModeSocket, os.ModeDevice:
    74  		// Ignore the files that of these types
    75  		logrus.Warningln("File ignored: %q", file.Name)
    76  
    77  	default:
    78  		err = extractZipFileEntry(file)
    79  	}
    80  	return
    81  }
    82  
    83  func ExtractZipArchive(archive *zip.Reader) error {
    84  	for _, file := range archive.File {
    85  		if err := extractZipFile(file); err != nil {
    86  			logrus.Warningf("%s: %s", file.Name, err)
    87  		}
    88  	}
    89  
    90  	for _, file := range archive.File {
    91  		// Update file permissions
    92  		if err := os.Chmod(file.Name, file.Mode().Perm()); err != nil {
    93  			logrus.Warningf("%s: %s", file.Name, err)
    94  		}
    95  
    96  		// Process zip metadata
    97  		if err := processZipExtra(&file.FileHeader); err != nil {
    98  			logrus.Warningf("%s: %s", file.Name, err)
    99  		}
   100  	}
   101  	return nil
   102  }
   103  
   104  func ExtractZipFile(fileName string) error {
   105  	archive, err := zip.OpenReader(fileName)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	defer archive.Close()
   110  
   111  	return ExtractZipArchive(&archive.Reader)
   112  }