diff options
Diffstat (limited to 'pkg/p9')
-rw-r--r-- | pkg/p9/BUILD | 3 | ||||
-rw-r--r-- | pkg/p9/buffer.go | 10 | ||||
-rw-r--r-- | pkg/p9/client.go | 9 | ||||
-rw-r--r-- | pkg/p9/client_file.go | 33 | ||||
-rw-r--r-- | pkg/p9/file.go | 16 | ||||
-rw-r--r-- | pkg/p9/handlers.go | 33 | ||||
-rw-r--r-- | pkg/p9/messages.go | 787 | ||||
-rw-r--r-- | pkg/p9/messages_test.go | 4 | ||||
-rw-r--r-- | pkg/p9/p9.go | 72 | ||||
-rw-r--r-- | pkg/p9/pool.go | 68 | ||||
-rw-r--r-- | pkg/p9/pool_test.go | 64 | ||||
-rw-r--r-- | pkg/p9/transport.go | 4 | ||||
-rw-r--r-- | pkg/p9/transport_flipcall.go | 4 | ||||
-rw-r--r-- | pkg/p9/transport_test.go | 8 | ||||
-rw-r--r-- | pkg/p9/version.go | 8 |
15 files changed, 602 insertions, 521 deletions
diff --git a/pkg/p9/BUILD b/pkg/p9/BUILD index 4ccc1de86..8904afad9 100644 --- a/pkg/p9/BUILD +++ b/pkg/p9/BUILD @@ -16,7 +16,6 @@ go_library( "messages.go", "p9.go", "path_tree.go", - "pool.go", "server.go", "transport.go", "transport_flipcall.go", @@ -27,6 +26,7 @@ go_library( "//pkg/fdchannel", "//pkg/flipcall", "//pkg/log", + "//pkg/pool", "//pkg/sync", "//pkg/unet", "@org_golang_x_sys//unix:go_default_library", @@ -41,7 +41,6 @@ go_test( "client_test.go", "messages_test.go", "p9_test.go", - "pool_test.go", "transport_test.go", "version_test.go", ], diff --git a/pkg/p9/buffer.go b/pkg/p9/buffer.go index 249536d8a..6a4951821 100644 --- a/pkg/p9/buffer.go +++ b/pkg/p9/buffer.go @@ -20,16 +20,16 @@ import ( // encoder is used for messages and 9P primitives. type encoder interface { - // Decode decodes from the given buffer. Decode may be called more than once + // decode decodes from the given buffer. decode may be called more than once // to reuse the instance. It must clear any previous state. // // This may not fail, exhaustion will be recorded in the buffer. - Decode(b *buffer) + decode(b *buffer) - // Encode encodes to the given buffer. + // encode encodes to the given buffer. // // This may not fail. - Encode(b *buffer) + encode(b *buffer) } // order is the byte order used for encoding. @@ -39,7 +39,7 @@ var order = binary.LittleEndian // // This is passed to the encoder methods. type buffer struct { - // data is the underlying data. This may grow during Encode. + // data is the underlying data. This may grow during encode. data []byte // overflow indicates whether an overflow has occurred. diff --git a/pkg/p9/client.go b/pkg/p9/client.go index 4045e41fa..a6f493b82 100644 --- a/pkg/p9/client.go +++ b/pkg/p9/client.go @@ -22,6 +22,7 @@ import ( "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/flipcall" "gvisor.dev/gvisor/pkg/log" + "gvisor.dev/gvisor/pkg/pool" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/unet" ) @@ -74,10 +75,10 @@ type Client struct { socket *unet.Socket // tagPool is the collection of available tags. - tagPool pool + tagPool pool.Pool // fidPool is the collection of available fids. - fidPool pool + fidPool pool.Pool // messageSize is the maximum total size of a message. messageSize uint32 @@ -155,8 +156,8 @@ func NewClient(socket *unet.Socket, messageSize uint32, version string) (*Client } c := &Client{ socket: socket, - tagPool: pool{start: 1, limit: uint64(NoTag)}, - fidPool: pool{start: 1, limit: uint64(NoFID)}, + tagPool: pool.Pool{Start: 1, Limit: uint64(NoTag)}, + fidPool: pool.Pool{Start: 1, Limit: uint64(NoFID)}, pending: make(map[Tag]*response), recvr: make(chan bool, 1), messageSize: messageSize, diff --git a/pkg/p9/client_file.go b/pkg/p9/client_file.go index 0254e4ccc..2ee07b664 100644 --- a/pkg/p9/client_file.go +++ b/pkg/p9/client_file.go @@ -194,6 +194,39 @@ func (c *clientFile) SetXattr(name, value string, flags uint32) error { return c.client.sendRecv(&Tsetxattr{FID: c.fid, Name: name, Value: value, Flags: flags}, &Rsetxattr{}) } +// ListXattr implements File.ListXattr. +func (c *clientFile) ListXattr(size uint64) (map[string]struct{}, error) { + if atomic.LoadUint32(&c.closed) != 0 { + return nil, syscall.EBADF + } + if !versionSupportsListRemoveXattr(c.client.version) { + return nil, syscall.EOPNOTSUPP + } + + rlistxattr := Rlistxattr{} + if err := c.client.sendRecv(&Tlistxattr{FID: c.fid, Size: size}, &rlistxattr); err != nil { + return nil, err + } + + xattrs := make(map[string]struct{}, len(rlistxattr.Xattrs)) + for _, x := range rlistxattr.Xattrs { + xattrs[x] = struct{}{} + } + return xattrs, nil +} + +// RemoveXattr implements File.RemoveXattr. +func (c *clientFile) RemoveXattr(name string) error { + if atomic.LoadUint32(&c.closed) != 0 { + return syscall.EBADF + } + if !versionSupportsListRemoveXattr(c.client.version) { + return syscall.EOPNOTSUPP + } + + return c.client.sendRecv(&Tremovexattr{FID: c.fid, Name: name}, &Rremovexattr{}) +} + // Allocate implements File.Allocate. func (c *clientFile) Allocate(mode AllocateMode, offset, length uint64) error { if atomic.LoadUint32(&c.closed) != 0 { diff --git a/pkg/p9/file.go b/pkg/p9/file.go index 4607cfcdf..d4ffbc8e3 100644 --- a/pkg/p9/file.go +++ b/pkg/p9/file.go @@ -105,6 +105,22 @@ type File interface { // TODO(b/127675828): Determine concurrency guarantees once implemented. SetXattr(name, value string, flags uint32) error + // ListXattr lists the names of the extended attributes on this node. + // + // Size indicates the size of the buffer that has been allocated to hold the + // attribute list. If the list would be larger than size, implementations may + // return ERANGE to indicate that the buffer is too small, but they are also + // free to ignore the hint entirely (i.e. the value returned may be larger + // than size). All size checking is done independently at the syscall layer. + // + // TODO(b/148303075): Determine concurrency guarantees once implemented. + ListXattr(size uint64) (map[string]struct{}, error) + + // RemoveXattr removes extended attributes on this node. + // + // TODO(b/148303075): Determine concurrency guarantees once implemented. + RemoveXattr(name string) error + // Allocate allows the caller to directly manipulate the allocated disk space // for the file. See fallocate(2) for more details. Allocate(mode AllocateMode, offset, length uint64) error diff --git a/pkg/p9/handlers.go b/pkg/p9/handlers.go index 7d6653a07..2ac45eb80 100644 --- a/pkg/p9/handlers.go +++ b/pkg/p9/handlers.go @@ -942,6 +942,39 @@ func (t *Tsetxattr) handle(cs *connState) message { } // handle implements handler.handle. +func (t *Tlistxattr) handle(cs *connState) message { + ref, ok := cs.LookupFID(t.FID) + if !ok { + return newErr(syscall.EBADF) + } + defer ref.DecRef() + + xattrs, err := ref.file.ListXattr(t.Size) + if err != nil { + return newErr(err) + } + xattrList := make([]string, 0, len(xattrs)) + for x := range xattrs { + xattrList = append(xattrList, x) + } + return &Rlistxattr{Xattrs: xattrList} +} + +// handle implements handler.handle. +func (t *Tremovexattr) handle(cs *connState) message { + ref, ok := cs.LookupFID(t.FID) + if !ok { + return newErr(syscall.EBADF) + } + defer ref.DecRef() + + if err := ref.file.RemoveXattr(t.Name); err != nil { + return newErr(err) + } + return &Rremovexattr{} +} + +// handle implements handler.handle. func (t *Treaddir) handle(cs *connState) message { ref, ok := cs.LookupFID(t.Directory) if !ok { diff --git a/pkg/p9/messages.go b/pkg/p9/messages.go index ceb723d86..3863ad1f5 100644 --- a/pkg/p9/messages.go +++ b/pkg/p9/messages.go @@ -51,7 +51,7 @@ type payloader interface { // SetPayload returns the decoded message. // // This is going to be total message size - FixedSize. But this should - // be validated during Decode, which will be called after SetPayload. + // be validated during decode, which will be called after SetPayload. SetPayload([]byte) } @@ -90,14 +90,14 @@ type Tversion struct { Version string } -// Decode implements encoder.Decode. -func (t *Tversion) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tversion) decode(b *buffer) { t.MSize = b.Read32() t.Version = b.ReadString() } -// Encode implements encoder.Encode. -func (t *Tversion) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tversion) encode(b *buffer) { b.Write32(t.MSize) b.WriteString(t.Version) } @@ -121,14 +121,14 @@ type Rversion struct { Version string } -// Decode implements encoder.Decode. -func (r *Rversion) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rversion) decode(b *buffer) { r.MSize = b.Read32() r.Version = b.ReadString() } -// Encode implements encoder.Encode. -func (r *Rversion) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rversion) encode(b *buffer) { b.Write32(r.MSize) b.WriteString(r.Version) } @@ -149,13 +149,13 @@ type Tflush struct { OldTag Tag } -// Decode implements encoder.Decode. -func (t *Tflush) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tflush) decode(b *buffer) { t.OldTag = b.ReadTag() } -// Encode implements encoder.Encode. -func (t *Tflush) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tflush) encode(b *buffer) { b.WriteTag(t.OldTag) } @@ -173,12 +173,12 @@ func (t *Tflush) String() string { type Rflush struct { } -// Decode implements encoder.Decode. -func (*Rflush) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rflush) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rflush) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rflush) encode(*buffer) { } // Type implements message.Type. @@ -188,7 +188,7 @@ func (*Rflush) Type() MsgType { // String implements fmt.Stringer. func (r *Rflush) String() string { - return fmt.Sprintf("RFlush{}") + return "RFlush{}" } // Twalk is a walk request. @@ -203,8 +203,8 @@ type Twalk struct { Names []string } -// Decode implements encoder.Decode. -func (t *Twalk) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Twalk) decode(b *buffer) { t.FID = b.ReadFID() t.NewFID = b.ReadFID() n := b.Read16() @@ -214,8 +214,8 @@ func (t *Twalk) Decode(b *buffer) { } } -// Encode implements encoder.Encode. -func (t *Twalk) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Twalk) encode(b *buffer) { b.WriteFID(t.FID) b.WriteFID(t.NewFID) b.Write16(uint16(len(t.Names))) @@ -240,22 +240,22 @@ type Rwalk struct { QIDs []QID } -// Decode implements encoder.Decode. -func (r *Rwalk) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rwalk) decode(b *buffer) { n := b.Read16() r.QIDs = r.QIDs[:0] for i := 0; i < int(n); i++ { var q QID - q.Decode(b) + q.decode(b) r.QIDs = append(r.QIDs, q) } } -// Encode implements encoder.Encode. -func (r *Rwalk) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rwalk) encode(b *buffer) { b.Write16(uint16(len(r.QIDs))) for _, q := range r.QIDs { - q.Encode(b) + q.encode(b) } } @@ -275,13 +275,13 @@ type Tclunk struct { FID FID } -// Decode implements encoder.Decode. -func (t *Tclunk) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tclunk) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Tclunk) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tclunk) encode(b *buffer) { b.WriteFID(t.FID) } @@ -299,12 +299,12 @@ func (t *Tclunk) String() string { type Rclunk struct { } -// Decode implements encoder.Decode. -func (*Rclunk) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rclunk) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rclunk) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rclunk) encode(*buffer) { } // Type implements message.Type. @@ -314,7 +314,7 @@ func (*Rclunk) Type() MsgType { // String implements fmt.Stringer. func (r *Rclunk) String() string { - return fmt.Sprintf("Rclunk{}") + return "Rclunk{}" } // Tremove is a remove request. @@ -325,13 +325,13 @@ type Tremove struct { FID FID } -// Decode implements encoder.Decode. -func (t *Tremove) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tremove) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Tremove) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tremove) encode(b *buffer) { b.WriteFID(t.FID) } @@ -349,12 +349,12 @@ func (t *Tremove) String() string { type Rremove struct { } -// Decode implements encoder.Decode. -func (*Rremove) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rremove) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rremove) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rremove) encode(*buffer) { } // Type implements message.Type. @@ -364,7 +364,7 @@ func (*Rremove) Type() MsgType { // String implements fmt.Stringer. func (r *Rremove) String() string { - return fmt.Sprintf("Rremove{}") + return "Rremove{}" } // Rlerror is an error response. @@ -374,13 +374,13 @@ type Rlerror struct { Error uint32 } -// Decode implements encoder.Decode. -func (r *Rlerror) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rlerror) decode(b *buffer) { r.Error = b.Read32() } -// Encode implements encoder.Encode. -func (r *Rlerror) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rlerror) encode(b *buffer) { b.Write32(r.Error) } @@ -409,16 +409,16 @@ type Tauth struct { UID UID } -// Decode implements encoder.Decode. -func (t *Tauth) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tauth) decode(b *buffer) { t.AuthenticationFID = b.ReadFID() t.UserName = b.ReadString() t.AttachName = b.ReadString() t.UID = b.ReadUID() } -// Encode implements encoder.Encode. -func (t *Tauth) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tauth) encode(b *buffer) { b.WriteFID(t.AuthenticationFID) b.WriteString(t.UserName) b.WriteString(t.AttachName) @@ -437,7 +437,7 @@ func (t *Tauth) String() string { // Rauth is an authentication response. // -// Encode, Decode and Length are inherited directly from QID. +// encode and decode are inherited directly from QID. type Rauth struct { QID } @@ -463,16 +463,16 @@ type Tattach struct { Auth Tauth } -// Decode implements encoder.Decode. -func (t *Tattach) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tattach) decode(b *buffer) { t.FID = b.ReadFID() - t.Auth.Decode(b) + t.Auth.decode(b) } -// Encode implements encoder.Encode. -func (t *Tattach) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tattach) encode(b *buffer) { b.WriteFID(t.FID) - t.Auth.Encode(b) + t.Auth.encode(b) } // Type implements message.Type. @@ -509,14 +509,14 @@ type Tlopen struct { Flags OpenFlags } -// Decode implements encoder.Decode. -func (t *Tlopen) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tlopen) decode(b *buffer) { t.FID = b.ReadFID() t.Flags = b.ReadOpenFlags() } -// Encode implements encoder.Encode. -func (t *Tlopen) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tlopen) encode(b *buffer) { b.WriteFID(t.FID) b.WriteOpenFlags(t.Flags) } @@ -542,15 +542,15 @@ type Rlopen struct { filePayload } -// Decode implements encoder.Decode. -func (r *Rlopen) Decode(b *buffer) { - r.QID.Decode(b) +// decode implements encoder.decode. +func (r *Rlopen) decode(b *buffer) { + r.QID.decode(b) r.IoUnit = b.Read32() } -// Encode implements encoder.Encode. -func (r *Rlopen) Encode(b *buffer) { - r.QID.Encode(b) +// encode implements encoder.encode. +func (r *Rlopen) encode(b *buffer) { + r.QID.encode(b) b.Write32(r.IoUnit) } @@ -587,8 +587,8 @@ type Tlcreate struct { GID GID } -// Decode implements encoder.Decode. -func (t *Tlcreate) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tlcreate) decode(b *buffer) { t.FID = b.ReadFID() t.Name = b.ReadString() t.OpenFlags = b.ReadOpenFlags() @@ -596,8 +596,8 @@ func (t *Tlcreate) Decode(b *buffer) { t.GID = b.ReadGID() } -// Encode implements encoder.Encode. -func (t *Tlcreate) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tlcreate) encode(b *buffer) { b.WriteFID(t.FID) b.WriteString(t.Name) b.WriteOpenFlags(t.OpenFlags) @@ -617,7 +617,7 @@ func (t *Tlcreate) String() string { // Rlcreate is a create response. // -// The Encode, Decode, etc. methods are inherited from Rlopen. +// The encode, decode, etc. methods are inherited from Rlopen. type Rlcreate struct { Rlopen } @@ -647,16 +647,16 @@ type Tsymlink struct { GID GID } -// Decode implements encoder.Decode. -func (t *Tsymlink) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tsymlink) decode(b *buffer) { t.Directory = b.ReadFID() t.Name = b.ReadString() t.Target = b.ReadString() t.GID = b.ReadGID() } -// Encode implements encoder.Encode. -func (t *Tsymlink) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tsymlink) encode(b *buffer) { b.WriteFID(t.Directory) b.WriteString(t.Name) b.WriteString(t.Target) @@ -679,14 +679,14 @@ type Rsymlink struct { QID QID } -// Decode implements encoder.Decode. -func (r *Rsymlink) Decode(b *buffer) { - r.QID.Decode(b) +// decode implements encoder.decode. +func (r *Rsymlink) decode(b *buffer) { + r.QID.decode(b) } -// Encode implements encoder.Encode. -func (r *Rsymlink) Encode(b *buffer) { - r.QID.Encode(b) +// encode implements encoder.encode. +func (r *Rsymlink) encode(b *buffer) { + r.QID.encode(b) } // Type implements message.Type. @@ -711,15 +711,15 @@ type Tlink struct { Name string } -// Decode implements encoder.Decode. -func (t *Tlink) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tlink) decode(b *buffer) { t.Directory = b.ReadFID() t.Target = b.ReadFID() t.Name = b.ReadString() } -// Encode implements encoder.Encode. -func (t *Tlink) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tlink) encode(b *buffer) { b.WriteFID(t.Directory) b.WriteFID(t.Target) b.WriteString(t.Name) @@ -744,17 +744,17 @@ func (*Rlink) Type() MsgType { return MsgRlink } -// Decode implements encoder.Decode. -func (*Rlink) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rlink) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rlink) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rlink) encode(*buffer) { } // String implements fmt.Stringer. func (r *Rlink) String() string { - return fmt.Sprintf("Rlink{}") + return "Rlink{}" } // Trenameat is a rename request. @@ -772,16 +772,16 @@ type Trenameat struct { NewName string } -// Decode implements encoder.Decode. -func (t *Trenameat) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Trenameat) decode(b *buffer) { t.OldDirectory = b.ReadFID() t.OldName = b.ReadString() t.NewDirectory = b.ReadFID() t.NewName = b.ReadString() } -// Encode implements encoder.Encode. -func (t *Trenameat) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Trenameat) encode(b *buffer) { b.WriteFID(t.OldDirectory) b.WriteString(t.OldName) b.WriteFID(t.NewDirectory) @@ -802,12 +802,12 @@ func (t *Trenameat) String() string { type Rrenameat struct { } -// Decode implements encoder.Decode. -func (*Rrenameat) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rrenameat) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rrenameat) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rrenameat) encode(*buffer) { } // Type implements message.Type. @@ -817,7 +817,7 @@ func (*Rrenameat) Type() MsgType { // String implements fmt.Stringer. func (r *Rrenameat) String() string { - return fmt.Sprintf("Rrenameat{}") + return "Rrenameat{}" } // Tunlinkat is an unlink request. @@ -832,15 +832,15 @@ type Tunlinkat struct { Flags uint32 } -// Decode implements encoder.Decode. -func (t *Tunlinkat) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tunlinkat) decode(b *buffer) { t.Directory = b.ReadFID() t.Name = b.ReadString() t.Flags = b.Read32() } -// Encode implements encoder.Encode. -func (t *Tunlinkat) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tunlinkat) encode(b *buffer) { b.WriteFID(t.Directory) b.WriteString(t.Name) b.Write32(t.Flags) @@ -860,12 +860,12 @@ func (t *Tunlinkat) String() string { type Runlinkat struct { } -// Decode implements encoder.Decode. -func (*Runlinkat) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Runlinkat) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Runlinkat) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Runlinkat) encode(*buffer) { } // Type implements message.Type. @@ -875,7 +875,7 @@ func (*Runlinkat) Type() MsgType { // String implements fmt.Stringer. func (r *Runlinkat) String() string { - return fmt.Sprintf("Runlinkat{}") + return "Runlinkat{}" } // Trename is a rename request. @@ -893,15 +893,15 @@ type Trename struct { Name string } -// Decode implements encoder.Decode. -func (t *Trename) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Trename) decode(b *buffer) { t.FID = b.ReadFID() t.Directory = b.ReadFID() t.Name = b.ReadString() } -// Encode implements encoder.Encode. -func (t *Trename) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Trename) encode(b *buffer) { b.WriteFID(t.FID) b.WriteFID(t.Directory) b.WriteString(t.Name) @@ -921,12 +921,12 @@ func (t *Trename) String() string { type Rrename struct { } -// Decode implements encoder.Decode. -func (*Rrename) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rrename) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rrename) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rrename) encode(*buffer) { } // Type implements message.Type. @@ -936,7 +936,7 @@ func (*Rrename) Type() MsgType { // String implements fmt.Stringer. func (r *Rrename) String() string { - return fmt.Sprintf("Rrename{}") + return "Rrename{}" } // Treadlink is a readlink request. @@ -945,13 +945,13 @@ type Treadlink struct { FID FID } -// Decode implements encoder.Decode. -func (t *Treadlink) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Treadlink) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Treadlink) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Treadlink) encode(b *buffer) { b.WriteFID(t.FID) } @@ -971,13 +971,13 @@ type Rreadlink struct { Target string } -// Decode implements encoder.Decode. -func (r *Rreadlink) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rreadlink) decode(b *buffer) { r.Target = b.ReadString() } -// Encode implements encoder.Encode. -func (r *Rreadlink) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rreadlink) encode(b *buffer) { b.WriteString(r.Target) } @@ -1003,15 +1003,15 @@ type Tread struct { Count uint32 } -// Decode implements encoder.Decode. -func (t *Tread) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tread) decode(b *buffer) { t.FID = b.ReadFID() t.Offset = b.Read64() t.Count = b.Read32() } -// Encode implements encoder.Encode. -func (t *Tread) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tread) encode(b *buffer) { b.WriteFID(t.FID) b.Write64(t.Offset) b.Write32(t.Count) @@ -1033,20 +1033,20 @@ type Rread struct { Data []byte } -// Decode implements encoder.Decode. +// decode implements encoder.decode. // // Data is automatically decoded via Payload. -func (r *Rread) Decode(b *buffer) { +func (r *Rread) decode(b *buffer) { count := b.Read32() if count != uint32(len(r.Data)) { b.markOverrun() } } -// Encode implements encoder.Encode. +// encode implements encoder.encode. // // Data is automatically encoded via Payload. -func (r *Rread) Encode(b *buffer) { +func (r *Rread) encode(b *buffer) { b.Write32(uint32(len(r.Data))) } @@ -1087,8 +1087,8 @@ type Twrite struct { Data []byte } -// Decode implements encoder.Decode. -func (t *Twrite) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Twrite) decode(b *buffer) { t.FID = b.ReadFID() t.Offset = b.Read64() count := b.Read32() @@ -1097,10 +1097,10 @@ func (t *Twrite) Decode(b *buffer) { } } -// Encode implements encoder.Encode. +// encode implements encoder.encode. // // This uses the buffer payload to avoid a copy. -func (t *Twrite) Encode(b *buffer) { +func (t *Twrite) encode(b *buffer) { b.WriteFID(t.FID) b.Write64(t.Offset) b.Write32(uint32(len(t.Data))) @@ -1137,13 +1137,13 @@ type Rwrite struct { Count uint32 } -// Decode implements encoder.Decode. -func (r *Rwrite) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rwrite) decode(b *buffer) { r.Count = b.Read32() } -// Encode implements encoder.Encode. -func (r *Rwrite) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rwrite) encode(b *buffer) { b.Write32(r.Count) } @@ -1178,8 +1178,8 @@ type Tmknod struct { GID GID } -// Decode implements encoder.Decode. -func (t *Tmknod) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tmknod) decode(b *buffer) { t.Directory = b.ReadFID() t.Name = b.ReadString() t.Mode = b.ReadFileMode() @@ -1188,8 +1188,8 @@ func (t *Tmknod) Decode(b *buffer) { t.GID = b.ReadGID() } -// Encode implements encoder.Encode. -func (t *Tmknod) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tmknod) encode(b *buffer) { b.WriteFID(t.Directory) b.WriteString(t.Name) b.WriteFileMode(t.Mode) @@ -1214,14 +1214,14 @@ type Rmknod struct { QID QID } -// Decode implements encoder.Decode. -func (r *Rmknod) Decode(b *buffer) { - r.QID.Decode(b) +// decode implements encoder.decode. +func (r *Rmknod) decode(b *buffer) { + r.QID.decode(b) } -// Encode implements encoder.Encode. -func (r *Rmknod) Encode(b *buffer) { - r.QID.Encode(b) +// encode implements encoder.encode. +func (r *Rmknod) encode(b *buffer) { + r.QID.encode(b) } // Type implements message.Type. @@ -1249,16 +1249,16 @@ type Tmkdir struct { GID GID } -// Decode implements encoder.Decode. -func (t *Tmkdir) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tmkdir) decode(b *buffer) { t.Directory = b.ReadFID() t.Name = b.ReadString() t.Permissions = b.ReadPermissions() t.GID = b.ReadGID() } -// Encode implements encoder.Encode. -func (t *Tmkdir) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tmkdir) encode(b *buffer) { b.WriteFID(t.Directory) b.WriteString(t.Name) b.WritePermissions(t.Permissions) @@ -1281,14 +1281,14 @@ type Rmkdir struct { QID QID } -// Decode implements encoder.Decode. -func (r *Rmkdir) Decode(b *buffer) { - r.QID.Decode(b) +// decode implements encoder.decode. +func (r *Rmkdir) decode(b *buffer) { + r.QID.decode(b) } -// Encode implements encoder.Encode. -func (r *Rmkdir) Encode(b *buffer) { - r.QID.Encode(b) +// encode implements encoder.encode. +func (r *Rmkdir) encode(b *buffer) { + r.QID.encode(b) } // Type implements message.Type. @@ -1310,16 +1310,16 @@ type Tgetattr struct { AttrMask AttrMask } -// Decode implements encoder.Decode. -func (t *Tgetattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tgetattr) decode(b *buffer) { t.FID = b.ReadFID() - t.AttrMask.Decode(b) + t.AttrMask.decode(b) } -// Encode implements encoder.Encode. -func (t *Tgetattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tgetattr) encode(b *buffer) { b.WriteFID(t.FID) - t.AttrMask.Encode(b) + t.AttrMask.encode(b) } // Type implements message.Type. @@ -1344,18 +1344,18 @@ type Rgetattr struct { Attr Attr } -// Decode implements encoder.Decode. -func (r *Rgetattr) Decode(b *buffer) { - r.Valid.Decode(b) - r.QID.Decode(b) - r.Attr.Decode(b) +// decode implements encoder.decode. +func (r *Rgetattr) decode(b *buffer) { + r.Valid.decode(b) + r.QID.decode(b) + r.Attr.decode(b) } -// Encode implements encoder.Encode. -func (r *Rgetattr) Encode(b *buffer) { - r.Valid.Encode(b) - r.QID.Encode(b) - r.Attr.Encode(b) +// encode implements encoder.encode. +func (r *Rgetattr) encode(b *buffer) { + r.Valid.encode(b) + r.QID.encode(b) + r.Attr.encode(b) } // Type implements message.Type. @@ -1380,18 +1380,18 @@ type Tsetattr struct { SetAttr SetAttr } -// Decode implements encoder.Decode. -func (t *Tsetattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tsetattr) decode(b *buffer) { t.FID = b.ReadFID() - t.Valid.Decode(b) - t.SetAttr.Decode(b) + t.Valid.decode(b) + t.SetAttr.decode(b) } -// Encode implements encoder.Encode. -func (t *Tsetattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tsetattr) encode(b *buffer) { b.WriteFID(t.FID) - t.Valid.Encode(b) - t.SetAttr.Encode(b) + t.Valid.encode(b) + t.SetAttr.encode(b) } // Type implements message.Type. @@ -1408,12 +1408,12 @@ func (t *Tsetattr) String() string { type Rsetattr struct { } -// Decode implements encoder.Decode. -func (*Rsetattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rsetattr) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rsetattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rsetattr) encode(*buffer) { } // Type implements message.Type. @@ -1423,7 +1423,7 @@ func (*Rsetattr) Type() MsgType { // String implements fmt.Stringer. func (r *Rsetattr) String() string { - return fmt.Sprintf("Rsetattr{}") + return "Rsetattr{}" } // Tallocate is an allocate request. This is an extension to 9P protocol, not @@ -1435,18 +1435,18 @@ type Tallocate struct { Length uint64 } -// Decode implements encoder.Decode. -func (t *Tallocate) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tallocate) decode(b *buffer) { t.FID = b.ReadFID() - t.Mode.Decode(b) + t.Mode.decode(b) t.Offset = b.Read64() t.Length = b.Read64() } -// Encode implements encoder.Encode. -func (t *Tallocate) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tallocate) encode(b *buffer) { b.WriteFID(t.FID) - t.Mode.Encode(b) + t.Mode.encode(b) b.Write64(t.Offset) b.Write64(t.Length) } @@ -1465,12 +1465,12 @@ func (t *Tallocate) String() string { type Rallocate struct { } -// Decode implements encoder.Decode. -func (*Rallocate) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rallocate) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rallocate) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rallocate) encode(*buffer) { } // Type implements message.Type. @@ -1480,7 +1480,71 @@ func (*Rallocate) Type() MsgType { // String implements fmt.Stringer. func (r *Rallocate) String() string { - return fmt.Sprintf("Rallocate{}") + return "Rallocate{}" +} + +// Tlistxattr is a listxattr request. +type Tlistxattr struct { + // FID refers to the file on which to list xattrs. + FID FID + + // Size is the buffer size for the xattr list. + Size uint64 +} + +// decode implements encoder.decode. +func (t *Tlistxattr) decode(b *buffer) { + t.FID = b.ReadFID() + t.Size = b.Read64() +} + +// encode implements encoder.encode. +func (t *Tlistxattr) encode(b *buffer) { + b.WriteFID(t.FID) + b.Write64(t.Size) +} + +// Type implements message.Type. +func (*Tlistxattr) Type() MsgType { + return MsgTlistxattr +} + +// String implements fmt.Stringer. +func (t *Tlistxattr) String() string { + return fmt.Sprintf("Tlistxattr{FID: %d, Size: %d}", t.FID, t.Size) +} + +// Rlistxattr is a listxattr response. +type Rlistxattr struct { + // Xattrs is a list of extended attribute names. + Xattrs []string +} + +// decode implements encoder.decode. +func (r *Rlistxattr) decode(b *buffer) { + n := b.Read16() + r.Xattrs = r.Xattrs[:0] + for i := 0; i < int(n); i++ { + r.Xattrs = append(r.Xattrs, b.ReadString()) + } +} + +// encode implements encoder.encode. +func (r *Rlistxattr) encode(b *buffer) { + b.Write16(uint16(len(r.Xattrs))) + for _, x := range r.Xattrs { + b.WriteString(x) + } +} + +// Type implements message.Type. +func (*Rlistxattr) Type() MsgType { + return MsgRlistxattr +} + +// String implements fmt.Stringer. +func (r *Rlistxattr) String() string { + return fmt.Sprintf("Rlistxattr{Xattrs: %v}", r.Xattrs) } // Txattrwalk walks extended attributes. @@ -1495,15 +1559,15 @@ type Txattrwalk struct { Name string } -// Decode implements encoder.Decode. -func (t *Txattrwalk) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Txattrwalk) decode(b *buffer) { t.FID = b.ReadFID() t.NewFID = b.ReadFID() t.Name = b.ReadString() } -// Encode implements encoder.Encode. -func (t *Txattrwalk) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Txattrwalk) encode(b *buffer) { b.WriteFID(t.FID) b.WriteFID(t.NewFID) b.WriteString(t.Name) @@ -1525,13 +1589,13 @@ type Rxattrwalk struct { Size uint64 } -// Decode implements encoder.Decode. -func (r *Rxattrwalk) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rxattrwalk) decode(b *buffer) { r.Size = b.Read64() } -// Encode implements encoder.Encode. -func (r *Rxattrwalk) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rxattrwalk) encode(b *buffer) { b.Write64(r.Size) } @@ -1563,16 +1627,16 @@ type Txattrcreate struct { Flags uint32 } -// Decode implements encoder.Decode. -func (t *Txattrcreate) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Txattrcreate) decode(b *buffer) { t.FID = b.ReadFID() t.Name = b.ReadString() t.AttrSize = b.Read64() t.Flags = b.Read32() } -// Encode implements encoder.Encode. -func (t *Txattrcreate) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Txattrcreate) encode(b *buffer) { b.WriteFID(t.FID) b.WriteString(t.Name) b.Write64(t.AttrSize) @@ -1593,12 +1657,12 @@ func (t *Txattrcreate) String() string { type Rxattrcreate struct { } -// Decode implements encoder.Decode. -func (r *Rxattrcreate) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rxattrcreate) decode(*buffer) { } -// Encode implements encoder.Encode. -func (r *Rxattrcreate) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rxattrcreate) encode(*buffer) { } // Type implements message.Type. @@ -1608,7 +1672,7 @@ func (*Rxattrcreate) Type() MsgType { // String implements fmt.Stringer. func (r *Rxattrcreate) String() string { - return fmt.Sprintf("Rxattrcreate{}") + return "Rxattrcreate{}" } // Tgetxattr is a getxattr request. @@ -1623,15 +1687,15 @@ type Tgetxattr struct { Size uint64 } -// Decode implements encoder.Decode. -func (t *Tgetxattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tgetxattr) decode(b *buffer) { t.FID = b.ReadFID() t.Name = b.ReadString() t.Size = b.Read64() } -// Encode implements encoder.Encode. -func (t *Tgetxattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tgetxattr) encode(b *buffer) { b.WriteFID(t.FID) b.WriteString(t.Name) b.Write64(t.Size) @@ -1653,13 +1717,13 @@ type Rgetxattr struct { Value string } -// Decode implements encoder.Decode. -func (r *Rgetxattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rgetxattr) decode(b *buffer) { r.Value = b.ReadString() } -// Encode implements encoder.Encode. -func (r *Rgetxattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rgetxattr) encode(b *buffer) { b.WriteString(r.Value) } @@ -1688,16 +1752,16 @@ type Tsetxattr struct { Flags uint32 } -// Decode implements encoder.Decode. -func (t *Tsetxattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tsetxattr) decode(b *buffer) { t.FID = b.ReadFID() t.Name = b.ReadString() t.Value = b.ReadString() t.Flags = b.Read32() } -// Encode implements encoder.Encode. -func (t *Tsetxattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tsetxattr) encode(b *buffer) { b.WriteFID(t.FID) b.WriteString(t.Name) b.WriteString(t.Value) @@ -1718,12 +1782,12 @@ func (t *Tsetxattr) String() string { type Rsetxattr struct { } -// Decode implements encoder.Decode. -func (r *Rsetxattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rsetxattr) decode(*buffer) { } -// Encode implements encoder.Encode. -func (r *Rsetxattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rsetxattr) encode(*buffer) { } // Type implements message.Type. @@ -1733,7 +1797,60 @@ func (*Rsetxattr) Type() MsgType { // String implements fmt.Stringer. func (r *Rsetxattr) String() string { - return fmt.Sprintf("Rsetxattr{}") + return "Rsetxattr{}" +} + +// Tremovexattr is a removexattr request. +type Tremovexattr struct { + // FID refers to the file on which to set xattrs. + FID FID + + // Name is the attribute name. + Name string +} + +// decode implements encoder.decode. +func (t *Tremovexattr) decode(b *buffer) { + t.FID = b.ReadFID() + t.Name = b.ReadString() +} + +// encode implements encoder.encode. +func (t *Tremovexattr) encode(b *buffer) { + b.WriteFID(t.FID) + b.WriteString(t.Name) +} + +// Type implements message.Type. +func (*Tremovexattr) Type() MsgType { + return MsgTremovexattr +} + +// String implements fmt.Stringer. +func (t *Tremovexattr) String() string { + return fmt.Sprintf("Tremovexattr{FID: %d, Name: %s}", t.FID, t.Name) +} + +// Rremovexattr is a removexattr response. +type Rremovexattr struct { +} + +// decode implements encoder.decode. +func (r *Rremovexattr) decode(*buffer) { +} + +// encode implements encoder.encode. +func (r *Rremovexattr) encode(*buffer) { +} + +// Type implements message.Type. +func (*Rremovexattr) Type() MsgType { + return MsgRremovexattr +} + +// String implements fmt.Stringer. +func (r *Rremovexattr) String() string { + return "Rremovexattr{}" } // Treaddir is a readdir request. @@ -1748,15 +1865,15 @@ type Treaddir struct { Count uint32 } -// Decode implements encoder.Decode. -func (t *Treaddir) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Treaddir) decode(b *buffer) { t.Directory = b.ReadFID() t.Offset = b.Read64() t.Count = b.Read32() } -// Encode implements encoder.Encode. -func (t *Treaddir) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Treaddir) encode(b *buffer) { b.WriteFID(t.Directory) b.Write64(t.Offset) b.Write32(t.Count) @@ -1790,14 +1907,14 @@ type Rreaddir struct { payload []byte } -// Decode implements encoder.Decode. -func (r *Rreaddir) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rreaddir) decode(b *buffer) { r.Count = b.Read32() entriesBuf := buffer{data: r.payload} r.Entries = r.Entries[:0] for { var d Dirent - d.Decode(&entriesBuf) + d.decode(&entriesBuf) if entriesBuf.isOverrun() { // Couldn't decode a complete entry. break @@ -1806,11 +1923,11 @@ func (r *Rreaddir) Decode(b *buffer) { } } -// Encode implements encoder.Encode. -func (r *Rreaddir) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rreaddir) encode(b *buffer) { entriesBuf := buffer{} for _, d := range r.Entries { - d.Encode(&entriesBuf) + d.encode(&entriesBuf) if len(entriesBuf.data) >= int(r.Count) { break } @@ -1855,13 +1972,13 @@ type Tfsync struct { FID FID } -// Decode implements encoder.Decode. -func (t *Tfsync) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tfsync) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Tfsync) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tfsync) encode(b *buffer) { b.WriteFID(t.FID) } @@ -1879,12 +1996,12 @@ func (t *Tfsync) String() string { type Rfsync struct { } -// Decode implements encoder.Decode. -func (*Rfsync) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rfsync) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rfsync) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rfsync) encode(*buffer) { } // Type implements message.Type. @@ -1894,7 +2011,7 @@ func (*Rfsync) Type() MsgType { // String implements fmt.Stringer. func (r *Rfsync) String() string { - return fmt.Sprintf("Rfsync{}") + return "Rfsync{}" } // Tstatfs is a stat request. @@ -1903,13 +2020,13 @@ type Tstatfs struct { FID FID } -// Decode implements encoder.Decode. -func (t *Tstatfs) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tstatfs) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Tstatfs) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tstatfs) encode(b *buffer) { b.WriteFID(t.FID) } @@ -1929,14 +2046,14 @@ type Rstatfs struct { FSStat FSStat } -// Decode implements encoder.Decode. -func (r *Rstatfs) Decode(b *buffer) { - r.FSStat.Decode(b) +// decode implements encoder.decode. +func (r *Rstatfs) decode(b *buffer) { + r.FSStat.decode(b) } -// Encode implements encoder.Encode. -func (r *Rstatfs) Encode(b *buffer) { - r.FSStat.Encode(b) +// encode implements encoder.encode. +func (r *Rstatfs) encode(b *buffer) { + r.FSStat.encode(b) } // Type implements message.Type. @@ -1955,13 +2072,13 @@ type Tflushf struct { FID FID } -// Decode implements encoder.Decode. -func (t *Tflushf) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tflushf) decode(b *buffer) { t.FID = b.ReadFID() } -// Encode implements encoder.Encode. -func (t *Tflushf) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tflushf) encode(b *buffer) { b.WriteFID(t.FID) } @@ -1979,12 +2096,12 @@ func (t *Tflushf) String() string { type Rflushf struct { } -// Decode implements encoder.Decode. -func (*Rflushf) Decode(b *buffer) { +// decode implements encoder.decode. +func (*Rflushf) decode(*buffer) { } -// Encode implements encoder.Encode. -func (*Rflushf) Encode(b *buffer) { +// encode implements encoder.encode. +func (*Rflushf) encode(*buffer) { } // Type implements message.Type. @@ -1994,7 +2111,7 @@ func (*Rflushf) Type() MsgType { // String implements fmt.Stringer. func (*Rflushf) String() string { - return fmt.Sprintf("Rflushf{}") + return "Rflushf{}" } // Twalkgetattr is a walk request. @@ -2009,8 +2126,8 @@ type Twalkgetattr struct { Names []string } -// Decode implements encoder.Decode. -func (t *Twalkgetattr) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Twalkgetattr) decode(b *buffer) { t.FID = b.ReadFID() t.NewFID = b.ReadFID() n := b.Read16() @@ -2020,8 +2137,8 @@ func (t *Twalkgetattr) Decode(b *buffer) { } } -// Encode implements encoder.Encode. -func (t *Twalkgetattr) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Twalkgetattr) encode(b *buffer) { b.WriteFID(t.FID) b.WriteFID(t.NewFID) b.Write16(uint16(len(t.Names))) @@ -2052,26 +2169,26 @@ type Rwalkgetattr struct { QIDs []QID } -// Decode implements encoder.Decode. -func (r *Rwalkgetattr) Decode(b *buffer) { - r.Valid.Decode(b) - r.Attr.Decode(b) +// decode implements encoder.decode. +func (r *Rwalkgetattr) decode(b *buffer) { + r.Valid.decode(b) + r.Attr.decode(b) n := b.Read16() r.QIDs = r.QIDs[:0] for i := 0; i < int(n); i++ { var q QID - q.Decode(b) + q.decode(b) r.QIDs = append(r.QIDs, q) } } -// Encode implements encoder.Encode. -func (r *Rwalkgetattr) Encode(b *buffer) { - r.Valid.Encode(b) - r.Attr.Encode(b) +// encode implements encoder.encode. +func (r *Rwalkgetattr) encode(b *buffer) { + r.Valid.encode(b) + r.Attr.encode(b) b.Write16(uint16(len(r.QIDs))) for _, q := range r.QIDs { - q.Encode(b) + q.encode(b) } } @@ -2093,15 +2210,15 @@ type Tucreate struct { UID UID } -// Decode implements encoder.Decode. -func (t *Tucreate) Decode(b *buffer) { - t.Tlcreate.Decode(b) +// decode implements encoder.decode. +func (t *Tucreate) decode(b *buffer) { + t.Tlcreate.decode(b) t.UID = b.ReadUID() } -// Encode implements encoder.Encode. -func (t *Tucreate) Encode(b *buffer) { - t.Tlcreate.Encode(b) +// encode implements encoder.encode. +func (t *Tucreate) encode(b *buffer) { + t.Tlcreate.encode(b) b.WriteUID(t.UID) } @@ -2138,15 +2255,15 @@ type Tumkdir struct { UID UID } -// Decode implements encoder.Decode. -func (t *Tumkdir) Decode(b *buffer) { - t.Tmkdir.Decode(b) +// decode implements encoder.decode. +func (t *Tumkdir) decode(b *buffer) { + t.Tmkdir.decode(b) t.UID = b.ReadUID() } -// Encode implements encoder.Encode. -func (t *Tumkdir) Encode(b *buffer) { - t.Tmkdir.Encode(b) +// encode implements encoder.encode. +func (t *Tumkdir) encode(b *buffer) { + t.Tmkdir.encode(b) b.WriteUID(t.UID) } @@ -2183,15 +2300,15 @@ type Tumknod struct { UID UID } -// Decode implements encoder.Decode. -func (t *Tumknod) Decode(b *buffer) { - t.Tmknod.Decode(b) +// decode implements encoder.decode. +func (t *Tumknod) decode(b *buffer) { + t.Tmknod.decode(b) t.UID = b.ReadUID() } -// Encode implements encoder.Encode. -func (t *Tumknod) Encode(b *buffer) { - t.Tmknod.Encode(b) +// encode implements encoder.encode. +func (t *Tumknod) encode(b *buffer) { + t.Tmknod.encode(b) b.WriteUID(t.UID) } @@ -2228,15 +2345,15 @@ type Tusymlink struct { UID UID } -// Decode implements encoder.Decode. -func (t *Tusymlink) Decode(b *buffer) { - t.Tsymlink.Decode(b) +// decode implements encoder.decode. +func (t *Tusymlink) decode(b *buffer) { + t.Tsymlink.decode(b) t.UID = b.ReadUID() } -// Encode implements encoder.Encode. -func (t *Tusymlink) Encode(b *buffer) { - t.Tsymlink.Encode(b) +// encode implements encoder.encode. +func (t *Tusymlink) encode(b *buffer) { + t.Tsymlink.encode(b) b.WriteUID(t.UID) } @@ -2274,14 +2391,14 @@ type Tlconnect struct { Flags ConnectFlags } -// Decode implements encoder.Decode. -func (t *Tlconnect) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tlconnect) decode(b *buffer) { t.FID = b.ReadFID() t.Flags = b.ReadConnectFlags() } -// Encode implements encoder.Encode. -func (t *Tlconnect) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tlconnect) encode(b *buffer) { b.WriteFID(t.FID) b.WriteConnectFlags(t.Flags) } @@ -2301,11 +2418,11 @@ type Rlconnect struct { filePayload } -// Decode implements encoder.Decode. -func (r *Rlconnect) Decode(*buffer) {} +// decode implements encoder.decode. +func (r *Rlconnect) decode(*buffer) {} -// Encode implements encoder.Encode. -func (r *Rlconnect) Encode(*buffer) {} +// encode implements encoder.encode. +func (r *Rlconnect) encode(*buffer) {} // Type implements message.Type. func (*Rlconnect) Type() MsgType { @@ -2328,14 +2445,14 @@ type Tchannel struct { Control uint32 } -// Decode implements encoder.Decode. -func (t *Tchannel) Decode(b *buffer) { +// decode implements encoder.decode. +func (t *Tchannel) decode(b *buffer) { t.ID = b.Read32() t.Control = b.Read32() } -// Encode implements encoder.Encode. -func (t *Tchannel) Encode(b *buffer) { +// encode implements encoder.encode. +func (t *Tchannel) encode(b *buffer) { b.Write32(t.ID) b.Write32(t.Control) } @@ -2357,14 +2474,14 @@ type Rchannel struct { filePayload } -// Decode implements encoder.Decode. -func (r *Rchannel) Decode(b *buffer) { +// decode implements encoder.decode. +func (r *Rchannel) decode(b *buffer) { r.Offset = b.Read64() r.Length = b.Read64() } -// Encode implements encoder.Encode. -func (r *Rchannel) Encode(b *buffer) { +// encode implements encoder.encode. +func (r *Rchannel) encode(b *buffer) { b.Write64(r.Offset) b.Write64(r.Length) } @@ -2460,7 +2577,7 @@ func calculateSize(m message) uint32 { return p.FixedSize() } var dataBuf buffer - m.Encode(&dataBuf) + m.encode(&dataBuf) return uint32(len(dataBuf.data)) } @@ -2484,6 +2601,8 @@ func init() { msgRegistry.register(MsgRgetattr, func() message { return &Rgetattr{} }) msgRegistry.register(MsgTsetattr, func() message { return &Tsetattr{} }) msgRegistry.register(MsgRsetattr, func() message { return &Rsetattr{} }) + msgRegistry.register(MsgTlistxattr, func() message { return &Tlistxattr{} }) + msgRegistry.register(MsgRlistxattr, func() message { return &Rlistxattr{} }) msgRegistry.register(MsgTxattrwalk, func() message { return &Txattrwalk{} }) msgRegistry.register(MsgRxattrwalk, func() message { return &Rxattrwalk{} }) msgRegistry.register(MsgTxattrcreate, func() message { return &Txattrcreate{} }) @@ -2492,6 +2611,8 @@ func init() { msgRegistry.register(MsgRgetxattr, func() message { return &Rgetxattr{} }) msgRegistry.register(MsgTsetxattr, func() message { return &Tsetxattr{} }) msgRegistry.register(MsgRsetxattr, func() message { return &Rsetxattr{} }) + msgRegistry.register(MsgTremovexattr, func() message { return &Tremovexattr{} }) + msgRegistry.register(MsgRremovexattr, func() message { return &Rremovexattr{} }) msgRegistry.register(MsgTreaddir, func() message { return &Treaddir{} }) msgRegistry.register(MsgRreaddir, func() message { return &Rreaddir{} }) msgRegistry.register(MsgTfsync, func() message { return &Tfsync{} }) diff --git a/pkg/p9/messages_test.go b/pkg/p9/messages_test.go index 825c939da..c20324404 100644 --- a/pkg/p9/messages_test.go +++ b/pkg/p9/messages_test.go @@ -382,7 +382,7 @@ func TestEncodeDecode(t *testing.T) { // Encode the original. data := make([]byte, initialBufferLength) buf := buffer{data: data[:0]} - enc.Encode(&buf) + enc.encode(&buf) // Create a new object, same as the first. enc2 := reflect.New(reflect.ValueOf(enc).Elem().Type()).Interface().(encoder) @@ -399,7 +399,7 @@ func TestEncodeDecode(t *testing.T) { } // Mark sure it was okay. - enc2.Decode(&buf2) + enc2.decode(&buf2) if buf2.isOverrun() { t.Errorf("object %#v->%#v got overrun on decode", enc, enc2) continue diff --git a/pkg/p9/p9.go b/pkg/p9/p9.go index 5ab00d625..28d851ff5 100644 --- a/pkg/p9/p9.go +++ b/pkg/p9/p9.go @@ -335,6 +335,8 @@ const ( MsgRgetattr = 25 MsgTsetattr = 26 MsgRsetattr = 27 + MsgTlistxattr = 28 + MsgRlistxattr = 29 MsgTxattrwalk = 30 MsgRxattrwalk = 31 MsgTxattrcreate = 32 @@ -343,6 +345,8 @@ const ( MsgRgetxattr = 35 MsgTsetxattr = 36 MsgRsetxattr = 37 + MsgTremovexattr = 38 + MsgRremovexattr = 39 MsgTreaddir = 40 MsgRreaddir = 41 MsgTfsync = 50 @@ -446,15 +450,15 @@ func (q QID) String() string { return fmt.Sprintf("QID{Type: %d, Version: %d, Path: %d}", q.Type, q.Version, q.Path) } -// Decode implements encoder.Decode. -func (q *QID) Decode(b *buffer) { +// decode implements encoder.decode. +func (q *QID) decode(b *buffer) { q.Type = b.ReadQIDType() q.Version = b.Read32() q.Path = b.Read64() } -// Encode implements encoder.Encode. -func (q *QID) Encode(b *buffer) { +// encode implements encoder.encode. +func (q *QID) encode(b *buffer) { b.WriteQIDType(q.Type) b.Write32(q.Version) b.Write64(q.Path) @@ -511,8 +515,8 @@ type FSStat struct { NameLength uint32 } -// Decode implements encoder.Decode. -func (f *FSStat) Decode(b *buffer) { +// decode implements encoder.decode. +func (f *FSStat) decode(b *buffer) { f.Type = b.Read32() f.BlockSize = b.Read32() f.Blocks = b.Read64() @@ -524,8 +528,8 @@ func (f *FSStat) Decode(b *buffer) { f.NameLength = b.Read32() } -// Encode implements encoder.Encode. -func (f *FSStat) Encode(b *buffer) { +// encode implements encoder.encode. +func (f *FSStat) encode(b *buffer) { b.Write32(f.Type) b.Write32(f.BlockSize) b.Write64(f.Blocks) @@ -675,8 +679,8 @@ func (a AttrMask) String() string { return fmt.Sprintf("AttrMask{with: %s}", strings.Join(masks, " ")) } -// Decode implements encoder.Decode. -func (a *AttrMask) Decode(b *buffer) { +// decode implements encoder.decode. +func (a *AttrMask) decode(b *buffer) { mask := b.Read64() a.Mode = mask&0x00000001 != 0 a.NLink = mask&0x00000002 != 0 @@ -694,8 +698,8 @@ func (a *AttrMask) Decode(b *buffer) { a.DataVersion = mask&0x00002000 != 0 } -// Encode implements encoder.Encode. -func (a *AttrMask) Encode(b *buffer) { +// encode implements encoder.encode. +func (a *AttrMask) encode(b *buffer) { var mask uint64 if a.Mode { mask |= 0x00000001 @@ -770,8 +774,8 @@ func (a Attr) String() string { a.Mode, a.UID, a.GID, a.NLink, a.RDev, a.Size, a.BlockSize, a.Blocks, a.ATimeSeconds, a.ATimeNanoSeconds, a.MTimeSeconds, a.MTimeNanoSeconds, a.CTimeSeconds, a.CTimeNanoSeconds, a.BTimeSeconds, a.BTimeNanoSeconds, a.Gen, a.DataVersion) } -// Encode implements encoder.Encode. -func (a *Attr) Encode(b *buffer) { +// encode implements encoder.encode. +func (a *Attr) encode(b *buffer) { b.WriteFileMode(a.Mode) b.WriteUID(a.UID) b.WriteGID(a.GID) @@ -792,8 +796,8 @@ func (a *Attr) Encode(b *buffer) { b.Write64(a.DataVersion) } -// Decode implements encoder.Decode. -func (a *Attr) Decode(b *buffer) { +// decode implements encoder.decode. +func (a *Attr) decode(b *buffer) { a.Mode = b.ReadFileMode() a.UID = b.ReadUID() a.GID = b.ReadGID() @@ -922,8 +926,8 @@ func (s SetAttrMask) Empty() bool { return !s.Permissions && !s.UID && !s.GID && !s.Size && !s.ATime && !s.MTime && !s.CTime && !s.ATimeNotSystemTime && !s.MTimeNotSystemTime } -// Decode implements encoder.Decode. -func (s *SetAttrMask) Decode(b *buffer) { +// decode implements encoder.decode. +func (s *SetAttrMask) decode(b *buffer) { mask := b.Read32() s.Permissions = mask&0x00000001 != 0 s.UID = mask&0x00000002 != 0 @@ -968,8 +972,8 @@ func (s SetAttrMask) bitmask() uint32 { return mask } -// Encode implements encoder.Encode. -func (s *SetAttrMask) Encode(b *buffer) { +// encode implements encoder.encode. +func (s *SetAttrMask) encode(b *buffer) { b.Write32(s.bitmask()) } @@ -990,8 +994,8 @@ func (s SetAttr) String() string { return fmt.Sprintf("SetAttr{Permissions: 0o%o, UID: %d, GID: %d, Size: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}}", s.Permissions, s.UID, s.GID, s.Size, s.ATimeSeconds, s.ATimeNanoSeconds, s.MTimeSeconds, s.MTimeNanoSeconds) } -// Decode implements encoder.Decode. -func (s *SetAttr) Decode(b *buffer) { +// decode implements encoder.decode. +func (s *SetAttr) decode(b *buffer) { s.Permissions = b.ReadPermissions() s.UID = b.ReadUID() s.GID = b.ReadGID() @@ -1002,8 +1006,8 @@ func (s *SetAttr) Decode(b *buffer) { s.MTimeNanoSeconds = b.Read64() } -// Encode implements encoder.Encode. -func (s *SetAttr) Encode(b *buffer) { +// encode implements encoder.encode. +func (s *SetAttr) encode(b *buffer) { b.WritePermissions(s.Permissions) b.WriteUID(s.UID) b.WriteGID(s.GID) @@ -1060,17 +1064,17 @@ func (d Dirent) String() string { return fmt.Sprintf("Dirent{QID: %d, Offset: %d, Type: 0x%X, Name: %s}", d.QID, d.Offset, d.Type, d.Name) } -// Decode implements encoder.Decode. -func (d *Dirent) Decode(b *buffer) { - d.QID.Decode(b) +// decode implements encoder.decode. +func (d *Dirent) decode(b *buffer) { + d.QID.decode(b) d.Offset = b.Read64() d.Type = b.ReadQIDType() d.Name = b.ReadString() } -// Encode implements encoder.Encode. -func (d *Dirent) Encode(b *buffer) { - d.QID.Encode(b) +// encode implements encoder.encode. +func (d *Dirent) encode(b *buffer) { + d.QID.encode(b) b.Write64(d.Offset) b.WriteQIDType(d.Type) b.WriteString(d.Name) @@ -1114,8 +1118,8 @@ func (a *AllocateMode) ToLinux() uint32 { return rv } -// Decode implements encoder.Decode. -func (a *AllocateMode) Decode(b *buffer) { +// decode implements encoder.decode. +func (a *AllocateMode) decode(b *buffer) { mask := b.Read32() a.KeepSize = mask&0x01 != 0 a.PunchHole = mask&0x02 != 0 @@ -1126,8 +1130,8 @@ func (a *AllocateMode) Decode(b *buffer) { a.Unshare = mask&0x40 != 0 } -// Encode implements encoder.Encode. -func (a *AllocateMode) Encode(b *buffer) { +// encode implements encoder.encode. +func (a *AllocateMode) encode(b *buffer) { mask := uint32(0) if a.KeepSize { mask |= 0x01 diff --git a/pkg/p9/pool.go b/pkg/p9/pool.go deleted file mode 100644 index 2b14a5ce3..000000000 --- a/pkg/p9/pool.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package p9 - -import ( - "gvisor.dev/gvisor/pkg/sync" -) - -// pool is a simple allocator. -// -// It is used for both tags and FIDs. -type pool struct { - mu sync.Mutex - - // cache is the set of returned values. - cache []uint64 - - // start is the starting value (if needed). - start uint64 - - // max is the current maximum issued. - max uint64 - - // limit is the upper limit. - limit uint64 -} - -// Get gets a value from the pool. -func (p *pool) Get() (uint64, bool) { - p.mu.Lock() - defer p.mu.Unlock() - - // Anything cached? - if len(p.cache) > 0 { - v := p.cache[len(p.cache)-1] - p.cache = p.cache[:len(p.cache)-1] - return v, true - } - - // Over the limit? - if p.start == p.limit { - return 0, false - } - - // Generate a new value. - v := p.start - p.start++ - return v, true -} - -// Put returns a value to the pool. -func (p *pool) Put(v uint64) { - p.mu.Lock() - p.cache = append(p.cache, v) - p.mu.Unlock() -} diff --git a/pkg/p9/pool_test.go b/pkg/p9/pool_test.go deleted file mode 100644 index e4746b8da..000000000 --- a/pkg/p9/pool_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package p9 - -import ( - "testing" -) - -func TestPoolUnique(t *testing.T) { - p := pool{start: 1, limit: 3} - got := make(map[uint64]bool) - - for { - n, ok := p.Get() - if !ok { - break - } - - // Check unique. - if _, ok := got[n]; ok { - t.Errorf("pool spit out %v multiple times", n) - } - - // Record. - got[n] = true - } -} - -func TestExausted(t *testing.T) { - p := pool{start: 1, limit: 500} - for i := 0; i < 499; i++ { - _, ok := p.Get() - if !ok { - t.Fatalf("pool exhausted before 499 items") - } - } - - _, ok := p.Get() - if ok { - t.Errorf("pool not exhausted when it should be") - } -} - -func TestPoolRecycle(t *testing.T) { - p := pool{start: 1, limit: 500} - n1, _ := p.Get() - p.Put(n1) - n2, _ := p.Get() - if n1 != n2 { - t.Errorf("pool not recycling items") - } -} diff --git a/pkg/p9/transport.go b/pkg/p9/transport.go index 9c11e28ce..7cec0e86d 100644 --- a/pkg/p9/transport.go +++ b/pkg/p9/transport.go @@ -80,7 +80,7 @@ func send(s *unet.Socket, tag Tag, m message) error { } // Encode the message. The buffer will grow automatically. - m.Encode(&dataBuf) + m.encode(&dataBuf) // Get our vectors to send. var hdr [headerLength]byte @@ -316,7 +316,7 @@ func recv(s *unet.Socket, msize uint32, lookup lookupTagAndType) (Tag, message, } // Decode the message data. - m.Decode(&dataBuf) + m.decode(&dataBuf) if dataBuf.isOverrun() { // No need to drain the socket. return NoTag, nil, ErrNoValidMessage diff --git a/pkg/p9/transport_flipcall.go b/pkg/p9/transport_flipcall.go index 233f825e3..a0d274f3b 100644 --- a/pkg/p9/transport_flipcall.go +++ b/pkg/p9/transport_flipcall.go @@ -151,7 +151,7 @@ func (ch *channel) send(m message) (uint32, error) { } else { ch.buf.Write8(0) // No incoming FD. } - m.Encode(&ch.buf) + m.encode(&ch.buf) ssz := uint32(len(ch.buf.data)) // Updated below. // Is there a payload? @@ -205,7 +205,7 @@ func (ch *channel) recv(r message, rsz uint32) (message, error) { ch.buf.data = ch.buf.data[:fs] } - r.Decode(&ch.buf) + r.decode(&ch.buf) if ch.buf.isOverrun() { // Nothing valid was available. log.Debugf("recv [got %d bytes, needed more]", rsz) diff --git a/pkg/p9/transport_test.go b/pkg/p9/transport_test.go index 2f50ff3ea..3668fcad7 100644 --- a/pkg/p9/transport_test.go +++ b/pkg/p9/transport_test.go @@ -56,8 +56,8 @@ func TestSendRecv(t *testing.T) { // badDecode overruns on decode. type badDecode struct{} -func (*badDecode) Decode(b *buffer) { b.markOverrun() } -func (*badDecode) Encode(b *buffer) {} +func (*badDecode) decode(b *buffer) { b.markOverrun() } +func (*badDecode) encode(b *buffer) {} func (*badDecode) Type() MsgType { return MsgTypeBadDecode } func (*badDecode) String() string { return "badDecode{}" } @@ -81,8 +81,8 @@ func TestRecvOverrun(t *testing.T) { // unregistered is not registered on decode. type unregistered struct{} -func (*unregistered) Decode(b *buffer) {} -func (*unregistered) Encode(b *buffer) {} +func (*unregistered) decode(b *buffer) {} +func (*unregistered) encode(b *buffer) {} func (*unregistered) Type() MsgType { return MsgTypeUnregistered } func (*unregistered) String() string { return "unregistered{}" } diff --git a/pkg/p9/version.go b/pkg/p9/version.go index 34a15eb55..09cde9f5a 100644 --- a/pkg/p9/version.go +++ b/pkg/p9/version.go @@ -26,7 +26,7 @@ const ( // // Clients are expected to start requesting this version number and // to continuously decrement it until a Tversion request succeeds. - highestSupportedVersion uint32 = 10 + highestSupportedVersion uint32 = 11 // lowestSupportedVersion is the lowest supported version X in a // version string of the format 9P2000.L.Google.X. @@ -167,3 +167,9 @@ func VersionSupportsOpenTruncateFlag(v uint32) bool { func versionSupportsGetSetXattr(v uint32) bool { return v >= 10 } + +// versionSupportsListRemoveXattr returns true if version v supports +// the Tlistxattr and Tremovexattr messages. +func versionSupportsListRemoveXattr(v uint32) bool { + return v >= 11 +} |