...

Source file src/golang.org/x/sys/unix/xattr_test.go

Documentation: golang.org/x/sys/unix

     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  //go:build darwin || freebsd || linux || netbsd
     6  
     7  package unix_test
     8  
     9  import (
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"strings"
    14  	"testing"
    15  
    16  	"golang.org/x/sys/unix"
    17  )
    18  
    19  func TestXattr(t *testing.T) {
    20  	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  	switch runtime.GOOS {
    60  	case "freebsd", "netbsd":
    61  		// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
    62  		// name and Listxattr doesn't return the namespace prefix.
    63  		xattrWant = strings.TrimPrefix(xattrWant, "user.")
    64  	}
    65  	found := false
    66  	for _, name := range xattrs {
    67  		if name == xattrWant {
    68  			found = true
    69  			break
    70  		}
    71  	}
    72  
    73  	if !found {
    74  		t.Errorf("Listxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
    75  	}
    76  
    77  	// find size
    78  	size, err = unix.Getxattr(f, xattrName, nil)
    79  	if err != nil {
    80  		t.Fatalf("Getxattr: %v", err)
    81  	}
    82  
    83  	if size <= 0 {
    84  		t.Fatalf("Getxattr returned an empty attribute")
    85  	}
    86  
    87  	xattrDataGet := make([]byte, size)
    88  	_, err = unix.Getxattr(f, xattrName, xattrDataGet)
    89  	if err != nil {
    90  		t.Fatalf("Getxattr: %v", err)
    91  	}
    92  
    93  	got := string(xattrDataGet)
    94  	if got != xattrDataSet {
    95  		t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
    96  	}
    97  
    98  	err = unix.Removexattr(f, xattrName)
    99  	if err != nil {
   100  		t.Fatalf("Removexattr: %v", err)
   101  	}
   102  
   103  	n := "nonexistent"
   104  	err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
   105  	if err != unix.ENOENT {
   106  		t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
   107  	}
   108  
   109  	_, err = unix.Lgetxattr(n, xattrName, nil)
   110  	if err != unix.ENOENT {
   111  		t.Errorf("Lgetxattr: %v", err)
   112  	}
   113  
   114  	s := "symlink1"
   115  	err = os.Symlink(n, s)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
   121  	if err != nil {
   122  		// Linux and Android doesn't support xattrs on symlinks according
   123  		// to xattr(7), so just test that we get the proper error.
   124  		if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
   125  			t.Fatalf("Lsetxattr: %v", err)
   126  		}
   127  	}
   128  }
   129  
   130  func TestFdXattr(t *testing.T) {
   131  	file, err := os.Create(filepath.Join(t.TempDir(), "TestFdXattr"))
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	defer file.Close()
   136  
   137  	fd := int(file.Fd())
   138  	xattrName := "user.test"
   139  	xattrDataSet := "gopher"
   140  
   141  	err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
   142  	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
   143  		t.Skip("filesystem does not support extended attributes, skipping test")
   144  	} else if err != nil {
   145  		t.Fatalf("Fsetxattr: %v", err)
   146  	}
   147  
   148  	// find size
   149  	size, err := unix.Flistxattr(fd, nil)
   150  	if err != nil {
   151  		t.Fatalf("Flistxattr: %v", err)
   152  	}
   153  
   154  	if size <= 0 {
   155  		t.Fatalf("Flistxattr returned an empty list of attributes")
   156  	}
   157  
   158  	buf := make([]byte, size)
   159  	read, err := unix.Flistxattr(fd, buf)
   160  	if err != nil {
   161  		t.Fatalf("Flistxattr: %v", err)
   162  	}
   163  
   164  	xattrs := stringsFromByteSlice(buf[:read])
   165  
   166  	xattrWant := xattrName
   167  	switch runtime.GOOS {
   168  	case "freebsd", "netbsd":
   169  		// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
   170  		// name and Listxattr doesn't return the namespace prefix.
   171  		xattrWant = strings.TrimPrefix(xattrWant, "user.")
   172  	}
   173  	found := false
   174  	for _, name := range xattrs {
   175  		if name == xattrWant {
   176  			found = true
   177  			break
   178  		}
   179  	}
   180  
   181  	if !found {
   182  		t.Errorf("Flistxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
   183  	}
   184  
   185  	// find size
   186  	size, err = unix.Fgetxattr(fd, xattrName, nil)
   187  	if err != nil {
   188  		t.Fatalf("Fgetxattr: %v", err)
   189  	}
   190  
   191  	if size <= 0 {
   192  		t.Fatalf("Fgetxattr returned an empty attribute")
   193  	}
   194  
   195  	xattrDataGet := make([]byte, size)
   196  	_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
   197  	if err != nil {
   198  		t.Fatalf("Fgetxattr: %v", err)
   199  	}
   200  
   201  	got := string(xattrDataGet)
   202  	if got != xattrDataSet {
   203  		t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
   204  	}
   205  
   206  	err = unix.Fremovexattr(fd, xattrName)
   207  	if err != nil {
   208  		t.Fatalf("Fremovexattr: %v", err)
   209  	}
   210  }
   211  

View as plain text