5 Commits

Author SHA1 Message Date
402558c226 添加说明 2019-09-02 00:38:49 +08:00
45b3acae13 添加对XP的支持 2019-09-02 00:33:03 +08:00
b77a9f2339 添加对XP的支持 2019-09-02 00:31:53 +08:00
dd6e73bf0c add windows test 2019-08-09 17:08:37 +08:00
f88ca00814 init 2019-08-08 21:55:17 +08:00
6 changed files with 162 additions and 23 deletions

3
.gitignore vendored
View File

@ -3,3 +3,6 @@
# Test out
/test/out
# VS Code
.vscode

View File

@ -1,11 +1,9 @@
# Unzip
Golang \*.zip decompress.
[![Build Status](https://img.shields.io/travis/com/yi-ge/unzip/master.svg)](https://travis-ci.com/yi-ge/unzip)
[![GoDoc](https://godoc.org/github.com/yi-ge/unzip?status.svg)](https://godoc.org/github.com/yi-ge/unzip)
Golang \*.tar.xz decompress.
Golang \*.zip decompress.
Fork from [https://github.com/artdarek/go-unzip](https://github.com/artdarek/go-unzip) and remove print, add support for Symlink.
@ -19,3 +17,7 @@ import "github.com/yi-ge/unzip"
u := unzip.New(filePath, outDir)
err := u.Extract()
```
## Notice
由于 Golang1.12 不再支持 Windows XP因此使用 Golang 自带的 zip 库将在 XP 系统下发生报错,此库对老版本的支持则是自动下载远程`unzip.exe`并自动调用[http://infozip.sourceforge.net/UnZip.html](http://infozip.sourceforge.net/UnZip.html)实现。

View File

@ -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() < 6.1 {
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

View File

@ -5,6 +5,7 @@ import (
"os"
"path"
"path/filepath"
"runtime"
"testing"
)
@ -17,7 +18,7 @@ func currentDir() string {
}
func testNullContent(t *testing.T) {
aFile, err := os.Open(path.Join(currentDir(), "./test/a.txt"))
aFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/a.txt")))
if err != nil {
t.Fatal(err)
}
@ -28,7 +29,7 @@ func testNullContent(t *testing.T) {
t.Fatal(err)
}
aOutFile, err := os.Open(path.Join(currentDir(), "./test/out/a.txt"))
aOutFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/a.txt")))
if err != nil {
t.Fatal(err)
}
@ -49,7 +50,7 @@ func testNullContent(t *testing.T) {
}
func testContentEqual(t *testing.T) {
bFile, err := os.Open(path.Join(currentDir(), "./test/b.txt"))
bFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/b.txt")))
if err != nil {
t.Fatal(err)
}
@ -60,7 +61,7 @@ func testContentEqual(t *testing.T) {
t.Fatal(err)
}
bOutFile, err := os.Open(path.Join(currentDir(), "./test/out/b.txt"))
bOutFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/b.txt")))
if err != nil {
t.Fatal(err)
}
@ -79,7 +80,7 @@ func testContentEqual(t *testing.T) {
}
func testLink(t *testing.T) {
cOutFile, err := os.OpenFile(path.Join(currentDir(), "./test/out/c.txt"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
cOutFile, err := os.OpenFile(filepath.FromSlash(path.Join(currentDir(), "./test/out/c.txt")), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
t.Fatal(err)
}
@ -90,7 +91,7 @@ func testLink(t *testing.T) {
t.Fatal(err)
}
cOutLinkFile, err := os.Open(path.Join(currentDir(), "./test/out/dir/c.txt"))
cOutLinkFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/c.txt")))
if err != nil {
t.Fatal(err)
}
@ -112,7 +113,7 @@ func testLink(t *testing.T) {
t.Fatal(err)
}
cOutFileNew, err := os.Open(path.Join(currentDir(), "./test/out/c.txt"))
cOutFileNew, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/c.txt")))
if err != nil {
t.Fatal(err)
}
@ -124,7 +125,7 @@ func testLink(t *testing.T) {
}
t.Log("New c.txt content:", string(cOutFileContentNew))
cOutLinkFileNew, err := os.Open(path.Join(currentDir(), "./test/out/dir/c.txt"))
cOutLinkFileNew, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/c.txt")))
if err != nil {
t.Fatal(err)
}
@ -141,17 +142,22 @@ func testLink(t *testing.T) {
}
func testSymlink(t *testing.T) {
targetURL, err := filepath.EvalSymlinks(path.Join(currentDir(), "./test/out/d.txt"))
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)
}
t.Log("targetURL:", targetURL)
if targetURL != path.Join(currentDir(), "./test/out/dir/d.txt") {
if targetURL != filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/d.txt")) {
t.Fatal("Unzip file Symlink error.")
}
dOutSymlinkFile, err := os.Open(path.Join(currentDir(), "./test/out/d.txt"))
dOutSymlinkFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/d.txt")))
if err != nil {
t.Fatal(err)
}
@ -162,7 +168,7 @@ func testSymlink(t *testing.T) {
t.Fatal(err)
}
dOutFile, err := os.Open(path.Join(currentDir(), "./test/out/dir/d.txt"))
dOutFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/d.txt")))
if err != nil {
t.Fatal(err)
}
@ -179,7 +185,7 @@ func testSymlink(t *testing.T) {
}
func testLintInDir(t *testing.T) {
eOutFile, err := os.OpenFile(path.Join(currentDir(), "./test/out/dir/dir/e.txt"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
eOutFile, err := os.OpenFile(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/dir/e.txt")), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
t.Fatal(err)
}
@ -190,7 +196,7 @@ func testLintInDir(t *testing.T) {
t.Fatal(err)
}
eOutLinkFile, err := os.Open(path.Join(currentDir(), "./test/out/dir/e.txt"))
eOutLinkFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/e.txt")))
if err != nil {
t.Fatal(err)
}
@ -212,7 +218,7 @@ func testLintInDir(t *testing.T) {
t.Fatal(err)
}
eOutFileNew, err := os.Open(path.Join(currentDir(), "./test/out/dir/dir/e.txt"))
eOutFileNew, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/dir/e.txt")))
if err != nil {
t.Fatal(err)
}
@ -224,7 +230,7 @@ func testLintInDir(t *testing.T) {
}
t.Log("New dir/dir/e.txt content:", string(eOutFileContentNew))
eOutLinkFileNew, err := os.Open(path.Join(currentDir(), "./test/out/dir/e.txt"))
eOutLinkFileNew, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/e.txt")))
if err != nil {
t.Fatal(err)
}
@ -241,17 +247,21 @@ func testLintInDir(t *testing.T) {
}
func testSymlinkInDir(t *testing.T) {
inDirTargetURL, err := filepath.EvalSymlinks(path.Join(currentDir(), "./test/out/dir/dir/f.txt"))
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)
}
t.Log("F outSymlinkFile link:", inDirTargetURL)
if inDirTargetURL != path.Join(currentDir(), "./test/out/dir/f.txt") {
if inDirTargetURL != filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/f.txt")) {
t.Fatal("Unzip file Symlink error.")
}
fOutSymlinkFile, err := os.Open(path.Join(currentDir(), "./test/out/dir/dir/f.txt"))
fOutSymlinkFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/dir/f.txt")))
if err != nil {
t.Fatal(err)
}
@ -262,7 +272,7 @@ func testSymlinkInDir(t *testing.T) {
t.Fatal(err)
}
fOutFile, err := os.Open(path.Join(currentDir(), "./test/out/dir/f.txt"))
fOutFile, err := os.Open(filepath.FromSlash(path.Join(currentDir(), "./test/out/dir/f.txt")))
if err != nil {
t.Fatal(err)
}

20
util_unix.go Normal file
View File

@ -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
}

44
util_windows.go Normal file
View File

@ -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
}