<commit_before>// Copyright 2017-2019 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package storage

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/rekby/gpt"
)

var (
	// LinuxMountsPath is the standard mountpoint list path
	LinuxMountsPath = "/proc/mounts"
)

// BlockDev maps a device name to a BlockStat structure for a given block device
type BlockDev struct {
	Name   string
	Stat   BlockStat
	FsUUID string
}

// Summary prints a multiline summary of the BlockDev object
// https://www.kernel.org/doc/Documentation/block/stat.txt
func (b BlockDev) Summary() string {
	return fmt.Sprintf(`BlockStat{
    Name: %v
    ReadIOs: %v
    ReadMerges: %v
    ReadSectors: %v
    ReadTicks: %v
    WriteIOs: %v
    WriteMerges: %v
    WriteSectors: %v
    WriteTicks: %v
    InFlight: %v
    IOTicks: %v
    TimeInQueue: %v
}`,
		b.Name,
		b.Stat.ReadIOs,
		b.Stat.ReadMerges,
		b.Stat.ReadSectors,
		b.Stat.ReadTicks,
		b.Stat.WriteIOs,
		b.Stat.WriteMerges,
		b.Stat.WriteSectors,
		b.Stat.WriteTicks,
		b.Stat.InFlight,
		b.Stat.IOTicks,
		b.Stat.TimeInQueue,
	)
}

// BlockStat provides block device information as contained in
// /sys/class/block/<device_name>/stat
type BlockStat struct {
	ReadIOs      uint64
	ReadMerges   uint64
	ReadSectors  uint64
	ReadTicks    uint64
	WriteIOs     uint64
	WriteMerges  uint64
	WriteSectors uint64
	WriteTicks   uint64
	InFlight     uint64
	IOTicks      uint64
	TimeInQueue  uint64
	// Kernel 4.18 added four fields for discard tracking, see
	// https://github.com/torvalds/linux/commit/bdca3c87fb7ad1cc61d231d37eb0d8f90d001e0c
	DiscardIOs     uint64
	DiscardMerges  uint64
	DiscardSectors uint64
	DiscardTicks   uint64
}

// SystemPartitionGUID is the GUID of EFI system partitions
// EFI System partitions have GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
var SystemPartitionGUID = gpt.Guid([...]byte{
	0x28, 0x73, 0x2a, 0xc1,
	0x1f, 0xf8,
	0xd2, 0x11,
	0xba, 0x4b,
	0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b,
})

// BlockStatFromBytes parses a block stat file and returns a BlockStat object.
// The format of the block stat file is the one defined by Linux for
// /sys/class/block/<device_name>/stat
func BlockStatFromBytes(buf []byte) (*BlockStat, error) {
	fields := strings.Fields(string(buf))
	// BlockStat has 11 fields
	if len(fields) < 11 {
		return nil, fmt.Errorf("BlockStatFromBytes: parsing %q: got %d fields(%q), want at least 11", buf, len(fields), fields)
	}
	intfields := make([]uint64, 0)
	for _, field := range fields {
		v, err := strconv.ParseUint(field, 10, 64)
		if err != nil {
			return nil, err
		}
		intfields = append(intfields, v)
	}
	bs := BlockStat{
		ReadIOs:      intfields[0],
		ReadMerges:   intfields[1],
		ReadSectors:  intfields[2],
		ReadTicks:    intfields[3],
		WriteIOs:     intfields[4],
		WriteMerges:  intfields[5],
		WriteSectors: intfields[6],
		WriteTicks:   intfields[7],
		InFlight:     intfields[8],
		IOTicks:      intfields[9],
		TimeInQueue:  intfields[10],
	}
	if len(fields) >= 15 {
		bs.DiscardIOs = intfields[11]
		bs.DiscardMerges = intfields[12]
		bs.DiscardSectors = intfields[13]
		bs.DiscardTicks = intfields[14]
	}
	return &bs, nil
}

// GetBlockStats iterates over /sys/class/block entries and returns a list of
// BlockDev objects, or an error if any
func GetBlockStats() ([]BlockDev, error) {
	blockdevs := make([]BlockDev, 0)
	devnames := make([]string, 0)
	root := "/sys/class/block"
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		rel, err := filepath.Rel(root, path)
		if err != nil {
			return err
		}
		if rel == "." {
			return nil
		}
		devnames = append(devnames, rel)
		return nil
	})
	if err != nil {
		return nil, err
	}
	for _, devname := range devnames {
		fd, err := os.Open(fmt.Sprintf("%s/%s/stat", root, devname))
		if err != nil {
			return nil, err
		}
		defer fd.Close()
		buf, err := ioutil.ReadAll(fd)
		if err != nil {
			return nil, err
		}
		bstat, err := BlockStatFromBytes(buf)
		if err != nil {
			return nil, err
		}
		devpath := path.Join("/dev/", devname)
		uuid := getUUID(devpath)
		blockdevs = append(blockdevs, BlockDev{Name: devname, Stat: *bstat, FsUUID: uuid})
	}
	return blockdevs, nil
}

func getUUID(devpath string) (fsuuid string) {

	fsuuid = tryVFAT(devpath)
	if fsuuid != "" {
		log.Printf("###### FsUUIS in %s: %s", devpath, fsuuid)
		return fsuuid
	}
	fsuuid = tryEXT4(devpath)
	if fsuuid != "" {
		log.Printf("###### FsUUIS in %s: %s", devpath, fsuuid)
		return fsuuid
	}
	log.Printf("###### FsUUIS in %s: NONE", devpath)
	return ""
}

//see https://www.nongnu.org/ext2-doc/ext2.html#DISK-ORGANISATION
const (
	EXT2SprblkOff       = 1024 // Offset of superblock in partition
	EXT2SprblkSize      = 512  // Actually 1024 but most of the last byters are reserved
	EXT2SprblkMagicOff  = 56   // Offset of magic number in suberblock
	EXT2SprblkMagicSize = 2
	EXT2SprblkMagic     = '\uEF53' // fixed value
	EXT2SprblkUUIDOff   = 104      // Offset of UUID in superblock
	EXT2SprblkUUIDSize  = 16
)

func tryEXT4(devname string) (uuid string) {
	log.Printf("try ext4")
	var off int64

	file, err := os.Open(devname)
	if err != nil {
		log.Println(err)
		return ""
	}
	defer file.Close()

	fileinfo, err := file.Stat()
	if err != nil {
		log.Println(err)
		return ""
	}
	fmt.Printf("%s %d\n", fileinfo.Name(), fileinfo.Size())

	// magic number
	b := make([]byte, EXT2SprblkMagicSize)
	off = EXT2SprblkOff + EXT2SprblkMagicOff
	_, err = file.ReadAt(b, off)
	if err != nil {
		log.Println(err)
		return ""
	}
	magic := uint16(b[1])<<8 + uint16(b[0])
	fmt.Printf("magic: 0x%x\n", magic)
	if magic != EXT2SprblkMagic {
		log.Printf("try ext4")
		return ""
	}

	// filesystem UUID
	b = make([]byte, EXT2SprblkUUIDSize)
	off = EXT2SprblkOff + EXT2SprblkUUIDOff
	_, err = file.ReadAt(b, off)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	uuid = fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
		b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8],
		b[9], b[10], b[11], b[12], b[13], b[14], b[15])
	fmt.Printf("UUID=%s\n", uuid)

	return uuid
}

// see https://de.wikipedia.org/wiki/File_Allocation_Table#Aufbau
const (
	FAT32MagicOff  = 82 // Offset of magic number
	FAT32MagicSize = 8
	FAT32Magic     = "FAT32   " // fixed value
	FAT32IDOff     = 67         // Offset of filesystem-ID / serielnumber. Treated as short filesystem UUID
	FAT32IDSize    = 4
)

func tryVFAT(devname string) (uuid string) {
	log.Printf("try vfat")
	var off int64

	file, err := os.Open(devname)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	defer file.Close()

	fileinfo, err := file.Stat()
	if err != nil {
		fmt.Println(err)
		return ""
	}
	fmt.Printf("%s %d\n", fileinfo.Name(), fileinfo.Size())

	// magic number
	b := make([]byte, FAT32MagicSize)
	off = 0 + FAT32MagicOff
	_, err = file.ReadAt(b, off)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	magic := string(b)
	fmt.Printf("magic: %s\n", magic)
	if magic != FAT32Magic {
		log.Printf("no vfat")
		return ""
	}

	// filesystem UUID
	b = make([]byte, FAT32IDSize)
	off = 0 + FAT32IDOff
	_, err = file.ReadAt(b, off)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	uuid = fmt.Sprintf("%02x%02x-%02x%02x",
		b[3], b[2], b[1], b[0])
	fmt.Printf("UUID=%s\n", uuid)

	return uuid
}

// GetGPTTable tries to read a GPT table from the block device described by the
// passed BlockDev object, and returns a gpt.Table object, or an error if any
func GetGPTTable(device BlockDev) (*gpt.Table, error) {
	fd, err := os.Open(fmt.Sprintf("/dev/%s", device.Name))
	if err != nil {
		return nil, err
	}
	defer fd.Close()
	if _, err = fd.Seek(512, io.SeekStart); err != nil {
		return nil, err
	}
	table, err := gpt.ReadTable(fd, 512)
	if err != nil {
		return nil, err
	}
	return &table, nil
}

// FilterEFISystemPartitions returns a list of BlockDev objects whose underlying
// block device is a valid EFI system partition, or an error if any
func FilterEFISystemPartitions(devices []BlockDev) ([]BlockDev, error) {
	return PartitionsByGUID(devices, SystemPartitionGUID.String())
}

// PartitionsByGUID returns a list of BlockDev objects whose underlying
// block device has the given GUID
func PartitionsByGUID(devices []BlockDev, guid string) ([]BlockDev, error) {
	partitions := make([]BlockDev, 0)
	for _, device := range devices {
		table, err := GetGPTTable(device)
		if err != nil {
			log.Printf("Skipping %s: %v", device.Name, err)
			continue
		}
		for _, part := range table.Partitions {
			if part.IsEmpty() {
				continue
			}
			if part.Type.String() == guid {
				partitions = append(partitions, device)
			}
		}
	}
	return partitions, nil
}

// PartitionsByFsUUID returns a list of BlockDev objects whose underlying
// block device has a filesystem with the given UUID
func PartitionsByFsUUID(devices []BlockDev, fsuuid string) []BlockDev {
	partitions := make([]BlockDev, 0)
	for _, device := range devices {
		if device.FsUUID == fsuuid {
			partitions = append(partitions, device)
		}
	}
	return partitions
}

// GetMountpointByDevice gets the mountpoint by given
// device name. Returns on first match
func GetMountpointByDevice(devicePath string) (*string, error) {
	file, err := os.Open(LinuxMountsPath)
	if err != nil {
		return nil, err
	}

	defer file.Close()
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		deviceInfo := strings.Fields(scanner.Text())
		if deviceInfo[0] == devicePath {
			return &deviceInfo[1], nil
		}
	}

	return nil, errors.New("Mountpoint not found")
}
<commit_msg>pkg/storage: add XFS UUID support<commit_after>// Copyright 2017-2019 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package storage

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/rekby/gpt"
)

var (
	// LinuxMountsPath is the standard mountpoint list path
	LinuxMountsPath = "/proc/mounts"
)

// BlockDev maps a device name to a BlockStat structure for a given block device
type BlockDev struct {
	Name   string
	Stat   BlockStat
	FsUUID string
}

// Summary prints a multiline summary of the BlockDev object
// https://www.kernel.org/doc/Documentation/block/stat.txt
func (b BlockDev) Summary() string {
	return fmt.Sprintf(`BlockStat{
    Name: %v
    ReadIOs: %v
    ReadMerges: %v
    ReadSectors: %v
    ReadTicks: %v
    WriteIOs: %v
    WriteMerges: %v
    WriteSectors: %v
    WriteTicks: %v
    InFlight: %v
    IOTicks: %v
    TimeInQueue: %v
}`,
		b.Name,
		b.Stat.ReadIOs,
		b.Stat.ReadMerges,
		b.Stat.ReadSectors,
		b.Stat.ReadTicks,
		b.Stat.WriteIOs,
		b.Stat.WriteMerges,
		b.Stat.WriteSectors,
		b.Stat.WriteTicks,
		b.Stat.InFlight,
		b.Stat.IOTicks,
		b.Stat.TimeInQueue,
	)
}

// BlockStat provides block device information as contained in
// /sys/class/block/<device_name>/stat
type BlockStat struct {
	ReadIOs      uint64
	ReadMerges   uint64
	ReadSectors  uint64
	ReadTicks    uint64
	WriteIOs     uint64
	WriteMerges  uint64
	WriteSectors uint64
	WriteTicks   uint64
	InFlight     uint64
	IOTicks      uint64
	TimeInQueue  uint64
	// Kernel 4.18 added four fields for discard tracking, see
	// https://github.com/torvalds/linux/commit/bdca3c87fb7ad1cc61d231d37eb0d8f90d001e0c
	DiscardIOs     uint64
	DiscardMerges  uint64
	DiscardSectors uint64
	DiscardTicks   uint64
}

// SystemPartitionGUID is the GUID of EFI system partitions
// EFI System partitions have GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
var SystemPartitionGUID = gpt.Guid([...]byte{
	0x28, 0x73, 0x2a, 0xc1,
	0x1f, 0xf8,
	0xd2, 0x11,
	0xba, 0x4b,
	0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b,
})

// BlockStatFromBytes parses a block stat file and returns a BlockStat object.
// The format of the block stat file is the one defined by Linux for
// /sys/class/block/<device_name>/stat
func BlockStatFromBytes(buf []byte) (*BlockStat, error) {
	fields := strings.Fields(string(buf))
	// BlockStat has 11 fields
	if len(fields) < 11 {
		return nil, fmt.Errorf("BlockStatFromBytes: parsing %q: got %d fields(%q), want at least 11", buf, len(fields), fields)
	}
	intfields := make([]uint64, 0)
	for _, field := range fields {
		v, err := strconv.ParseUint(field, 10, 64)
		if err != nil {
			return nil, err
		}
		intfields = append(intfields, v)
	}
	bs := BlockStat{
		ReadIOs:      intfields[0],
		ReadMerges:   intfields[1],
		ReadSectors:  intfields[2],
		ReadTicks:    intfields[3],
		WriteIOs:     intfields[4],
		WriteMerges:  intfields[5],
		WriteSectors: intfields[6],
		WriteTicks:   intfields[7],
		InFlight:     intfields[8],
		IOTicks:      intfields[9],
		TimeInQueue:  intfields[10],
	}
	if len(fields) >= 15 {
		bs.DiscardIOs = intfields[11]
		bs.DiscardMerges = intfields[12]
		bs.DiscardSectors = intfields[13]
		bs.DiscardTicks = intfields[14]
	}
	return &bs, nil
}

// GetBlockStats iterates over /sys/class/block entries and returns a list of
// BlockDev objects, or an error if any
func GetBlockStats() ([]BlockDev, error) {
	blockdevs := make([]BlockDev, 0)
	devnames := make([]string, 0)
	root := "/sys/class/block"
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		rel, err := filepath.Rel(root, path)
		if err != nil {
			return err
		}
		if rel == "." {
			return nil
		}
		devnames = append(devnames, rel)
		return nil
	})
	if err != nil {
		return nil, err
	}
	for _, devname := range devnames {
		buf, err := ioutil.ReadFile(fmt.Sprintf("%s/%s/stat", root, devname))
		if err != nil {
			return nil, err
		}
		bstat, err := BlockStatFromBytes(buf)
		if err != nil {
			return nil, err
		}
		devpath := path.Join("/dev/", devname)
		if uuid, err := getUUID(devpath); err != nil {
			blockdevs = append(blockdevs, BlockDev{Name: devname, Stat: *bstat})
		} else {
			blockdevs = append(blockdevs, BlockDev{Name: devname, Stat: *bstat, FsUUID: uuid})
		}
	}
	return blockdevs, nil
}

func getUUID(devpath string) (string, error) {
	file, err := os.Open(devpath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	fsuuid, err := tryVFAT(file)
	if err == nil {
		return fsuuid, nil
	}
	fsuuid, err = tryEXT4(file)
	if err == nil {
		return fsuuid, nil
	}
	fsuuid, err = tryXFS(file)
	if err == nil {
		return fsuuid, nil
	}
	return "", fmt.Errorf("unknown UUID (not vfat, ext4, nor xfs)")
}

// See https://www.nongnu.org/ext2-doc/ext2.html#DISK-ORGANISATION.
const (
	// Offset of superblock in partition.
	ext2SprblkOff = 1024

	// Offset of magic number in suberblock.
	ext2SprblkMagicOff  = 56
	ext2SprblkMagicSize = 2

	ext2SprblkMagic = 0xEF53

	// Offset of UUID in superblock.
	ext2SprblkUUIDOff  = 104
	ext2SprblkUUIDSize = 16
)

func tryEXT4(file io.ReaderAt) (string, error) {
	var off int64

	// Read magic number.
	b := make([]byte, ext2SprblkMagicSize)
	off = ext2SprblkOff + ext2SprblkMagicOff
	if _, err := file.ReadAt(b, off); err != nil {
		return "", err
	}
	magic := binary.LittleEndian.Uint16(b[:2])
	if magic != ext2SprblkMagic {
		return "", fmt.Errorf("ext4 magic not found")
	}

	// Filesystem UUID.
	b = make([]byte, ext2SprblkUUIDSize)
	off = ext2SprblkOff + ext2SprblkUUIDOff
	if _, err := file.ReadAt(b, off); err != nil {
		return "", err
	}

	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]), nil
}

// See https://de.wikipedia.org/wiki/File_Allocation_Table#Aufbau.
const (
	fat32Magic = "FAT32   "

	// Offset of magic number.
	fat32MagicOff  = 82
	fat32MagicSize = 8

	// Offset of filesystem ID / serial number. Treated as short filesystem UUID.
	fat32IDOff  = 67
	fat32IDSize = 4
)

func tryVFAT(file io.ReaderAt) (string, error) {
	// Read magic number.
	b := make([]byte, fat32MagicSize)
	if _, err := file.ReadAt(b, fat32MagicOff); err != nil {
		return "", err
	}
	magic := string(b)
	if magic != fat32Magic {
		return "", fmt.Errorf("fat32 magic not found")
	}

	// Filesystem UUID.
	b = make([]byte, fat32IDSize)
	if _, err := file.ReadAt(b, fat32IDOff); err != nil {
		return "", err
	}

	return fmt.Sprintf("%02x%02x-%02x%02x", b[3], b[2], b[1], b[0]), nil
}

const (
	xfsMagic     = "XFSB"
	xfsMagicSize = 4
	xfsUUIDOff   = 32
	xfsUUIDSize  = 16
)

func tryXFS(file io.ReaderAt) (string, error) {
	// Read magic number.
	b := make([]byte, xfsMagicSize)
	if _, err := file.ReadAt(b, 0); err != nil {
		return "", err
	}
	magic := string(b)
	if magic != xfsMagic {
		return "", fmt.Errorf("xfs magic not found")
	}

	// Filesystem UUID.
	b = make([]byte, xfsUUIDSize)
	if _, err := file.ReadAt(b, xfsUUIDOff); err != nil {
		return "", err
	}

	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]), nil
}

// GetGPTTable tries to read a GPT table from the block device described by the
// passed BlockDev object, and returns a gpt.Table object, or an error if any
func GetGPTTable(device BlockDev) (*gpt.Table, error) {
	fd, err := os.Open(fmt.Sprintf("/dev/%s", device.Name))
	if err != nil {
		return nil, err
	}
	defer fd.Close()
	if _, err = fd.Seek(512, io.SeekStart); err != nil {
		return nil, err
	}
	table, err := gpt.ReadTable(fd, 512)
	if err != nil {
		return nil, err
	}
	return &table, nil
}

// FilterEFISystemPartitions returns a list of BlockDev objects whose underlying
// block device is a valid EFI system partition, or an error if any
func FilterEFISystemPartitions(devices []BlockDev) ([]BlockDev, error) {
	return PartitionsByGUID(devices, SystemPartitionGUID.String())
}

// PartitionsByGUID returns a list of BlockDev objects whose underlying
// block device has the given GUID
func PartitionsByGUID(devices []BlockDev, guid string) ([]BlockDev, error) {
	partitions := make([]BlockDev, 0)
	for _, device := range devices {
		table, err := GetGPTTable(device)
		if err != nil {
			log.Printf("Skipping %s: %v", device.Name, err)
			continue
		}
		for _, part := range table.Partitions {
			if part.IsEmpty() {
				continue
			}
			if part.Type.String() == guid {
				partitions = append(partitions, device)
			}
		}
	}
	return partitions, nil
}

// PartitionsByFsUUID returns a list of BlockDev objects whose underlying
// block device has a filesystem with the given UUID
func PartitionsByFsUUID(devices []BlockDev, fsuuid string) []BlockDev {
	partitions := make([]BlockDev, 0)
	for _, device := range devices {
		if device.FsUUID == fsuuid {
			partitions = append(partitions, device)
		}
	}
	return partitions
}

// GetMountpointByDevice gets the mountpoint by given
// device name. Returns on first match
func GetMountpointByDevice(devicePath string) (*string, error) {
	file, err := os.Open(LinuxMountsPath)
	if err != nil {
		return nil, err
	}

	defer file.Close()
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		deviceInfo := strings.Fields(scanner.Text())
		if deviceInfo[0] == devicePath {
			return &deviceInfo[1], nil
		}
	}

	return nil, errors.New("Mountpoint not found")
}
<|endoftext|>


<commit_before>package sm2

import (
	"DNA/crypto/sm3"
	"DNA/crypto/util"
	"crypto/aes"
	"crypto/cipher"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha512"
	"errors"
	"io"
	"math/big"
)

type zr struct {
	io.Reader
}

const (
	aesIV  = "IV for <SM2> CTR"
	USERID = "1234567812345678"
)

var zeroReader = &zr{}
var p256_sm2 *elliptic.CurveParams
var one = new(big.Int).SetInt64(1)

type combinedMult interface {
	CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
}

func (z *zr) Read(dst []byte) (n int, err error) {
	for i := range dst {
		dst[i] = 0
	}
	return len(dst), nil
}

func Init(algSet *util.CryptoAlgSet) {
	p256_sm2 = &elliptic.CurveParams{Name: "SM2-P-256"}
	p256_sm2.P, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
	p256_sm2.N, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
	p256_sm2.B, _ = new(big.Int).SetString("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16)
	p256_sm2.Gx, _ = new(big.Int).SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
	p256_sm2.Gy, _ = new(big.Int).SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
	p256_sm2.BitSize = 256

	algSet.EccParams = *p256_sm2
	algSet.Curve = p256_sm2
}

func randFieldElement(c elliptic.Curve, rand io.Reader) (*big.Int, error) {
	params := c.Params()
	b := make([]byte, params.BitSize/8+8)
	_, err := io.ReadFull(rand, b)
	if err != nil {
		return nil, err
	}

	k := new(big.Int).SetBytes(b)
	n := new(big.Int).Sub(params.N, one)
	n = n.Sub(n, one) //n-2

	// 1 <= k <= n-2
	k.Mod(k, n)
	k.Add(k, one)
	return k, nil
}

func GenKeyPair(algSet *util.CryptoAlgSet) ([]byte, *big.Int, *big.Int, error) {
	k, err := randFieldElement(algSet.Curve, rand.Reader)
	if err != nil {
		return nil, nil, nil, errors.New("Generate key pair error")
	}

	publicKeyX, publicKeyY := algSet.Curve.ScalarBaseMult(k.Bytes())
	return k.Bytes(), publicKeyX, publicKeyY, nil
}

func Sign(algSet *util.CryptoAlgSet, priKey []byte, data []byte) (r *big.Int, s *big.Int, err error) {
	publicKeyX, publicKeyY := algSet.Curve.ScalarBaseMult(priKey)
	hash := sm3.Sum(combineZ(data, publicKeyX, publicKeyY, USERID))
	entropyLen := (algSet.EccParams.BitSize + 7) / 16
	if entropyLen > 32 {
		entropyLen = 32
	}
	entropy := make([]byte, entropyLen)
	_, err = io.ReadFull(rand.Reader, entropy)
	if err != nil {
		return nil, nil, err
	}

	md := sha512.New()
	md.Write(priKey)
	md.Write(entropy)
	md.Write(hash[:])
	key := md.Sum(nil)[:32]

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, nil, err
	}

	cspRng := cipher.StreamReader{
		R: zeroReader,
		S: cipher.NewCTR(block, []byte(aesIV)),
	}

	c := algSet.Curve
	N := c.Params().N
	if N.Sign() == 0 {
		return nil, nil, errors.New("zero parameter")
	}
	var k *big.Int
	e := new(big.Int).SetBytes(hash[:])
	for {
		for {
			k, err = randFieldElement(c, cspRng)
			if err != nil {
				r = nil
				return nil, nil, errors.New("randFieldElement error")
			}

			r, _ = algSet.Curve.ScalarBaseMult(k.Bytes())
			r.Add(r, e)
			r.Mod(r, N)
			if r.Sign() != 0 {
				break
			}
			if t := new(big.Int).Add(r, k); t.Cmp(N) == 0 {
				break
			}
		}
		D := new(big.Int).SetBytes(priKey)
		rD := new(big.Int).Mul(D, r)
		s = new(big.Int).Sub(k, rD)
		d1 := new(big.Int).Add(D, one)
		d1Inv := new(big.Int).ModInverse(d1, N)
		s.Mul(s, d1Inv)
		s.Mod(s, N)
		if s.Sign() != 0 {
			break
		}
	}

	return
}

func Verify(algSet *util.CryptoAlgSet, publicKeyX *big.Int, publicKeyY *big.Int, data []byte, r, s *big.Int) (bool, error) {
	c := algSet.Curve
	N := c.Params().N

	if r.Sign() <= 0 || s.Sign() <= 0 {
		return false, errors.New("SM2 signature contained zero or negative values")
	}
	if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
		return false, errors.New("SM2 signature contained zero or negative values")
	}

	t := new(big.Int).Add(r, s)
	t.Mod(t, N)
	if N.Sign() == 0 {
		return false, errors.New("SM2 Params N contained zero or negative values")
	}

	var x *big.Int
	if opt, ok := c.(combinedMult); ok {
		x, _ = opt.CombinedMult(publicKeyX, publicKeyY, s.Bytes(), t.Bytes())
	} else {
		x1, y1 := c.ScalarBaseMult(s.Bytes())
		x2, y2 := c.ScalarMult(publicKeyX, publicKeyY, t.Bytes())
		x, _ = c.Add(x1, y1, x2, y2)
	}

	hash := sm3.Sum(combineZ(data, publicKeyX, publicKeyY, USERID))
	e := new(big.Int).SetBytes(hash[:])
	x.Add(x, e)
	x.Mod(x, N)
	return x.Cmp(r) == 0, nil
}

// Combine the raw data with user ID, curve parameters and public key
// to generate the signed data used in Sign and Verify
func combineZ(raw []byte, publicKeyX, publicKeyY *big.Int, userID string) []byte {
	h := sm3.New()

	id := []byte(userID)
	len := len(id) * 8
	blen := []byte{byte((len >> 8) & 0xff), byte(len & 0xff)}

	h.Write(blen)
	h.Write(id)
	h.Write([]byte("\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC"))
	h.Write(p256_sm2.B.Bytes())
	h.Write(p256_sm2.Gx.Bytes())
	h.Write(p256_sm2.Gy.Bytes())
	h.Write(publicKeyX.Bytes())
	h.Write(publicKeyY.Bytes())
	return append(h.Sum(make([]byte, 0)), raw...)
}
<commit_msg>Add a variable in crypto/sm2/sm2.go<commit_after>package sm2

import (
	"DNA/crypto/sm3"
	"DNA/crypto/util"
	"crypto/aes"
	"crypto/cipher"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha512"
	"errors"
	"io"
	"math/big"
)

type zr struct {
	io.Reader
}

const (
	aesIV  = "IV for <SM2> CTR"
	USERID = "1234567812345678"
)

var paramA *big.Int

var zeroReader = &zr{}
var p256_sm2 *elliptic.CurveParams
var one = new(big.Int).SetInt64(1)

type combinedMult interface {
	CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
}

func (z *zr) Read(dst []byte) (n int, err error) {
	for i := range dst {
		dst[i] = 0
	}
	return len(dst), nil
}

func Init(algSet *util.CryptoAlgSet) {
	p256_sm2 = &elliptic.CurveParams{Name: "SM2-P-256"}
	p256_sm2.P, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
	p256_sm2.N, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
	p256_sm2.B, _ = new(big.Int).SetString("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16)
	p256_sm2.Gx, _ = new(big.Int).SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
	p256_sm2.Gy, _ = new(big.Int).SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
	p256_sm2.BitSize = 256

	paramA, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16)

	algSet.EccParams = *p256_sm2
	algSet.Curve = p256_sm2
}

func randFieldElement(c elliptic.Curve, rand io.Reader) (*big.Int, error) {
	params := c.Params()
	b := make([]byte, params.BitSize/8+8)
	_, err := io.ReadFull(rand, b)
	if err != nil {
		return nil, err
	}

	k := new(big.Int).SetBytes(b)
	n := new(big.Int).Sub(params.N, one)
	n = n.Sub(n, one) //n-2

	// 1 <= k <= n-2
	k.Mod(k, n)
	k.Add(k, one)
	return k, nil
}

func GenKeyPair(algSet *util.CryptoAlgSet) ([]byte, *big.Int, *big.Int, error) {
	k, err := randFieldElement(algSet.Curve, rand.Reader)
	if err != nil {
		return nil, nil, nil, errors.New("Generate key pair error")
	}

	publicKeyX, publicKeyY := algSet.Curve.ScalarBaseMult(k.Bytes())
	return k.Bytes(), publicKeyX, publicKeyY, nil
}

func Sign(algSet *util.CryptoAlgSet, priKey []byte, data []byte) (r *big.Int, s *big.Int, err error) {
	publicKeyX, publicKeyY := algSet.Curve.ScalarBaseMult(priKey)
	hash := sm3.Sum(combineZ(data, publicKeyX, publicKeyY, USERID))
	entropyLen := (algSet.EccParams.BitSize + 7) / 16
	if entropyLen > 32 {
		entropyLen = 32
	}
	entropy := make([]byte, entropyLen)
	_, err = io.ReadFull(rand.Reader, entropy)
	if err != nil {
		return nil, nil, err
	}

	md := sha512.New()
	md.Write(priKey)
	md.Write(entropy)
	md.Write(hash[:])
	key := md.Sum(nil)[:32]

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, nil, err
	}

	cspRng := cipher.StreamReader{
		R: zeroReader,
		S: cipher.NewCTR(block, []byte(aesIV)),
	}

	c := algSet.Curve
	N := c.Params().N
	if N.Sign() == 0 {
		return nil, nil, errors.New("zero parameter")
	}
	var k *big.Int
	e := new(big.Int).SetBytes(hash[:])
	for {
		for {
			k, err = randFieldElement(c, cspRng)
			if err != nil {
				r = nil
				return nil, nil, errors.New("randFieldElement error")
			}

			r, _ = algSet.Curve.ScalarBaseMult(k.Bytes())
			r.Add(r, e)
			r.Mod(r, N)
			if r.Sign() != 0 {
				break
			}
			if t := new(big.Int).Add(r, k); t.Cmp(N) == 0 {
				break
			}
		}
		D := new(big.Int).SetBytes(priKey)
		rD := new(big.Int).Mul(D, r)
		s = new(big.Int).Sub(k, rD)
		d1 := new(big.Int).Add(D, one)
		d1Inv := new(big.Int).ModInverse(d1, N)
		s.Mul(s, d1Inv)
		s.Mod(s, N)
		if s.Sign() != 0 {
			break
		}
	}

	return
}

func Verify(algSet *util.CryptoAlgSet, publicKeyX *big.Int, publicKeyY *big.Int, data []byte, r, s *big.Int) (bool, error) {
	c := algSet.Curve
	N := c.Params().N

	if r.Sign() <= 0 || s.Sign() <= 0 {
		return false, errors.New("SM2 signature contained zero or negative values")
	}
	if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
		return false, errors.New("SM2 signature contained zero or negative values")
	}

	t := new(big.Int).Add(r, s)
	t.Mod(t, N)
	if N.Sign() == 0 {
		return false, errors.New("SM2 Params N contained zero or negative values")
	}

	var x *big.Int
	if opt, ok := c.(combinedMult); ok {
		x, _ = opt.CombinedMult(publicKeyX, publicKeyY, s.Bytes(), t.Bytes())
	} else {
		x1, y1 := c.ScalarBaseMult(s.Bytes())
		x2, y2 := c.ScalarMult(publicKeyX, publicKeyY, t.Bytes())
		x, _ = c.Add(x1, y1, x2, y2)
	}

	hash := sm3.Sum(combineZ(data, publicKeyX, publicKeyY, USERID))
	e := new(big.Int).SetBytes(hash[:])
	x.Add(x, e)
	x.Mod(x, N)
	return x.Cmp(r) == 0, nil
}

// Combine the raw data with user ID, curve parameters and public key
// to generate the signed data used in Sign and Verify
func combineZ(raw []byte, publicKeyX, publicKeyY *big.Int, userID string) []byte {
	h := sm3.New()

	id := []byte(userID)
	len := len(id) * 8
	blen := []byte{byte((len >> 8) & 0xff), byte(len & 0xff)}

	h.Write(blen)
	h.Write(id)
	h.Write(paramA.Bytes())
	h.Write(p256_sm2.B.Bytes())
	h.Write(p256_sm2.Gx.Bytes())
	h.Write(p256_sm2.Gy.Bytes())
	h.Write(publicKeyX.Bytes())
	h.Write(publicKeyY.Bytes())
	return append(h.Sum(make([]byte, 0)), raw...)
}
<|endoftext|>


<commit_before>package model

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestNewTeachersFromIDOrURL(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)
	teachers, err := NewTeachersFromIDsOrURL("1,2")
	r.Nil(err)
	a.Equal(2, len(teachers))

	teachers2, err := NewTeachersFromIDsOrURL("1,2,3,")
	r.Nil(err)
	a.Equal(3, len(teachers2))

	teachers3, err := NewTeachersFromIDsOrURL("")
	r.Error(err)
	a.Equal(0, len(teachers3))
}

func TestTeacherService_CreateOrUpdate(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)

	teacher := &Teacher{
		ID:                1,
		Name:              "Donald",
		CountryID:         688, // Serbia
		Gender:            "male",
		Birthday:          time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC),
		YearsOfExperience: 2,
		FavoriteCount:     100,
		ReviewCount:       50,
		Rating:            5.0,
		LastLessonAt:      time.Date(2018, 3, 1, 11, 10, 0, 0, time.UTC),
	}
	err := teacherService.CreateOrUpdate(teacher)
	r.NoError(err)

	actual, err := teacherService.FindByPK(teacher.ID)
	r.NoError(err)
	a.Equal(teacher.Name, actual.Name)
	a.Equal(LastLessonAt)
}

func TestTeacherService_IncrementFetchErrorCount(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)

	teacher := &Teacher{
		ID:     1,
		Name:   "test",
		Gender: "male",
	}
	err := teacherService.CreateOrUpdate(teacher)
	r.Nil(err)

	err = teacherService.IncrementFetchErrorCount(teacher.ID, 1)
	r.Nil(err)
	teacher2, err := teacherService.FindByPK(teacher.ID)
	r.Nil(err)
	a.Equal(uint8(1), teacher2.FetchErrorCount)
}
<commit_msg>Fix test failure<commit_after>package model

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestNewTeachersFromIDOrURL(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)
	teachers, err := NewTeachersFromIDsOrURL("1,2")
	r.Nil(err)
	a.Equal(2, len(teachers))

	teachers2, err := NewTeachersFromIDsOrURL("1,2,3,")
	r.Nil(err)
	a.Equal(3, len(teachers2))

	teachers3, err := NewTeachersFromIDsOrURL("")
	r.Error(err)
	a.Equal(0, len(teachers3))
}

func TestTeacherService_CreateOrUpdate(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)

	teacher := &Teacher{
		ID:                1,
		Name:              "Donald",
		CountryID:         688, // Serbia
		Gender:            "male",
		Birthday:          time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC),
		YearsOfExperience: 2,
		FavoriteCount:     100,
		ReviewCount:       50,
		Rating:            5.0,
		LastLessonAt:      time.Date(2018, 3, 1, 11, 10, 0, 0, time.UTC),
	}
	err := teacherService.CreateOrUpdate(teacher)
	r.NoError(err)

	actual, err := teacherService.FindByPK(teacher.ID)
	r.NoError(err)
	a.Equal(teacher.Name, actual.Name)
	a.Equal(teacher.LastLessonAt, actual.LastLessonAt)
}

func TestTeacherService_IncrementFetchErrorCount(t *testing.T) {
	a := assert.New(t)
	r := require.New(t)

	teacher := &Teacher{
		ID:     1,
		Name:   "test",
		Gender: "male",
	}
	err := teacherService.CreateOrUpdate(teacher)
	r.Nil(err)

	err = teacherService.IncrementFetchErrorCount(teacher.ID, 1)
	r.Nil(err)
	teacher2, err := teacherService.FindByPK(teacher.ID)
	r.Nil(err)
	a.Equal(uint8(1), teacher2.FetchErrorCount)
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"github.com/artemnikitin/devicefarm-ci-tool/model"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
)

func TestRunJob(t *testing.T) {
	cases := []struct {
		name              string
		project           string
		file              string
		config            *model.RunConfig
		failed            []*model.FailedTest
		pass              bool
		partlyUnavailable bool
		fullyUnavailable  bool
	}{
		{
			name:    "Success run",
			project: "test",
			file:    "main_test.go",
			config:  &model.RunConfig{},
			failed:  []*model.FailedTest{},
			pass:    true,
		},
		{
			name:    "Run with failed tests",
			project: "test",
			file:    "main_test.go",
			config:  &model.RunConfig{},
			failed:  []*model.FailedTest{},
			pass:    false,
		},
		{
			name:    "Run with failed job because of infrastructure issues",
			project: "test",
			file:    "main_test.go",
			config: &model.RunConfig{
				Name: "AWSFail",
			},
			failed: []*model.FailedTest{},
			pass:   false,
		},
		{
			name:              "Run with some devices as unavailable",
			project:           "test",
			file:              "main_test.go",
			config:            &model.RunConfig{},
			failed:            []*model.FailedTest{},
			pass:              true,
			partlyUnavailable: true,
		},
		{
			name:    "Run with all devices as unavailable",
			project: "test",
			file:    "main_test.go",
			config: &model.RunConfig{
				Name: "AWSFail",
			},
			failed:           []*model.FailedTest{},
			pass:             false,
			fullyUnavailable: true,
		},
	}

	for _, v := range cases {
		t.Run(v.name, func(t *testing.T) {
			client := &service.MockClient{}
			if v.config.Name == "AWSFail" {
				client.AWSFail = true
			}
			if v.partlyUnavailable {
				client.PartlyUnavailableDevice = true
			}
			if v.fullyUnavailable {
				client.FullUnavailableDevices = true
			}

			client.FakeServer = service.CreateFakeServer()
			defer client.FakeServer.Close()

			*project = v.project
			*appPath = v.file
			*wait = true
			client.Failed = !v.pass
			client.UploadTest = true

			failed, pass := runJob(client, v.config)
			if pass != v.pass {
				t.Errorf("Test: %s\nTest result expected: %t, actual: %t", v.name, v.pass, pass)
			}
			if len(failed) != len(v.failed) {
				t.Errorf("Test: %s\nNumber of failed tests expected: %d, actual: %d", v.name, len(v.failed), len(failed))
			}
		})
	}
}
<commit_msg>Fix failing test<commit_after>package main

import (
	"testing"

	"github.com/artemnikitin/devicefarm-ci-tool/model"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
)

func TestRunJob(t *testing.T) {
	cases := []struct {
		name              string
		project           string
		file              string
		config            *model.RunConfig
		failed            []*model.FailedTest
		pass              bool
		partlyUnavailable bool
		fullyUnavailable  bool
	}{
		{
			name:    "Success run",
			project: "test",
			file:    "main_test.go",
			config:  &model.RunConfig{},
			failed:  []*model.FailedTest{},
			pass:    true,
		},
		{
			name:    "Run with failed tests",
			project: "test",
			file:    "main_test.go",
			config:  &model.RunConfig{},
			failed:  []*model.FailedTest{{}, {}},
			pass:    false,
		},
		{
			name:    "Run with failed job because of infrastructure issues",
			project: "test",
			file:    "main_test.go",
			config: &model.RunConfig{
				Name: "AWSFail",
			},
			failed: []*model.FailedTest{},
			pass:   false,
		},
		{
			name:              "Run with some devices as unavailable",
			project:           "test",
			file:              "main_test.go",
			config:            &model.RunConfig{},
			failed:            []*model.FailedTest{},
			pass:              true,
			partlyUnavailable: true,
		},
		{
			name:    "Run with all devices as unavailable",
			project: "test",
			file:    "main_test.go",
			config: &model.RunConfig{
				Name: "AWSFail",
			},
			failed:           []*model.FailedTest{},
			pass:             false,
			fullyUnavailable: true,
		},
	}

	for _, v := range cases {
		t.Run(v.name, func(t *testing.T) {
			client := &service.MockClient{}
			if v.config.Name == "AWSFail" {
				client.AWSFail = true
			}
			if v.partlyUnavailable {
				client.PartlyUnavailableDevice = true
			}
			if v.fullyUnavailable {
				client.FullUnavailableDevices = true
			}

			client.FakeServer = service.CreateFakeServer()
			defer client.FakeServer.Close()

			*project = v.project
			*appPath = v.file
			*wait = true
			client.Failed = !v.pass
			client.UploadTest = true

			failed, pass := runJob(client, v.config)
			if pass != v.pass {
				t.Errorf("Test: %s\nTest result expected: %t, actual: %t", v.name, v.pass, pass)
			}
			if len(failed) != len(v.failed) {
				t.Errorf("Test: %s\nNumber of failed tests expected: %d, actual: %d", v.name, len(v.failed), len(failed))
			}
		})
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// Package install 一个简短的安装日志显示功能。
// 可以在控制台细粒度地显示安装进程。
//
// 正常安装内容，则显示如下内容：
//  安装模块users...
//      install  users [ok]
//      install  email [ok]
//  完成安装
//
// 安装出错，则显示如下内容：
//  安装模块users...
//      install  users [ok]
//      install  email [falid:message]
//  完成失败
//
// 使用方法：
//  声明一个安装模块
//  i := install.New("admin")
//  defer i.Done()
//
//  i.Event("创建表:users", func()*install.Result{
//      return nil
//  })
//
//  i.Event("创建表:users2", func()*install.Result{
//      err := db.Insert(...)
//      return install.ReturnError(err)
//  })
//
//
//  // 执行安装
//  install.Install()
package install

import (
	"github.com/issue9/term/colors"
	"github.com/issue9/web/modules"
)

var defaultModules = modules.New()

// Module 声明了一个用于安装的模块。
// 所有的安装事件都可以向模块注册，模块会在适当的时候进行初始化。
type Module struct {
	name     string
	deps     []string
	hasError bool
	events   []*event
}

type event struct {
	title string
	fn    func() *Return
}

// New 输出模块开始安装的信息。
func New(module string, deps ...string) *Module {
	return &Module{
		name:     module,
		deps:     deps,
		hasError: false,
		events:   make([]*event, 0, 10),
	}
}

// Event 为当前模块注册安装事件。
//
// name 事件名称。
// fn 事件的处理函数。
func (i *Module) Event(title string, fn func() *Return) {
	i.events = append(i.events, &event{
		title: title,
		fn:    fn,
	})
}

// Events 批量注册事件。
//
// events 为一个 map，键名为事件名称，键值为事件处理函数。
//
// NOTE:事件名称若相同，会相互覆盖。
func (i *Module) Events(events map[string]func() *Return) {
	for title, fn := range events {
		i.Event(title, fn)
	}
}

// Done 完成当前安装模块的所有事件注册
func (i *Module) Done() error {
	return defaultModules.New(i.name, i.run, i.deps...)
}

// 运行当前模块的安装事件。
//
// NOTE: 此函数会作为 modules 包中的模块初始化函数，
// 在初始化所有模块时，根据依赖顺序被调用。
func (i *Module) run() error {
	colorPrint(colors.Green, "安装模块:")
	colorPrintf(colors.Default, "[%v]\n", i.name)

	for _, e := range i.events {
		i.runEvent(e)
	}

	if i.hasError {
		colorPrint(colors.Red, "安装失败!\n\n")
	} else {
		colorPrint(colors.Green, "安装完成!\n\n")
	}
	return nil
}

// 运行一条注册的事件。
func (i *Module) runEvent(e *event) {
	colorPrint(colors.Default, "\t", e.title, "......")

	ret := e.fn()

	if ret != nil && ret.typ == typeFailed {
		i.hasError = true
		colorPrintf(colors.Red, "[FALID:%v]\n", ret.message)
		return
	}

	colorPrint(colors.Green, "[OK")
	if ret != nil && len(ret.message) > 0 {
		colorPrint(colors.Magenta, ":")
		colorPrint(colors.Magenta, ret.message)
	}
	colorPrintln(colors.Green, "]")
}

// Install 安装各个模块
func Install() error {
	return defaultModules.Init()
}

// 打印指定颜色的字符串
func colorPrint(color colors.Color, msg ...interface{}) {
	colors.Print(color, colors.Default, msg...)
}

// 打印指定颜色的字符串并换行
func colorPrintln(color colors.Color, msg ...interface{}) {
	colors.Println(color, colors.Default, msg...)
}

// 打印指定颜色的字符串
func colorPrintf(color colors.Color, msg string, vals ...interface{}) {
	colors.Printf(color, colors.Default, msg, vals...)
}
<commit_msg>去掉 Module.Events 参数的顺序是未知的，若存在前后依赖，有可能出错<commit_after>// Copyright 2017 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// Package install 一个简短的安装日志显示功能。
// 可以在控制台细粒度地显示安装进程。
//
// 正常安装内容，则显示如下内容：
//  安装模块users...
//      install  users [ok]
//      install  email [ok]
//  完成安装
//
// 安装出错，则显示如下内容：
//  安装模块users...
//      install  users [ok]
//      install  email [falid:message]
//  安装失败
//
// 使用方法：
//  声明一个安装模块
//  i := install.New("admin")
//  defer i.Done()
//
//  i.Event("创建表:users", func()*install.Result{
//      return nil
//  })
//
//  i.Event("创建表:users2", func()*install.Result{
//      err := db.Insert(...)
//      return install.ReturnError(err)
//  })
//
//
//  // 执行安装
//  install.Install()
package install

import (
	"github.com/issue9/term/colors"
	"github.com/issue9/web/modules"
)

var defaultModules = modules.New()

// Module 声明了一个用于安装的模块。
// 所有的安装事件都可以向模块注册，模块会在适当的时候进行初始化。
type Module struct {
	name     string
	deps     []string
	hasError bool
	events   []*event
}

type event struct {
	title string
	fn    func() *Return
}

// New 输出模块开始安装的信息。
func New(module string, deps ...string) *Module {
	return &Module{
		name:     module,
		deps:     deps,
		hasError: false,
		events:   make([]*event, 0, 10),
	}
}

// Event 为当前模块注册安装事件。
//
// name 事件名称。
// fn 事件的处理函数。
func (i *Module) Event(title string, fn func() *Return) {
	i.events = append(i.events, &event{
		title: title,
		fn:    fn,
	})
}

// Done 完成当前安装模块的所有事件注册
func (i *Module) Done() error {
	return defaultModules.New(i.name, i.run, i.deps...)
}

// 运行当前模块的安装事件。
//
// NOTE: 此函数会作为 modules 包中的模块初始化函数，
// 在初始化所有模块时，根据依赖顺序被调用。
func (i *Module) run() error {
	colorPrint(colors.Green, "安装模块:")
	colorPrintf(colors.Default, "[%v]\n", i.name)

	for _, e := range i.events {
		i.runEvent(e)
	}

	if i.hasError {
		colorPrint(colors.Red, "安装失败!\n\n")
	} else {
		colorPrint(colors.Green, "安装完成!\n\n")
	}
	return nil
}

// 运行一条注册的事件。
func (i *Module) runEvent(e *event) {
	colorPrint(colors.Default, "\t", e.title, "......")

	ret := e.fn()

	if ret != nil && ret.typ == typeFailed {
		i.hasError = true
		colorPrintf(colors.Red, "[FALID:%v]\n", ret.message)
		return
	}

	colorPrint(colors.Green, "[OK")
	if ret != nil && len(ret.message) > 0 {
		colorPrint(colors.Magenta, ":")
		colorPrint(colors.Magenta, ret.message)
	}
	colorPrintln(colors.Green, "]")
}

// Install 安装各个模块
func Install() error {
	return defaultModules.Init()
}

// 打印指定颜色的字符串
func colorPrint(color colors.Color, msg ...interface{}) {
	colors.Print(color, colors.Default, msg...)
}

// 打印指定颜色的字符串并换行
func colorPrintln(color colors.Color, msg ...interface{}) {
	colors.Println(color, colors.Default, msg...)
}

// 打印指定颜色的字符串
func colorPrintf(color colors.Color, msg string, vals ...interface{}) {
	colors.Printf(color, colors.Default, msg, vals...)
}
<|endoftext|>


<commit_before>package gitnotify

import (
	"encoding/gob"
	"os"

	"github.com/gorilla/sessions"
	"github.com/markbates/goth/gothic"
	"github.com/sairam/kinli"
)

const (
	userInfoProvider = "provider"
	userInfoName     = "name"
	userInfoEmail    = "email"
	userInfoUser     = "user"
	userInfoToken    = "token"

	loginFlash = "Login to customize settings"
)

// InitSession registers and everything related to the user's session
func InitSession() {
	gob.Register(&Authentication{})
	kinli.SessionName = "_git_notify"
	kinli.HomePathNonAuthed = "/home"
	kinli.HomePathAuthed = "/"

	var store = sessions.NewFilesystemStore("./sessions", []byte(os.Getenv("SESSION_FS_STORE")))
	// TODO mark session as httpOnly, secure
	// http://www.gorillatoolkit.org/pkg/sessions#Options
	store.Options = &sessions.Options{
		Path: "/",
		// Domain:   config.serverHostWithoutPort(),  // take from config
		MaxAge:   86400 * 30,                      // 30 days
		HttpOnly: true,                            // to avoid cookie stealing and session is on server side
		Secure:   (config.ServerProto == "https"), // for https
	}

	kinli.SessionStore = store

	// init Gothic
	gothic.Store = store
	gothic.GetProviderName = getProviderName

}

// TODO use gob for encoding. See example here - http://www.gorillatoolkit.org/pkg/sessions

func loginTheUser(hc *kinli.HttpContext, userInfo *Authentication, provider string) {
	hc.SetSessionData("user", userInfo)
	hc.SetSessionData("provider", provider)
	hc.AddFlash("Logged in via " + provider)
}

func isAuthed(hc *kinli.HttpContext) bool {
	provider := hc.GetSessionData("provider")
	data, ok := provider.(string)
	if !ok {
		return false
	}
	if data != "" {
		return true
	}
	return false
}

func getUserInfo(hc *kinli.HttpContext) *Authentication {
	var userInfo *Authentication
	var isUserAuthed = isAuthed(hc)
	var ok = false
	if isUserAuthed {
		data := hc.GetSessionData("user")
		userInfo, ok = data.(*Authentication)
	}
	if !isUserAuthed || !ok {
		userInfo = &Authentication{}
	}

	return userInfo
}
<commit_msg>update sessionname to ignore old info<commit_after>package gitnotify

import (
	"encoding/gob"
	"os"

	"github.com/gorilla/sessions"
	"github.com/markbates/goth/gothic"
	"github.com/sairam/kinli"
)

const (
	userInfoProvider = "provider"
	userInfoName     = "name"
	userInfoEmail    = "email"
	userInfoUser     = "user"
	userInfoToken    = "token"

	loginFlash = "Login to customize settings"
)

// InitSession registers and everything related to the user's session
func InitSession() {
	gob.Register(&Authentication{})
	kinli.SessionName = "_git_notify1"
	kinli.HomePathNonAuthed = "/home"
	kinli.HomePathAuthed = "/"

	var store = sessions.NewFilesystemStore("./sessions", []byte(os.Getenv("SESSION_FS_STORE")))
	// TODO mark session as httpOnly, secure
	// http://www.gorillatoolkit.org/pkg/sessions#Options
	store.Options = &sessions.Options{
		Path: "/",
		// Domain:   config.serverHostWithoutPort(),  // take from config
		MaxAge:   86400 * 30,                      // 30 days
		HttpOnly: true,                            // to avoid cookie stealing and session is on server side
		Secure:   (config.ServerProto == "https"), // for https
	}

	kinli.SessionStore = store

	// init Gothic
	gothic.Store = store
	gothic.GetProviderName = getProviderName

}

// TODO use gob for encoding. See example here - http://www.gorillatoolkit.org/pkg/sessions

func loginTheUser(hc *kinli.HttpContext, userInfo *Authentication, provider string) {
	hc.SetSessionData("user", userInfo)
	hc.SetSessionData("provider", provider)
	hc.AddFlash("Logged in via " + provider)
}

func isAuthed(hc *kinli.HttpContext) bool {
	provider := hc.GetSessionData("provider")
	data, ok := provider.(string)
	if !ok {
		return false
	}
	if data != "" {
		return true
	}
	return false
}

func getUserInfo(hc *kinli.HttpContext) *Authentication {
	var userInfo *Authentication
	var isUserAuthed = isAuthed(hc)
	var ok = false
	if isUserAuthed {
		data := hc.GetSessionData("user")
		userInfo, ok = data.(*Authentication)
	}
	if !isUserAuthed || !ok {
		userInfo = &Authentication{}
	}

	return userInfo
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"github.com/chrislusf/seaweedfs/go/operation"
	"github.com/chrislusf/seaweedfs/go/security"
)

var (
	upload UploadOptions
)

type UploadOptions struct {
	server      *string
	dir         *string
	include     *string
	replication *string
	collection  *string
	ttl         *string
	maxMB       *int
	secretKey   *string
}

func init() {
	cmdUpload.Run = runUpload // break init cycle
	cmdUpload.IsDebug = cmdUpload.Flag.Bool("debug", false, "verbose debug information")
	upload.server = cmdUpload.Flag.String("server", "localhost:9333", "SeaweedFS master location")
	upload.dir = cmdUpload.Flag.String("dir", "", "Upload the whole folder recursively if specified.")
	upload.include = cmdUpload.Flag.String("include", "", "pattens of files to upload, e.g., *.pdf, *.html, ab?d.txt, works together with -dir")
	upload.replication = cmdUpload.Flag.String("replication", "", "replication type")
	upload.collection = cmdUpload.Flag.String("collection", "", "optional collection name")
	upload.ttl = cmdUpload.Flag.String("ttl", "", "time to live, e.g.: 1m, 1h, 1d, 1M, 1y")
	upload.maxMB = cmdUpload.Flag.Int("maxMB", 0, "split files larger than the limit")
	upload.secretKey = cmdUpload.Flag.String("secure.secret", "", "secret to encrypt Json Web Token(JWT)")
}

var cmdUpload = &Command{
	UsageLine: "upload -server=localhost:9333 file1 [file2 file3]\n upload -server=localhost:9333 -dir=one_directory -include=*.pdf",
	Short:     "upload one or a list of files",
	Long: `upload one or a list of files, or batch upload one whole folder recursively.

  If uploading a list of files:
  It uses consecutive file keys for the list of files.
  e.g. If the file1 uses key k, file2 can be read via k_1

  If uploading a whole folder recursively:
  All files under the folder and subfolders will be uploaded, each with its own file key.
  Optional parameter "-include" allows you to specify the file name patterns.

  If any file has a ".gz" extension, the content are considered gzipped already, and will be stored as is.
  This can save volume server's gzipped processing and allow customizable gzip compression level.
  The file name will strip out ".gz" and stored. For example, "jquery.js.gz" will be stored as "jquery.js".

  If "maxMB" is set to a positive number, files larger than it would be split into chunks and uploaded separatedly.
  The list of file ids of those chunks would be stored in an additional chunk, and this additional chunk's file id would be returned.

  `,
}

func runUpload(cmd *Command, args []string) bool {
	secret := security.Secret(*upload.secretKey)
	if len(cmdUpload.Flag.Args()) == 0 {
		if *upload.dir == "" {
			return false
		}
		filepath.Walk(*upload.dir, func(path string, info os.FileInfo, err error) error {
			if err == nil {
				if !info.IsDir() {
					if *upload.include != "" {
						if ok, _ := filepath.Match(*upload.include, filepath.Base(path)); !ok {
							return nil
						}
					}
					parts, e := operation.NewFileParts([]string{path})
					if e != nil {
						return e
					}
					results, e := operation.SubmitFiles(*upload.server, parts,
						*upload.replication, *upload.collection,
						*upload.ttl, *upload.maxMB, secret)
					bytes, _ := json.Marshal(results)
					fmt.Println(string(bytes))
					if e != nil {
						return e
					}
				}
			} else {
				fmt.Println(err)
			}
			return err
		})
	} else {
		parts, e := operation.NewFileParts(args)
		if e != nil {
			fmt.Println(e.Error())
		}
		results, _ := operation.SubmitFiles(*upload.server, parts,
			*upload.replication, *upload.collection,
			*upload.ttl, *upload.maxMB, secret)
		bytes, _ := json.Marshal(results)
		fmt.Println(string(bytes))
	}
	return true
}
<commit_msg>adjust usage text to fit the display<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"github.com/chrislusf/seaweedfs/go/operation"
	"github.com/chrislusf/seaweedfs/go/security"
)

var (
	upload UploadOptions
)

type UploadOptions struct {
	server      *string
	dir         *string
	include     *string
	replication *string
	collection  *string
	ttl         *string
	maxMB       *int
	secretKey   *string
}

func init() {
	cmdUpload.Run = runUpload // break init cycle
	cmdUpload.IsDebug = cmdUpload.Flag.Bool("debug", false, "verbose debug information")
	upload.server = cmdUpload.Flag.String("server", "localhost:9333", "SeaweedFS master location")
	upload.dir = cmdUpload.Flag.String("dir", "", "Upload the whole folder recursively if specified.")
	upload.include = cmdUpload.Flag.String("include", "", "pattens of files to upload, e.g., *.pdf, *.html, ab?d.txt, works together with -dir")
	upload.replication = cmdUpload.Flag.String("replication", "", "replication type")
	upload.collection = cmdUpload.Flag.String("collection", "", "optional collection name")
	upload.ttl = cmdUpload.Flag.String("ttl", "", "time to live, e.g.: 1m, 1h, 1d, 1M, 1y")
	upload.maxMB = cmdUpload.Flag.Int("maxMB", 0, "split files larger than the limit")
	upload.secretKey = cmdUpload.Flag.String("secure.secret", "", "secret to encrypt Json Web Token(JWT)")
}

var cmdUpload = &Command{
	UsageLine: "upload -server=localhost:9333 file1 [file2 file3]\n         weed upload -server=localhost:9333 -dir=one_directory -include=*.pdf",
	Short:     "upload one or a list of files",
	Long: `upload one or a list of files, or batch upload one whole folder recursively.

  If uploading a list of files:
  It uses consecutive file keys for the list of files.
  e.g. If the file1 uses key k, file2 can be read via k_1

  If uploading a whole folder recursively:
  All files under the folder and subfolders will be uploaded, each with its own file key.
  Optional parameter "-include" allows you to specify the file name patterns.

  If any file has a ".gz" extension, the content are considered gzipped already, and will be stored as is.
  This can save volume server's gzipped processing and allow customizable gzip compression level.
  The file name will strip out ".gz" and stored. For example, "jquery.js.gz" will be stored as "jquery.js".

  If "maxMB" is set to a positive number, files larger than it would be split into chunks and uploaded separatedly.
  The list of file ids of those chunks would be stored in an additional chunk, and this additional chunk's file id would be returned.

  `,
}

func runUpload(cmd *Command, args []string) bool {
	secret := security.Secret(*upload.secretKey)
	if len(cmdUpload.Flag.Args()) == 0 {
		if *upload.dir == "" {
			return false
		}
		filepath.Walk(*upload.dir, func(path string, info os.FileInfo, err error) error {
			if err == nil {
				if !info.IsDir() {
					if *upload.include != "" {
						if ok, _ := filepath.Match(*upload.include, filepath.Base(path)); !ok {
							return nil
						}
					}
					parts, e := operation.NewFileParts([]string{path})
					if e != nil {
						return e
					}
					results, e := operation.SubmitFiles(*upload.server, parts,
						*upload.replication, *upload.collection,
						*upload.ttl, *upload.maxMB, secret)
					bytes, _ := json.Marshal(results)
					fmt.Println(string(bytes))
					if e != nil {
						return e
					}
				}
			} else {
				fmt.Println(err)
			}
			return err
		})
	} else {
		parts, e := operation.NewFileParts(args)
		if e != nil {
			fmt.Println(e.Error())
		}
		results, _ := operation.SubmitFiles(*upload.server, parts,
			*upload.replication, *upload.collection,
			*upload.ttl, *upload.maxMB, secret)
		bytes, _ := json.Marshal(results)
		fmt.Println(string(bytes))
	}
	return true
}
<|endoftext|>


<commit_before><commit_msg>feat(API): Added missing private "User funding" methods. (#25)<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/kardianos/service"
)

var args []string = os.Args

type program struct{}

func main() {

	ServiceArg := make([]string, 1)
	ServiceArg[0] = "service"

	var sc = &service.Config{
		Name:        "YourServiceName",
		DisplayName: "YourServiceName",
		Description: "Monitors the YourServiceName applications.",
		Arguments:   ServiceArg,
	}

	prg := &program{}
	s, err := service.New(prg, sc)
	if err != nil {
		fmt.Println(err)
	}

	strCmdArg := getCommandLineargs()

	switch strCmdArg {

	case "install":
		err = s.Install()
		if err != nil {
			fmt.Println("Application service not Installed successfully, ErrorInfo : ", err)
		}

		err = s.Start()
		if err != nil {
			fmt.Println("Application service not Started , ErrorInfo : ", err)
		}
		os.Exit(0)

	case "start":
		err = s.Start()
		if err != nil {
			fmt.Println("Application service not Started , ErrorInfo : ", err)
		}
		os.Exit(0)

	case "stop":
		err = s.Stop()
		if err != nil {
			fmt.Println("Application service not stopped , ErrorInfo : ", err)
		}

		os.Exit(0)

	case "uninstall":
		err = s.Stop()
		if err != nil {
			fmt.Println("Application service not stopped , ErrorInfo : ", err)
		}

		err = s.Uninstall()
		if err != nil {
			fmt.Println("Application service not uninstalled successfully, ErrorInfo : ", err)
		}
		os.Exit(0)
	case "service":
		err = s.Run()
		if err != nil {
			fmt.Println("Application not running properly, ErrorInfo : ", err)
		}

	default:
		fmt.Println("Invalid Argument for executable")
		os.Exit(0)
	}

}

func (p *program) Start(s service.Service) error {
	go p.run()
	return nil
}

func (p *program) Stop(s service.Service) error {
	fmt.Println("########################################## Stopping Application Service ##########################################")
	return nil
}

func getCommandLineargs() (result string) {
	result = args[1]
	return result
}

func (p *program) run() {

	defer func() {
		if errD := recover(); errD != nil {
			fmt.Println("Exception Occurred at run() and Recovered in run(), Error Info: ", errD)
		}
	}()
	fmt.Println("########################################## Application started as Service ##########################################")
	for {
		time.Sleep(time.Second * 1)
		fmt.Println("Process is running as service")
	}
}
<commit_msg>Delete service.go<commit_after><|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"os"
	"runtime"
	"strconv"

	"cloud.google.com/go/pubsub"
	"golang.org/x/net/context"
)

func main() {
	ctx := context.Background()
	projectID := os.Getenv("PROJECT_ID")
	listenHost := os.Getenv("LISTEN_HOST")
	listenPort := os.Getenv("LISTEN_PORT")
	log.Printf("GOPUB Server start\n"+
		"GOMAXPROCS: %v\n"+
		"projectID:  %v\n"+
		"listenHost: %v\n"+
		"listenPort: %v\n"+
		"topicName:  %v\n"+
		"bufferSize: %v",
		runtime.GOMAXPROCS(0),
		projectID,
		listenHost,
		listenPort,
		os.Getenv("GOPUB_TOPIC_NAME"),
		os.Getenv("GOPUB_BUFFER_SIZE"))

	// Creates a client.
	pub_client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		log.Printf("Failed to create client: %v", err)
		return
	}
	topic := createTopicIfNotExists(ctx, pub_client)
	var listen net.Listener

	listen, err = net.Listen("tcp", listenHost+":"+listenPort)
	if err != nil {
		log.Printf("Failed to listen tcp %v", err)
		return
	}
	defer listen.Close()

	for {
		conn, e := listen.Accept()
		if e != nil {
			log.Printf("Failed to accept %v", e)
			return
		}
		connection_handler(conn, ctx, topic)
	}
}

func connection_handler(conn net.Conn, ctx context.Context, topic *pubsub.Topic) {
	defer conn.Close()
	bufferSize, _ := strconv.ParseUint(os.Getenv("GOPUB_BUFFER_SIZE"), 10, 64)
	buf := make([]byte, bufferSize)
	for {
		n, err := conn.Read(buf)
		if err != nil {
			if err.Error() == "EOF" {
				return
			}
			log.Printf("conn.Read error: %v", err)
			return
		}
		go publish_handler(ctx, topic, buf[:n])
		conn.Write(buf[:n])
	}
}

func publish_handler(ctx context.Context, topic *pubsub.Topic, buf []byte) {
	buf_copy := make([]byte, len(buf))
	copy(buf_copy, buf)
	result := topic.Publish(ctx, &pubsub.Message{Data: buf_copy})
	_, err := result.Get(ctx)
	if err != nil {
		log.Printf("Publish error: %v", err)
		return
	}
}

func createTopicIfNotExists(ctx context.Context, c *pubsub.Client) *pubsub.Topic {
	// Create a topic to subscribe to.
	topicName := os.Getenv("GOPUB_TOPIC_NAME")
	t := c.Topic(topicName)
	ok, err := t.Exists(ctx)
	if err != nil {
		log.Printf("Topic not exsits %v", err)
	}
	if ok {
		return t
	}

	t, err = c.CreateTopic(ctx, topicName)
	if err != nil {
		log.Printf("Failed to create the topic: %v", err)
	}
	return t
}
<commit_msg>temp error handling<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"

	"cloud.google.com/go/pubsub"
	"golang.org/x/net/context"
	//"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

type ReceivedData struct {
	Key   string
	Value []byte
}

func NewReceivedData(buf []byte) (*ReceivedData, error) {
	fields := bytes.Fields(buf)
	d := &ReceivedData{}
	if len(fields) == 0 {
		return d, errors.New("Received bytes have not fields")
	}
	d.Key = string(fields[0])
	d.Value = bytes.Join(fields[1:], []byte(" "))
	return d, nil
}

type PubService struct {
	Ctx    context.Context
	Client *pubsub.Client
	Topics map[string]*pubsub.Topic
}

func NewPubService(tm *TopicsMeta) (*PubService, error) {
	ps := &PubService{}
	ps.Ctx = context.Background()
	projectID := os.Getenv("PROJECT_ID")
	client, err := pubsub.NewClient(ps.Ctx, projectID)
	if err != nil {
		return ps, errors.New(fmt.Sprintf("Failed to create client: %v", err))
	}
	ps.Client = client
	ps.Topics, err = ps.getTopics(tm)
	if err != nil {
		return ps, err
	}
	return ps, nil
}
func (s *PubService) getTopics(tm *TopicsMeta) (map[string]*pubsub.Topic, error) {
	topics := make(map[string]*pubsub.Topic)
	if len(tm.Names) == 0 {
		return topics, errors.New("Names is empty")
	}
	for _, name := range tm.Names {
		topics[name] = s.createTopicIfNotExists(name)
		log.Printf("topic %v loaded\n", name)
	}
	return topics, nil
}
func (s *PubService) createTopicIfNotExists(topicName string) *pubsub.Topic {
	t := s.Client.Topic(topicName)
	ok, err := t.Exists(s.Ctx)
	if err != nil {
		log.Printf("Topic not exsits %v", err)
	}
	if ok {
		return t
	}
	t, err = s.Client.CreateTopic(s.Ctx, topicName)
	if err != nil {
		log.Printf("Failed to create the topic: %v", err)
	}
	return t
}
func (s *PubService) publishHandler(buf []byte) error {
	buf_copy := make([]byte, len(buf))
	copy(buf_copy, buf)
	data, err := NewReceivedData(buf_copy)
	if err != nil {
		log.Printf("Error in Received Data: %v", err)
		return err
	}
	topicName := addPrefix(data.Key)
	topic, ok := s.Topics[topicName]
	if ok == false {
		msg := fmt.Sprintf("Topic %v does not exists in config file", topicName)
		log.Print(msg)
		return errors.New(msg)

	}
	result := topic.Publish(s.Ctx, &pubsub.Message{Data: data.Value})
	_, err = result.Get(s.Ctx)
	if err != nil {
		return err
	}
	return nil
}

type TopicsMeta struct {
	Names         []string
	OriginalNames []string
	Count         int
	ConfigString  string
}

func addPrefix(name string) string {
	prefix := os.Getenv("GOPUB_TOPIC_NAME_PREFIX")
	return prefix + name
}
func NewTopicsMeta() (*TopicsMeta, error) {
	configString := os.Getenv("GOPUB_TOPICS")
	configNames := strings.Split(configString, ",")
	if len(configNames) == 0 {
		return &TopicsMeta{}, errors.New("no configName found")
	}
	names := []string{}
	orgNames := []string{}
	for _, name := range configNames {
		names = append(names, addPrefix(name))
		orgNames = append(orgNames, name)
	}

	return &TopicsMeta{
		Names:         names,
		OriginalNames: orgNames,
		Count:         len(names),
		ConfigString:  configString,
	}, nil
}

func main() {
	projectID := os.Getenv("PROJECT_ID")
	listenHost := os.Getenv("LISTEN_HOST")
	listenPort := os.Getenv("LISTEN_PORT")
	topicsMeta, err := NewTopicsMeta()
	if err != nil {
		log.Printf("Failed to create topicsMeta %v", err)
		return
	}
	log.Printf("GOPUB Server start\n"+
		"GOMAXPROCS:              %v\n"+
		"projectID:               %v\n"+
		"topicsMeta.Names:        %v\n"+
		"topicsMeta.ConfigString: %v\n"+
		"topicsMeta.Count:        %v\n"+
		"listenHost:              %v\n"+
		"listenPort:              %v\n"+
		"bufferSize:              %v",
		runtime.GOMAXPROCS(0),
		projectID,
		topicsMeta.Names,
		topicsMeta.ConfigString,
		topicsMeta.Count,
		listenHost,
		listenPort,
		os.Getenv("GOPUB_BUFFER_SIZE"))

	listen, err := net.Listen("tcp", listenHost+":"+listenPort)
	defer listen.Close()
	if err != nil {
		log.Printf("Failed to listen tcp %v", err)
		return
	}
	service, err := NewPubService(topicsMeta)
	if err != nil {
		log.Printf("NewPubService error: %v", err)
		return
	}
	log.Println("PubService created")

	for {
		conn, err := listen.Accept()
		if err != nil {
			log.Printf("Failed to accept %v", err)
			return
		}
		connectionHandler(conn, service)
	}
}

func connectionHandler(conn net.Conn, ps *PubService) {
	defer conn.Close()
	bufferSize, _ := strconv.ParseUint(os.Getenv("GOPUB_BUFFER_SIZE"), 10, 64)
	buf := make([]byte, bufferSize)

	for {
		n, err := conn.Read(buf)
		if err != nil {
			if err.Error() == "EOF" {
				return
			}
			log.Printf("conn.Read error: %v", err)
			return
		}
		go func() {
			err = ps.publishHandler(buf[:n])
			if err != nil {
				log.Printf("publishHandler err: %v", err)
				log.Printf("err type:%v", reflect.TypeOf(err).String())
				if reflect.TypeOf(err).String() == "*grpc.rpcError" {
					log.Printf("reflect.TypeOf(err).String()!!!!!!!!!!!!!!")
				}

			}
		}()
		conn.Write(buf[:n])
	}
}
<|endoftext|>


<commit_before>package db

import (
	"gopkg.in/mgo.v2"
	"os"
)

func GetMongoSession() *mgo.Session {
	mongoUri := os.Getenv("MONGO_URI")
	if len(mongoUri) <= 0 {
		panic("MONGO_URI variable not set!")
	}
	session, err := mgo.Dial(mongoUri)
	if err != nil {
		panic(err)
	}
	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	return session
}

func GetMongoCollection(session *mgo.Session, name string) *mgo.Collection {
	return session.DB("").C(name)
}

type QueryDef func(session *mgo.Session) (result interface{}, err error)
type Command func(session *mgo.Session) (err error)

func Query(session *mgo.Session, query QueryDef) (interface{}, error) {
	newSession := session.Copy()
	defer newSession.Close()
	return query(newSession)
}

func Execute(session *mgo.Session, command Command) error {
	newSession := session.Copy()
	defer newSession.Close()
	return command(newSession)
}
<commit_msg>Added support for SSL, based on https://github.com/hashicorp/vault/blob/b9711d040f4dcf00b95619d323d6bbfeae9ebf76/plugins/database/mongodb/connection_producer.go#L101 implementation<commit_after>package db

import (
	"crypto/tls"
	"errors"
	"gopkg.in/mgo.v2"
	"net"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

/*
Source : https://github.com/hashicorp/vault/blob/master/plugins/database/mongodb/connection_producer.go#L101
*/
func parseMongoURL(rawURL string) (*mgo.DialInfo, error) {
	url, err := url.Parse(rawURL)
	if err != nil {
		return nil, err
	}

	info := mgo.DialInfo{
		Addrs:    strings.Split(url.Host, ","),
		Database: strings.TrimPrefix(url.Path, "/"),
		Timeout:  10 * time.Second,
	}

	if url.User != nil {
		info.Username = url.User.Username()
		info.Password, _ = url.User.Password()
	}

	query := url.Query()
	for key, values := range query {
		var value string
		if len(values) > 0 {
			value = values[0]
		}

		switch key {
		case "authSource":
			info.Source = value
		case "authMechanism":
			info.Mechanism = value
		case "gssapiServiceName":
			info.Service = value
		case "replicaSet":
			info.ReplicaSetName = value
		case "maxPoolSize":
			poolLimit, err := strconv.Atoi(value)
			if err != nil {
				return nil, errors.New("bad value for maxPoolSize: " + value)
			}
			info.PoolLimit = poolLimit
		case "ssl":
			// Unfortunately, mgo doesn't support the ssl parameter in its MongoDB URI parsing logic, so we have to handle that
			// ourselves. See https://github.com/go-mgo/mgo/issues/84
			ssl, err := strconv.ParseBool(value)
			if err != nil {
				return nil, errors.New("bad value for ssl: " + value)
			}
			if ssl {
				info.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
					return tls.Dial("tcp", addr.String(), &tls.Config{})
				}
			}
		case "connect":
			if value == "direct" {
				info.Direct = true
				break
			}
			if value == "replicaSet" {
				break
			}
			fallthrough
		default:
			return nil, errors.New("unsupported connection URL option: " + key + "=" + value)
		}
	}

	return &info, nil
}

func GetMongoSession() *mgo.Session {
	uri := os.Getenv("MONGO_URI")
	if len(uri) <= 0 {
		panic("MONGO_URI variable not set!")
	}

	info, err := parseMongoURL(uri)
	if err != nil {
		panic(err)
	}

	session, err := mgo.DialWithInfo(info)

	if err != nil {
		panic(err)
	}
	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	return session
}

func GetMongoCollection(session *mgo.Session, name string) *mgo.Collection {
	return session.DB("").C(name)
}

type QueryDef func(session *mgo.Session) (result interface{}, err error)
type Command func(session *mgo.Session) (err error)

func Query(session *mgo.Session, query QueryDef) (interface{}, error) {
	newSession := session.Copy()
	defer newSession.Close()
	return query(newSession)
}

func Execute(session *mgo.Session, command Command) error {
	newSession := session.Copy()
	defer newSession.Close()
	return command(newSession)
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Package vm provides an abstract test machine (VM, physical machine, etc)
// interface for the rest of the system.
// For convenience test machines are subsequently collectively called VMs.
// Package wraps vmimpl package interface with some common functionality
// and higher-level interface.
package vm

import (
	"bytes"
	"fmt"
	"os"
	"time"

	"github.com/google/syzkaller/pkg/osutil"
	"github.com/google/syzkaller/pkg/report"
	"github.com/google/syzkaller/syz-manager/mgrconfig"
	"github.com/google/syzkaller/vm/vmimpl"

	// Import all VM implementations, so that users only need to import vm.
	_ "github.com/google/syzkaller/vm/adb"
	_ "github.com/google/syzkaller/vm/gce"
	_ "github.com/google/syzkaller/vm/gvisor"
	_ "github.com/google/syzkaller/vm/isolated"
	_ "github.com/google/syzkaller/vm/kvm"
	_ "github.com/google/syzkaller/vm/odroid"
	_ "github.com/google/syzkaller/vm/qemu"
)

type Pool struct {
	impl    vmimpl.Pool
	workdir string
}

type Instance struct {
	impl    vmimpl.Instance
	workdir string
	index   int
}

var (
	Shutdown   = vmimpl.Shutdown
	ErrTimeout = vmimpl.ErrTimeout
)

type BootErrorer interface {
	BootError() (string, []byte)
}

func Create(cfg *mgrconfig.Config, debug bool) (*Pool, error) {
	env := &vmimpl.Env{
		Name:    cfg.Name,
		OS:      cfg.TargetOS,
		Arch:    cfg.TargetVMArch,
		Workdir: cfg.Workdir,
		Image:   cfg.Image,
		SSHKey:  cfg.SSHKey,
		SSHUser: cfg.SSHUser,
		Debug:   debug,
		Config:  cfg.VM,
	}
	impl, err := vmimpl.Create(cfg.Type, env)
	if err != nil {
		return nil, err
	}
	return &Pool{
		impl:    impl,
		workdir: env.Workdir,
	}, nil
}

func (pool *Pool) Count() int {
	return pool.impl.Count()
}

func (pool *Pool) Create(index int) (*Instance, error) {
	if index < 0 || index >= pool.Count() {
		return nil, fmt.Errorf("invalid VM index %v (count %v)", index, pool.Count())
	}
	workdir, err := osutil.ProcessTempDir(pool.workdir)
	if err != nil {
		return nil, fmt.Errorf("failed to create instance temp dir: %v", err)
	}
	impl, err := pool.impl.Create(workdir, index)
	if err != nil {
		os.RemoveAll(workdir)
		return nil, err
	}
	return &Instance{
		impl:    impl,
		workdir: workdir,
		index:   index,
	}, nil
}

func (inst *Instance) Copy(hostSrc string) (string, error) {
	return inst.impl.Copy(hostSrc)
}

func (inst *Instance) Forward(port int) (string, error) {
	return inst.impl.Forward(port)
}

func (inst *Instance) Run(timeout time.Duration, stop <-chan bool, command string) (
	outc <-chan []byte, errc <-chan error, err error) {
	return inst.impl.Run(timeout, stop, command)
}

func (inst *Instance) Diagnose() bool {
	return inst.impl.Diagnose()
}

func (inst *Instance) Close() {
	inst.impl.Close()
	os.RemoveAll(inst.workdir)
}

// MonitorExecution monitors execution of a program running inside of a VM.
// It detects kernel oopses in output, lost connections, hangs, etc.
// outc/errc is what vm.Instance.Run returns, reporter parses kernel output for oopses.
// If canExit is false and the program exits, it is treated as an error.
// Returns a non-symbolized crash report, or nil if no error happens.
func (inst *Instance) MonitorExecution(outc <-chan []byte, errc <-chan error,
	reporter report.Reporter, canExit bool) (
	rep *report.Report) {
	var output []byte
	waitForOutput := func() {
		timer := time.NewTimer(10 * time.Second).C
		for {
			select {
			case out, ok := <-outc:
				if !ok {
					return
				}
				output = append(output, out...)
			case <-timer:
				return
			}
		}
	}

	matchPos := 0
	const (
		beforeContext = 1024 << 10
		afterContext  = 128 << 10
	)
	extractError := func(defaultError string) *report.Report {
		// Give it some time to finish writing the error message.
		inst.Diagnose()
		waitForOutput()
		if bytes.Contains(output, []byte("SYZ-FUZZER: PREEMPTED")) {
			return nil
		}
		if !reporter.ContainsCrash(output[matchPos:]) {
			if defaultError == "" {
				if canExit {
					return nil
				}
				defaultError = "lost connection to test machine"
			}
			rep := &report.Report{
				Title:      defaultError,
				Output:     output,
				Suppressed: report.IsSuppressed(reporter, output),
			}
			return rep
		}
		rep := reporter.Parse(output[matchPos:])
		if rep == nil {
			panic(fmt.Sprintf("reporter.ContainsCrash/Parse disagree:\n%s", output[matchPos:]))
		}
		start := matchPos + rep.StartPos - beforeContext
		if start < 0 {
			start = 0
		}
		end := matchPos + rep.EndPos + afterContext
		if end > len(output) {
			end = len(output)
		}
		rep.Output = output[start:end]
		rep.StartPos += matchPos - start
		rep.EndPos += matchPos - start
		return rep
	}

	lastExecuteTime := time.Now()
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case err := <-errc:
			switch err {
			case nil:
				// The program has exited without errors,
				// but wait for kernel output in case there is some delayed oops.
				return extractError("")
			case ErrTimeout:
				return nil
			default:
				// Note: connection lost can race with a kernel oops message.
				// In such case we want to return the kernel oops.
				return extractError("lost connection to test machine")
			}
		case out := <-outc:
			lastPos := len(output)
			output = append(output, out...)
			if bytes.Contains(output[lastPos:], executingProgram1) ||
				bytes.Contains(output[lastPos:], executingProgram2) {
				lastExecuteTime = time.Now()
			}
			if reporter.ContainsCrash(output[matchPos:]) {
				return extractError("unknown error")
			}
			if len(output) > 2*beforeContext {
				copy(output, output[len(output)-beforeContext:])
				output = output[:beforeContext]
			}
			matchPos = len(output) - 512
			if matchPos < 0 {
				matchPos = 0
			}
		case <-ticker.C:
			// Detect both "not output whatsoever" and "kernel episodically prints
			// something to console, but fuzzer is not actually executing programs".
			// The timeout used to be 3 mins for a long time.
			// But (1) we were seeing flakes on linux where net namespace
			// destruction can be really slow, and (2) gVisor watchdog timeout
			// is 3 mins + 1/4 of that for checking period = 3m45s.
			// Current linux max timeout is CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
			// and workqueue.watchdog_thresh=140 which both actually result
			// in 140-280s detection delay.
			// So the current timeout is 5 mins (300s).
			// We don't want it to be too long too because it will waste time on real hangs.
			if time.Since(lastExecuteTime) < 5*time.Minute {
				break
			}
			if inst.Diagnose() {
				waitForOutput()
			}
			rep := &report.Report{
				Title:      "no output from test machine",
				Output:     output,
				Suppressed: report.IsSuppressed(reporter, output),
			}
			return rep
		case <-Shutdown:
			return nil
		}
	}
}

var (
	executingProgram1 = []byte("executing program")  // syz-fuzzer output
	executingProgram2 = []byte("executed programs:") // syz-execprog output
)
<commit_msg>vm: refactor MonitorExecution<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Package vm provides an abstract test machine (VM, physical machine, etc)
// interface for the rest of the system.
// For convenience test machines are subsequently collectively called VMs.
// Package wraps vmimpl package interface with some common functionality
// and higher-level interface.
package vm

import (
	"bytes"
	"fmt"
	"os"
	"time"

	"github.com/google/syzkaller/pkg/osutil"
	"github.com/google/syzkaller/pkg/report"
	"github.com/google/syzkaller/syz-manager/mgrconfig"
	"github.com/google/syzkaller/vm/vmimpl"

	// Import all VM implementations, so that users only need to import vm.
	_ "github.com/google/syzkaller/vm/adb"
	_ "github.com/google/syzkaller/vm/gce"
	_ "github.com/google/syzkaller/vm/gvisor"
	_ "github.com/google/syzkaller/vm/isolated"
	_ "github.com/google/syzkaller/vm/kvm"
	_ "github.com/google/syzkaller/vm/odroid"
	_ "github.com/google/syzkaller/vm/qemu"
)

type Pool struct {
	impl    vmimpl.Pool
	workdir string
}

type Instance struct {
	impl    vmimpl.Instance
	workdir string
	index   int
}

var (
	Shutdown   = vmimpl.Shutdown
	ErrTimeout = vmimpl.ErrTimeout
)

type BootErrorer interface {
	BootError() (string, []byte)
}

func Create(cfg *mgrconfig.Config, debug bool) (*Pool, error) {
	env := &vmimpl.Env{
		Name:    cfg.Name,
		OS:      cfg.TargetOS,
		Arch:    cfg.TargetVMArch,
		Workdir: cfg.Workdir,
		Image:   cfg.Image,
		SSHKey:  cfg.SSHKey,
		SSHUser: cfg.SSHUser,
		Debug:   debug,
		Config:  cfg.VM,
	}
	impl, err := vmimpl.Create(cfg.Type, env)
	if err != nil {
		return nil, err
	}
	return &Pool{
		impl:    impl,
		workdir: env.Workdir,
	}, nil
}

func (pool *Pool) Count() int {
	return pool.impl.Count()
}

func (pool *Pool) Create(index int) (*Instance, error) {
	if index < 0 || index >= pool.Count() {
		return nil, fmt.Errorf("invalid VM index %v (count %v)", index, pool.Count())
	}
	workdir, err := osutil.ProcessTempDir(pool.workdir)
	if err != nil {
		return nil, fmt.Errorf("failed to create instance temp dir: %v", err)
	}
	impl, err := pool.impl.Create(workdir, index)
	if err != nil {
		os.RemoveAll(workdir)
		return nil, err
	}
	return &Instance{
		impl:    impl,
		workdir: workdir,
		index:   index,
	}, nil
}

func (inst *Instance) Copy(hostSrc string) (string, error) {
	return inst.impl.Copy(hostSrc)
}

func (inst *Instance) Forward(port int) (string, error) {
	return inst.impl.Forward(port)
}

func (inst *Instance) Run(timeout time.Duration, stop <-chan bool, command string) (
	outc <-chan []byte, errc <-chan error, err error) {
	return inst.impl.Run(timeout, stop, command)
}

func (inst *Instance) Diagnose() bool {
	return inst.impl.Diagnose()
}

func (inst *Instance) Close() {
	inst.impl.Close()
	os.RemoveAll(inst.workdir)
}

// MonitorExecution monitors execution of a program running inside of a VM.
// It detects kernel oopses in output, lost connections, hangs, etc.
// outc/errc is what vm.Instance.Run returns, reporter parses kernel output for oopses.
// If canExit is false and the program exits, it is treated as an error.
// Returns a non-symbolized crash report, or nil if no error happens.
func (inst *Instance) MonitorExecution(outc <-chan []byte, errc <-chan error,
	reporter report.Reporter, canExit bool) (rep *report.Report) {
	mon := &monitor{
		inst:     inst,
		outc:     outc,
		errc:     errc,
		reporter: reporter,
		canExit:  canExit,
	}
	lastExecuteTime := time.Now()
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case err := <-errc:
			switch err {
			case nil:
				// The program has exited without errors,
				// but wait for kernel output in case there is some delayed oops.
				return mon.extractError("")
			case ErrTimeout:
				return nil
			default:
				// Note: connection lost can race with a kernel oops message.
				// In such case we want to return the kernel oops.
				return mon.extractError("lost connection to test machine")
			}
		case out := <-outc:
			lastPos := len(mon.output)
			mon.output = append(mon.output, out...)
			if bytes.Contains(mon.output[lastPos:], executingProgram1) ||
				bytes.Contains(mon.output[lastPos:], executingProgram2) {
				lastExecuteTime = time.Now()
			}
			if reporter.ContainsCrash(mon.output[mon.matchPos:]) {
				return mon.extractError("unknown error")
			}
			if len(mon.output) > 2*beforeContext {
				copy(mon.output, mon.output[len(mon.output)-beforeContext:])
				mon.output = mon.output[:beforeContext]
			}
			mon.matchPos = len(mon.output) - maxErrorLength
			if mon.matchPos < 0 {
				mon.matchPos = 0
			}
		case <-ticker.C:
			// Detect both "not output whatsoever" and "kernel episodically prints
			// something to console, but fuzzer is not actually executing programs".
			// The timeout used to be 3 mins for a long time.
			// But (1) we were seeing flakes on linux where net namespace
			// destruction can be really slow, and (2) gVisor watchdog timeout
			// is 3 mins + 1/4 of that for checking period = 3m45s.
			// Current linux max timeout is CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
			// and workqueue.watchdog_thresh=140 which both actually result
			// in 140-280s detection delay.
			// So the current timeout is 5 mins (300s).
			// We don't want it to be too long too because it will waste time on real hangs.
			if time.Since(lastExecuteTime) < 5*time.Minute {
				break
			}
			if inst.Diagnose() {
				mon.waitForOutput()
			}
			rep := &report.Report{
				Title:      "no output from test machine",
				Output:     mon.output,
				Suppressed: report.IsSuppressed(mon.reporter, mon.output),
			}
			return rep
		case <-Shutdown:
			return nil
		}
	}
}

type monitor struct {
	inst     *Instance
	outc     <-chan []byte
	errc     <-chan error
	reporter report.Reporter
	canExit  bool
	output   []byte
	matchPos int
}

func (mon *monitor) extractError(defaultError string) *report.Report {
	// Give it some time to finish writing the error message.
	mon.inst.Diagnose()
	mon.waitForOutput()
	if bytes.Contains(mon.output, []byte("SYZ-FUZZER: PREEMPTED")) {
		return nil
	}
	if !mon.reporter.ContainsCrash(mon.output[mon.matchPos:]) {
		if defaultError == "" {
			if mon.canExit {
				return nil
			}
			defaultError = "lost connection to test machine"
		}
		rep := &report.Report{
			Title:      defaultError,
			Output:     mon.output,
			Suppressed: report.IsSuppressed(mon.reporter, mon.output),
		}
		return rep
	}
	rep := mon.reporter.Parse(mon.output[mon.matchPos:])
	if rep == nil {
		panic(fmt.Sprintf("reporter.ContainsCrash/Parse disagree:\n%s", mon.output[mon.matchPos:]))
	}
	start := mon.matchPos + rep.StartPos - beforeContext
	if start < 0 {
		start = 0
	}
	end := mon.matchPos + rep.EndPos + afterContext
	if end > len(mon.output) {
		end = len(mon.output)
	}
	rep.Output = mon.output[start:end]
	rep.StartPos += mon.matchPos - start
	rep.EndPos += mon.matchPos - start
	return rep
}

func (mon *monitor) waitForOutput() {
	timer := time.NewTimer(10 * time.Second)
	for {
		select {
		case out, ok := <-mon.outc:
			if !ok {
				timer.Stop()
				return
			}
			mon.output = append(mon.output, out...)
		case <-timer.C:
			return
		}
	}
}

const (
	beforeContext  = 1024 << 10
	afterContext   = 128 << 10
	maxErrorLength = 512
)

var (
	executingProgram1 = []byte("executing program")  // syz-fuzzer output
	executingProgram2 = []byte("executed programs:") // syz-execprog output
)
<|endoftext|>