helpers/archives/zip_extract.go (91 lines of code) (raw):

package archives import ( "archive/zip" "io" "os" "path/filepath" "github.com/sirupsen/logrus" ) func extractZipDirectoryEntry(file *zip.File) (err error) { err = os.Mkdir(file.Name, file.Mode().Perm()) // The error that directory does exists is not a error for us if os.IsExist(err) { err = nil } return } func extractZipSymlinkEntry(file *zip.File) (err error) { var data []byte in, err := file.Open() if err != nil { return err } defer func() { _ = in.Close() }() data, err = io.ReadAll(in) if err != nil { return err } // Remove symlink before creating a new one, otherwise we can error that file does exist _ = os.Remove(file.Name) err = os.Symlink(string(data), file.Name) return } func extractZipFileEntry(file *zip.File) (err error) { var out *os.File in, err := file.Open() if err != nil { return err } defer func() { _ = in.Close() }() // Remove file before creating a new one, otherwise we can error that file does exist _ = os.Remove(file.Name) out, err = os.OpenFile(file.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode().Perm()) if err != nil { return err } defer func() { _ = out.Close() }() _, err = io.Copy(out, in) return } func extractZipFile(file *zip.File) (err error) { // Create all parents to extract the file err = os.MkdirAll(filepath.Dir(file.Name), 0o777) if err != nil { return err } switch file.Mode() & os.ModeType { case os.ModeDir: err = extractZipDirectoryEntry(file) case os.ModeSymlink: err = extractZipSymlinkEntry(file) case os.ModeNamedPipe, os.ModeSocket, os.ModeDevice: // Ignore the files that of these types logrus.Warningf("File ignored: %q", file.Name) default: err = extractZipFileEntry(file) } return } func ExtractZipArchive(archive *zip.Reader) error { tracker := newPathErrorTracker() for _, file := range archive.File { if err := errorIfGitDirectory(file.Name); tracker.actionable(err) { printGitArchiveWarning("extract") } if err := extractZipFile(file); tracker.actionable(err) { logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err) } } for _, file := range archive.File { if err := lchmod(file.Name, file.Mode()); tracker.actionable(err) { logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err) } // Process zip metadata if err := processZipExtra(&file.FileHeader); tracker.actionable(err) { logrus.Warningf("%s: %s (suppressing repeats)", file.Name, err) } } return nil } func ExtractZipFile(fileName string) error { archive, err := zip.OpenReader(fileName) if err != nil { return err } defer func() { _ = archive.Close() }() return ExtractZipArchive(&archive.Reader) }