package security

import (
	"os"
	"syscall"
)

// Flock acquires an exclusive advisory lock on the file at path, creating it
// if missing. Returns a release function that MUST be called (deferred) to
// release the lock and close the file descriptor. Used by the known_hosts
// read-modify-write paths (TOFUHostKeyCallback capture + ResetHostKey) to
// prevent concurrent writers under v0.9's parallel SSH fan-out (REQ-063,
// deferred P1 from REVIEW_v0.8 A2).
func Flock(path string) (release func(), err error) {
	f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600)
	if err != nil {
		return nil, err
	}
	// REQ-139 / F15: tighten pre-existing looser perms to 0600.
	// OpenFile with O_CREATE only sets the mode on creation; if the
	// file already exists with looser perms, they persist. Chmod
	// ensures 0600 regardless.
	_ = os.Chmod(path, 0o600)
	if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil {
		f.Close()
		return nil, err
	}
	return func() {
		_ = syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
		_ = f.Close()
	}, nil
}

func tryFlockEx(fd int) error {
	return syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB)
}

func releaseFlock(fd int) error {
	return syscall.Flock(fd, syscall.LOCK_UN)
}
