// Copyright 2018 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 build

import (
	"fmt"
	"path/filepath"
	"runtime"
	"strconv"
	"time"

	"github.com/google/syzkaller/pkg/log"
	"github.com/google/syzkaller/pkg/osutil"
)

type openbsd struct{}

func (ctx openbsd) build(targetArch, vmType, kernelDir, outputDir, compiler, userspaceDir,
	cmdlineFile, sysctlFile string, config []byte) error {
	const kernelName = "SYZKALLER"
	confDir := fmt.Sprintf("%v/sys/arch/%v/conf", kernelDir, targetArch)
	compileDir := fmt.Sprintf("%v/sys/arch/%v/compile/%v", kernelDir, targetArch, kernelName)

	if err := osutil.WriteFile(filepath.Join(confDir, kernelName), config); err != nil {
		return err
	}

	if err := osutil.MkdirAll(compileDir); err != nil {
		return err
	}
	makefile := []byte(".include \"../Makefile.inc\"\n")
	if err := osutil.WriteFile(filepath.Join(compileDir, "Makefile"), makefile); err != nil {
		return err
	}
	for _, tgt := range []string{"clean", "obj", "config", "all"} {
		if err := ctx.make(compileDir, tgt); err != nil {
			return err
		}
	}
	for _, s := range []struct{ dir, src, dst string }{
		{compileDir, "obj/bsd", "kernel"},
		{compileDir, "obj/bsd.gdb", "obj/bsd.gdb"},
		{userspaceDir, "image", "image"},
		{userspaceDir, "key", "key"},
	} {
		fullSrc := filepath.Join(s.dir, s.src)
		fullDst := filepath.Join(outputDir, s.dst)
		if err := osutil.CopyFile(fullSrc, fullDst); err != nil {
			return fmt.Errorf("failed to copy %v -> %v: %v", fullSrc, fullDst, err)
		}
	}
	if vmType == "gce" {
		return ctx.copyFilesToImage(
			filepath.Join(userspaceDir, "overlay"), outputDir)
	}
	return nil
}

func (ctx openbsd) clean(kernelDir, targetArch string) error {
	// Building clean is fast enough and incremental builds in face of
	// changing config files don't work. Instead of optimizing for the
	// case where humans have to think, let's bludgeon it with a
	// machine.
	return nil
}

func (ctx openbsd) make(kernelDir string, args ...string) error {
	args = append([]string{"-j", strconv.Itoa(runtime.NumCPU())}, args...)
	_, err := osutil.RunCmd(10*time.Minute, kernelDir, "make", args...)
	return err
}

// copyFilesToImage populates the filesystem image in outputDir with
// run-specific files. The kernel is copied as /bsd and if overlayDir
// exists, its contents are copied into corresponding files in the
// image.
//
// Ideally a user space tool capable of understanding FFS should
// interpret FFS inside the image file, but vnd(4) device would do in
// a pinch.
func (ctx openbsd) copyFilesToImage(overlayDir, outputDir string) error {
	script := fmt.Sprintf(`set -eux
OVERLAY="%s"
# Cleanup in case something failed before.
doas umount /altroot || true
doas vnconfig -u vnd0 || true

doas /sbin/vnconfig vnd0 image
doas mount /dev/vnd0a /altroot
doas cp kernel /altroot/bsd
test -d "$OVERLAY" && doas cp -Rf "$OVERLAY"/. /altroot
doas umount /altroot
doas vnconfig -u vnd0
`, overlayDir)
	debugOut, err := osutil.RunCmd(10*time.Minute, outputDir, "/bin/sh", "-c", script)
	if err != nil {
		log.Logf(0, "Error copying kernel into image %v\n%v\n", outputDir, debugOut)
	}
	return err
}
