-
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
648 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package archive | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
// Archive is ... | ||
type Archive interface { | ||
Directory(name string) error | ||
Header(os.FileInfo) (io.Writer, error) | ||
Close() error | ||
} | ||
|
||
func extractFile(path string, mode os.FileMode, data io.Reader, dest string) error { | ||
target := filepath.Join(dest, filepath.FromSlash(path)) | ||
if !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) { | ||
return fmt.Errorf("path %q escapes archive destination", target) | ||
} | ||
|
||
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { | ||
return err | ||
} | ||
|
||
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) | ||
if err != nil { | ||
return err | ||
} | ||
if _, err := io.Copy(file, data); err != nil { | ||
file.Close() | ||
os.Remove(target) | ||
return err | ||
} | ||
return file.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package archive | ||
|
||
import ( | ||
"archive/tar" | ||
"compress/gzip" | ||
"fmt" | ||
"io" | ||
"os" | ||
"time" | ||
) | ||
|
||
// TarArchive is ... | ||
type TarArchive struct { | ||
dir string | ||
tarw *tar.Writer | ||
gzw *gzip.Writer | ||
file io.Closer | ||
} | ||
|
||
// NewTarArchive is ... | ||
func NewTarArchive(w io.WriteCloser) Archive { | ||
gzw := gzip.NewWriter(w) | ||
tarw := tar.NewWriter(gzw) | ||
return &TarArchive{"", tarw, gzw, w} | ||
} | ||
|
||
// Directory is ... | ||
func (a *TarArchive) Directory(name string) error { | ||
a.dir = name + "/" | ||
return a.tarw.WriteHeader(&tar.Header{ | ||
Name: a.dir, | ||
Mode: 0755, | ||
Typeflag: tar.TypeDir, | ||
ModTime: time.Now(), | ||
}) | ||
} | ||
|
||
// Header is ... | ||
func (a *TarArchive) Header(fi os.FileInfo) (io.Writer, error) { | ||
head, err := tar.FileInfoHeader(fi, "") | ||
if err != nil { | ||
return nil, fmt.Errorf("can't make tar header: %v", err) | ||
} | ||
head.Name = a.dir + head.Name | ||
if err := a.tarw.WriteHeader(head); err != nil { | ||
return nil, fmt.Errorf("can't add tar header: %v", err) | ||
} | ||
return a.tarw, nil | ||
} | ||
|
||
// Close is ... | ||
func (a *TarArchive) Close() error { | ||
if err := a.tarw.Close(); err != nil { | ||
return err | ||
} | ||
if err := a.gzw.Close(); err != nil { | ||
return err | ||
} | ||
return a.file.Close() | ||
} | ||
|
||
// Extract extracts the tar archive at src to dest. | ||
func ExtractTar(src, dest string) error { | ||
ar, err := os.Open(src) | ||
if err != nil { | ||
return err | ||
} | ||
defer ar.Close() | ||
|
||
gzr, err := gzip.NewReader(ar) | ||
if err != nil { | ||
return err | ||
} | ||
defer gzr.Close() | ||
|
||
tr := tar.NewReader(gzr) | ||
for { | ||
header, err := tr.Next() | ||
if err != nil { | ||
if err == io.EOF { | ||
return nil | ||
} | ||
return err | ||
} | ||
if header.Typeflag == tar.TypeReg { | ||
mode := header.FileInfo().Mode() | ||
err := extractFile(header.Name, mode, tr, dest) | ||
if err != nil { | ||
return fmt.Errorf("extract %s: %v", header.Name, err) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package archive | ||
|
||
import ( | ||
"archive/zip" | ||
"fmt" | ||
"io" | ||
"os" | ||
) | ||
|
||
type ZipArchive struct { | ||
dir string | ||
zipw *zip.Writer | ||
file io.Closer | ||
} | ||
|
||
// NewZipArchive is ... | ||
func NewZipArchive(w io.WriteCloser) Archive { | ||
return &ZipArchive{"", zip.NewWriter(w), w} | ||
} | ||
|
||
// Directory is ... | ||
func (a *ZipArchive) Directory(name string) error { | ||
a.dir = name + "/" | ||
return nil | ||
} | ||
|
||
// Header is ... | ||
func (a *ZipArchive) Header(fi os.FileInfo) (io.Writer, error) { | ||
head, err := zip.FileInfoHeader(fi) | ||
if err != nil { | ||
return nil, fmt.Errorf("can't make zip header: %v", err) | ||
} | ||
head.Name = a.dir + head.Name | ||
head.Method = zip.Deflate | ||
w, err := a.zipw.CreateHeader(head) | ||
if err != nil { | ||
return nil, fmt.Errorf("can't add zip header: %v", err) | ||
} | ||
return w, nil | ||
} | ||
|
||
// Close is ... | ||
func (a *ZipArchive) Close() error { | ||
if err := a.zipw.Close(); err != nil { | ||
return err | ||
} | ||
return a.file.Close() | ||
} | ||
|
||
// Extract extracts the zip archive at src to dest. | ||
func ExtractZip(src, dest string) error { | ||
ar, err := os.Open(src) | ||
if err != nil { | ||
return err | ||
} | ||
defer ar.Close() | ||
|
||
info, err := ar.Stat() | ||
if err != nil { | ||
return err | ||
} | ||
zr, err := zip.NewReader(ar, info.Size()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, zf := range zr.File { | ||
if !zf.Mode().IsRegular() { | ||
continue | ||
} | ||
|
||
data, err := zf.Open() | ||
if err != nil { | ||
return err | ||
} | ||
err = extractFile(zf.Name, zf.Mode(), data, dest) | ||
data.Close() | ||
if err != nil { | ||
return fmt.Errorf("extract %s: %v", zf.Name, err) | ||
} | ||
} | ||
return nil | ||
} |
Oops, something went wrong.