github.com/secure-build/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 }