github.com/nilium/gitlab-runner@v12.5.0+incompatible/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  	err = os.MkdirAll(filepath.Dir(file.Name), 0777)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	switch file.Mode() & os.ModeType {
    70  	case os.ModeDir:
    71  		err = extractZipDirectoryEntry(file)
    72  
    73  	case os.ModeSymlink:
    74  		err = extractZipSymlinkEntry(file)
    75  
    76  	case os.ModeNamedPipe, os.ModeSocket, os.ModeDevice:
    77  		// Ignore the files that of these types
    78  		logrus.Warningf("File ignored: %q", file.Name)
    79  
    80  	default:
    81  		err = extractZipFileEntry(file)
    82  	}
    83  	return
    84  }
    85  
    86  func ExtractZipArchive(archive *zip.Reader) error {
    87  	tracker := newPathErrorTracker()
    88  
    89  	for _, file := range archive.File {
    90  		if err := errorIfGitDirectory(file.Name); tracker.actionable(err) {
    91  			printGitArchiveWarning("extract")
    92  		}
    93  
    94  		if err := extractZipFile(file); tracker.actionable(err) {
    95  			logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err)
    96  		}
    97  	}
    98  
    99  	for _, file := range archive.File {
   100  		// Update file permissions
   101  		if err := os.Chmod(file.Name, file.Mode().Perm()); tracker.actionable(err) {
   102  			logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err)
   103  		}
   104  
   105  		// Process zip metadata
   106  		if err := processZipExtra(&file.FileHeader); tracker.actionable(err) {
   107  			logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err)
   108  		}
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  func ExtractZipFile(fileName string) error {
   115  	archive, err := zip.OpenReader(fileName)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	defer archive.Close()
   120  
   121  	return ExtractZipArchive(&archive.Reader)
   122  }