// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build darwin || freebsd || linux || netbsd

package unix_test

import (
	"os"
	"path/filepath"
	"runtime"
	"slices"
	"strings"
	"testing"

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

func TestXattr(t *testing.T) {
	chtmpdir(t)

	f := "xattr1"
	touch(t, f)

	xattrName := "user.test"
	xattrDataSet := "gopher"

	err := unix.Setxattr(f, xattrName, []byte{}, 0)
	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
		t.Skip("filesystem does not support extended attributes, skipping test")
	} else if err != nil {
		t.Fatalf("Setxattr: %v", err)
	}

	err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
	if err != nil {
		t.Fatalf("Setxattr: %v", err)
	}

	// find size
	size, err := unix.Listxattr(f, nil)
	if err != nil {
		t.Fatalf("Listxattr: %v", err)
	}

	if size <= 0 {
		t.Fatalf("Listxattr returned an empty list of attributes")
	}

	buf := make([]byte, size)
	read, err := unix.Listxattr(f, buf)
	if err != nil {
		t.Fatalf("Listxattr: %v", err)
	}

	xattrs := stringsFromByteSlice(buf[:read])

	xattrWant := xattrName
	switch runtime.GOOS {
	case "freebsd", "netbsd":
		// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
		// name and Listxattr doesn't return the namespace prefix.
		xattrWant = strings.TrimPrefix(xattrWant, "user.")
	}
	found := slices.Contains(xattrs, xattrWant)

	if !found {
		t.Errorf("Listxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
	}

	// find size
	size, err = unix.Getxattr(f, xattrName, nil)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}

	if size <= 0 {
		t.Fatalf("Getxattr returned an empty attribute")
	}

	xattrDataGet := make([]byte, size)
	_, err = unix.Getxattr(f, xattrName, xattrDataGet)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}

	got := string(xattrDataGet)
	if got != xattrDataSet {
		t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
	}

	err = unix.Removexattr(f, xattrName)
	if err != nil {
		t.Fatalf("Removexattr: %v", err)
	}

	n := "nonexistent"
	err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
	if err != unix.ENOENT {
		t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
	}

	_, err = unix.Lgetxattr(n, xattrName, nil)
	if err != unix.ENOENT {
		t.Errorf("Lgetxattr: %v", err)
	}

	s := "symlink1"
	err = os.Symlink(n, s)
	if err != nil {
		t.Fatal(err)
	}

	err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
	if err != nil {
		// Linux and Android doesn't support xattrs on symlinks according
		// to xattr(7), so just test that we get the proper error.
		if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
			t.Fatalf("Lsetxattr: %v", err)
		}
	}
}

func TestFdXattr(t *testing.T) {
	file, err := os.Create(filepath.Join(t.TempDir(), "TestFdXattr"))
	if err != nil {
		t.Fatal(err)
	}
	defer file.Close()

	fd := int(file.Fd())
	xattrName := "user.test"
	xattrDataSet := "gopher"

	err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
		t.Skip("filesystem does not support extended attributes, skipping test")
	} else if err != nil {
		t.Fatalf("Fsetxattr: %v", err)
	}

	// find size
	size, err := unix.Flistxattr(fd, nil)
	if err != nil {
		t.Fatalf("Flistxattr: %v", err)
	}

	if size <= 0 {
		t.Fatalf("Flistxattr returned an empty list of attributes")
	}

	buf := make([]byte, size)
	read, err := unix.Flistxattr(fd, buf)
	if err != nil {
		t.Fatalf("Flistxattr: %v", err)
	}

	xattrs := stringsFromByteSlice(buf[:read])

	xattrWant := xattrName
	switch runtime.GOOS {
	case "freebsd", "netbsd":
		// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
		// name and Listxattr doesn't return the namespace prefix.
		xattrWant = strings.TrimPrefix(xattrWant, "user.")
	}
	found := slices.Contains(xattrs, xattrWant)

	if !found {
		t.Errorf("Flistxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
	}

	// find size
	size, err = unix.Fgetxattr(fd, xattrName, nil)
	if err != nil {
		t.Fatalf("Fgetxattr: %v", err)
	}

	if size <= 0 {
		t.Fatalf("Fgetxattr returned an empty attribute")
	}

	xattrDataGet := make([]byte, size)
	_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
	if err != nil {
		t.Fatalf("Fgetxattr: %v", err)
	}

	got := string(xattrDataGet)
	if got != xattrDataSet {
		t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
	}

	err = unix.Fremovexattr(fd, xattrName)
	if err != nil {
		t.Fatalf("Fremovexattr: %v", err)
	}
}
