// 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 loop implements an interface to configure Linux loop devices.
//
// This package requires Linux 5.8 or higher because it uses the newer LOOP_CONFIGURE ioctl, which is better-behaved
// and twice as fast as the old approach. It doesn't support all of the cryptloop functionality as it has been
// superseded by dm-crypt and has known vulnerabilities. It also doesn't support on-the-fly reconfiguration of loop
// devices as this is rather unusual, works only under very specific circumstances and would make the API less clean.
package loop

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/bits"
	"os"
	"sync"
	"syscall"
	"unsafe"

	"golang.org/x/sys/unix"
)

// Lazily-initialized file descriptor for the control device /dev/loop-control (singleton)
var (
	mutex         sync.Mutex
	loopControlFd *os.File
)

const (
	// LOOP_CONFIGURE from @linux//include/uapi/linux:loop.h
	loopConfigure = 0x4C0A
	// LOOP_MAJOR from @linux//include/uapi/linux:major.h
	loopMajor = 7
)

// struct loop_config from @linux//include/uapi/linux:loop.h
type loopConfig struct {
	fd        uint32
	blockSize uint32 // Power of 2 between 512 and os.Getpagesize(), defaults reasonably
	info      loopInfo64
	_reserved [64]byte
}

// struct loop_info64 from @linux//include/uapi/linux:loop.h
type loopInfo64 struct {
	device         uint64
	inode          uint64
	rdevice        uint64
	offset         uint64 // used
	sizeLimit      uint64 // used
	number         uint32
	encryptType    uint32
	encryptKeySize uint32
	flags          uint32   // Flags from Flag constant
	filename       [64]byte // used
	cryptname      [64]byte
	encryptkey     [32]byte
	init           [2]uint64
}

type Config struct {
	// Block size of the loop device in bytes. Power of 2 between 512 and page size.
	// Zero defaults to an reasonable block size.
	BlockSize uint32
	// Combination of flags from the Flag constants in this package.
	Flags uint32
	// Offset in bytes from the start of the file to the first byte of the device. Usually zero.
	Offset uint64
	// Maximum size of the loop device in bytes. Zero defaults to the whole file.
	SizeLimit uint64
}

func (c *Config) validate() error {
	// Additional validation because of inconsistent kernel-side enforcement
	if c.BlockSize != 0 {
		if c.BlockSize < 512 || c.BlockSize > uint32(os.Getpagesize()) || bits.OnesCount32(c.BlockSize) > 1 {
			return errors.New("BlockSize needs to be a power of two between 512 bytes and the OS page size")
		}
	}
	return nil
}

// ensureFds lazily initializes control devices
func ensureFds() (err error) {
	mutex.Lock()
	defer mutex.Unlock()
	if loopControlFd != nil {
		return
	}
	loopControlFd, err = os.Open("/dev/loop-control")
	return
}

// Device represents a loop device.
type Device struct {
	num uint32
	dev *os.File

	closed bool
}

// All from @linux//include/uapi/linux:loop.h
const (
	// Makes the loop device read-only even if the backing file is read-write.
	FlagReadOnly = 1
	// Unbinds the backing file as soon as the last user is gone. Useful for unbinding after unmount.
	FlagAutoclear = 4
	// Enables kernel-side partition scanning on the loop device. Needed if you want to access specific partitions on
	// a loop device.
	FlagPartscan = 8
	// Enables direct IO for the loop device, bypassing caches and buffer copying.
	FlagDirectIO = 16
)

// Create creates a new loop device backed with the given file.
func Create(f *os.File, c Config) (*Device, error) {
	if err := c.validate(); err != nil {
		return nil, err
	}
	if err := ensureFds(); err != nil {
		return nil, fmt.Errorf("failed to access loop control device: %w", err)
	}
	for {
		devNum, _, errno := syscall.Syscall(unix.SYS_IOCTL, loopControlFd.Fd(), unix.LOOP_CTL_GET_FREE, 0)
		if errno != unix.Errno(0) {
			return nil, fmt.Errorf("failed to allocate loop device: %w", os.NewSyscallError("ioctl(LOOP_CTL_GET_FREE)", errno))
		}
		dev, err := os.OpenFile(fmt.Sprintf("/dev/loop%v", devNum), os.O_RDWR|os.O_EXCL, 0)
		if pe, ok := err.(*os.PathError); ok {
			if pe.Err == unix.EBUSY {
				// We have lost the race, get a new device
				continue
			}
		}
		if err != nil {
			return nil, fmt.Errorf("failed to open newly-allocated loop device: %w", err)
		}

		var config loopConfig
		config.fd = uint32(f.Fd())
		config.blockSize = c.BlockSize
		config.info.flags = c.Flags
		config.info.offset = c.Offset
		config.info.sizeLimit = c.SizeLimit

		if _, _, err := syscall.Syscall(unix.SYS_IOCTL, dev.Fd(), loopConfigure, uintptr(unsafe.Pointer(&config))); err != 0 {
			if err == unix.EBUSY {
				// We have lost the race, get a new device
				continue
			}
			return nil, os.NewSyscallError("ioctl(LOOP_CONFIGURE)", err)
		}
		return &Device{dev: dev, num: uint32(devNum)}, nil
	}
}

// Open opens a loop device at the given path. It returns an error if the path is not a loop device.
func Open(path string) (*Device, error) {
	potentialDevice, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("failed to open device: %w", err)
	}
	var loopInfo loopInfo64
	_, _, err = syscall.Syscall(unix.SYS_IOCTL, potentialDevice.Fd(), unix.LOOP_GET_STATUS64, uintptr(unsafe.Pointer(&loopInfo)))
	if err == syscall.Errno(0) {
		return &Device{dev: potentialDevice, num: loopInfo.number}, nil
	}
	potentialDevice.Close()
	if err == syscall.EINVAL {
		return nil, errors.New("not a loop device")
	}
	return nil, fmt.Errorf("failed to determine state of potential loop device: %w", err)
}

func (d *Device) ensureOpen() error {
	if d.closed {
		return errors.New("device is closed")
	}
	return nil
}

// DevPath returns the canonical path of this loop device in /dev.
func (d *Device) DevPath() (string, error) {
	if err := d.ensureOpen(); err != nil {
		return "", err
	}
	return fmt.Sprintf("/dev/loop%d", d.num), nil
}

// Dev returns the Linux device ID of the loop device.
func (d *Device) Dev() (uint64, error) {
	if err := d.ensureOpen(); err != nil {
		return 0, err
	}
	return unix.Mkdev(loopMajor, d.num), nil
}

// BackingFilePath returns the path of the backing file
func (d *Device) BackingFilePath() (string, error) {
	backingFile, err := ioutil.ReadFile(fmt.Sprintf("/sys/block/loop%d/loop/backing_file", d.num))
	if err != nil {
		return "", fmt.Errorf("failed to get backing file path: %w", err)
	}
	return string(backingFile), err
}

// RefreshSize recalculates the size of the loop device based on the config and the size of the backing file.
func (d *Device) RefreshSize() error {
	if err := d.ensureOpen(); err != nil {
		return err
	}
	return unix.IoctlSetInt(int(d.dev.Fd()), unix.LOOP_SET_CAPACITY, 0)
}

// Close closes all file descriptors open to the device. Does not remove the device itself or alter its configuration.
func (d *Device) Close() error {
	if err := d.ensureOpen(); err != nil {
		return err
	}
	d.closed = true
	return d.dev.Close()
}

// Remove removes the loop device.
func (d *Device) Remove() error {
	if err := d.ensureOpen(); err != nil {
		return err
	}
	err := unix.IoctlSetInt(int(d.dev.Fd()), unix.LOOP_CLR_FD, 0)
	if err != nil {
		return err
	}
	if err := d.Close(); err != nil {
		return fmt.Errorf("failed to close device: %w", err)
	}
	if err := unix.IoctlSetInt(int(loopControlFd.Fd()), unix.LOOP_CTL_REMOVE, int(d.num)); err != nil {
		return err
	}
	return nil
}
