Commit 648e8455 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Implement SetXAttr.

parent 5f24a9ec
......@@ -54,7 +54,7 @@ Grep source code for TODO. Major topics:
* Missing support for file locking: FUSE_GETLK, FUSE_SETLK, FUSE_SETLKW
* Missing support for extended attributes FUSE_SETXATTR, FUSE_LISTXATTR
* Missing support for extended attributes FUSE_REMOVE_XATTR
* Missing support for FUSE_INTERRUPT, FUSE_NOTIFY, CUSE, BMAP, POLL, IOCTL
......
......@@ -503,14 +503,14 @@ func (me *SubmountFileSystem) Link(header *fuse.InHeader, input *fuse.LinkIn, na
return out, code
}
func (me *SubmountFileSystem) SetXAttr(header *fuse.InHeader, input *fuse.SetXAttrIn) fuse.Status {
func (me *SubmountFileSystem) SetXAttr(header *fuse.InHeader, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status {
var subfs *subFsInfo
header.NodeId, subfs = me.getSubFs(header.NodeId)
if subfs == nil {
return fuse.ENOENT
}
return subfs.Fs.SetXAttr(header, input)
return subfs.Fs.SetXAttr(header, input, attr, data)
}
func (me *SubmountFileSystem) GetXAttr(header *fuse.InHeader, attr string) (data []byte, code fuse.Status) {
......
......@@ -65,14 +65,14 @@ func (me *DefaultRawFuseFileSystem) Link(header *InHeader, input *LinkIn, name s
return nil, ENOSYS
}
func (me *DefaultRawFuseFileSystem) SetXAttr(header *InHeader, input *SetXAttrIn) Status {
return ENOSYS
}
func (me *DefaultRawFuseFileSystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
return nil, ENOSYS
}
func (me *DefaultRawFuseFileSystem) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) (Status) {
return ENOSYS
}
func (me *DefaultRawFuseFileSystem) ListXAttr(header *InHeader) (data []byte, code Status) {
return nil, ENOSYS
}
......@@ -108,6 +108,7 @@ func (me *DefaultRawFuseFileSystem) ReleaseDir(header *InHeader, f RawFuseDir) {
}
////////////////////////////////////////////////////////////////
// DefaultRawFuseFile
......@@ -157,6 +158,10 @@ func (me *DefaultPathFilesystem) GetXAttr(name string, attr string) ([]byte, Sta
return nil, ENOSYS
}
func (me *DefaultPathFilesystem) SetXAttr(name string, attr string, data []byte, flags int) (Status) {
return ENOSYS
}
func (me *DefaultPathFilesystem) ListXAttr(name string) ([]string, Status) {
return nil, ENOSYS
}
......
package fuse
import (
"bytes"
"fmt"
"log"
"os"
......@@ -470,10 +471,9 @@ func (me *MountState) dispatch(req *fuseRequest) {
case FUSE_FSYNCDIR:
// todo- check inData type.
status = doFsyncDir(me, h, (*FsyncIn)(inData))
// TODO - implement XAttr routines.
// case FUSE_SETXATTR:
// status = fs.SetXAttr(h, (*SetXAttrIn)(inData))
case FUSE_SETXATTR:
splits := bytes.Split(data, []byte{0}, 2)
status = fs.SetXAttr(h, (*SetXAttrIn)(inData), string(splits[0]), splits[1])
case FUSE_GETXATTR:
req.data, req.flatData, status = doGetXAttr(me, h, (*GetXAttrIn)(inData), filename, h.Opcode)
case FUSE_LISTXATTR:
......
......@@ -728,6 +728,15 @@ func (me *PathFileSystemConnector) GetXAttr(header *InHeader, attribute string)
return data, code
}
func (me *PathFileSystemConnector) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) (Status) {
path, mount := me.GetPath(header.NodeId)
if mount == nil {
return ENOENT
}
return mount.fs.SetXAttr(path, attr, data, int(input.Flags))
}
func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, code Status) {
path, mount := me.GetPath(header.NodeId)
if mount == nil {
......@@ -751,10 +760,6 @@ func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, cod
////////////////////////////////////////////////////////////////
// unimplemented.
func (me *PathFileSystemConnector) SetXAttr(header *InHeader, input *SetXAttrIn) Status {
return ENOSYS
}
func (me *PathFileSystemConnector) Bmap(header *InHeader, input *BmapIn) (out *BmapOut, code Status) {
return nil, ENOSYS
}
......
......@@ -96,6 +96,11 @@ func (me *TimingPathFilesystem) GetXAttr(name string, attr string) ([]byte, Stat
return me.original.GetXAttr(name, attr)
}
func (me *TimingPathFilesystem) SetXAttr(name string, attr string, data []byte, flags int) Status {
defer me.startTimer("SetXAttr", name)()
return me.original.SetXAttr(name, attr, data, flags)
}
func (me *TimingPathFilesystem) ListXAttr(name string) ([]string, Status) {
defer me.startTimer("ListXAttr", name)()
return me.original.ListXAttr(name)
......
......@@ -121,9 +121,9 @@ func (me *TimingRawFilesystem) Link(header *InHeader, input *LinkIn, name string
return me.original.Link(header, input, name)
}
func (me *TimingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn) Status {
func (me *TimingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) Status {
defer me.startTimer("SetXAttr")()
return me.original.SetXAttr(header, input)
return me.original.SetXAttr(header, input, attr, data)
}
func (me *TimingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
......
......@@ -518,9 +518,7 @@ type RawFileSystem interface {
GetXAttr(header *InHeader, attr string) (data []byte, code Status)
ListXAttr(header *InHeader) (attributes []byte, code Status)
// Unused:
SetXAttr(header *InHeader, input *SetXAttrIn) Status
SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) (Status)
Access(header *InHeader, input *AccessIn) (code Status)
Create(header *InHeader, input *CreateIn, name string) (flags uint32, fuseFile RawFuseFile, out *EntryOut, code Status)
......@@ -571,7 +569,8 @@ type PathFilesystem interface {
// Where to hook up statfs?
//
// Unimplemented:
// RemoveXAttr, SetXAttr,
// RemoveXAttr,
SetXAttr(name string, attr string, data []byte, flags int) Status
ListXAttr(name string) (attributes []string, code Status)
OpenDir(name string) (stream chan DirEntry, code Status)
......
......@@ -156,8 +156,8 @@ func (me *WrappingRawFilesystem) Link(header *InHeader, input *LinkIn, name stri
return me.original.Link(header, input, name)
}
func (me *WrappingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn) Status {
return me.original.SetXAttr(header, input)
func (me *WrappingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) Status {
return me.original.SetXAttr(header, input, attr, data)
}
func (me *WrappingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
......
......@@ -72,3 +72,17 @@ func ListXAttr(path string) (attributes []string, errno int) {
}
return attributes, errno
}
func Setxattr(path string, attr string, data []byte, flags int) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall6(
syscall.SYS_SETXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)),
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
uintptr(flags), 0)
return int(errNo)
}
......@@ -35,6 +35,13 @@ func (me *XAttrTestFs) GetAttr(name string) (*Attr, Status) {
return nil, ENOENT
}
func (me *XAttrTestFs) SetXAttr(name string, attr string, data []byte, flags int) (Status) {
if name != me.filename {
return ENOENT
}
me.attrs[attr] = data
return OK
}
func (me *XAttrTestFs) GetXAttr(name string, attr string) ([]byte, Status) {
if name != me.filename {
......@@ -47,6 +54,7 @@ func (me *XAttrTestFs) GetXAttr(name string, attr string) ([]byte, Status) {
return v, OK
}
func (me *XAttrTestFs) ListXAttr(name string) (data []string, code Status) {
if name != me.filename {
return nil, ENOENT
......@@ -111,5 +119,11 @@ func TestXAttrRead(t *testing.T) {
}
}
}
Setxattr(mounted, "third", []byte("value"), 0)
val, errno = GetXAttr(mounted, "third")
if errno != 0 || string(val) != "value" {
t.Error("Read back set xattr:", err, val)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment