package sysx

import (
	"bytes"
	"fmt"
	"syscall"
)

const defaultXattrBufferSize = 5

var ErrNotSupported = fmt.Errorf("not supported")

type listxattrFunc func(path string, dest []byte) (int, error)

func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
	var p []byte // nil on first execution

	for {
		n, err := listFunc(path, p) // first call gets buffer size.
		if err != nil {
			return nil, err
		}

		if n > len(p) {
			p = make([]byte, n)
			continue
		}

		p = p[:n]

		ps := bytes.Split(bytes.TrimSuffix(p, []byte{0}), []byte{0})
		var entries []string
		for _, p := range ps {
			s := string(p)
			if s != "" {
				entries = append(entries, s)
			}
		}

		return entries, nil
	}
}

type getxattrFunc func(string, string, []byte) (int, error)

func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
	p := make([]byte, defaultXattrBufferSize)
	for {
		n, err := getFunc(path, attr, p)
		if err != nil {
			if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERANGE {
				p = make([]byte, len(p)*2) // this can't be ideal.
				continue                   // try again!
			}

			return nil, err
		}

		// realloc to correct size and repeat
		if n > len(p) {
			p = make([]byte, n)
			continue
		}

		return p[:n], nil
	}
}