/*
Copyright (c) Edgeless Systems GmbH

SPDX-License-Identifier: AGPL-3.0-only
*/

package user

import (
	"bufio"
	"errors"
	"strings"

	"github.com/spf13/afero"
)

// Entry is an entry of a '/etc/passwd' file.
type Entry struct {
	Password  string
	UID       string
	GID       string
	GECOS     string
	Directory string
	Shell     string
}

// Entries contains the information for each user defined in '/etc/passwd'.
type Entries map[string]Entry

// Passwd allows to parse users from '/etc/passwd' on the local system.
type Passwd struct{}

// Parse opens the '/etc/passwd' file and parses it into a map from usernames to Entries.
func (p Passwd) Parse(fs afero.Fs) (Entries, error) {
	return p.parseFile(fs, "/etc/passwd")
}

// parseFile opens the file and parses it into a map from usernames to Entries.
func (p Passwd) parseFile(fs afero.Fs, path string) (Entries, error) {
	file, err := fs.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	entries := Entries{}
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		// File format: https://man7.org/linux/man-pages/man5/passwd.5.html

		fields := strings.Split(scanner.Text(), ":")
		if len(fields) != 7 {
			return nil, errors.New("invalid number of fields")
		}

		entries[fields[0]] = Entry{
			Password:  fields[1],
			UID:       fields[2],
			GID:       fields[3],
			GECOS:     fields[4],
			Directory: fields[5],
			Shell:     fields[6],
		}
	}

	return entries, scanner.Err()
}