@@ -35,7 +35,6 @@ import (
35
35
"crypto/sha256"
36
36
"encoding/hex"
37
37
"encoding/json"
38
- "errors"
39
38
"fmt"
40
39
"hash"
41
40
"io"
@@ -45,65 +44,93 @@ import (
45
44
"strings"
46
45
)
47
46
48
- func getHashAlgoAndComponent (checksum string ) (hash.Hash , []byte ) {
49
- components := strings .SplitN (checksum , ":" , 2 )
50
- hashAlgo := components [0 ]
51
- hashMid , err := hex .DecodeString (components [1 ])
47
+ // IsCached returns a bool representing if the release has already been downloaded
48
+ func (r * DownloadResource ) IsCached () (bool , error ) {
49
+ archivePath , err := r .ArchivePath ()
52
50
if err != nil {
53
- return nil , nil
51
+ return false , fmt . Errorf ( "getting archive path: %s" , err )
54
52
}
55
53
56
- hash := []byte (hashMid )
57
- switch hashAlgo {
54
+ _ , err = os .Stat (archivePath )
55
+ if err != nil && ! os .IsNotExist (err ) {
56
+ return false , fmt .Errorf ("checking archive existence: %s" , err )
57
+ }
58
+
59
+ return ! os .IsNotExist (err ), nil
60
+ }
61
+
62
+ // TestLocalArchiveChecksum test if the checksum of the local archive match the checksum of the DownloadResource
63
+ func (r * DownloadResource ) TestLocalArchiveChecksum () (bool , error ) {
64
+ split := strings .SplitN (r .Checksum , ":" , 2 )
65
+ if len (split ) != 2 {
66
+ return false , fmt .Errorf ("invalid checksum format: %s" , r .Checksum )
67
+ }
68
+ digest , err := hex .DecodeString (split [1 ])
69
+ if err != nil {
70
+ return false , fmt .Errorf ("invalid hash '%s': %s" , split [1 ], err )
71
+ }
72
+
73
+ // names based on: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest
74
+ var algo hash.Hash
75
+ switch split [0 ] {
58
76
case "SHA-256" :
59
- return crypto .SHA256 .New (), hash
60
- case "SHA1 " :
61
- return crypto .SHA1 .New (), hash
77
+ algo = crypto .SHA256 .New ()
78
+ case "SHA-1 " :
79
+ algo = crypto .SHA1 .New ()
62
80
case "MD5" :
63
- return crypto .MD5 .New (), hash
81
+ algo = crypto .MD5 .New ()
64
82
default :
65
- return nil , nil
83
+ return false , fmt . Errorf ( "unsupported hash algorithm: %s" , split [ 0 ])
66
84
}
67
- }
68
85
69
- // ChecksumMatches checks the checksum of a DownloadResource archive, in compliance with
70
- // What Checksum is expected.
71
- func checksumMatches (r * DownloadResource ) bool {
72
- hash , content := getHashAlgoAndComponent (r .Checksum )
73
86
filePath , err := r .ArchivePath ()
74
87
if err != nil {
75
- return false
88
+ return false , fmt . Errorf ( "getting archive path: %s" , err )
76
89
}
77
90
78
91
file , err := os .Open (filePath )
79
92
if err != nil {
80
- return false
93
+ return false , fmt . Errorf ( "opening archive file: %s" , err )
81
94
}
82
95
defer file .Close ()
83
- io .Copy (hash , file )
84
- return bytes .Compare (hash .Sum (nil ), content ) == 0
96
+ if _ , err := io .Copy (algo , file ); err != nil {
97
+ return false , fmt .Errorf ("computing hash: %s" , err )
98
+ }
99
+ return bytes .Compare (algo .Sum (nil ), digest ) == 0 , nil
85
100
}
86
101
87
- // checkLocalArchive check for integrity of the local archive.
88
- func checkLocalArchive ( release * DownloadResource ) error {
89
- archivePath , err := release .ArchivePath ()
102
+ // TestLocalArchiveSize test if the local archive size match the DownloadResource size
103
+ func ( r * DownloadResource ) TestLocalArchiveSize () ( bool , error ) {
104
+ filePath , err := r .ArchivePath ()
90
105
if err != nil {
91
- return err
92
- }
93
- stats , err := os .Stat (archivePath )
94
- if os .IsNotExist (err ) {
95
- return errors .New ("Archive does not exist" )
106
+ return false , fmt .Errorf ("getting archive path: %s" , err )
96
107
}
108
+ info , err := os .Stat (filePath )
97
109
if err != nil {
98
- return err
110
+ return false , fmt .Errorf ("getting archive info: %s" , err )
111
+ }
112
+ return info .Size () != r .Size , nil
113
+ }
114
+
115
+ // TestLocalArchiveIntegrity checks for integrity of the local archive.
116
+ func (r * DownloadResource ) TestLocalArchiveIntegrity () (bool , error ) {
117
+ if cached , err := r .IsCached (); err != nil {
118
+ return false , fmt .Errorf ("testing if archive is cached: %s" , err )
119
+ } else if ! cached {
120
+ return false , nil
99
121
}
100
- if stats .Size () > release .Size {
101
- return errors .New ("Archive size does not match with specification of this release, assuming corruption" )
122
+
123
+ if ok , err := r .TestLocalArchiveSize (); err != nil {
124
+ return false , fmt .Errorf ("teting archive size: %s" , err )
125
+ } else if ! ok {
126
+ return false , nil
102
127
}
103
- if ! checksumMatches (release ) {
104
- return errors .New ("Checksum does not match, assuming corruption" )
128
+
129
+ ok , err := r .TestLocalArchiveChecksum ()
130
+ if err != nil {
131
+ return false , fmt .Errorf ("testing archive checksum: %s" , err )
105
132
}
106
- return nil
133
+ return ok , nil
107
134
}
108
135
109
136
const (
0 commit comments