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: ...@@ -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 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 * 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 ...@@ -503,14 +503,14 @@ func (me *SubmountFileSystem) Link(header *fuse.InHeader, input *fuse.LinkIn, na
return out, code 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 var subfs *subFsInfo
header.NodeId, subfs = me.getSubFs(header.NodeId) header.NodeId, subfs = me.getSubFs(header.NodeId)
if subfs == nil { if subfs == nil {
return fuse.ENOENT 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) { 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 ...@@ -65,14 +65,14 @@ func (me *DefaultRawFuseFileSystem) Link(header *InHeader, input *LinkIn, name s
return nil, ENOSYS 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) { func (me *DefaultRawFuseFileSystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
return nil, ENOSYS 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) { func (me *DefaultRawFuseFileSystem) ListXAttr(header *InHeader) (data []byte, code Status) {
return nil, ENOSYS return nil, ENOSYS
} }
...@@ -108,6 +108,7 @@ func (me *DefaultRawFuseFileSystem) ReleaseDir(header *InHeader, f RawFuseDir) { ...@@ -108,6 +108,7 @@ func (me *DefaultRawFuseFileSystem) ReleaseDir(header *InHeader, f RawFuseDir) {
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// DefaultRawFuseFile // DefaultRawFuseFile
...@@ -157,6 +158,10 @@ func (me *DefaultPathFilesystem) GetXAttr(name string, attr string) ([]byte, Sta ...@@ -157,6 +158,10 @@ func (me *DefaultPathFilesystem) GetXAttr(name string, attr string) ([]byte, Sta
return nil, ENOSYS 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) { func (me *DefaultPathFilesystem) ListXAttr(name string) ([]string, Status) {
return nil, ENOSYS return nil, ENOSYS
} }
......
package fuse package fuse
import ( import (
"bytes"
"fmt" "fmt"
"log" "log"
"os" "os"
...@@ -470,10 +471,9 @@ func (me *MountState) dispatch(req *fuseRequest) { ...@@ -470,10 +471,9 @@ func (me *MountState) dispatch(req *fuseRequest) {
case FUSE_FSYNCDIR: case FUSE_FSYNCDIR:
// todo- check inData type. // todo- check inData type.
status = doFsyncDir(me, h, (*FsyncIn)(inData)) status = doFsyncDir(me, h, (*FsyncIn)(inData))
case FUSE_SETXATTR:
// TODO - implement XAttr routines. splits := bytes.Split(data, []byte{0}, 2)
// case FUSE_SETXATTR: status = fs.SetXAttr(h, (*SetXAttrIn)(inData), string(splits[0]), splits[1])
// status = fs.SetXAttr(h, (*SetXAttrIn)(inData))
case FUSE_GETXATTR: case FUSE_GETXATTR:
req.data, req.flatData, status = doGetXAttr(me, h, (*GetXAttrIn)(inData), filename, h.Opcode) req.data, req.flatData, status = doGetXAttr(me, h, (*GetXAttrIn)(inData), filename, h.Opcode)
case FUSE_LISTXATTR: case FUSE_LISTXATTR:
......
...@@ -728,6 +728,15 @@ func (me *PathFileSystemConnector) GetXAttr(header *InHeader, attribute string) ...@@ -728,6 +728,15 @@ func (me *PathFileSystemConnector) GetXAttr(header *InHeader, attribute string)
return data, code 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) { func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, code Status) {
path, mount := me.GetPath(header.NodeId) path, mount := me.GetPath(header.NodeId)
if mount == nil { if mount == nil {
...@@ -751,10 +760,6 @@ func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, cod ...@@ -751,10 +760,6 @@ func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, cod
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// unimplemented. // unimplemented.
func (me *PathFileSystemConnector) SetXAttr(header *InHeader, input *SetXAttrIn) Status {
return ENOSYS
}
func (me *PathFileSystemConnector) Bmap(header *InHeader, input *BmapIn) (out *BmapOut, code Status) { func (me *PathFileSystemConnector) Bmap(header *InHeader, input *BmapIn) (out *BmapOut, code Status) {
return nil, ENOSYS return nil, ENOSYS
} }
......
...@@ -96,6 +96,11 @@ func (me *TimingPathFilesystem) GetXAttr(name string, attr string) ([]byte, Stat ...@@ -96,6 +96,11 @@ func (me *TimingPathFilesystem) GetXAttr(name string, attr string) ([]byte, Stat
return me.original.GetXAttr(name, attr) 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) { func (me *TimingPathFilesystem) ListXAttr(name string) ([]string, Status) {
defer me.startTimer("ListXAttr", name)() defer me.startTimer("ListXAttr", name)()
return me.original.ListXAttr(name) return me.original.ListXAttr(name)
......
...@@ -121,9 +121,9 @@ func (me *TimingRawFilesystem) Link(header *InHeader, input *LinkIn, name string ...@@ -121,9 +121,9 @@ func (me *TimingRawFilesystem) Link(header *InHeader, input *LinkIn, name string
return me.original.Link(header, input, name) 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")() 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) { func (me *TimingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
......
...@@ -518,9 +518,7 @@ type RawFileSystem interface { ...@@ -518,9 +518,7 @@ type RawFileSystem interface {
GetXAttr(header *InHeader, attr string) (data []byte, code Status) GetXAttr(header *InHeader, attr string) (data []byte, code Status)
ListXAttr(header *InHeader) (attributes []byte, code Status) ListXAttr(header *InHeader) (attributes []byte, code Status)
SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) (Status)
// Unused:
SetXAttr(header *InHeader, input *SetXAttrIn) Status
Access(header *InHeader, input *AccessIn) (code Status) Access(header *InHeader, input *AccessIn) (code Status)
Create(header *InHeader, input *CreateIn, name string) (flags uint32, fuseFile RawFuseFile, out *EntryOut, code Status) Create(header *InHeader, input *CreateIn, name string) (flags uint32, fuseFile RawFuseFile, out *EntryOut, code Status)
...@@ -571,7 +569,8 @@ type PathFilesystem interface { ...@@ -571,7 +569,8 @@ type PathFilesystem interface {
// Where to hook up statfs? // Where to hook up statfs?
// //
// Unimplemented: // Unimplemented:
// RemoveXAttr, SetXAttr, // RemoveXAttr,
SetXAttr(name string, attr string, data []byte, flags int) Status
ListXAttr(name string) (attributes []string, code Status) ListXAttr(name string) (attributes []string, code Status)
OpenDir(name string) (stream chan DirEntry, code Status) OpenDir(name string) (stream chan DirEntry, code Status)
......
...@@ -156,8 +156,8 @@ func (me *WrappingRawFilesystem) Link(header *InHeader, input *LinkIn, name stri ...@@ -156,8 +156,8 @@ func (me *WrappingRawFilesystem) Link(header *InHeader, input *LinkIn, name stri
return me.original.Link(header, input, name) return me.original.Link(header, input, name)
} }
func (me *WrappingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn) Status { func (me *WrappingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) Status {
return me.original.SetXAttr(header, input) return me.original.SetXAttr(header, input, attr, data)
} }
func (me *WrappingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) { func (me *WrappingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) {
......
...@@ -72,3 +72,17 @@ func ListXAttr(path string) (attributes []string, errno int) { ...@@ -72,3 +72,17 @@ func ListXAttr(path string) (attributes []string, errno int) {
} }
return attributes, errno 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) { ...@@ -35,6 +35,13 @@ func (me *XAttrTestFs) GetAttr(name string) (*Attr, Status) {
return nil, ENOENT 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) { func (me *XAttrTestFs) GetXAttr(name string, attr string) ([]byte, Status) {
if name != me.filename { if name != me.filename {
...@@ -47,6 +54,7 @@ func (me *XAttrTestFs) GetXAttr(name string, attr string) ([]byte, Status) { ...@@ -47,6 +54,7 @@ func (me *XAttrTestFs) GetXAttr(name string, attr string) ([]byte, Status) {
return v, OK return v, OK
} }
func (me *XAttrTestFs) ListXAttr(name string) (data []string, code Status) { func (me *XAttrTestFs) ListXAttr(name string) (data []string, code Status) {
if name != me.filename { if name != me.filename {
return nil, ENOENT return nil, ENOENT
...@@ -111,5 +119,11 @@ func TestXAttrRead(t *testing.T) { ...@@ -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