// Copyright 2019 The Prometheus Authors
// 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 procfs

import (
	"bufio"
	"bytes"
	"fmt"
	"strconv"
	"strings"

	"github.com/prometheus/procfs/internal/util"
)

// A MountInfo is a type that describes the details, options
// for each mount, parsed from /proc/self/mountinfo.
// The fields described in each entry of /proc/self/mountinfo
// is described in the following man page.
// http://man7.org/linux/man-pages/man5/proc.5.html
type MountInfo struct {
	// Unique ID for the mount
	MountID int
	// The ID of the parent mount
	ParentID int
	// The value of `st_dev` for the files on this FS
	MajorMinorVer string
	// The pathname of the directory in the FS that forms
	// the root for this mount
	Root string
	// The pathname of the mount point relative to the root
	MountPoint string
	// Mount options
	Options map[string]string
	// Zero or more optional fields
	OptionalFields map[string]string
	// The Filesystem type
	FSType string
	// FS specific information or "none"
	Source string
	// Superblock options
	SuperOptions map[string]string
}

// Reads each line of the mountinfo file, and returns a list of formatted MountInfo structs.
func parseMountInfo(info []byte) ([]*MountInfo, error) {
	mounts := []*MountInfo{}
	scanner := bufio.NewScanner(bytes.NewReader(info))
	for scanner.Scan() {
		mountString := scanner.Text()
		parsedMounts, err := parseMountInfoString(mountString)
		if err != nil {
			return nil, err
		}
		mounts = append(mounts, parsedMounts)
	}

	err := scanner.Err()
	return mounts, err
}

// Parses a mountinfo file line, and converts it to a MountInfo struct.
// An important check here is to see if the hyphen separator, as if it does not exist,
// it means that the line is malformed.
func parseMountInfoString(mountString string) (*MountInfo, error) {
	var err error

	mountInfo := strings.Split(mountString, " ")
	mountInfoLength := len(mountInfo)
	if mountInfoLength < 10 {
		return nil, fmt.Errorf("couldn't find enough fields in mount string: %s", mountString)
	}

	if mountInfo[mountInfoLength-4] != "-" {
		return nil, fmt.Errorf("couldn't find separator in expected field: %s", mountInfo[mountInfoLength-4])
	}

	mount := &MountInfo{
		MajorMinorVer:  mountInfo[2],
		Root:           mountInfo[3],
		MountPoint:     mountInfo[4],
		Options:        mountOptionsParser(mountInfo[5]),
		OptionalFields: nil,
		FSType:         mountInfo[mountInfoLength-3],
		Source:         mountInfo[mountInfoLength-2],
		SuperOptions:   mountOptionsParser(mountInfo[mountInfoLength-1]),
	}

	mount.MountID, err = strconv.Atoi(mountInfo[0])
	if err != nil {
		return nil, fmt.Errorf("failed to parse mount ID")
	}
	mount.ParentID, err = strconv.Atoi(mountInfo[1])
	if err != nil {
		return nil, fmt.Errorf("failed to parse parent ID")
	}
	// Has optional fields, which is a space separated list of values.
	// Example: shared:2 master:7
	if mountInfo[6] != "" {
		mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4])
		if err != nil {
			return nil, err
		}
	}
	return mount, nil
}

// mountOptionsIsValidField checks a string against a valid list of optional fields keys.
func mountOptionsIsValidField(s string) bool {
	switch s {
	case
		"shared",
		"master",
		"propagate_from",
		"unbindable":
		return true
	}
	return false
}

// mountOptionsParseOptionalFields parses a list of optional fields strings into a double map of strings.
func mountOptionsParseOptionalFields(o []string) (map[string]string, error) {
	optionalFields := make(map[string]string)
	for _, field := range o {
		optionSplit := strings.SplitN(field, ":", 2)
		value := ""
		if len(optionSplit) == 2 {
			value = optionSplit[1]
		}
		if mountOptionsIsValidField(optionSplit[0]) {
			optionalFields[optionSplit[0]] = value
		}
	}
	return optionalFields, nil
}

// mountOptionsParser parses the mount options, superblock options.
func mountOptionsParser(mountOptions string) map[string]string {
	opts := make(map[string]string)
	options := strings.Split(mountOptions, ",")
	for _, opt := range options {
		splitOption := strings.Split(opt, "=")
		if len(splitOption) < 2 {
			key := splitOption[0]
			opts[key] = ""
		} else {
			key, value := splitOption[0], splitOption[1]
			opts[key] = value
		}
	}
	return opts
}

// GetMounts retrieves mountinfo information from `/proc/self/mountinfo`.
func GetMounts() ([]*MountInfo, error) {
	data, err := util.ReadFileNoStat("/proc/self/mountinfo")
	if err != nil {
		return nil, err
	}
	return parseMountInfo(data)
}

// GetProcMounts retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
func GetProcMounts(pid int) ([]*MountInfo, error) {
	data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/mountinfo", pid))
	if err != nil {
		return nil, err
	}
	return parseMountInfo(data)
}
