func (n *Node) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error { defer trace(NewGetxattrOp(req, n.path)) size, err := syscallx.Getxattr(n.path, req.Name, []byte{}) if err != nil || size <= 0 { return fuse.ErrNoXattr } buffer := make([]byte, size) size, err = syscallx.Getxattr(n.path, req.Name, buffer) if err != nil { return osErrorToFuseError(err) } resp.Xattr = buffer return nil }
func Get(path string, name string) (bytes []byte) { buf := make([]byte, GetBufsize) read, err := syscallx.Getxattr(path, name, buf) if err == nil && read > 0 { bytes = buf[:read] } return }
func (n *Node) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error { defer trace(NewRemovexattrOp(req, n.path)) // TODO: this needs to be improved, since the behavior of Removexattr depends // on the previous existance of the attribute. The return code of the operation // is governed by the flags. See bazil.org/fuse/syscallx.Removexattr comments. _, err := syscallx.Getxattr(n.path, req.Name, []byte{}) if err == nil { // TODO: There is already an attribute with that name. Should return // the expected error code according to the request's flags err = syscallx.Removexattr(n.path, req.Name) return osErrorToFuseError(err) } return nil }
func (file *File) Getxattr(req *fuse.GetxattrRequest, res *fuse.GetxattrResponse, intr fs.Intr) fuse.Error { // return fuse.EPERM // fmt.Printf("Get attr: %s\n", req.Name) buf := make([]byte, 8192) size, err := syscallx.Getxattr(file.Path, req.Name, buf) if err != nil { // fmt.Printf("Get xattr error: %s - %s: \n", file.Path, req.Name, err) // return err // On osx, we need to return NOATTR, but this isn't built into go or bazil.org/fuse, so we need to do this: return fuse.Errno(93) } res.Xattr = buf[:size] return nil }
func TestGetxattrSize(t *testing.T) { t.Parallel() f := &getxattrSize{} mnt, err := fstestutil.MountedT(t, childMapFS{"child": f}) if err != nil { t.Fatal(err) } defer mnt.Close() n, err := syscallx.Getxattr(mnt.Dir+"/child", "whatever", nil) if err != nil { t.Errorf("Getxattr unexpected error: %v", err) return } if g, e := n, len("hello, world"); g != e { t.Errorf("Getxattr incorrect size: %d != %d", g, e) } }
func TestGetxattrTooSmall(t *testing.T) { t.Parallel() f := &getxattrTooSmall{} mnt, err := fstestutil.MountedT(t, childMapFS{"child": f}) if err != nil { t.Fatal(err) } defer mnt.Close() buf := make([]byte, 3) _, err = syscallx.Getxattr(mnt.Dir+"/child", "whatever", buf) if err == nil { t.Error("Getxattr = nil; want some error") } if err != syscall.ERANGE { t.Errorf("unexpected error: %v", err) return } }
func TestGetxattr(t *testing.T) { t.Parallel() f := &getxattr{} mnt, err := fstestutil.MountedT(t, childMapFS{"child": f}) if err != nil { t.Fatal(err) } defer mnt.Close() buf := make([]byte, 8192) n, err := syscallx.Getxattr(mnt.Dir+"/child", "not-there", buf) if err != nil { t.Errorf("unexpected error: %v", err) return } buf = buf[:n] if g, e := string(buf), "hello, world"; g != e { t.Errorf("wrong getxattr content: %#v != %#v", g, e) } seen := f.RecordedGetxattr() if g, e := seen.Name, "not-there"; g != e { t.Errorf("wrong getxattr name: %#v != %#v", g, e) } }
func TestXattr(t *testing.T) { condSkip(t) inEmptyMutDir(t, func(env *mountEnv, rootDir string) { name1 := filepath.Join(rootDir, "1") attr1 := "attr1" attr2 := "attr2" contents := []byte("Some file contents") if err := ioutil.WriteFile(name1, contents, 0644); err != nil { t.Fatal(err) } buf := make([]byte, 8192) // list empty n, err := syscallx.Listxattr(name1, buf) if err != nil { t.Errorf("Error in initial listxattr: %v", err) } if n != 0 { t.Errorf("Expected zero-length xattr list, got %q", buf[:n]) } // get missing n, err = syscallx.Getxattr(name1, attr1, buf) if err == nil { t.Errorf("Expected error getting non-existent xattr, got %q", buf[:n]) } // Set (two different attributes) err = syscallx.Setxattr(name1, attr1, []byte("hello1"), 0) if err != nil { t.Fatalf("Error setting xattr: %v", err) } err = syscallx.Setxattr(name1, attr2, []byte("hello2"), 0) if err != nil { t.Fatalf("Error setting xattr: %v", err) } // Alternate value for first attribute err = syscallx.Setxattr(name1, attr1, []byte("hello1a"), 0) if err != nil { t.Fatalf("Error setting xattr: %v", err) } // list attrs n, err = syscallx.Listxattr(name1, buf) if err != nil { t.Errorf("Error in initial listxattr: %v", err) } m := parseXattrList(buf[:n]) if !(len(m) == 2 && m[attr1] && m[attr2]) { t.Errorf("Missing an attribute: %q", buf[:n]) } // Remove attr err = syscallx.Removexattr(name1, attr2) if err != nil { t.Errorf("Failed to remove attr: %v", err) } // List attrs n, err = syscallx.Listxattr(name1, buf) if err != nil { t.Errorf("Error in initial listxattr: %v", err) } m = parseXattrList(buf[:n]) if !(len(m) == 1 && m[attr1]) { t.Errorf("Missing an attribute: %q", buf[:n]) } // Get remaining attr n, err = syscallx.Getxattr(name1, attr1, buf) if err != nil { t.Errorf("Error getting attr1: %v", err) } if string(buf[:n]) != "hello1a" { t.Logf("Expected hello1a, got %q", buf[:n]) } }) }