// 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"
	"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 := false
	for _, name := range xattrs {
		if name == xattrWant {
			found = true
			break
		}
	}

	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 doen'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 := false
	for _, name := range xattrs {
		if name == xattrWant {
			found = true
			break
		}
	}

	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)
	}
}
