306 lines
7.3 KiB
Go
306 lines
7.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"fmt"
|
||
|
"github.com/blakesmith/ar"
|
||
|
"bytes"
|
||
|
"io"
|
||
|
"compress/gzip"
|
||
|
"archive/tar"
|
||
|
"log"
|
||
|
"path/filepath"
|
||
|
"io/ioutil"
|
||
|
"strings"
|
||
|
"crypto/md5"
|
||
|
"crypto/sha1"
|
||
|
"crypto/sha256"
|
||
|
"encoding/hex"
|
||
|
"golang.org/x/crypto/openpgp"
|
||
|
"bufio"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
func inspectPackage(filename string) (string, error) {
|
||
|
f, err := os.Open(filename)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("error opening package file %s: %s", filename, err)
|
||
|
}
|
||
|
|
||
|
arReader := ar.NewReader(f)
|
||
|
defer f.Close()
|
||
|
var controlBuf bytes.Buffer
|
||
|
|
||
|
for {
|
||
|
header, err := arReader.Next()
|
||
|
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("error in inspectPackage loop: %s", err)
|
||
|
}
|
||
|
|
||
|
if strings.Trim(header.Name, "/") == "control.tar.gz" {
|
||
|
io.Copy(&controlBuf, arReader)
|
||
|
return inspectPackageControl(controlBuf)
|
||
|
}
|
||
|
}
|
||
|
return "", nil
|
||
|
}
|
||
|
|
||
|
func inspectPackageControl(filename bytes.Buffer) (string, error) {
|
||
|
gzf, err := gzip.NewReader(bytes.NewReader(filename.Bytes()))
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("error creating gzip reader: %s", err)
|
||
|
}
|
||
|
|
||
|
tarReader := tar.NewReader(gzf)
|
||
|
var controlBuf bytes.Buffer
|
||
|
for {
|
||
|
header, err := tarReader.Next()
|
||
|
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to inspect package: %s", err)
|
||
|
}
|
||
|
|
||
|
name := header.Name
|
||
|
|
||
|
switch header.Typeflag {
|
||
|
case tar.TypeDir:
|
||
|
continue
|
||
|
case tar.TypeReg:
|
||
|
if name == "./control" {
|
||
|
io.Copy(&controlBuf, tarReader)
|
||
|
return controlBuf.String(), nil
|
||
|
}
|
||
|
default:
|
||
|
log.Printf(
|
||
|
"Unable to figure out type : %c in file %s\n",
|
||
|
header.Typeflag, name,
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
return "", nil
|
||
|
}
|
||
|
|
||
|
func createPackagesGz(config Conf, distro, arch string) error {
|
||
|
stdFile, err := os.Create(filepath.Join(config.ArchPath(distro, arch), "Packages"))
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create packages: %s", err)
|
||
|
}
|
||
|
defer stdFile.Close()
|
||
|
|
||
|
gzipFile, err := os.Create(filepath.Join(config.ArchPath(distro, arch), "Packages.gz"))
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create packages.gz: %s", err)
|
||
|
}
|
||
|
defer gzipFile.Close()
|
||
|
|
||
|
gzWriter := gzip.NewWriter(gzipFile)
|
||
|
defer gzWriter.Close()
|
||
|
|
||
|
stdOut := bufio.NewWriter(stdFile)
|
||
|
|
||
|
// loop through each directory
|
||
|
// run inspectPackage
|
||
|
|
||
|
poolPath := config.PoolPath(distro, arch)
|
||
|
|
||
|
dirList, err := ioutil.ReadDir(poolPath)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("scanning: %s: %s", poolPath, err)
|
||
|
}
|
||
|
for _, firstChar := range dirList {
|
||
|
// Recursing isn't fun...
|
||
|
dirList, err := ioutil.ReadDir(filepath.Join(poolPath, firstChar.Name()))
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("scanning: %s: %s", poolPath, err)
|
||
|
}
|
||
|
|
||
|
for _, p := range dirList {
|
||
|
dirList, err := ioutil.ReadDir(filepath.Join(poolPath, firstChar.Name(), p.Name()))
|
||
|
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("scanning: %s: %s", poolPath, err)
|
||
|
}
|
||
|
|
||
|
for _, debFile := range dirList {
|
||
|
if strings.HasSuffix(debFile.Name(), "deb") {
|
||
|
var packBuf bytes.Buffer
|
||
|
debName := packageName(debFile.Name())
|
||
|
debPath := filepath.Join(config.PoolPackagePath(distro, arch, debFile.Name()), debFile.Name())
|
||
|
tempCtlData, err := inspectPackage(debPath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
packBuf.WriteString(tempCtlData)
|
||
|
|
||
|
var size int64 = debFile.Size()
|
||
|
|
||
|
if size == 0 {
|
||
|
if stat, err := os.Stat(debPath); err == nil {
|
||
|
size = stat.Size()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dir := filepath.Join("pool/main", distro, arch, debName[0:1], debName, debFile.Name())
|
||
|
log.Println("path:", dir)
|
||
|
fmt.Fprintf(&packBuf, "Filename: %s\n", strings.Replace(dir, "\\", "/", -1))
|
||
|
fmt.Fprintf(&packBuf, "Size: %d\n", size)
|
||
|
|
||
|
f, err := os.Open(debPath)
|
||
|
|
||
|
if err != nil {
|
||
|
log.Println("error opening deb file: ", err)
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
md5hash = md5.New()
|
||
|
sha1hash = sha1.New()
|
||
|
sha256hash = sha256.New()
|
||
|
)
|
||
|
|
||
|
f.Seek(0, 0)
|
||
|
if _, err := io.Copy(md5hash, f); err != nil {
|
||
|
log.Println("error with the md5 hash: ", err)
|
||
|
}
|
||
|
fmt.Fprintf(&packBuf, "MD5sum: %s\n",
|
||
|
hex.EncodeToString(md5hash.Sum(nil)))
|
||
|
f.Seek(0, 0)
|
||
|
if _, err = io.Copy(sha1hash, f); err != nil {
|
||
|
log.Println("error with the sha1 hash: ", err)
|
||
|
}
|
||
|
fmt.Fprintf(&packBuf, "SHA1: %s\n",
|
||
|
hex.EncodeToString(sha1hash.Sum(nil)))
|
||
|
f.Seek(0, 0)
|
||
|
if _, err = io.Copy(sha256hash, f); err != nil {
|
||
|
log.Println("error with the sha256 hash: ", err)
|
||
|
}
|
||
|
fmt.Fprintf(&packBuf, "SHA256: %s\n",
|
||
|
hex.EncodeToString(sha256hash.Sum(nil)))
|
||
|
packBuf.WriteString("\n\n")
|
||
|
|
||
|
stdOut.Write(packBuf.Bytes())
|
||
|
gzWriter.Write(packBuf.Bytes())
|
||
|
|
||
|
f.Close()
|
||
|
f = nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
stdOut.Flush()
|
||
|
|
||
|
gzWriter.Flush()
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func createRelease(config Conf, distro, arch string) error {
|
||
|
outfile, err := os.Create(filepath.Join(config.DistPath(distro), "Release"))
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create Release: %s", err)
|
||
|
}
|
||
|
defer outfile.Close()
|
||
|
|
||
|
var packBuf bytes.Buffer
|
||
|
fmt.Fprintf(&packBuf, "Suite: %s\n", distro)
|
||
|
fmt.Fprintf(&packBuf, "Architectures: %s\n", arch)
|
||
|
fmt.Fprint(&packBuf, "Components: main\n")
|
||
|
fmt.Fprintf(&packBuf, "Date: %s\n", time.Now().In(time.UTC).Format("Mon, 02 Jan 2006 15:04:05 -0700"))
|
||
|
|
||
|
basePath := filepath.Join("main", "binary-" + arch)
|
||
|
|
||
|
dirList, err := ioutil.ReadDir(filepath.Join(config.DistPath(distro), "main", "binary-" + arch))
|
||
|
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("scanning: %s: %s", config.PoolPath(distro, arch), err)
|
||
|
}
|
||
|
|
||
|
var md5Buf bytes.Buffer
|
||
|
var sha1Buf bytes.Buffer
|
||
|
var sha256Buf bytes.Buffer
|
||
|
|
||
|
for _, file := range dirList {
|
||
|
filePath := filepath.Join(config.DistPath(distro), basePath, file.Name())
|
||
|
|
||
|
log.Println("File path:", filePath)
|
||
|
|
||
|
fileLocalPath := filepath.Join(basePath, file.Name())
|
||
|
|
||
|
fileLocalPath = strings.Replace(fileLocalPath, "\\", "/", -1)
|
||
|
|
||
|
f, err := os.Open(filePath)
|
||
|
|
||
|
if err != nil {
|
||
|
log.Println("error opening source file: ", err)
|
||
|
}
|
||
|
|
||
|
var size int64 = file.Size()
|
||
|
|
||
|
if size == 0 {
|
||
|
if stat, err := os.Stat(filePath); err == nil {
|
||
|
size = stat.Size()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
md5hash = md5.New()
|
||
|
sha1hash = sha1.New()
|
||
|
sha256hash = sha256.New()
|
||
|
)
|
||
|
|
||
|
f.Seek(0, 0)
|
||
|
if _, err := io.Copy(md5hash, f); err != nil {
|
||
|
log.Println("error with the md5 hashing: ", err)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&md5Buf, " %s %d %s\n", hex.EncodeToString(md5hash.Sum(nil)), size, fileLocalPath)
|
||
|
|
||
|
f.Seek(0, 0)
|
||
|
if _, err := io.Copy(sha1hash, f); err != nil {
|
||
|
log.Println("error with the sha1 hashing: ", err)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&sha1Buf, " %s %d %s\n", hex.EncodeToString(sha1hash.Sum(nil)), size, fileLocalPath)
|
||
|
|
||
|
f.Seek(0, 0)
|
||
|
if _, err := io.Copy(sha256hash, f); err != nil {
|
||
|
log.Println("error with the sha256 hashing: ", err)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&sha256Buf, " %s %d %s\n", hex.EncodeToString(sha256hash.Sum(nil)), size, fileLocalPath)
|
||
|
|
||
|
f.Close()
|
||
|
f = nil
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&packBuf, "MD5Sum:\n%s", string(md5Buf.Bytes()))
|
||
|
fmt.Fprintf(&packBuf, "SHA1:\n%s", string(sha1Buf.Bytes()))
|
||
|
fmt.Fprintf(&packBuf, "SHA256:\n%s", string(sha256Buf.Bytes()))
|
||
|
|
||
|
outfile.Write(packBuf.Bytes())
|
||
|
|
||
|
if pgpEntity != nil {
|
||
|
gpgfile, err := os.Create(filepath.Join(config.DistPath(distro), "Release.gpg"))
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create Release.gpg: %s", err)
|
||
|
}
|
||
|
defer gpgfile.Close()
|
||
|
|
||
|
byteReader := bytes.NewReader(packBuf.Bytes())
|
||
|
|
||
|
if err := openpgp.ArmoredDetachSignText(gpgfile, pgpEntity, byteReader, nil); err != nil {
|
||
|
return fmt.Errorf("failed to sign Release: %s", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|