// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This wrapper uses syscall.Flock to prevent concurrent adb commands,
// so for now it only builds on platforms that support that system call.
// TODO(#33974): use a more portable library for file locking.

//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd

// This program can be used as go_android_GOARCH_exec by the Go tool.
// It executes binaries on an android device using adb.
package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
)

func adbRun(args string) (int, error) {
	// The exit code of adb is often wrong. In theory it was fixed in 2016
	// (https://code.google.com/p/android/issues/detail?id=3254), but it's
	// still broken on our builders in 2023. Instead, append the exitcode to
	// the output and parse it from there.
	filter, exitStr := newExitCodeFilter(os.Stdout)
	args += "; echo -n " + exitStr + "$?"

	cmd := adbCmd("exec-out", args)
	cmd.Stdout = filter
	// If the adb subprocess somehow hangs, go test will kill this wrapper
	// and wait for our os.Stderr (and os.Stdout) to close as a result.
	// However, if the os.Stderr (or os.Stdout) file descriptors are
	// passed on, the hanging adb subprocess will hold them open and
	// go test will hang forever.
	//
	// Avoid that by wrapping stderr, breaking the short circuit and
	// forcing cmd.Run to use another pipe and goroutine to pass
	// along stderr from adb.
	cmd.Stderr = struct{ io.Writer }{os.Stderr}
	err := cmd.Run()

	// Before we process err, flush any further output and get the exit code.
	exitCode, err2 := filter.Finish()

	if err != nil {
		return 0, fmt.Errorf("adb exec-out %s: %v", args, err)
	}
	return exitCode, err2
}

func adb(args ...string) error {
	if out, err := adbCmd(args...).CombinedOutput(); err != nil {
		fmt.Fprintf(os.Stderr, "adb %s\n%s", strings.Join(args, " "), out)
		return err
	}
	return nil
}

func adbCmd(args ...string) *exec.Cmd {
	if flags := os.Getenv("GOANDROID_ADB_FLAGS"); flags != "" {
		args = append(strings.Split(flags, " "), args...)
	}
	return exec.Command("adb", args...)
}

const (
	deviceRoot   = "/data/local/tmp/go_android_exec"
	deviceGoroot = deviceRoot + "/goroot"
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("go_android_exec: ")
	exitCode, err := runMain()
	if err != nil {
		log.Fatal(err)
	}
	os.Exit(exitCode)
}

func runMain() (int, error) {
	// Concurrent use of adb is flaky, so serialize adb commands.
	// See https://github.com/golang/go/issues/23795 or
	// https://issuetracker.google.com/issues/73230216.
	lockPath := filepath.Join(os.TempDir(), "go_android_exec-adb-lock")
	lock, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		return 0, err
	}
	defer lock.Close()
	if err := syscall.Flock(int(lock.Fd()), syscall.LOCK_EX); err != nil {
		return 0, err
	}

	// In case we're booting a device or emulator alongside all.bash, wait for
	// it to be ready. adb wait-for-device is not enough, we have to
	// wait for sys.boot_completed.
	if err := adb("wait-for-device", "exec-out", "while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;"); err != nil {
		return 0, err
	}

	// Done once per make.bash.
	if err := adbCopyGoroot(); err != nil {
		return 0, err
	}

	// Prepare a temporary directory that will be cleaned up at the end.
	// Binary names can conflict.
	// E.g. template.test from the {html,text}/template packages.
	binName := filepath.Base(os.Args[1])
	deviceGotmp := fmt.Sprintf(deviceRoot+"/%s-%d", binName, os.Getpid())
	deviceGopath := deviceGotmp + "/gopath"
	defer adb("exec-out", "rm", "-rf", deviceGotmp) // Clean up.

	// Determine the package by examining the current working
	// directory, which will look something like
	// "$GOROOT/src/mime/multipart" or "$GOPATH/src/golang.org/x/mobile".
	// We extract everything after the $GOROOT or $GOPATH to run on the
	// same relative directory on the target device.
	importPath, isStd, modPath, modDir, err := pkgPath()
	if err != nil {
		return 0, err
	}
	var deviceCwd string
	if isStd {
		// Note that we use path.Join here instead of filepath.Join:
		// The device paths should be slash-separated even if the go_android_exec
		// wrapper itself is compiled for Windows.
		deviceCwd = path.Join(deviceGoroot, "src", importPath)
	} else {
		deviceCwd = path.Join(deviceGopath, "src", importPath)
		if modDir != "" {
			// In module mode, the user may reasonably expect the entire module
			// to be present. Copy it over.
			deviceModDir := path.Join(deviceGopath, "src", modPath)
			if err := adb("exec-out", "mkdir", "-p", path.Dir(deviceModDir)); err != nil {
				return 0, err
			}
			// We use a single recursive 'adb push' of the module root instead of
			// walking the tree and copying it piecewise. If the directory tree
			// contains nested modules this could push a lot of unnecessary contents,
			// but for the golang.org/x repos it seems to be significantly (~2x)
			// faster than copying one file at a time (via filepath.WalkDir),
			// apparently due to high latency in 'adb' commands.
			if err := adb("push", modDir, deviceModDir); err != nil {
				return 0, err
			}
		} else {
			if err := adb("exec-out", "mkdir", "-p", deviceCwd); err != nil {
				return 0, err
			}
			if err := adbCopyTree(deviceCwd, importPath); err != nil {
				return 0, err
			}

			// Copy .go files from the package.
			goFiles, err := filepath.Glob("*.go")
			if err != nil {
				return 0, err
			}
			if len(goFiles) > 0 {
				args := append(append([]string{"push"}, goFiles...), deviceCwd)
				if err := adb(args...); err != nil {
					return 0, err
				}
			}
		}
	}

	deviceBin := fmt.Sprintf("%s/%s", deviceGotmp, binName)
	if err := adb("push", os.Args[1], deviceBin); err != nil {
		return 0, err
	}

	// Forward SIGQUIT from the go command to show backtraces from
	// the binary instead of from this wrapper.
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGQUIT)
	go func() {
		for range quit {
			// We don't have the PID of the running process; use the
			// binary name instead.
			adb("exec-out", "killall -QUIT "+binName)
		}
	}()
	cmd := `export TMPDIR="` + deviceGotmp + `"` +
		`; export GOROOT="` + deviceGoroot + `"` +
		`; export GOPATH="` + deviceGopath + `"` +
		`; export CGO_ENABLED=0` +
		`; export GOPROXY=` + os.Getenv("GOPROXY") +
		`; export GOCACHE="` + deviceRoot + `/gocache"` +
		`; export PATH="` + deviceGoroot + `/bin":$PATH` +
		`; cd "` + deviceCwd + `"` +
		"; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ")
	code, err := adbRun(cmd)
	signal.Reset(syscall.SIGQUIT)
	close(quit)
	return code, err
}

type exitCodeFilter struct {
	w      io.Writer // Pass through to w
	exitRe *regexp.Regexp
	buf    bytes.Buffer
}

func newExitCodeFilter(w io.Writer) (*exitCodeFilter, string) {
	const exitStr = "exitcode="

	// Build a regexp that matches any prefix of the exit string at the end of
	// the input. We do it this way to avoid assuming anything about the
	// subcommand output (e.g., it might not be \n-terminated).
	var exitReStr strings.Builder
	for i := 1; i <= len(exitStr); i++ {
		fmt.Fprintf(&exitReStr, "%s$|", exitStr[:i])
	}
	// Finally, match the exit string along with an exit code.
	// This is the only case we use a group, and we'll use this
	// group to extract the numeric code.
	fmt.Fprintf(&exitReStr, "%s([0-9]+)$", exitStr)
	exitRe := regexp.MustCompile(exitReStr.String())

	return &exitCodeFilter{w: w, exitRe: exitRe}, exitStr
}

func (f *exitCodeFilter) Write(data []byte) (int, error) {
	n := len(data)
	f.buf.Write(data)
	// Flush to w until a potential match of exitRe
	b := f.buf.Bytes()
	match := f.exitRe.FindIndex(b)
	if match == nil {
		// Flush all of the buffer.
		_, err := f.w.Write(b)
		f.buf.Reset()
		if err != nil {
			return n, err
		}
	} else {
		// Flush up to the beginning of the (potential) match.
		_, err := f.w.Write(b[:match[0]])
		f.buf.Next(match[0])
		if err != nil {
			return n, err
		}
	}
	return n, nil
}

func (f *exitCodeFilter) Finish() (int, error) {
	// f.buf could be empty, contain a partial match of exitRe, or
	// contain a full match.
	b := f.buf.Bytes()
	defer f.buf.Reset()
	match := f.exitRe.FindSubmatch(b)
	if len(match) < 2 || match[1] == nil {
		// Not a full match. Flush.
		if _, err := f.w.Write(b); err != nil {
			return 0, err
		}
		return 0, fmt.Errorf("no exit code (in %q)", string(b))
	}

	// Parse the exit code.
	code, err := strconv.Atoi(string(match[1]))
	if err != nil {
		// Something is malformed. Flush.
		if _, err := f.w.Write(b); err != nil {
			return 0, err
		}
		return 0, fmt.Errorf("bad exit code: %v (in %q)", err, string(b))
	}
	return code, nil
}

// pkgPath determines the package import path of the current working directory,
// and indicates whether it is
// and returns the path to the package source relative to $GOROOT (or $GOPATH).
func pkgPath() (importPath string, isStd bool, modPath, modDir string, err error) {
	errorf := func(format string, args ...any) (string, bool, string, string, error) {
		return "", false, "", "", fmt.Errorf(format, args...)
	}
	goTool, err := goTool()
	if err != nil {
		return errorf("%w", err)
	}
	cmd := exec.Command(goTool, "list", "-e", "-f", "{{.ImportPath}}:{{.Standard}}{{with .Module}}:{{.Path}}:{{.Dir}}{{end}}", ".")
	out, err := cmd.Output()
	if err != nil {
		if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
			return errorf("%v: %s", cmd, ee.Stderr)
		}
		return errorf("%v: %w", cmd, err)
	}

	parts := strings.SplitN(string(bytes.TrimSpace(out)), ":", 4)
	if len(parts) < 2 {
		return errorf("%v: missing ':' in output: %q", cmd, out)
	}
	importPath = parts[0]
	if importPath == "" || importPath == "." {
		return errorf("current directory does not have a Go import path")
	}
	isStd, err = strconv.ParseBool(parts[1])
	if err != nil {
		return errorf("%v: non-boolean .Standard in output: %q", cmd, out)
	}
	if len(parts) >= 4 {
		modPath = parts[2]
		modDir = parts[3]
	}

	return importPath, isStd, modPath, modDir, nil
}

// adbCopyTree copies testdata, go.mod, go.sum files from subdir
// and from parent directories all the way up to the root of subdir.
// go.mod and go.sum files are needed for the go tool modules queries,
// and the testdata directories for tests.  It is common for tests to
// reach out into testdata from parent packages.
func adbCopyTree(deviceCwd, subdir string) error {
	dir := ""
	for {
		for _, name := range []string{"testdata", "go.mod", "go.sum"} {
			hostPath := filepath.Join(dir, name)
			if _, err := os.Stat(hostPath); err != nil {
				continue
			}
			devicePath := path.Join(deviceCwd, dir)
			if err := adb("exec-out", "mkdir", "-p", devicePath); err != nil {
				return err
			}
			if err := adb("push", hostPath, devicePath); err != nil {
				return err
			}
		}
		if subdir == "." {
			break
		}
		subdir = filepath.Dir(subdir)
		dir = path.Join(dir, "..")
	}
	return nil
}

// adbCopyGoroot clears deviceRoot for previous versions of GOROOT, GOPATH
// and temporary data. Then, it copies relevant parts of GOROOT to the device,
// including the go tool built for android.
// A lock file ensures this only happens once, even with concurrent exec
// wrappers.
func adbCopyGoroot() error {
	goTool, err := goTool()
	if err != nil {
		return err
	}
	cmd := exec.Command(goTool, "version")
	cmd.Stderr = os.Stderr
	out, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("%v: %w", cmd, err)
	}
	goVersion := string(out)

	// Also known by cmd/dist. The bootstrap command deletes the file.
	statPath := filepath.Join(os.TempDir(), "go_android_exec-adb-sync-status")
	stat, err := os.OpenFile(statPath, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		return err
	}
	defer stat.Close()
	// Serialize check and copying.
	if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
		return err
	}
	s, err := io.ReadAll(stat)
	if err != nil {
		return err
	}
	if string(s) == goVersion {
		return nil
	}

	goroot, err := findGoroot()
	if err != nil {
		return err
	}

	// Delete the device's GOROOT, GOPATH and any leftover test data,
	// and recreate GOROOT.
	if err := adb("exec-out", "rm", "-rf", deviceRoot); err != nil {
		return err
	}

	// Build Go for Android.
	cmd = exec.Command(goTool, "install", "cmd")
	out, err = cmd.CombinedOutput()
	if err != nil {
		if len(bytes.TrimSpace(out)) > 0 {
			log.Printf("\n%s", out)
		}
		return fmt.Errorf("%v: %w", cmd, err)
	}
	if err := adb("exec-out", "mkdir", "-p", deviceGoroot); err != nil {
		return err
	}

	// Copy the Android tools from the relevant bin subdirectory to GOROOT/bin.
	cmd = exec.Command(goTool, "list", "-f", "{{.Target}}", "cmd/go")
	cmd.Stderr = os.Stderr
	out, err = cmd.Output()
	if err != nil {
		return fmt.Errorf("%v: %w", cmd, err)
	}
	platformBin := filepath.Dir(string(bytes.TrimSpace(out)))
	if platformBin == "." {
		return errors.New("failed to locate cmd/go for target platform")
	}
	if err := adb("push", platformBin, path.Join(deviceGoroot, "bin")); err != nil {
		return err
	}

	// Copy only the relevant subdirectories from pkg: pkg/include and the
	// platform-native binaries in pkg/tool.
	if err := adb("exec-out", "mkdir", "-p", path.Join(deviceGoroot, "pkg", "tool")); err != nil {
		return err
	}
	if err := adb("push", filepath.Join(goroot, "pkg", "include"), path.Join(deviceGoroot, "pkg", "include")); err != nil {
		return err
	}

	cmd = exec.Command(goTool, "list", "-f", "{{.Target}}", "cmd/compile")
	cmd.Stderr = os.Stderr
	out, err = cmd.Output()
	if err != nil {
		return fmt.Errorf("%v: %w", cmd, err)
	}
	platformToolDir := filepath.Dir(string(bytes.TrimSpace(out)))
	if platformToolDir == "." {
		return errors.New("failed to locate cmd/compile for target platform")
	}
	relToolDir, err := filepath.Rel(filepath.Join(goroot), platformToolDir)
	if err != nil {
		return err
	}
	if err := adb("push", platformToolDir, path.Join(deviceGoroot, relToolDir)); err != nil {
		return err
	}

	// Copy all other files from GOROOT.
	dirents, err := os.ReadDir(goroot)
	if err != nil {
		return err
	}
	for _, de := range dirents {
		switch de.Name() {
		case "bin", "pkg":
			// We already created GOROOT/bin and GOROOT/pkg above; skip those.
			continue
		}
		if err := adb("push", filepath.Join(goroot, de.Name()), path.Join(deviceGoroot, de.Name())); err != nil {
			return err
		}
	}

	if _, err := stat.WriteString(goVersion); err != nil {
		return err
	}
	return nil
}

func findGoroot() (string, error) {
	gorootOnce.Do(func() {
		// If runtime.GOROOT reports a non-empty path, assume that it is valid.
		// (It may be empty if this binary was built with -trimpath.)
		gorootPath = runtime.GOROOT()
		if gorootPath != "" {
			return
		}

		// runtime.GOROOT is empty — perhaps go_android_exec was built with
		// -trimpath and GOROOT is unset. Try 'go env GOROOT' as a fallback,
		// assuming that the 'go' command in $PATH is the correct one.

		cmd := exec.Command("go", "env", "GOROOT")
		cmd.Stderr = os.Stderr
		out, err := cmd.Output()
		if err != nil {
			gorootErr = fmt.Errorf("%v: %w", cmd, err)
		}

		gorootPath = string(bytes.TrimSpace(out))
		if gorootPath == "" {
			gorootErr = errors.New("GOROOT not found")
		}
	})

	return gorootPath, gorootErr
}

func goTool() (string, error) {
	goroot, err := findGoroot()
	if err != nil {
		return "", err
	}
	return filepath.Join(goroot, "bin", "go"), nil
}

var (
	gorootOnce sync.Once
	gorootPath string
	gorootErr  error
)
