github.com/Andyfoo/golang/x/sys@v0.0.0-20190901054642-57c1bf301704/unix/xattr_test.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin freebsd linux netbsd
     6  
     7  package unix_test
     8  
     9  import (
    10  	"io/ioutil"
    11  	"os"
    12  	"runtime"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/Andyfoo/golang/x/sys/unix"
    17  )
    18  
    19  func TestXattr(t *testing.T) {
    20  	defer chtmpdir(t)()
    21  
    22  	f := "xattr1"
    23  	touch(t, f)
    24  
    25  	xattrName := "user.test"
    26  	xattrDataSet := "gopher"
    27  
    28  	err := unix.Setxattr(f, xattrName, []byte{}, 0)
    29  	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
    30  		t.Skip("filesystem does not support extended attributes, skipping test")
    31  	} else if err != nil {
    32  		t.Fatalf("Setxattr: %v", err)
    33  	}
    34  
    35  	err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
    36  	if err != nil {
    37  		t.Fatalf("Setxattr: %v", err)
    38  	}
    39  
    40  	// find size
    41  	size, err := unix.Listxattr(f, nil)
    42  	if err != nil {
    43  		t.Fatalf("Listxattr: %v", err)
    44  	}
    45  
    46  	if size <= 0 {
    47  		t.Fatalf("Listxattr returned an empty list of attributes")
    48  	}
    49  
    50  	buf := make([]byte, size)
    51  	read, err := unix.Listxattr(f, buf)
    52  	if err != nil {
    53  		t.Fatalf("Listxattr: %v", err)
    54  	}
    55  
    56  	xattrs := stringsFromByteSlice(buf[:read])
    57  
    58  	xattrWant := xattrName
    59  	if runtime.GOOS == "freebsd" {
    60  		// On FreeBSD, the namespace is stored separately from the xattr
    61  		// name and Listxattr doesn't return the namespace prefix.
    62  		xattrWant = strings.TrimPrefix(xattrWant, "user.")
    63  	}
    64  	found := false
    65  	for _, name := range xattrs {
    66  		if name == xattrWant {
    67  			found = true
    68  		}
    69  	}
    70  
    71  	if !found {
    72  		t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName)
    73  	}
    74  
    75  	// find size
    76  	size, err = unix.Getxattr(f, xattrName, nil)
    77  	if err != nil {
    78  		t.Fatalf("Getxattr: %v", err)
    79  	}
    80  
    81  	if size <= 0 {
    82  		t.Fatalf("Getxattr returned an empty attribute")
    83  	}
    84  
    85  	xattrDataGet := make([]byte, size)
    86  	_, err = unix.Getxattr(f, xattrName, xattrDataGet)
    87  	if err != nil {
    88  		t.Fatalf("Getxattr: %v", err)
    89  	}
    90  
    91  	got := string(xattrDataGet)
    92  	if got != xattrDataSet {
    93  		t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
    94  	}
    95  
    96  	err = unix.Removexattr(f, xattrName)
    97  	if err != nil {
    98  		t.Fatalf("Removexattr: %v", err)
    99  	}
   100  
   101  	n := "nonexistent"
   102  	err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
   103  	if err != unix.ENOENT {
   104  		t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
   105  	}
   106  
   107  	_, err = unix.Lgetxattr(n, xattrName, nil)
   108  	if err != unix.ENOENT {
   109  		t.Errorf("Lgetxattr: %v", err)
   110  	}
   111  
   112  	s := "symlink1"
   113  	err = os.Symlink(n, s)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
   119  	if err != nil {
   120  		// Linux and Android doen't support xattrs on symlinks according
   121  		// to xattr(7), so just test that we get the proper error.
   122  		if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
   123  			t.Fatalf("Lsetxattr: %v", err)
   124  		}
   125  	}
   126  }
   127  
   128  func TestFdXattr(t *testing.T) {
   129  	file, err := ioutil.TempFile("", "TestFdXattr")
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	defer os.Remove(file.Name())
   134  	defer file.Close()
   135  
   136  	fd := int(file.Fd())
   137  	xattrName := "user.test"
   138  	xattrDataSet := "gopher"
   139  
   140  	err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
   141  	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
   142  		t.Skip("filesystem does not support extended attributes, skipping test")
   143  	} else if err != nil {
   144  		t.Fatalf("Fsetxattr: %v", err)
   145  	}
   146  
   147  	// find size
   148  	size, err := unix.Flistxattr(fd, nil)
   149  	if err != nil {
   150  		t.Fatalf("Flistxattr: %v", err)
   151  	}
   152  
   153  	if size <= 0 {
   154  		t.Fatalf("Flistxattr returned an empty list of attributes")
   155  	}
   156  
   157  	buf := make([]byte, size)
   158  	read, err := unix.Flistxattr(fd, buf)
   159  	if err != nil {
   160  		t.Fatalf("Flistxattr: %v", err)
   161  	}
   162  
   163  	xattrs := stringsFromByteSlice(buf[:read])
   164  
   165  	xattrWant := xattrName
   166  	if runtime.GOOS == "freebsd" {
   167  		// On FreeBSD, the namespace is stored separately from the xattr
   168  		// name and Listxattr doesn't return the namespace prefix.
   169  		xattrWant = strings.TrimPrefix(xattrWant, "user.")
   170  	}
   171  	found := false
   172  	for _, name := range xattrs {
   173  		if name == xattrWant {
   174  			found = true
   175  		}
   176  	}
   177  
   178  	if !found {
   179  		t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName)
   180  	}
   181  
   182  	// find size
   183  	size, err = unix.Fgetxattr(fd, xattrName, nil)
   184  	if err != nil {
   185  		t.Fatalf("Fgetxattr: %v", err)
   186  	}
   187  
   188  	if size <= 0 {
   189  		t.Fatalf("Fgetxattr returned an empty attribute")
   190  	}
   191  
   192  	xattrDataGet := make([]byte, size)
   193  	_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
   194  	if err != nil {
   195  		t.Fatalf("Fgetxattr: %v", err)
   196  	}
   197  
   198  	got := string(xattrDataGet)
   199  	if got != xattrDataSet {
   200  		t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
   201  	}
   202  
   203  	err = unix.Fremovexattr(fd, xattrName)
   204  	if err != nil {
   205  		t.Fatalf("Fremovexattr: %v", err)
   206  	}
   207  }