2017-12-29 09:18:30 +00:00
package selfupdate
import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
2017-12-29 10:34:18 +00:00
"path/filepath"
2017-12-29 09:18:30 +00:00
"strings"
)
2017-12-30 08:32:14 +00:00
// UncompressCommand uncompresses the given source. Archive and compression format is automatically detected from 'url' parameter, which represents the URL of asset. This returns a reader for the uncompressed command given by 'cmd'.
func UncompressCommand ( src io . Reader , url , cmd string ) ( io . Reader , error ) {
2017-12-29 09:18:30 +00:00
if strings . HasSuffix ( url , ".zip" ) {
2017-12-30 04:25:42 +00:00
log . Println ( "Uncompressing zip file" , url )
2017-12-29 09:18:30 +00:00
// Zip format requires its file size for uncompressing.
// So we need to read the HTTP response into a buffer at first.
buf , err := ioutil . ReadAll ( src )
if err != nil {
2017-12-29 10:34:18 +00:00
return nil , fmt . Errorf ( "Failed to create buffer for zip file: %s" , err )
2017-12-29 09:18:30 +00:00
}
r := bytes . NewReader ( buf )
z , err := zip . NewReader ( r , r . Size ( ) )
if err != nil {
2017-12-29 10:34:18 +00:00
return nil , fmt . Errorf ( "Failed to uncompress zip file: %s" , err )
2017-12-29 09:18:30 +00:00
}
for _ , file := range z . File {
2017-12-29 10:34:18 +00:00
_ , name := filepath . Split ( file . Name )
if ! file . FileInfo ( ) . IsDir ( ) && name == cmd {
2017-12-29 09:18:30 +00:00
return file . Open ( )
}
}
return nil , fmt . Errorf ( "File '%s' for the command is not found in %s" , cmd , url )
} else if strings . HasSuffix ( url , ".tar.gz" ) {
2017-12-30 04:25:42 +00:00
log . Println ( "Uncompressing tar.gz file" , url )
2017-12-29 09:18:30 +00:00
gz , err := gzip . NewReader ( src )
if err != nil {
2017-12-29 10:34:18 +00:00
return nil , fmt . Errorf ( "Failed to uncompress .tar.gz file: %s" , err )
2017-12-29 09:18:30 +00:00
}
t := tar . NewReader ( gz )
for {
h , err := t . Next ( )
if err == io . EOF {
break
}
if err != nil {
2017-12-29 10:34:18 +00:00
return nil , fmt . Errorf ( "Failed to unarchive .tar file: %s" , err )
2017-12-29 09:18:30 +00:00
}
2017-12-29 10:34:18 +00:00
_ , name := filepath . Split ( h . Name )
if name == cmd {
2017-12-29 09:18:30 +00:00
return t , nil
}
}
return nil , fmt . Errorf ( "File '%s' for the command is not found in %s" , cmd , url )
2017-12-29 10:34:18 +00:00
} else if strings . HasSuffix ( url , ".gzip" ) || strings . HasSuffix ( url , ".gz" ) {
2017-12-30 04:25:42 +00:00
log . Println ( "Uncompressing gzip file" , url )
2017-12-29 10:34:18 +00:00
r , err := gzip . NewReader ( src )
if err != nil {
return nil , fmt . Errorf ( "Failed to uncompress gzip file downloaded from %s: %s" , url , err )
}
name := r . Header . Name
if name != cmd {
return nil , fmt . Errorf ( "File name '%s' does not match to command '%s' found in %s" , name , cmd , url )
}
return r , nil
2017-12-29 09:18:30 +00:00
}
2017-12-30 04:25:42 +00:00
log . Println ( "Uncompression is not needed" , url )
2017-12-29 09:18:30 +00:00
return src , nil
}