-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxz.go
162 lines (150 loc) · 4.06 KB
/
xz.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//Package xz is a wrapper around a xz executable that must be avaialbe at path
package xz
import (
"bytes"
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
log "github.com/Sirupsen/logrus"
)
func init() {
// chekc if we have the xz executalbe on the platform
path, err := exec.LookPath("xz")
if err != nil {
log.Fatal("installing fortune is in your future")
}
log.Debug("xz is available at %s\n", path)
}
// Checksum contains a Sha256 checksum as a byte array
// and a md5 check sum as string.
type Checksum struct {
Sha256 [sha256.Size]byte
Md5 string
}
// Base64md5 converts a md5 checksum as []byte to a base 16 encoded string
func Base64md5(data []byte) string {
h := md5.New()
h.Write(data)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// ChecksumFromPath returns a struct with the checksum of the file at path using the strategy selected with strategy string
// currently implemented sha256 and md5
func ChecksumFromPath(file string, strategy string) Checksum {
var localchecksum Checksum
data, err := ioutil.ReadFile(file)
if err != nil {
panic(err)
}
switch strategy {
default:
log.Fatalf("stregy %v not implemented", strategy)
case "md5":
localchecksum.Md5 = Base64md5(data)
case "sha256":
localchecksum.Sha256 = sha256.Sum256(data)
}
return localchecksum
}
// ChecksumFromArr returns a struct with the checksum of the byte array passed the strategy selected with strategy string
// currently implemented sha256 and md5
func ChecksumFromArr(data []byte, strategy string) Checksum {
var localchecksum Checksum
switch strategy {
default:
log.Fatalf("stregy %v not implemented", strategy)
case "md5":
localchecksum.Md5 = Base64md5(data)
case "sha256":
localchecksum.Sha256 = sha256.Sum256(data)
}
return localchecksum
}
// Reader inflates the file (named file).
// if stdout is true the inflated file is returned as io.ReadCloser
// else it's written to disk.
func Reader(file string, stdout bool) (io.ReadCloser, error) {
f, err := os.Open(file)
if err != nil {
panic(err)
}
if stdout {
rpipe, wpipe := io.Pipe()
cmd := exec.Command("xz", "--decompress", "--stdout")
cmd.Stdin = f
cmd.Stdout = wpipe
// print the error
cmd.Stderr = os.Stderr
go func() {
err := cmd.Run()
wpipe.CloseWithError(err)
defer f.Close()
}()
return rpipe, err
}
// Create an *exec.Cmd
cmd := exec.Command("xz", "--decompress", file)
// Stdout buffer
cmdOutput := &bytes.Buffer{}
// Attach buffer to command
cmd.Stdout = cmdOutput
// Stderr buffer
cmderror := &bytes.Buffer{}
// Attach buffer to command
cmd.Stderr = cmderror
// Execute command
err = cmd.Run() // will wait for command to return
if err != nil {
errstr := string(cmderror.Bytes())
err = errors.New(errstr)
}
return nil, err
}
// Writer deflates the file (named file) to disk
// if keep is true the original file is kept on disk else
// is blindly removed
func Writer(file string, keep bool) error {
// Create an *exec.Cmd
var cmd *exec.Cmd
if keep {
cmd = exec.Command("xz", "--keep", file)
} else {
cmd = exec.Command("xz", file)
}
// buffer
cmdOutput := &bytes.Buffer{}
// Attach buffer to command
cmd.Stdout = cmdOutput
// Stderr buffer
cmderror := &bytes.Buffer{}
// Attach buffer to command
cmd.Stderr = cmderror
// Execute command
err := cmd.Run() // will wait for command to return
if err != nil {
errstr := string(cmderror.Bytes())
err = errors.New(errstr)
}
return err
}
// DeflateCheck deflates a file to file.xz, and deletes file if all went good.
// integrity check is done internally by xz. see: http://www.freebsd.org/cgi/man.cgi?query=xz&sektion=1&manpath=FreeBSD+8.3-RELEASE
// If there is an error, its returned and the old file is not deleted, BUT
// there is no guarantee that the deflated file has been created.
func DeflateCheck(file string, strategy string) error {
keep := true
err := Writer(file, keep)
if err == nil {
fmt.Printf("Removing old file \n")
os.Remove(file)
fmt.Printf("Removed: %v \n", file)
return nil
}
fmt.Printf("Err: %v \n", err)
return err
}