diff --git a/conversions.go b/conversions.go index 1a77652..05fce2f 100644 --- a/conversions.go +++ b/conversions.go @@ -487,6 +487,35 @@ func convertInMessage( return } } + case fusekernel.OpSetxattr: + type input fusekernel.SetxattrIn + in := (*input)(inMsg.Consume(unsafe.Sizeof(input{}))) + if in == nil { + err = errors.New("Corrupt OpSetxattr") + return + } + + payload := inMsg.ConsumeBytes(inMsg.Len()) + // payload should be "name\x00value" + if len(payload) < 3 { + err = errors.New("Corrupt OpSetxattr") + return + } + i := bytes.IndexByte(payload, '\x00') + if i < 0 { + err = errors.New("Corrupt OpSetxattr") + return + } + + name, value := payload[:i], payload[i+1:len(payload)] + fmt.Printf("Setting %v to %v\n", name, value) + + o = &fuseops.SetXattrOp{ + Inode: fuseops.InodeID(inMsg.Header().Nodeid), + Name: string(name), + Data: value, + Flags: in.Flags, + } default: o = &unknownOp{ @@ -726,6 +755,9 @@ func (c *Connection) kernelResponseForOp( m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead) } + case *fuseops.SetXattrOp: + // Empty response + case *initOp: out := (*fusekernel.InitOut)(m.Grow(int(unsafe.Sizeof(fusekernel.InitOut{})))) diff --git a/debug.go b/debug.go index b59e698..d6f9fdc 100644 --- a/debug.go +++ b/debug.go @@ -95,6 +95,9 @@ func describeRequest(op interface{}) (s string) { case *fuseops.GetXattrOp: addComponent("name %s", typed.Name) + + case *fuseops.SetXattrOp: + addComponent("name %s", typed.Name) } // Use just the name if there is no extra info. diff --git a/fuseops/ops.go b/fuseops/ops.go index 3579d1a..a8d8220 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -815,3 +815,18 @@ type ListXattrOp struct { // big enough BytesRead int } + +type SetXattrOp struct { + // The inode that we are changing + Inode InodeID + + // The name of the extended attribute + Name string + + // The data to for the extened attribute. + Data []byte + + // If Flags is 0x1, and the attribute exists already, EEXIST should be returned. + // If Flags is 0x2, and the attribute does not exist, ENOATTR should be returned. + Flags uint32 +} diff --git a/fuseutil/file_system.go b/fuseutil/file_system.go index 302d402..9cc0fa8 100644 --- a/fuseutil/file_system.go +++ b/fuseutil/file_system.go @@ -60,6 +60,7 @@ type FileSystem interface { RemoveXattr(context.Context, *fuseops.RemoveXattrOp) error GetXattr(context.Context, *fuseops.GetXattrOp) error ListXattr(context.Context, *fuseops.ListXattrOp) error + SetXattr(context.Context, *fuseops.SetXattrOp) error // Regard all inodes (including the root inode) as having their lookup counts // decremented to zero, and clean up any resources associated with the file @@ -198,6 +199,9 @@ func (s *fileSystemServer) handleOp( case *fuseops.ListXattrOp: err = s.fs.ListXattr(ctx, typed) + + case *fuseops.SetXattrOp: + err = s.fs.SetXattr(ctx, typed) } c.Reply(ctx, err) diff --git a/fuseutil/not_implemented_file_system.go b/fuseutil/not_implemented_file_system.go index a3f0142..b21e1e3 100644 --- a/fuseutil/not_implemented_file_system.go +++ b/fuseutil/not_implemented_file_system.go @@ -204,5 +204,12 @@ func (fs *NotImplementedFileSystem) ListXattr( return } +func (fs *NotImplementedFileSystem) SetXattr( + ctx context.Context, + op *fuseops.SetXattrOp) (err error) { + err = fuse.ENOSYS + return +} + func (fs *NotImplementedFileSystem) Destroy() { }