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 }