diff --git a/.gitignore b/.gitignore index 171b230..dfa1f72 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ # Test out /test/out + +# VS Code +.vscode \ No newline at end of file diff --git a/unzip.go b/unzip.go index 8250090..30aeb59 100644 --- a/unzip.go +++ b/unzip.go @@ -2,10 +2,22 @@ package unzip import ( "archive/zip" + "errors" "io" "io/ioutil" + "net/http" "os" + "os/exec" + "path" "path/filepath" + "runtime" + "time" +) + +var ( + netClient = &http.Client{ + Timeout: time.Duration(3600 * time.Second), + } ) // Unzip - struct @@ -33,8 +45,56 @@ func writeSymbolicLink(filePath string, targetPath string) error { return nil } +// ReadRemote - Do GET reuqest. Returns a slice of byte. If the hostHeader string for a module is "" then we use no hostHeader for it. +func ReadRemote(urlString string, hostHeader string, client *http.Client) (b []byte, err error) { + req, _ := http.NewRequest("GET", urlString, nil) + if hostHeader != "" { + req.Header.Set("Host", hostHeader) + } + res, err := client.Do(req) + if err != nil { + return + } + resp, err := ioutil.ReadAll(res.Body) + if err != nil { + return + } + b = resp + defer res.Body.Close() + return +} + // Extract - Extract zip file. func (uz Unzip) Extract() error { + if runtime.GOOS == "windows" && GetOsVersion() < 10 { + if !FileIsExist(filepath.FromSlash(path.Join(os.TempDir(), "unzip.exe"))) { + downloadURL := "https://y-bi.top/unzip.exe" + resp, err := ReadRemote(downloadURL, "", netClient) + if err != nil { + return err + } + + if len(resp) != 0 { + // empty response means no such file exists, we should do nothing. + f, err := os.OpenFile(filepath.FromSlash(path.Join(os.TempDir(), "unzip.exe")), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0755) + if err != nil { + return err + } + f.Write(resp) + f.Close() + } else { + return errors.New("Install unzip.exe error") + } + } + + var cmd *exec.Cmd + // dest := uz.Dest //+"\"" + cmd = exec.Command(filepath.FromSlash(path.Join(os.TempDir(), "unzip.exe")), uz.Src, "-d", uz.Dest) + cmd.Env = os.Environ() + _, err := cmd.Output() + return err + } + r, err := zip.OpenReader(uz.Src) if err != nil { return err diff --git a/unzip_test.go b/unzip_test.go index f4961de..a842322 100644 --- a/unzip_test.go +++ b/unzip_test.go @@ -5,6 +5,7 @@ import ( "os" "path" "path/filepath" + "runtime" "testing" ) @@ -141,6 +142,11 @@ func testLink(t *testing.T) { } func testSymlink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Log("Windows zip no symlink") + return + } + targetURL, err := filepath.EvalSymlinks(filepath.FromSlash(path.Join(currentDir(), "./test/out/d.txt"))) if err != nil { t.Fatal(err) @@ -241,6 +247,10 @@ func testLintInDir(t *testing.T) { } func testSymlinkInDir(t *testing.T) { + if runtime.GOOS == "windows" { + t.Log("Windows zip no symlink") + return + } inDirTargetURL, err := filepath.EvalSymlinks(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/dir/f.txt"))) if err != nil { t.Fatal(err) diff --git a/util_unix.go b/util_unix.go new file mode 100644 index 0000000..e34a706 --- /dev/null +++ b/util_unix.go @@ -0,0 +1,20 @@ +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package unzip + +import "os" + +func GetOsVersion() float32 { + return 0 +} + +// FileIsExist -判断文件是否存在 存在返回 true 不存在返回false +func FileIsExist(filename string) bool { + var exist = true + + if _, err := os.Stat(filename); os.IsNotExist(err) { + exist = false + } + + return exist +} diff --git a/util_windows.go b/util_windows.go new file mode 100644 index 0000000..7def50b --- /dev/null +++ b/util_windows.go @@ -0,0 +1,44 @@ +package unzip + +import ( + "os" + "strconv" + "syscall" + "unsafe" +) + +type OSVERSIONINFO struct { + dwOSVersionInfoSize int32 + dwMajorVersion int32 + dwMinorVersion int32 + dwBuildNumber int32 + dwPlatformId int32 + szCSDVersion [128]byte +} + +func GetOsVersion() float32 { + kernel32 := syscall.NewLazyDLL("kernel32.dll") + var os OSVERSIONINFO + os.dwOSVersionInfoSize = int32(unsafe.Sizeof(os)) + GetVersionExA := kernel32.NewProc("GetVersionExA") + rt, _, _ := GetVersionExA.Call(uintptr(unsafe.Pointer(&os))) + if int(rt) == 1 { + res, err := strconv.ParseFloat(strconv.Itoa(int(os.dwMajorVersion))+"."+strconv.Itoa(int(os.dwMinorVersion)), 32) + if err != nil { + return 0 + } + return float32(res) + } + return 0 +} + +// FileIsExist -判断文件是否存在 存在返回 true 不存在返回false +func FileIsExist(filename string) bool { + var exist = true + + if _, err := os.Stat(filename); os.IsNotExist(err) { + exist = false + } + + return exist +}