gvisor/pkg/p9/messages.go

2723 lines
60 KiB
Go

// 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 (
"fmt"
"math"
"gvisor.dev/gvisor/pkg/fd"
)
// ErrInvalidMsgType is returned when an unsupported message type is found.
type ErrInvalidMsgType struct {
MsgType
}
// Error returns a useful string.
func (e *ErrInvalidMsgType) Error() string {
return fmt.Sprintf("invalid message type: %d", e.MsgType)
}
// message is a generic 9P message.
type message interface {
encoder
fmt.Stringer
// Type returns the message type number.
Type() MsgType
}
// payloader is a special message which may include an inline payload.
type payloader interface {
// FixedSize returns the size of the fixed portion of this message.
FixedSize() uint32
// Payload returns the payload for sending.
Payload() []byte
// 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.
SetPayload([]byte)
}
// filer is a message capable of passing a file.
type filer interface {
// FilePayload returns the file payload.
FilePayload() *fd.FD
// SetFilePayload sets the file payload.
SetFilePayload(*fd.FD)
}
// filePayload embeds a File object.
type filePayload struct {
File *fd.FD
}
// FilePayload returns the file payload.
func (f *filePayload) FilePayload() *fd.FD {
return f.File
}
// SetFilePayload sets the received file.
func (f *filePayload) SetFilePayload(file *fd.FD) {
f.File = file
}
// Tversion is a version request.
type Tversion struct {
// MSize is the message size to use.
MSize uint32
// Version is the version string.
//
// For this implementation, this must be 9P2000.L.
Version string
}
// 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) {
b.Write32(t.MSize)
b.WriteString(t.Version)
}
// Type implements message.Type.
func (*Tversion) Type() MsgType {
return MsgTversion
}
// String implements fmt.Stringer.
func (t *Tversion) String() string {
return fmt.Sprintf("Tversion{MSize: %d, Version: %s}", t.MSize, t.Version)
}
// Rversion is a version response.
type Rversion struct {
// MSize is the negotiated size.
MSize uint32
// Version is the negotiated version.
Version string
}
// 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) {
b.Write32(r.MSize)
b.WriteString(r.Version)
}
// Type implements message.Type.
func (*Rversion) Type() MsgType {
return MsgRversion
}
// String implements fmt.Stringer.
func (r *Rversion) String() string {
return fmt.Sprintf("Rversion{MSize: %d, Version: %s}", r.MSize, r.Version)
}
// Tflush is a flush request.
type Tflush struct {
// OldTag is the tag to wait on.
OldTag Tag
}
// decode implements encoder.decode.
func (t *Tflush) decode(b *buffer) {
t.OldTag = b.ReadTag()
}
// encode implements encoder.encode.
func (t *Tflush) encode(b *buffer) {
b.WriteTag(t.OldTag)
}
// Type implements message.Type.
func (*Tflush) Type() MsgType {
return MsgTflush
}
// String implements fmt.Stringer.
func (t *Tflush) String() string {
return fmt.Sprintf("Tflush{OldTag: %d}", t.OldTag)
}
// Rflush is a flush response.
type Rflush struct {
}
// decode implements encoder.decode.
func (*Rflush) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rflush) encode(*buffer) {
}
// Type implements message.Type.
func (*Rflush) Type() MsgType {
return MsgRflush
}
// String implements fmt.Stringer.
func (r *Rflush) String() string {
return "RFlush{}"
}
// Twalk is a walk request.
type Twalk struct {
// FID is the FID to be walked.
FID FID
// NewFID is the resulting FID.
NewFID FID
// Names are the set of names to be walked.
Names []string
}
// decode implements encoder.decode.
func (t *Twalk) decode(b *buffer) {
t.FID = b.ReadFID()
t.NewFID = b.ReadFID()
n := b.Read16()
t.Names = t.Names[:0]
for i := 0; i < int(n); i++ {
t.Names = append(t.Names, b.ReadString())
}
}
// encode implements encoder.encode.
func (t *Twalk) encode(b *buffer) {
b.WriteFID(t.FID)
b.WriteFID(t.NewFID)
b.Write16(uint16(len(t.Names)))
for _, name := range t.Names {
b.WriteString(name)
}
}
// Type implements message.Type.
func (*Twalk) Type() MsgType {
return MsgTwalk
}
// String implements fmt.Stringer.
func (t *Twalk) String() string {
return fmt.Sprintf("Twalk{FID: %d, NewFID: %d, Names: %v}", t.FID, t.NewFID, t.Names)
}
// Rwalk is a walk response.
type Rwalk struct {
// QIDs are the set of QIDs returned.
QIDs []QID
}
// 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)
r.QIDs = append(r.QIDs, q)
}
}
// encode implements encoder.encode.
func (r *Rwalk) encode(b *buffer) {
b.Write16(uint16(len(r.QIDs)))
for _, q := range r.QIDs {
q.encode(b)
}
}
// Type implements message.Type.
func (*Rwalk) Type() MsgType {
return MsgRwalk
}
// String implements fmt.Stringer.
func (r *Rwalk) String() string {
return fmt.Sprintf("Rwalk{QIDs: %v}", r.QIDs)
}
// Tclunk is a close request.
type Tclunk struct {
// FID is the FID to be closed.
FID FID
}
// decode implements encoder.decode.
func (t *Tclunk) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Tclunk) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Tclunk) Type() MsgType {
return MsgTclunk
}
// String implements fmt.Stringer.
func (t *Tclunk) String() string {
return fmt.Sprintf("Tclunk{FID: %d}", t.FID)
}
// Rclunk is a close response.
type Rclunk struct {
}
// decode implements encoder.decode.
func (*Rclunk) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rclunk) encode(*buffer) {
}
// Type implements message.Type.
func (*Rclunk) Type() MsgType {
return MsgRclunk
}
// String implements fmt.Stringer.
func (r *Rclunk) String() string {
return "Rclunk{}"
}
// Tsetattrclunk is a setattr+close request.
type Tsetattrclunk struct {
// FID is the FID to change.
FID FID
// Valid is the set of bits which will be used.
Valid SetAttrMask
// SetAttr is the set request.
SetAttr SetAttr
}
// decode implements encoder.decode.
func (t *Tsetattrclunk) decode(b *buffer) {
t.FID = b.ReadFID()
t.Valid.decode(b)
t.SetAttr.decode(b)
}
// encode implements encoder.encode.
func (t *Tsetattrclunk) encode(b *buffer) {
b.WriteFID(t.FID)
t.Valid.encode(b)
t.SetAttr.encode(b)
}
// Type implements message.Type.
func (*Tsetattrclunk) Type() MsgType {
return MsgTsetattrclunk
}
// String implements fmt.Stringer.
func (t *Tsetattrclunk) String() string {
return fmt.Sprintf("Tsetattrclunk{FID: %d, Valid: %v, SetAttr: %s}", t.FID, t.Valid, t.SetAttr)
}
// Rsetattrclunk is a setattr+close response.
type Rsetattrclunk struct {
}
// decode implements encoder.decode.
func (*Rsetattrclunk) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rsetattrclunk) encode(*buffer) {
}
// Type implements message.Type.
func (*Rsetattrclunk) Type() MsgType {
return MsgRsetattrclunk
}
// String implements fmt.Stringer.
func (r *Rsetattrclunk) String() string {
return "Rsetattrclunk{}"
}
// Tremove is a remove request.
//
// This will eventually be replaced by Tunlinkat.
type Tremove struct {
// FID is the FID to be removed.
FID FID
}
// decode implements encoder.decode.
func (t *Tremove) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Tremove) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Tremove) Type() MsgType {
return MsgTremove
}
// String implements fmt.Stringer.
func (t *Tremove) String() string {
return fmt.Sprintf("Tremove{FID: %d}", t.FID)
}
// Rremove is a remove response.
type Rremove struct {
}
// decode implements encoder.decode.
func (*Rremove) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rremove) encode(*buffer) {
}
// Type implements message.Type.
func (*Rremove) Type() MsgType {
return MsgRremove
}
// String implements fmt.Stringer.
func (r *Rremove) String() string {
return "Rremove{}"
}
// Rlerror is an error response.
//
// Note that this replaces the error code used in 9p.
type Rlerror struct {
Error uint32
}
// decode implements encoder.decode.
func (r *Rlerror) decode(b *buffer) {
r.Error = b.Read32()
}
// encode implements encoder.encode.
func (r *Rlerror) encode(b *buffer) {
b.Write32(r.Error)
}
// Type implements message.Type.
func (*Rlerror) Type() MsgType {
return MsgRlerror
}
// String implements fmt.Stringer.
func (r *Rlerror) String() string {
return fmt.Sprintf("Rlerror{Error: %d}", r.Error)
}
// Tauth is an authentication request.
type Tauth struct {
// AuthenticationFID is the FID to attach the authentication result.
AuthenticationFID FID
// UserName is the user to attach.
UserName string
// AttachName is the attach name.
AttachName string
// UserID is the numeric identifier for UserName.
UID UID
}
// 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) {
b.WriteFID(t.AuthenticationFID)
b.WriteString(t.UserName)
b.WriteString(t.AttachName)
b.WriteUID(t.UID)
}
// Type implements message.Type.
func (*Tauth) Type() MsgType {
return MsgTauth
}
// String implements fmt.Stringer.
func (t *Tauth) String() string {
return fmt.Sprintf("Tauth{AuthFID: %d, UserName: %s, AttachName: %s, UID: %d", t.AuthenticationFID, t.UserName, t.AttachName, t.UID)
}
// Rauth is an authentication response.
//
// encode and decode are inherited directly from QID.
type Rauth struct {
QID
}
// Type implements message.Type.
func (*Rauth) Type() MsgType {
return MsgRauth
}
// String implements fmt.Stringer.
func (r *Rauth) String() string {
return fmt.Sprintf("Rauth{QID: %s}", r.QID)
}
// Tattach is an attach request.
type Tattach struct {
// FID is the FID to be attached.
FID FID
// Auth is the embedded authentication request.
//
// See client.Attach for information regarding authentication.
Auth Tauth
}
// decode implements encoder.decode.
func (t *Tattach) decode(b *buffer) {
t.FID = b.ReadFID()
t.Auth.decode(b)
}
// encode implements encoder.encode.
func (t *Tattach) encode(b *buffer) {
b.WriteFID(t.FID)
t.Auth.encode(b)
}
// Type implements message.Type.
func (*Tattach) Type() MsgType {
return MsgTattach
}
// String implements fmt.Stringer.
func (t *Tattach) String() string {
return fmt.Sprintf("Tattach{FID: %d, AuthFID: %d, UserName: %s, AttachName: %s, UID: %d}", t.FID, t.Auth.AuthenticationFID, t.Auth.UserName, t.Auth.AttachName, t.Auth.UID)
}
// Rattach is an attach response.
type Rattach struct {
QID
}
// Type implements message.Type.
func (*Rattach) Type() MsgType {
return MsgRattach
}
// String implements fmt.Stringer.
func (r *Rattach) String() string {
return fmt.Sprintf("Rattach{QID: %s}", r.QID)
}
// Tlopen is an open request.
type Tlopen struct {
// FID is the FID to be opened.
FID FID
// Flags are the open flags.
Flags OpenFlags
}
// 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) {
b.WriteFID(t.FID)
b.WriteOpenFlags(t.Flags)
}
// Type implements message.Type.
func (*Tlopen) Type() MsgType {
return MsgTlopen
}
// String implements fmt.Stringer.
func (t *Tlopen) String() string {
return fmt.Sprintf("Tlopen{FID: %d, Flags: %v}", t.FID, t.Flags)
}
// Rlopen is a open response.
type Rlopen struct {
// QID is the file's QID.
QID QID
// IoUnit is the recommended I/O unit.
IoUnit uint32
filePayload
}
// 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)
b.Write32(r.IoUnit)
}
// Type implements message.Type.
func (*Rlopen) Type() MsgType {
return MsgRlopen
}
// String implements fmt.Stringer.
func (r *Rlopen) String() string {
return fmt.Sprintf("Rlopen{QID: %s, IoUnit: %d, File: %v}", r.QID, r.IoUnit, r.File)
}
// Tlcreate is a create request.
type Tlcreate struct {
// FID is the parent FID.
//
// This becomes the new file.
FID FID
// Name is the file name to create.
Name string
// Mode is the open mode (O_RDWR, etc.).
//
// Note that flags like O_TRUNC are ignored, as is O_EXCL. All
// create operations are exclusive.
OpenFlags OpenFlags
// Permissions is the set of permission bits.
Permissions FileMode
// GID is the group ID to use for creating the file.
GID GID
}
// decode implements encoder.decode.
func (t *Tlcreate) decode(b *buffer) {
t.FID = b.ReadFID()
t.Name = b.ReadString()
t.OpenFlags = b.ReadOpenFlags()
t.Permissions = b.ReadPermissions()
t.GID = b.ReadGID()
}
// encode implements encoder.encode.
func (t *Tlcreate) encode(b *buffer) {
b.WriteFID(t.FID)
b.WriteString(t.Name)
b.WriteOpenFlags(t.OpenFlags)
b.WritePermissions(t.Permissions)
b.WriteGID(t.GID)
}
// Type implements message.Type.
func (*Tlcreate) Type() MsgType {
return MsgTlcreate
}
// String implements fmt.Stringer.
func (t *Tlcreate) String() string {
return fmt.Sprintf("Tlcreate{FID: %d, Name: %s, OpenFlags: %s, Permissions: 0o%o, GID: %d}", t.FID, t.Name, t.OpenFlags, t.Permissions, t.GID)
}
// Rlcreate is a create response.
//
// The encode, decode, etc. methods are inherited from Rlopen.
type Rlcreate struct {
Rlopen
}
// Type implements message.Type.
func (*Rlcreate) Type() MsgType {
return MsgRlcreate
}
// String implements fmt.Stringer.
func (r *Rlcreate) String() string {
return fmt.Sprintf("Rlcreate{QID: %s, IoUnit: %d, File: %v}", r.QID, r.IoUnit, r.File)
}
// Tsymlink is a symlink request.
type Tsymlink struct {
// Directory is the directory FID.
Directory FID
// Name is the new in the directory.
Name string
// Target is the symlink target.
Target string
// GID is the owning group.
GID GID
}
// 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) {
b.WriteFID(t.Directory)
b.WriteString(t.Name)
b.WriteString(t.Target)
b.WriteGID(t.GID)
}
// Type implements message.Type.
func (*Tsymlink) Type() MsgType {
return MsgTsymlink
}
// String implements fmt.Stringer.
func (t *Tsymlink) String() string {
return fmt.Sprintf("Tsymlink{DirectoryFID: %d, Name: %s, Target: %s, GID: %d}", t.Directory, t.Name, t.Target, t.GID)
}
// Rsymlink is a symlink response.
type Rsymlink struct {
// QID is the new symlink's QID.
QID QID
}
// 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)
}
// Type implements message.Type.
func (*Rsymlink) Type() MsgType {
return MsgRsymlink
}
// String implements fmt.Stringer.
func (r *Rsymlink) String() string {
return fmt.Sprintf("Rsymlink{QID: %s}", r.QID)
}
// Tlink is a link request.
type Tlink struct {
// Directory is the directory to contain the link.
Directory FID
// FID is the target.
Target FID
// Name is the new source name.
Name string
}
// 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) {
b.WriteFID(t.Directory)
b.WriteFID(t.Target)
b.WriteString(t.Name)
}
// Type implements message.Type.
func (*Tlink) Type() MsgType {
return MsgTlink
}
// String implements fmt.Stringer.
func (t *Tlink) String() string {
return fmt.Sprintf("Tlink{DirectoryFID: %d, TargetFID: %d, Name: %s}", t.Directory, t.Target, t.Name)
}
// Rlink is a link response.
type Rlink struct {
}
// Type implements message.Type.
func (*Rlink) Type() MsgType {
return MsgRlink
}
// decode implements encoder.decode.
func (*Rlink) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rlink) encode(*buffer) {
}
// String implements fmt.Stringer.
func (r *Rlink) String() string {
return "Rlink{}"
}
// Trenameat is a rename request.
type Trenameat struct {
// OldDirectory is the source directory.
OldDirectory FID
// OldName is the source file name.
OldName string
// NewDirectory is the target directory.
NewDirectory FID
// NewName is the new file name.
NewName string
}
// 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) {
b.WriteFID(t.OldDirectory)
b.WriteString(t.OldName)
b.WriteFID(t.NewDirectory)
b.WriteString(t.NewName)
}
// Type implements message.Type.
func (*Trenameat) Type() MsgType {
return MsgTrenameat
}
// String implements fmt.Stringer.
func (t *Trenameat) String() string {
return fmt.Sprintf("TrenameAt{OldDirectoryFID: %d, OldName: %s, NewDirectoryFID: %d, NewName: %s}", t.OldDirectory, t.OldName, t.NewDirectory, t.NewName)
}
// Rrenameat is a rename response.
type Rrenameat struct {
}
// decode implements encoder.decode.
func (*Rrenameat) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rrenameat) encode(*buffer) {
}
// Type implements message.Type.
func (*Rrenameat) Type() MsgType {
return MsgRrenameat
}
// String implements fmt.Stringer.
func (r *Rrenameat) String() string {
return "Rrenameat{}"
}
// Tunlinkat is an unlink request.
type Tunlinkat struct {
// Directory is the originating directory.
Directory FID
// Name is the name of the entry to unlink.
Name string
// Flags are extra flags (e.g. O_DIRECTORY). These are not interpreted by p9.
Flags uint32
}
// 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) {
b.WriteFID(t.Directory)
b.WriteString(t.Name)
b.Write32(t.Flags)
}
// Type implements message.Type.
func (*Tunlinkat) Type() MsgType {
return MsgTunlinkat
}
// String implements fmt.Stringer.
func (t *Tunlinkat) String() string {
return fmt.Sprintf("Tunlinkat{DirectoryFID: %d, Name: %s, Flags: 0x%X}", t.Directory, t.Name, t.Flags)
}
// Runlinkat is an unlink response.
type Runlinkat struct {
}
// decode implements encoder.decode.
func (*Runlinkat) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Runlinkat) encode(*buffer) {
}
// Type implements message.Type.
func (*Runlinkat) Type() MsgType {
return MsgRunlinkat
}
// String implements fmt.Stringer.
func (r *Runlinkat) String() string {
return "Runlinkat{}"
}
// Trename is a rename request.
//
// Note that this generally isn't used anymore, and ideally all rename calls
// should Trenameat below.
type Trename struct {
// FID is the FID to rename.
FID FID
// Directory is the target directory.
Directory FID
// Name is the new file name.
Name string
}
// 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) {
b.WriteFID(t.FID)
b.WriteFID(t.Directory)
b.WriteString(t.Name)
}
// Type implements message.Type.
func (*Trename) Type() MsgType {
return MsgTrename
}
// String implements fmt.Stringer.
func (t *Trename) String() string {
return fmt.Sprintf("Trename{FID: %d, DirectoryFID: %d, Name: %s}", t.FID, t.Directory, t.Name)
}
// Rrename is a rename response.
type Rrename struct {
}
// decode implements encoder.decode.
func (*Rrename) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rrename) encode(*buffer) {
}
// Type implements message.Type.
func (*Rrename) Type() MsgType {
return MsgRrename
}
// String implements fmt.Stringer.
func (r *Rrename) String() string {
return "Rrename{}"
}
// Treadlink is a readlink request.
type Treadlink struct {
// FID is the symlink.
FID FID
}
// decode implements encoder.decode.
func (t *Treadlink) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Treadlink) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Treadlink) Type() MsgType {
return MsgTreadlink
}
// String implements fmt.Stringer.
func (t *Treadlink) String() string {
return fmt.Sprintf("Treadlink{FID: %d}", t.FID)
}
// Rreadlink is a readlink response.
type Rreadlink struct {
// Target is the symlink target.
Target string
}
// decode implements encoder.decode.
func (r *Rreadlink) decode(b *buffer) {
r.Target = b.ReadString()
}
// encode implements encoder.encode.
func (r *Rreadlink) encode(b *buffer) {
b.WriteString(r.Target)
}
// Type implements message.Type.
func (*Rreadlink) Type() MsgType {
return MsgRreadlink
}
// String implements fmt.Stringer.
func (r *Rreadlink) String() string {
return fmt.Sprintf("Rreadlink{Target: %s}", r.Target)
}
// Tread is a read request.
type Tread struct {
// FID is the FID to read.
FID FID
// Offset indicates the file offset.
Offset uint64
// Count indicates the number of bytes to read.
Count uint32
}
// 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) {
b.WriteFID(t.FID)
b.Write64(t.Offset)
b.Write32(t.Count)
}
// Type implements message.Type.
func (*Tread) Type() MsgType {
return MsgTread
}
// String implements fmt.Stringer.
func (t *Tread) String() string {
return fmt.Sprintf("Tread{FID: %d, Offset: %d, Count: %d}", t.FID, t.Offset, t.Count)
}
// Rread is the response for a Tread.
type Rread struct {
// Data is the resulting data.
Data []byte
}
// decode implements encoder.decode.
//
// Data is automatically decoded via Payload.
func (r *Rread) decode(b *buffer) {
count := b.Read32()
if count != uint32(len(r.Data)) {
b.markOverrun()
}
}
// encode implements encoder.encode.
//
// Data is automatically encoded via Payload.
func (r *Rread) encode(b *buffer) {
b.Write32(uint32(len(r.Data)))
}
// Type implements message.Type.
func (*Rread) Type() MsgType {
return MsgRread
}
// FixedSize implements payloader.FixedSize.
func (*Rread) FixedSize() uint32 {
return 4
}
// Payload implements payloader.Payload.
func (r *Rread) Payload() []byte {
return r.Data
}
// SetPayload implements payloader.SetPayload.
func (r *Rread) SetPayload(p []byte) {
r.Data = p
}
// String implements fmt.Stringer.
func (r *Rread) String() string {
return fmt.Sprintf("Rread{len(Data): %d}", len(r.Data))
}
// Twrite is a write request.
type Twrite struct {
// FID is the FID to read.
FID FID
// Offset indicates the file offset.
Offset uint64
// Data is the data to be written.
Data []byte
}
// decode implements encoder.decode.
func (t *Twrite) decode(b *buffer) {
t.FID = b.ReadFID()
t.Offset = b.Read64()
count := b.Read32()
if count != uint32(len(t.Data)) {
b.markOverrun()
}
}
// encode implements encoder.encode.
//
// This uses the buffer payload to avoid a copy.
func (t *Twrite) encode(b *buffer) {
b.WriteFID(t.FID)
b.Write64(t.Offset)
b.Write32(uint32(len(t.Data)))
}
// Type implements message.Type.
func (*Twrite) Type() MsgType {
return MsgTwrite
}
// FixedSize implements payloader.FixedSize.
func (*Twrite) FixedSize() uint32 {
return 16
}
// Payload implements payloader.Payload.
func (t *Twrite) Payload() []byte {
return t.Data
}
// SetPayload implements payloader.SetPayload.
func (t *Twrite) SetPayload(p []byte) {
t.Data = p
}
// String implements fmt.Stringer.
func (t *Twrite) String() string {
return fmt.Sprintf("Twrite{FID: %v, Offset %d, len(Data): %d}", t.FID, t.Offset, len(t.Data))
}
// Rwrite is the response for a Twrite.
type Rwrite struct {
// Count indicates the number of bytes successfully written.
Count uint32
}
// decode implements encoder.decode.
func (r *Rwrite) decode(b *buffer) {
r.Count = b.Read32()
}
// encode implements encoder.encode.
func (r *Rwrite) encode(b *buffer) {
b.Write32(r.Count)
}
// Type implements message.Type.
func (*Rwrite) Type() MsgType {
return MsgRwrite
}
// String implements fmt.Stringer.
func (r *Rwrite) String() string {
return fmt.Sprintf("Rwrite{Count: %d}", r.Count)
}
// Tmknod is a mknod request.
type Tmknod struct {
// Directory is the parent directory.
Directory FID
// Name is the device name.
Name string
// Mode is the device mode and permissions.
Mode FileMode
// Major is the device major number.
Major uint32
// Minor is the device minor number.
Minor uint32
// GID is the device GID.
GID GID
}
// decode implements encoder.decode.
func (t *Tmknod) decode(b *buffer) {
t.Directory = b.ReadFID()
t.Name = b.ReadString()
t.Mode = b.ReadFileMode()
t.Major = b.Read32()
t.Minor = b.Read32()
t.GID = b.ReadGID()
}
// encode implements encoder.encode.
func (t *Tmknod) encode(b *buffer) {
b.WriteFID(t.Directory)
b.WriteString(t.Name)
b.WriteFileMode(t.Mode)
b.Write32(t.Major)
b.Write32(t.Minor)
b.WriteGID(t.GID)
}
// Type implements message.Type.
func (*Tmknod) Type() MsgType {
return MsgTmknod
}
// String implements fmt.Stringer.
func (t *Tmknod) String() string {
return fmt.Sprintf("Tmknod{DirectoryFID: %d, Name: %s, Mode: 0o%o, Major: %d, Minor: %d, GID: %d}", t.Directory, t.Name, t.Mode, t.Major, t.Minor, t.GID)
}
// Rmknod is a mknod response.
type Rmknod struct {
// QID is the resulting QID.
QID QID
}
// 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)
}
// Type implements message.Type.
func (*Rmknod) Type() MsgType {
return MsgRmknod
}
// String implements fmt.Stringer.
func (r *Rmknod) String() string {
return fmt.Sprintf("Rmknod{QID: %s}", r.QID)
}
// Tmkdir is a mkdir request.
type Tmkdir struct {
// Directory is the parent directory.
Directory FID
// Name is the new directory name.
Name string
// Permissions is the set of permission bits.
Permissions FileMode
// GID is the owning group.
GID GID
}
// 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) {
b.WriteFID(t.Directory)
b.WriteString(t.Name)
b.WritePermissions(t.Permissions)
b.WriteGID(t.GID)
}
// Type implements message.Type.
func (*Tmkdir) Type() MsgType {
return MsgTmkdir
}
// String implements fmt.Stringer.
func (t *Tmkdir) String() string {
return fmt.Sprintf("Tmkdir{DirectoryFID: %d, Name: %s, Permissions: 0o%o, GID: %d}", t.Directory, t.Name, t.Permissions, t.GID)
}
// Rmkdir is a mkdir response.
type Rmkdir struct {
// QID is the resulting QID.
QID QID
}
// 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)
}
// Type implements message.Type.
func (*Rmkdir) Type() MsgType {
return MsgRmkdir
}
// String implements fmt.Stringer.
func (r *Rmkdir) String() string {
return fmt.Sprintf("Rmkdir{QID: %s}", r.QID)
}
// Tgetattr is a getattr request.
type Tgetattr struct {
// FID is the FID to get attributes for.
FID FID
// AttrMask is the set of attributes to get.
AttrMask AttrMask
}
// decode implements encoder.decode.
func (t *Tgetattr) decode(b *buffer) {
t.FID = b.ReadFID()
t.AttrMask.decode(b)
}
// encode implements encoder.encode.
func (t *Tgetattr) encode(b *buffer) {
b.WriteFID(t.FID)
t.AttrMask.encode(b)
}
// Type implements message.Type.
func (*Tgetattr) Type() MsgType {
return MsgTgetattr
}
// String implements fmt.Stringer.
func (t *Tgetattr) String() string {
return fmt.Sprintf("Tgetattr{FID: %d, AttrMask: %s}", t.FID, t.AttrMask)
}
// Rgetattr is a getattr response.
type Rgetattr struct {
// Valid indicates which fields are valid.
Valid AttrMask
// QID is the QID for this file.
QID
// Attr is the set of attributes.
Attr Attr
}
// 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)
}
// Type implements message.Type.
func (*Rgetattr) Type() MsgType {
return MsgRgetattr
}
// String implements fmt.Stringer.
func (r *Rgetattr) String() string {
return fmt.Sprintf("Rgetattr{Valid: %v, QID: %s, Attr: %s}", r.Valid, r.QID, r.Attr)
}
// Tsetattr is a setattr request.
type Tsetattr struct {
// FID is the FID to change.
FID FID
// Valid is the set of bits which will be used.
Valid SetAttrMask
// SetAttr is the set request.
SetAttr SetAttr
}
// decode implements encoder.decode.
func (t *Tsetattr) decode(b *buffer) {
t.FID = b.ReadFID()
t.Valid.decode(b)
t.SetAttr.decode(b)
}
// encode implements encoder.encode.
func (t *Tsetattr) encode(b *buffer) {
b.WriteFID(t.FID)
t.Valid.encode(b)
t.SetAttr.encode(b)
}
// Type implements message.Type.
func (*Tsetattr) Type() MsgType {
return MsgTsetattr
}
// String implements fmt.Stringer.
func (t *Tsetattr) String() string {
return fmt.Sprintf("Tsetattr{FID: %d, Valid: %v, SetAttr: %s}", t.FID, t.Valid, t.SetAttr)
}
// Rsetattr is a setattr response.
type Rsetattr struct {
}
// decode implements encoder.decode.
func (*Rsetattr) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rsetattr) encode(*buffer) {
}
// Type implements message.Type.
func (*Rsetattr) Type() MsgType {
return MsgRsetattr
}
// String implements fmt.Stringer.
func (r *Rsetattr) String() string {
return "Rsetattr{}"
}
// Tallocate is an allocate request. This is an extension to 9P protocol, not
// present in the 9P2000.L standard.
type Tallocate struct {
FID FID
Mode AllocateMode
Offset uint64
Length uint64
}
// decode implements encoder.decode.
func (t *Tallocate) decode(b *buffer) {
t.FID = b.ReadFID()
t.Mode.decode(b)
t.Offset = b.Read64()
t.Length = b.Read64()
}
// encode implements encoder.encode.
func (t *Tallocate) encode(b *buffer) {
b.WriteFID(t.FID)
t.Mode.encode(b)
b.Write64(t.Offset)
b.Write64(t.Length)
}
// Type implements message.Type.
func (*Tallocate) Type() MsgType {
return MsgTallocate
}
// String implements fmt.Stringer.
func (t *Tallocate) String() string {
return fmt.Sprintf("Tallocate{FID: %d, Offset: %d, Length: %d}", t.FID, t.Offset, t.Length)
}
// Rallocate is an allocate response.
type Rallocate struct {
}
// decode implements encoder.decode.
func (*Rallocate) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rallocate) encode(*buffer) {
}
// Type implements message.Type.
func (*Rallocate) Type() MsgType {
return MsgRallocate
}
// String implements fmt.Stringer.
func (r *Rallocate) String() string {
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.
type Txattrwalk struct {
// FID is the FID to check for attributes.
FID FID
// NewFID is the new FID associated with the attributes.
NewFID FID
// Name is the attribute name.
Name string
}
// 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) {
b.WriteFID(t.FID)
b.WriteFID(t.NewFID)
b.WriteString(t.Name)
}
// Type implements message.Type.
func (*Txattrwalk) Type() MsgType {
return MsgTxattrwalk
}
// String implements fmt.Stringer.
func (t *Txattrwalk) String() string {
return fmt.Sprintf("Txattrwalk{FID: %d, NewFID: %d, Name: %s}", t.FID, t.NewFID, t.Name)
}
// Rxattrwalk is a xattrwalk response.
type Rxattrwalk struct {
// Size is the size of the extended attribute.
Size uint64
}
// decode implements encoder.decode.
func (r *Rxattrwalk) decode(b *buffer) {
r.Size = b.Read64()
}
// encode implements encoder.encode.
func (r *Rxattrwalk) encode(b *buffer) {
b.Write64(r.Size)
}
// Type implements message.Type.
func (*Rxattrwalk) Type() MsgType {
return MsgRxattrwalk
}
// String implements fmt.Stringer.
func (r *Rxattrwalk) String() string {
return fmt.Sprintf("Rxattrwalk{Size: %d}", r.Size)
}
// Txattrcreate prepare to set extended attributes.
type Txattrcreate struct {
// FID is input/output parameter, it identifies the file on which
// extended attributes will be set but after successful Rxattrcreate
// it is used to write the extended attribute value.
FID FID
// Name is the attribute name.
Name string
// Size of the attribute value. When the FID is clunked it has to match
// the number of bytes written to the FID.
AttrSize uint64
// Linux setxattr(2) flags.
Flags uint32
}
// 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) {
b.WriteFID(t.FID)
b.WriteString(t.Name)
b.Write64(t.AttrSize)
b.Write32(t.Flags)
}
// Type implements message.Type.
func (*Txattrcreate) Type() MsgType {
return MsgTxattrcreate
}
// String implements fmt.Stringer.
func (t *Txattrcreate) String() string {
return fmt.Sprintf("Txattrcreate{FID: %d, Name: %s, AttrSize: %d, Flags: %d}", t.FID, t.Name, t.AttrSize, t.Flags)
}
// Rxattrcreate is a xattrcreate response.
type Rxattrcreate struct {
}
// decode implements encoder.decode.
func (r *Rxattrcreate) decode(*buffer) {
}
// encode implements encoder.encode.
func (r *Rxattrcreate) encode(*buffer) {
}
// Type implements message.Type.
func (*Rxattrcreate) Type() MsgType {
return MsgRxattrcreate
}
// String implements fmt.Stringer.
func (r *Rxattrcreate) String() string {
return "Rxattrcreate{}"
}
// Tgetxattr is a getxattr request.
type Tgetxattr struct {
// FID refers to the file for which to get xattrs.
FID FID
// Name is the xattr to get.
Name string
// Size is the buffer size for the xattr to get.
Size uint64
}
// 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) {
b.WriteFID(t.FID)
b.WriteString(t.Name)
b.Write64(t.Size)
}
// Type implements message.Type.
func (*Tgetxattr) Type() MsgType {
return MsgTgetxattr
}
// String implements fmt.Stringer.
func (t *Tgetxattr) String() string {
return fmt.Sprintf("Tgetxattr{FID: %d, Name: %s, Size: %d}", t.FID, t.Name, t.Size)
}
// Rgetxattr is a getxattr response.
type Rgetxattr struct {
// Value is the extended attribute value.
Value string
}
// decode implements encoder.decode.
func (r *Rgetxattr) decode(b *buffer) {
r.Value = b.ReadString()
}
// encode implements encoder.encode.
func (r *Rgetxattr) encode(b *buffer) {
b.WriteString(r.Value)
}
// Type implements message.Type.
func (*Rgetxattr) Type() MsgType {
return MsgRgetxattr
}
// String implements fmt.Stringer.
func (r *Rgetxattr) String() string {
return fmt.Sprintf("Rgetxattr{Value: %s}", r.Value)
}
// Tsetxattr sets extended attributes.
type Tsetxattr struct {
// FID refers to the file on which to set xattrs.
FID FID
// Name is the attribute name.
Name string
// Value is the attribute value.
Value string
// Linux setxattr(2) flags.
Flags uint32
}
// 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) {
b.WriteFID(t.FID)
b.WriteString(t.Name)
b.WriteString(t.Value)
b.Write32(t.Flags)
}
// Type implements message.Type.
func (*Tsetxattr) Type() MsgType {
return MsgTsetxattr
}
// String implements fmt.Stringer.
func (t *Tsetxattr) String() string {
return fmt.Sprintf("Tsetxattr{FID: %d, Name: %s, Value: %s, Flags: %d}", t.FID, t.Name, t.Value, t.Flags)
}
// Rsetxattr is a setxattr response.
type Rsetxattr struct {
}
// decode implements encoder.decode.
func (r *Rsetxattr) decode(*buffer) {
}
// encode implements encoder.encode.
func (r *Rsetxattr) encode(*buffer) {
}
// Type implements message.Type.
func (*Rsetxattr) Type() MsgType {
return MsgRsetxattr
}
// String implements fmt.Stringer.
func (r *Rsetxattr) String() string {
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.
type Treaddir struct {
// Directory is the directory FID to read.
Directory FID
// Offset is the offset to read at.
Offset uint64
// Count is the number of bytes to read.
Count uint32
}
// 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) {
b.WriteFID(t.Directory)
b.Write64(t.Offset)
b.Write32(t.Count)
}
// Type implements message.Type.
func (*Treaddir) Type() MsgType {
return MsgTreaddir
}
// String implements fmt.Stringer.
func (t *Treaddir) String() string {
return fmt.Sprintf("Treaddir{DirectoryFID: %d, Offset: %d, Count: %d}", t.Directory, t.Offset, t.Count)
}
// Rreaddir is a readdir response.
type Rreaddir struct {
// Count is the byte limit.
//
// This should always be set from the Treaddir request.
Count uint32
// Entries are the resulting entries.
//
// This may be constructed in decode.
Entries []Dirent
// payload is the encoded payload.
//
// This is constructed by encode.
payload []byte
}
// 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)
if entriesBuf.isOverrun() {
// Couldn't decode a complete entry.
break
}
r.Entries = append(r.Entries, d)
}
}
// encode implements encoder.encode.
func (r *Rreaddir) encode(b *buffer) {
entriesBuf := buffer{}
payloadSize := 0
for _, d := range r.Entries {
d.encode(&entriesBuf)
if len(entriesBuf.data) > int(r.Count) {
break
}
payloadSize = len(entriesBuf.data)
}
r.Count = uint32(payloadSize)
r.payload = entriesBuf.data[:payloadSize]
b.Write32(r.Count)
}
// Type implements message.Type.
func (*Rreaddir) Type() MsgType {
return MsgRreaddir
}
// FixedSize implements payloader.FixedSize.
func (*Rreaddir) FixedSize() uint32 {
return 4
}
// Payload implements payloader.Payload.
func (r *Rreaddir) Payload() []byte {
return r.payload
}
// SetPayload implements payloader.SetPayload.
func (r *Rreaddir) SetPayload(p []byte) {
r.payload = p
}
// String implements fmt.Stringer.
func (r *Rreaddir) String() string {
return fmt.Sprintf("Rreaddir{Count: %d, Entries: %s}", r.Count, r.Entries)
}
// Tfsync is an fsync request.
type Tfsync struct {
// FID is the fid to sync.
FID FID
}
// decode implements encoder.decode.
func (t *Tfsync) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Tfsync) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Tfsync) Type() MsgType {
return MsgTfsync
}
// String implements fmt.Stringer.
func (t *Tfsync) String() string {
return fmt.Sprintf("Tfsync{FID: %d}", t.FID)
}
// Rfsync is an fsync response.
type Rfsync struct {
}
// decode implements encoder.decode.
func (*Rfsync) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rfsync) encode(*buffer) {
}
// Type implements message.Type.
func (*Rfsync) Type() MsgType {
return MsgRfsync
}
// String implements fmt.Stringer.
func (r *Rfsync) String() string {
return "Rfsync{}"
}
// Tstatfs is a stat request.
type Tstatfs struct {
// FID is the root.
FID FID
}
// decode implements encoder.decode.
func (t *Tstatfs) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Tstatfs) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Tstatfs) Type() MsgType {
return MsgTstatfs
}
// String implements fmt.Stringer.
func (t *Tstatfs) String() string {
return fmt.Sprintf("Tstatfs{FID: %d}", t.FID)
}
// Rstatfs is the response for a Tstatfs.
type Rstatfs struct {
// FSStat is the stat result.
FSStat FSStat
}
// 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)
}
// Type implements message.Type.
func (*Rstatfs) Type() MsgType {
return MsgRstatfs
}
// String implements fmt.Stringer.
func (r *Rstatfs) String() string {
return fmt.Sprintf("Rstatfs{FSStat: %v}", r.FSStat)
}
// Tflushf is a flush file request, not to be confused with Tflush.
type Tflushf struct {
// FID is the FID to be flushed.
FID FID
}
// decode implements encoder.decode.
func (t *Tflushf) decode(b *buffer) {
t.FID = b.ReadFID()
}
// encode implements encoder.encode.
func (t *Tflushf) encode(b *buffer) {
b.WriteFID(t.FID)
}
// Type implements message.Type.
func (*Tflushf) Type() MsgType {
return MsgTflushf
}
// String implements fmt.Stringer.
func (t *Tflushf) String() string {
return fmt.Sprintf("Tflushf{FID: %d}", t.FID)
}
// Rflushf is a flush file response.
type Rflushf struct {
}
// decode implements encoder.decode.
func (*Rflushf) decode(*buffer) {
}
// encode implements encoder.encode.
func (*Rflushf) encode(*buffer) {
}
// Type implements message.Type.
func (*Rflushf) Type() MsgType {
return MsgRflushf
}
// String implements fmt.Stringer.
func (*Rflushf) String() string {
return "Rflushf{}"
}
// Twalkgetattr is a walk request.
type Twalkgetattr struct {
// FID is the FID to be walked.
FID FID
// NewFID is the resulting FID.
NewFID FID
// Names are the set of names to be walked.
Names []string
}
// decode implements encoder.decode.
func (t *Twalkgetattr) decode(b *buffer) {
t.FID = b.ReadFID()
t.NewFID = b.ReadFID()
n := b.Read16()
t.Names = t.Names[:0]
for i := 0; i < int(n); i++ {
t.Names = append(t.Names, b.ReadString())
}
}
// encode implements encoder.encode.
func (t *Twalkgetattr) encode(b *buffer) {
b.WriteFID(t.FID)
b.WriteFID(t.NewFID)
b.Write16(uint16(len(t.Names)))
for _, name := range t.Names {
b.WriteString(name)
}
}
// Type implements message.Type.
func (*Twalkgetattr) Type() MsgType {
return MsgTwalkgetattr
}
// String implements fmt.Stringer.
func (t *Twalkgetattr) String() string {
return fmt.Sprintf("Twalkgetattr{FID: %d, NewFID: %d, Names: %v}", t.FID, t.NewFID, t.Names)
}
// Rwalkgetattr is a walk response.
type Rwalkgetattr struct {
// Valid indicates which fields are valid in the Attr below.
Valid AttrMask
// Attr is the set of attributes for the last QID (the file walked to).
Attr Attr
// QIDs are the set of QIDs returned.
QIDs []QID
}
// 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)
r.QIDs = append(r.QIDs, q)
}
}
// 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)
}
}
// Type implements message.Type.
func (*Rwalkgetattr) Type() MsgType {
return MsgRwalkgetattr
}
// String implements fmt.Stringer.
func (r *Rwalkgetattr) String() string {
return fmt.Sprintf("Rwalkgetattr{Valid: %s, Attr: %s, QIDs: %v}", r.Valid, r.Attr, r.QIDs)
}
// Tucreate is a Tlcreate message that includes a UID.
type Tucreate struct {
Tlcreate
// UID is the UID to use as the effective UID in creation messages.
UID UID
}
// 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)
b.WriteUID(t.UID)
}
// Type implements message.Type.
func (t *Tucreate) Type() MsgType {
return MsgTucreate
}
// String implements fmt.Stringer.
func (t *Tucreate) String() string {
return fmt.Sprintf("Tucreate{Tlcreate: %v, UID: %d}", &t.Tlcreate, t.UID)
}
// Rucreate is a file creation response.
type Rucreate struct {
Rlcreate
}
// Type implements message.Type.
func (*Rucreate) Type() MsgType {
return MsgRucreate
}
// String implements fmt.Stringer.
func (r *Rucreate) String() string {
return fmt.Sprintf("Rucreate{%v}", &r.Rlcreate)
}
// Tumkdir is a Tmkdir message that includes a UID.
type Tumkdir struct {
Tmkdir
// UID is the UID to use as the effective UID in creation messages.
UID UID
}
// 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)
b.WriteUID(t.UID)
}
// Type implements message.Type.
func (t *Tumkdir) Type() MsgType {
return MsgTumkdir
}
// String implements fmt.Stringer.
func (t *Tumkdir) String() string {
return fmt.Sprintf("Tumkdir{Tmkdir: %v, UID: %d}", &t.Tmkdir, t.UID)
}
// Rumkdir is a umkdir response.
type Rumkdir struct {
Rmkdir
}
// Type implements message.Type.
func (*Rumkdir) Type() MsgType {
return MsgRumkdir
}
// String implements fmt.Stringer.
func (r *Rumkdir) String() string {
return fmt.Sprintf("Rumkdir{%v}", &r.Rmkdir)
}
// Tumknod is a Tmknod message that includes a UID.
type Tumknod struct {
Tmknod
// UID is the UID to use as the effective UID in creation messages.
UID UID
}
// 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)
b.WriteUID(t.UID)
}
// Type implements message.Type.
func (t *Tumknod) Type() MsgType {
return MsgTumknod
}
// String implements fmt.Stringer.
func (t *Tumknod) String() string {
return fmt.Sprintf("Tumknod{Tmknod: %v, UID: %d}", &t.Tmknod, t.UID)
}
// Rumknod is a umknod response.
type Rumknod struct {
Rmknod
}
// Type implements message.Type.
func (*Rumknod) Type() MsgType {
return MsgRumknod
}
// String implements fmt.Stringer.
func (r *Rumknod) String() string {
return fmt.Sprintf("Rumknod{%v}", &r.Rmknod)
}
// Tusymlink is a Tsymlink message that includes a UID.
type Tusymlink struct {
Tsymlink
// UID is the UID to use as the effective UID in creation messages.
UID UID
}
// 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)
b.WriteUID(t.UID)
}
// Type implements message.Type.
func (t *Tusymlink) Type() MsgType {
return MsgTusymlink
}
// String implements fmt.Stringer.
func (t *Tusymlink) String() string {
return fmt.Sprintf("Tusymlink{Tsymlink: %v, UID: %d}", &t.Tsymlink, t.UID)
}
// Rusymlink is a usymlink response.
type Rusymlink struct {
Rsymlink
}
// Type implements message.Type.
func (*Rusymlink) Type() MsgType {
return MsgRusymlink
}
// String implements fmt.Stringer.
func (r *Rusymlink) String() string {
return fmt.Sprintf("Rusymlink{%v}", &r.Rsymlink)
}
// Tlconnect is a connect request.
type Tlconnect struct {
// FID is the FID to be connected.
FID FID
// Flags are the connect flags.
Flags ConnectFlags
}
// 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) {
b.WriteFID(t.FID)
b.WriteConnectFlags(t.Flags)
}
// Type implements message.Type.
func (*Tlconnect) Type() MsgType {
return MsgTlconnect
}
// String implements fmt.Stringer.
func (t *Tlconnect) String() string {
return fmt.Sprintf("Tlconnect{FID: %d, Flags: %v}", t.FID, t.Flags)
}
// Rlconnect is a connect response.
type Rlconnect struct {
filePayload
}
// decode implements encoder.decode.
func (r *Rlconnect) decode(*buffer) {}
// encode implements encoder.encode.
func (r *Rlconnect) encode(*buffer) {}
// Type implements message.Type.
func (*Rlconnect) Type() MsgType {
return MsgRlconnect
}
// String implements fmt.Stringer.
func (r *Rlconnect) String() string {
return fmt.Sprintf("Rlconnect{File: %v}", r.File)
}
// Tchannel creates a new channel.
type Tchannel struct {
// ID is the channel ID.
ID uint32
// Control is 0 if the Rchannel response should provide the flipcall
// component of the channel, and 1 if the Rchannel response should
// provide the fdchannel component of the channel.
Control uint32
}
// 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) {
b.Write32(t.ID)
b.Write32(t.Control)
}
// Type implements message.Type.
func (*Tchannel) Type() MsgType {
return MsgTchannel
}
// String implements fmt.Stringer.
func (t *Tchannel) String() string {
return fmt.Sprintf("Tchannel{ID: %d, Control: %d}", t.ID, t.Control)
}
// Rchannel is the channel response.
type Rchannel struct {
Offset uint64
Length uint64
filePayload
}
// 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) {
b.Write64(r.Offset)
b.Write64(r.Length)
}
// Type implements message.Type.
func (*Rchannel) Type() MsgType {
return MsgRchannel
}
// String implements fmt.Stringer.
func (r *Rchannel) String() string {
return fmt.Sprintf("Rchannel{Offset: %d, Length: %d}", r.Offset, r.Length)
}
const maxCacheSize = 3
// msgFactory is used to reduce allocations by caching messages for reuse.
type msgFactory struct {
create func() message
cache chan message
}
// msgRegistry indexes all message factories by type.
var msgRegistry registry
type registry struct {
factories [math.MaxUint8 + 1]msgFactory
// largestFixedSize is computed so that given some message size M, you can
// compute the maximum payload size (e.g. for Twrite, Rread) with
// M-largestFixedSize. You could do this individual on a per-message basis,
// but it's easier to compute a single maximum safe payload.
largestFixedSize uint32
}
// get returns a new message by type.
//
// An error is returned in the case of an unknown message.
//
// This takes, and ignores, a message tag so that it may be used directly as a
// lookupTagAndType function for recv (by design).
func (r *registry) get(_ Tag, t MsgType) (message, error) {
entry := &r.factories[t]
if entry.create == nil {
return nil, &ErrInvalidMsgType{t}
}
select {
case msg := <-entry.cache:
return msg, nil
default:
return entry.create(), nil
}
}
func (r *registry) put(msg message) {
if p, ok := msg.(payloader); ok {
p.SetPayload(nil)
}
if f, ok := msg.(filer); ok {
f.SetFilePayload(nil)
}
entry := &r.factories[msg.Type()]
select {
case entry.cache <- msg:
default:
}
}
// register registers the given message type.
//
// This may cause panic on failure and should only be used from init.
func (r *registry) register(t MsgType, fn func() message) {
if int(t) >= len(r.factories) {
panic(fmt.Sprintf("message type %d is too large. It must be smaller than %d", t, len(r.factories)))
}
if r.factories[t].create != nil {
panic(fmt.Sprintf("duplicate message type %d: first is %T, second is %T", t, r.factories[t].create(), fn()))
}
r.factories[t] = msgFactory{
create: fn,
cache: make(chan message, maxCacheSize),
}
if size := calculateSize(fn()); size > r.largestFixedSize {
r.largestFixedSize = size
}
}
func calculateSize(m message) uint32 {
if p, ok := m.(payloader); ok {
return p.FixedSize()
}
var dataBuf buffer
m.encode(&dataBuf)
return uint32(len(dataBuf.data))
}
func init() {
msgRegistry.register(MsgRlerror, func() message { return &Rlerror{} })
msgRegistry.register(MsgTstatfs, func() message { return &Tstatfs{} })
msgRegistry.register(MsgRstatfs, func() message { return &Rstatfs{} })
msgRegistry.register(MsgTlopen, func() message { return &Tlopen{} })
msgRegistry.register(MsgRlopen, func() message { return &Rlopen{} })
msgRegistry.register(MsgTlcreate, func() message { return &Tlcreate{} })
msgRegistry.register(MsgRlcreate, func() message { return &Rlcreate{} })
msgRegistry.register(MsgTsymlink, func() message { return &Tsymlink{} })
msgRegistry.register(MsgRsymlink, func() message { return &Rsymlink{} })
msgRegistry.register(MsgTmknod, func() message { return &Tmknod{} })
msgRegistry.register(MsgRmknod, func() message { return &Rmknod{} })
msgRegistry.register(MsgTrename, func() message { return &Trename{} })
msgRegistry.register(MsgRrename, func() message { return &Rrename{} })
msgRegistry.register(MsgTreadlink, func() message { return &Treadlink{} })
msgRegistry.register(MsgRreadlink, func() message { return &Rreadlink{} })
msgRegistry.register(MsgTgetattr, func() message { return &Tgetattr{} })
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{} })
msgRegistry.register(MsgRxattrcreate, func() message { return &Rxattrcreate{} })
msgRegistry.register(MsgTgetxattr, func() message { return &Tgetxattr{} })
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{} })
msgRegistry.register(MsgRfsync, func() message { return &Rfsync{} })
msgRegistry.register(MsgTlink, func() message { return &Tlink{} })
msgRegistry.register(MsgRlink, func() message { return &Rlink{} })
msgRegistry.register(MsgTmkdir, func() message { return &Tmkdir{} })
msgRegistry.register(MsgRmkdir, func() message { return &Rmkdir{} })
msgRegistry.register(MsgTrenameat, func() message { return &Trenameat{} })
msgRegistry.register(MsgRrenameat, func() message { return &Rrenameat{} })
msgRegistry.register(MsgTunlinkat, func() message { return &Tunlinkat{} })
msgRegistry.register(MsgRunlinkat, func() message { return &Runlinkat{} })
msgRegistry.register(MsgTversion, func() message { return &Tversion{} })
msgRegistry.register(MsgRversion, func() message { return &Rversion{} })
msgRegistry.register(MsgTauth, func() message { return &Tauth{} })
msgRegistry.register(MsgRauth, func() message { return &Rauth{} })
msgRegistry.register(MsgTattach, func() message { return &Tattach{} })
msgRegistry.register(MsgRattach, func() message { return &Rattach{} })
msgRegistry.register(MsgTflush, func() message { return &Tflush{} })
msgRegistry.register(MsgRflush, func() message { return &Rflush{} })
msgRegistry.register(MsgTwalk, func() message { return &Twalk{} })
msgRegistry.register(MsgRwalk, func() message { return &Rwalk{} })
msgRegistry.register(MsgTread, func() message { return &Tread{} })
msgRegistry.register(MsgRread, func() message { return &Rread{} })
msgRegistry.register(MsgTwrite, func() message { return &Twrite{} })
msgRegistry.register(MsgRwrite, func() message { return &Rwrite{} })
msgRegistry.register(MsgTclunk, func() message { return &Tclunk{} })
msgRegistry.register(MsgRclunk, func() message { return &Rclunk{} })
msgRegistry.register(MsgTremove, func() message { return &Tremove{} })
msgRegistry.register(MsgRremove, func() message { return &Rremove{} })
msgRegistry.register(MsgTflushf, func() message { return &Tflushf{} })
msgRegistry.register(MsgRflushf, func() message { return &Rflushf{} })
msgRegistry.register(MsgTwalkgetattr, func() message { return &Twalkgetattr{} })
msgRegistry.register(MsgRwalkgetattr, func() message { return &Rwalkgetattr{} })
msgRegistry.register(MsgTucreate, func() message { return &Tucreate{} })
msgRegistry.register(MsgRucreate, func() message { return &Rucreate{} })
msgRegistry.register(MsgTumkdir, func() message { return &Tumkdir{} })
msgRegistry.register(MsgRumkdir, func() message { return &Rumkdir{} })
msgRegistry.register(MsgTumknod, func() message { return &Tumknod{} })
msgRegistry.register(MsgRumknod, func() message { return &Rumknod{} })
msgRegistry.register(MsgTusymlink, func() message { return &Tusymlink{} })
msgRegistry.register(MsgRusymlink, func() message { return &Rusymlink{} })
msgRegistry.register(MsgTlconnect, func() message { return &Tlconnect{} })
msgRegistry.register(MsgRlconnect, func() message { return &Rlconnect{} })
msgRegistry.register(MsgTallocate, func() message { return &Tallocate{} })
msgRegistry.register(MsgRallocate, func() message { return &Rallocate{} })
msgRegistry.register(MsgTsetattrclunk, func() message { return &Tsetattrclunk{} })
msgRegistry.register(MsgRsetattrclunk, func() message { return &Rsetattrclunk{} })
msgRegistry.register(MsgTchannel, func() message { return &Tchannel{} })
msgRegistry.register(MsgRchannel, func() message { return &Rchannel{} })
}