// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// package devicemapper is a thin wrapper for the devicemapper ioctl API.
// See: https://github.com/torvalds/linux/blob/master/include/uapi/linux/dm-ioctl.h
package devicemapper

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"os"
	"runtime"
	"unsafe"

	"github.com/pkg/errors"
	"github.com/yalue/native_endian"
	"golang.org/x/sys/unix"
)

type DMIoctl struct {
	Version     Version
	DataSize    uint32
	DataStart   uint32
	TargetCount uint32
	OpenCount   int32
	Flags       uint32
	EventNumber uint32
	_padding1   uint32
	Dev         uint64
	Name        [128]byte
	UUID        [129]byte
	_padding2   [7]byte
	Data        [16384]byte
}

type DMTargetSpec struct {
	SectorStart uint64
	Length      uint64
	Status      int32
	Next        uint32
	TargetType  [16]byte
}

type DMTargetDeps struct {
	Count   uint32
	Padding uint32
	Dev     []uint64
}

type DMNameList struct {
	Dev  uint64
	Next uint32
	Name []byte
}

type DMTargetVersions struct {
	Next    uint32
	Version [3]uint32
}

type DMTargetMessage struct {
	Sector  uint64
	Message []byte
}

type Version [3]uint32

const (
	/* Top level cmds */
	DM_VERSION_CMD uintptr = (0xc138fd << 8) + iota
	DM_REMOVE_ALL_CMD
	DM_LIST_DEVICES_CMD

	/* device level cmds */
	DM_DEV_CREATE_CMD
	DM_DEV_REMOVE_CMD
	DM_DEV_RENAME_CMD
	DM_DEV_SUSPEND_CMD
	DM_DEV_STATUS_CMD
	DM_DEV_WAIT_CMD

	/* Table level cmds */
	DM_TABLE_LOAD_CMD
	DM_TABLE_CLEAR_CMD
	DM_TABLE_DEPS_CMD
	DM_TABLE_STATUS_CMD

	/* Added later */
	DM_LIST_VERSIONS_CMD
	DM_TARGET_MSG_CMD
	DM_DEV_SET_GEOMETRY_CMD
	DM_DEV_ARM_POLL_CMD
)

const (
	DM_READONLY_FLAG       = 1 << 0 /* In/Out */
	DM_SUSPEND_FLAG        = 1 << 1 /* In/Out */
	DM_PERSISTENT_DEV_FLAG = 1 << 3 /* In */
)

const baseDataSize = uint32(unsafe.Sizeof(DMIoctl{})) - 16384

func newReq() DMIoctl {
	return DMIoctl{
		Version:   Version{4, 0, 0},
		DataSize:  baseDataSize,
		DataStart: baseDataSize,
	}
}

// stringToDelimitedBuf copies src to dst and returns an error if len(src) >
// len(dst), or when the string contains a null byte.
func stringToDelimitedBuf(dst []byte, src string) error {
	if len(src) > len(dst)-1 {
		return fmt.Errorf("string longer than target buffer (%v > %v)", len(src), len(dst)-1)
	}
	for i := 0; i < len(src); i++ {
		if src[i] == 0x00 {
			return errors.New("string contains null byte, this is unsupported by DM")
		}
		dst[i] = src[i]
	}
	return nil
}

var fd uintptr

func getFd() (uintptr, error) {
	if fd == 0 {
		f, err := os.Open("/dev/mapper/control")
		if os.IsNotExist(err) {
			_ = os.MkdirAll("/dev/mapper", 0755)
			if err := unix.Mknod("/dev/mapper/control", unix.S_IFCHR|0600, int(unix.Mkdev(10, 236))); err != nil {
				return 0, err
			}
			f, err = os.Open("/dev/mapper/control")
			if err != nil {
				return 0, err
			}
		} else if err != nil {
			return 0, err
		}
		fd = f.Fd()
		return f.Fd(), nil
	}
	return fd, nil
}

func GetVersion() (Version, error) {
	req := newReq()
	fd, err := getFd()
	if err != nil {
		return Version{}, err
	}
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, DM_VERSION_CMD, uintptr(unsafe.Pointer(&req))); err != 0 {
		return Version{}, err
	}
	return req.Version, nil
}

func CreateDevice(name string) (uint64, error) {
	req := newReq()
	if err := stringToDelimitedBuf(req.Name[:], name); err != nil {
		return 0, err
	}
	fd, err := getFd()
	if err != nil {
		return 0, err
	}
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, DM_DEV_CREATE_CMD, uintptr(unsafe.Pointer(&req))); err != 0 {
		return 0, err
	}
	return req.Dev, nil
}

func RemoveDevice(name string) error {
	req := newReq()
	if err := stringToDelimitedBuf(req.Name[:], name); err != nil {
		return err
	}
	fd, err := getFd()
	if err != nil {
		return err
	}
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, DM_DEV_REMOVE_CMD, uintptr(unsafe.Pointer(&req))); err != 0 {
		return err
	}
	runtime.KeepAlive(req)
	return nil
}

// Target represents a byte region inside a devicemapper table for a given
// device provided by a given target implementation.
type Target struct {
	// StartSector is the first sector (defined as being 512 bytes long) this
	// target covers.
	StartSector uint64
	// Length is the number of sectors (defined as being 512 bytes long) this
	// target covers, starting from StartSector.
	Length uint64
	// Type is the type of target handling this byte region.
	// Types implemented by the Linux kernel can be found at
	// @linux//drivers/md/... by looking for dm_register_target() calls.
	Type string
	// Parameters are additional parameters specific to the target type.
	Parameters string
}

func LoadTable(name string, readOnly bool, targets []Target) error {
	req := newReq()
	if err := stringToDelimitedBuf(req.Name[:], name); err != nil {
		return err
	}
	var data bytes.Buffer
	for _, target := range targets {
		// Gives the size of the spec and the null-terminated params aligned to 8 bytes
		padding := len(target.Parameters) % 8
		targetSize := uint32(int(unsafe.Sizeof(DMTargetSpec{})) + (len(target.Parameters) + 1) + padding)

		targetSpec := DMTargetSpec{
			SectorStart: target.StartSector,
			Length:      target.Length,
			Next:        targetSize,
		}
		if err := stringToDelimitedBuf(targetSpec.TargetType[:], target.Type); err != nil {
			return err
		}
		if err := binary.Write(&data, native_endian.NativeEndian(), &targetSpec); err != nil {
			panic(err)
		}
		data.WriteString(target.Parameters)
		data.WriteByte(0x00)
		for i := 0; i < padding; i++ {
			data.WriteByte(0x00)
		}
	}
	req.TargetCount = uint32(len(targets))
	if data.Len() >= 16384 {
		return errors.New("table too large for allocated memory")
	}
	req.DataSize = baseDataSize + uint32(data.Len())
	copy(req.Data[:], data.Bytes())
	if readOnly {
		req.Flags = DM_READONLY_FLAG
	}
	fd, err := getFd()
	if err != nil {
		return err
	}
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, DM_TABLE_LOAD_CMD, uintptr(unsafe.Pointer(&req))); err != 0 {
		return err
	}
	runtime.KeepAlive(req)
	return nil
}

func suspendResume(name string, suspend bool) error {
	req := newReq()
	if err := stringToDelimitedBuf(req.Name[:], name); err != nil {
		return err
	}
	if suspend {
		req.Flags = DM_SUSPEND_FLAG
	}
	fd, err := getFd()
	if err != nil {
		return err
	}
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, DM_DEV_SUSPEND_CMD, uintptr(unsafe.Pointer(&req))); err != 0 {
		return err
	}
	runtime.KeepAlive(req)
	return nil
}

func Suspend(name string) error {
	return suspendResume(name, true)
}
func Resume(name string) error {
	return suspendResume(name, false)
}

func CreateActiveDevice(name string, readOnly bool, targets []Target) (uint64, error) {
	dev, err := CreateDevice(name)
	if err != nil {
		return 0, fmt.Errorf("DM_DEV_CREATE failed: %w", err)
	}
	if err := LoadTable(name, readOnly, targets); err != nil {
		_ = RemoveDevice(name)
		return 0, fmt.Errorf("DM_TABLE_LOAD failed: %w", err)
	}
	if err := Resume(name); err != nil {
		_ = RemoveDevice(name)
		return 0, fmt.Errorf("DM_DEV_SUSPEND failed: %w", err)
	}
	return dev, nil
}
