@@ -35,7 +35,6 @@ import (
3535 "crypto/sha256"
3636 "encoding/hex"
3737 "encoding/json"
38- "errors"
3938 "fmt"
4039 "hash"
4140 "io"
@@ -45,65 +44,93 @@ import (
4544 "strings"
4645)
4746
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 ()
5250 if err != nil {
53- return nil , nil
51+ return false , fmt . Errorf ( "getting archive path: %s" , err )
5452 }
5553
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 ] {
5876 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 ()
6280 case "MD5" :
63- return crypto .MD5 .New (), hash
81+ algo = crypto .MD5 .New ()
6482 default :
65- return nil , nil
83+ return false , fmt . Errorf ( "unsupported hash algorithm: %s" , split [ 0 ])
6684 }
67- }
6885
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 )
7386 filePath , err := r .ArchivePath ()
7487 if err != nil {
75- return false
88+ return false , fmt . Errorf ( "getting archive path: %s" , err )
7689 }
7790
7891 file , err := os .Open (filePath )
7992 if err != nil {
80- return false
93+ return false , fmt . Errorf ( "opening archive file: %s" , err )
8194 }
8295 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
85100}
86101
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 ()
90105 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 )
96107 }
108+ info , err := os .Stat (filePath )
97109 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
99121 }
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
102127 }
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 )
105132 }
106- return nil
133+ return ok , nil
107134}
108135
109136const (
0 commit comments