github.com/vmware/govmomi@v0.37.2/toolbox/vix/protocol.go (about)

     1  /*
     2  Copyright (c) 2017 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package vix
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/base64"
    22  	"encoding/binary"
    23  	"fmt"
    24  	"os"
    25  	"os/exec"
    26  	"syscall"
    27  )
    28  
    29  const (
    30  	CommandMagicWord = 0xd00d0001
    31  
    32  	CommandGetToolsState = 62
    33  
    34  	CommandStartProgram     = 185
    35  	CommandListProcessesEx  = 186
    36  	CommandReadEnvVariables = 187
    37  	CommandTerminateProcess = 193
    38  
    39  	CommandCreateDirectoryEx        = 178
    40  	CommandMoveGuestFileEx          = 179
    41  	CommandMoveGuestDirectory       = 180
    42  	CommandCreateTemporaryFileEx    = 181
    43  	CommandCreateTemporaryDirectory = 182
    44  	CommandSetGuestFileAttributes   = 183
    45  	CommandDeleteGuestFileEx        = 194
    46  	CommandDeleteGuestDirectoryEx   = 195
    47  
    48  	CommandListFiles                     = 177
    49  	HgfsSendPacketCommand                = 84
    50  	CommandInitiateFileTransferFromGuest = 188
    51  	CommandInitiateFileTransferToGuest   = 189
    52  
    53  	// VIX_USER_CREDENTIAL_NAME_PASSWORD
    54  	UserCredentialTypeNamePassword = 1
    55  
    56  	// VIX_E_* constants from vix.h
    57  	OK                 = 0
    58  	Fail               = 1
    59  	InvalidArg         = 3
    60  	FileNotFound       = 4
    61  	FileAlreadyExists  = 12
    62  	FileAccessError    = 13
    63  	AuthenticationFail = 35
    64  
    65  	UnrecognizedCommandInGuest = 3025
    66  	InvalidMessageHeader       = 10000
    67  	InvalidMessageBody         = 10001
    68  	NotAFile                   = 20001
    69  	NotADirectory              = 20002
    70  	NoSuchProcess              = 20003
    71  	DirectoryNotEmpty          = 20006
    72  
    73  	// VIX_COMMAND_* constants from Commands.h
    74  	CommandGuestReturnsBinary = 0x80
    75  
    76  	// VIX_FILE_ATTRIBUTES_ constants from vix.h
    77  	FileAttributesDirectory = 0x0001
    78  	FileAttributesSymlink   = 0x0002
    79  )
    80  
    81  // SetGuestFileAttributes flags as defined in vixOpenSource.h
    82  const (
    83  	FileAttributeSetAccessDate      = 0x0001
    84  	FileAttributeSetModifyDate      = 0x0002
    85  	FileAttributeSetReadonly        = 0x0004
    86  	FileAttributeSetHidden          = 0x0008
    87  	FileAttributeSetUnixOwnerid     = 0x0010
    88  	FileAttributeSetUnixGroupid     = 0x0020
    89  	FileAttributeSetUnixPermissions = 0x0040
    90  )
    91  
    92  type Error int
    93  
    94  func (err Error) Error() string {
    95  	return fmt.Sprintf("vix error=%d", err)
    96  }
    97  
    98  // ErrorCode does its best to map the given error to a VIX error code.
    99  // See also: Vix_TranslateErrno
   100  func ErrorCode(err error) int {
   101  	switch t := err.(type) {
   102  	case Error:
   103  		return int(t)
   104  	case *os.PathError:
   105  		if errno, ok := t.Err.(syscall.Errno); ok {
   106  			switch errno {
   107  			case syscall.ENOTEMPTY:
   108  				return DirectoryNotEmpty
   109  			}
   110  		}
   111  	case *exec.Error:
   112  		if t.Err == exec.ErrNotFound {
   113  			return FileNotFound
   114  		}
   115  	}
   116  
   117  	switch {
   118  	case os.IsNotExist(err):
   119  		return FileNotFound
   120  	case os.IsExist(err):
   121  		return FileAlreadyExists
   122  	case os.IsPermission(err):
   123  		return FileAccessError
   124  	default:
   125  		return Fail
   126  	}
   127  }
   128  
   129  type Header struct {
   130  	Magic          uint32
   131  	MessageVersion uint16
   132  
   133  	TotalMessageLength uint32
   134  	HeaderLength       uint32
   135  	BodyLength         uint32
   136  	CredentialLength   uint32
   137  
   138  	CommonFlags uint8
   139  }
   140  
   141  type CommandRequestHeader struct {
   142  	Header
   143  
   144  	OpCode       uint32
   145  	RequestFlags uint32
   146  
   147  	TimeOut uint32
   148  
   149  	Cookie         uint64
   150  	ClientHandleID uint32
   151  
   152  	UserCredentialType uint32
   153  }
   154  
   155  type StartProgramRequest struct {
   156  	CommandRequestHeader
   157  
   158  	Body struct {
   159  		StartMinimized    uint8
   160  		ProgramPathLength uint32
   161  		ArgumentsLength   uint32
   162  		WorkingDirLength  uint32
   163  		NumEnvVars        uint32
   164  		EnvVarLength      uint32
   165  	}
   166  
   167  	ProgramPath string
   168  	Arguments   string
   169  	WorkingDir  string
   170  	EnvVars     []string
   171  }
   172  
   173  // MarshalBinary implements the encoding.BinaryMarshaler interface
   174  func (r *StartProgramRequest) MarshalBinary() ([]byte, error) {
   175  	var env bytes.Buffer
   176  
   177  	if n := len(r.EnvVars); n != 0 {
   178  		for _, e := range r.EnvVars {
   179  			_, _ = env.Write([]byte(e))
   180  			_ = env.WriteByte(0)
   181  		}
   182  		r.Body.NumEnvVars = uint32(n)
   183  		r.Body.EnvVarLength = uint32(env.Len())
   184  	}
   185  
   186  	var fields []string
   187  
   188  	add := func(s string, l *uint32) {
   189  		if n := len(s); n != 0 {
   190  			*l = uint32(n) + 1
   191  			fields = append(fields, s)
   192  		}
   193  	}
   194  
   195  	add(r.ProgramPath, &r.Body.ProgramPathLength)
   196  	add(r.Arguments, &r.Body.ArgumentsLength)
   197  	add(r.WorkingDir, &r.Body.WorkingDirLength)
   198  
   199  	buf := new(bytes.Buffer)
   200  
   201  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   202  
   203  	for _, val := range fields {
   204  		_, _ = buf.Write([]byte(val))
   205  		_ = buf.WriteByte(0)
   206  	}
   207  
   208  	if r.Body.EnvVarLength != 0 {
   209  		_, _ = buf.Write(env.Bytes())
   210  	}
   211  
   212  	return buf.Bytes(), nil
   213  }
   214  
   215  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   216  func (r *StartProgramRequest) UnmarshalBinary(data []byte) error {
   217  	buf := bytes.NewBuffer(data)
   218  
   219  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   220  	if err != nil {
   221  		return err
   222  	}
   223  
   224  	fields := []struct {
   225  		len uint32
   226  		val *string
   227  	}{
   228  		{r.Body.ProgramPathLength, &r.ProgramPath},
   229  		{r.Body.ArgumentsLength, &r.Arguments},
   230  		{r.Body.WorkingDirLength, &r.WorkingDir},
   231  	}
   232  
   233  	for _, field := range fields {
   234  		if field.len == 0 {
   235  			continue
   236  		}
   237  
   238  		x := buf.Next(int(field.len))
   239  		*field.val = string(bytes.TrimRight(x, "\x00"))
   240  	}
   241  
   242  	for i := 0; i < int(r.Body.NumEnvVars); i++ {
   243  		env, rerr := buf.ReadString(0)
   244  		if rerr != nil {
   245  			return rerr
   246  		}
   247  
   248  		env = env[:len(env)-1] // discard NULL terminator
   249  		r.EnvVars = append(r.EnvVars, env)
   250  	}
   251  
   252  	return nil
   253  }
   254  
   255  type KillProcessRequest struct {
   256  	CommandRequestHeader
   257  
   258  	Body struct {
   259  		Pid     int64
   260  		Options uint32
   261  	}
   262  }
   263  
   264  // MarshalBinary implements the encoding.BinaryMarshaler interface
   265  func (r *KillProcessRequest) MarshalBinary() ([]byte, error) {
   266  	buf := new(bytes.Buffer)
   267  
   268  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   269  
   270  	return buf.Bytes(), nil
   271  }
   272  
   273  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   274  func (r *KillProcessRequest) UnmarshalBinary(data []byte) error {
   275  	buf := bytes.NewBuffer(data)
   276  
   277  	return binary.Read(buf, binary.LittleEndian, &r.Body)
   278  }
   279  
   280  type ListProcessesRequest struct {
   281  	CommandRequestHeader
   282  
   283  	Body struct {
   284  		Key     uint32
   285  		Offset  uint32
   286  		NumPids uint32
   287  	}
   288  
   289  	Pids []int64
   290  }
   291  
   292  // MarshalBinary implements the encoding.BinaryMarshaler interface
   293  func (r *ListProcessesRequest) MarshalBinary() ([]byte, error) {
   294  	r.Body.NumPids = uint32(len(r.Pids))
   295  
   296  	buf := new(bytes.Buffer)
   297  
   298  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   299  
   300  	for _, pid := range r.Pids {
   301  		_ = binary.Write(buf, binary.LittleEndian, &pid)
   302  	}
   303  
   304  	return buf.Bytes(), nil
   305  }
   306  
   307  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   308  func (r *ListProcessesRequest) UnmarshalBinary(data []byte) error {
   309  	buf := bytes.NewBuffer(data)
   310  
   311  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   312  	if err != nil {
   313  		return err
   314  	}
   315  
   316  	r.Pids = make([]int64, r.Body.NumPids)
   317  
   318  	for i := uint32(0); i < r.Body.NumPids; i++ {
   319  		err := binary.Read(buf, binary.LittleEndian, &r.Pids[i])
   320  		if err != nil {
   321  			return err
   322  		}
   323  	}
   324  
   325  	return nil
   326  }
   327  
   328  type ReadEnvironmentVariablesRequest struct {
   329  	CommandRequestHeader
   330  
   331  	Body struct {
   332  		NumNames    uint32
   333  		NamesLength uint32
   334  	}
   335  
   336  	Names []string
   337  }
   338  
   339  // MarshalBinary implements the encoding.BinaryMarshaler interface
   340  func (r *ReadEnvironmentVariablesRequest) MarshalBinary() ([]byte, error) {
   341  	var env bytes.Buffer
   342  
   343  	if n := len(r.Names); n != 0 {
   344  		for _, e := range r.Names {
   345  			_, _ = env.Write([]byte(e))
   346  			_ = env.WriteByte(0)
   347  		}
   348  		r.Body.NumNames = uint32(n)
   349  		r.Body.NamesLength = uint32(env.Len())
   350  	}
   351  
   352  	buf := new(bytes.Buffer)
   353  
   354  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   355  
   356  	if r.Body.NamesLength != 0 {
   357  		_, _ = buf.Write(env.Bytes())
   358  	}
   359  
   360  	return buf.Bytes(), nil
   361  }
   362  
   363  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   364  func (r *ReadEnvironmentVariablesRequest) UnmarshalBinary(data []byte) error {
   365  	buf := bytes.NewBuffer(data)
   366  
   367  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   368  	if err != nil {
   369  		return err
   370  	}
   371  
   372  	for i := 0; i < int(r.Body.NumNames); i++ {
   373  		env, rerr := buf.ReadString(0)
   374  		if rerr != nil {
   375  			return rerr
   376  		}
   377  
   378  		env = env[:len(env)-1] // discard NULL terminator
   379  		r.Names = append(r.Names, env)
   380  	}
   381  
   382  	return nil
   383  }
   384  
   385  type CreateTempFileRequest struct {
   386  	CommandRequestHeader
   387  
   388  	Body struct {
   389  		Options             int32
   390  		FilePrefixLength    uint32
   391  		FileSuffixLength    uint32
   392  		DirectoryPathLength uint32
   393  		PropertyListLength  uint32
   394  	}
   395  
   396  	FilePrefix    string
   397  	FileSuffix    string
   398  	DirectoryPath string
   399  }
   400  
   401  // MarshalBinary implements the encoding.BinaryMarshaler interface
   402  func (r *CreateTempFileRequest) MarshalBinary() ([]byte, error) {
   403  	var fields []string
   404  
   405  	add := func(s string, l *uint32) {
   406  		*l = uint32(len(s)) // NOTE: NULL byte is not included in the length fields on the wire
   407  		fields = append(fields, s)
   408  	}
   409  
   410  	add(r.FilePrefix, &r.Body.FilePrefixLength)
   411  	add(r.FileSuffix, &r.Body.FileSuffixLength)
   412  	add(r.DirectoryPath, &r.Body.DirectoryPathLength)
   413  
   414  	buf := new(bytes.Buffer)
   415  
   416  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   417  
   418  	for _, val := range fields {
   419  		_, _ = buf.Write([]byte(val))
   420  		_ = buf.WriteByte(0)
   421  	}
   422  
   423  	return buf.Bytes(), nil
   424  }
   425  
   426  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   427  func (r *CreateTempFileRequest) UnmarshalBinary(data []byte) error {
   428  	buf := bytes.NewBuffer(data)
   429  
   430  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   431  	if err != nil {
   432  		return err
   433  	}
   434  
   435  	fields := []struct {
   436  		len uint32
   437  		val *string
   438  	}{
   439  		{r.Body.FilePrefixLength, &r.FilePrefix},
   440  		{r.Body.FileSuffixLength, &r.FileSuffix},
   441  		{r.Body.DirectoryPathLength, &r.DirectoryPath},
   442  	}
   443  
   444  	for _, field := range fields {
   445  		field.len++ // NOTE: NULL byte is not included in the length fields on the wire
   446  
   447  		x := buf.Next(int(field.len))
   448  		*field.val = string(bytes.TrimRight(x, "\x00"))
   449  	}
   450  
   451  	return nil
   452  }
   453  
   454  type FileRequest struct {
   455  	CommandRequestHeader
   456  
   457  	Body struct {
   458  		FileOptions         int32
   459  		GuestPathNameLength uint32
   460  	}
   461  
   462  	GuestPathName string
   463  }
   464  
   465  // MarshalBinary implements the encoding.BinaryMarshaler interface
   466  func (r *FileRequest) MarshalBinary() ([]byte, error) {
   467  	buf := new(bytes.Buffer)
   468  
   469  	r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
   470  
   471  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   472  
   473  	_, _ = buf.WriteString(r.GuestPathName)
   474  	_ = buf.WriteByte(0)
   475  
   476  	return buf.Bytes(), nil
   477  }
   478  
   479  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   480  func (r *FileRequest) UnmarshalBinary(data []byte) error {
   481  	buf := bytes.NewBuffer(data)
   482  
   483  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   484  	if err != nil {
   485  		return err
   486  	}
   487  
   488  	name := buf.Next(int(r.Body.GuestPathNameLength))
   489  	r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
   490  
   491  	return nil
   492  }
   493  
   494  type DirRequest struct {
   495  	CommandRequestHeader
   496  
   497  	Body struct {
   498  		FileOptions          int32
   499  		GuestPathNameLength  uint32
   500  		FilePropertiesLength uint32
   501  		Recursive            bool
   502  	}
   503  
   504  	GuestPathName string
   505  }
   506  
   507  // MarshalBinary implements the encoding.BinaryMarshaler interface
   508  func (r *DirRequest) MarshalBinary() ([]byte, error) {
   509  	buf := new(bytes.Buffer)
   510  
   511  	r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
   512  
   513  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   514  
   515  	_, _ = buf.WriteString(r.GuestPathName)
   516  	_ = buf.WriteByte(0)
   517  
   518  	return buf.Bytes(), nil
   519  }
   520  
   521  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   522  func (r *DirRequest) UnmarshalBinary(data []byte) error {
   523  	buf := bytes.NewBuffer(data)
   524  
   525  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   526  	if err != nil {
   527  		return err
   528  	}
   529  
   530  	name := buf.Next(int(r.Body.GuestPathNameLength))
   531  	r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
   532  
   533  	return nil
   534  }
   535  
   536  type RenameFileRequest struct {
   537  	CommandRequestHeader
   538  
   539  	Body struct {
   540  		CopyFileOptions      int32
   541  		OldPathNameLength    uint32
   542  		NewPathNameLength    uint32
   543  		FilePropertiesLength uint32
   544  		Overwrite            bool
   545  	}
   546  
   547  	OldPathName string
   548  	NewPathName string
   549  }
   550  
   551  // MarshalBinary implements the encoding.BinaryMarshaler interface
   552  func (r *RenameFileRequest) MarshalBinary() ([]byte, error) {
   553  	var fields []string
   554  
   555  	add := func(s string, l *uint32) {
   556  		*l = uint32(len(s)) // NOTE: NULL byte is not included in the length fields on the wire
   557  		fields = append(fields, s)
   558  	}
   559  
   560  	add(r.OldPathName, &r.Body.OldPathNameLength)
   561  	add(r.NewPathName, &r.Body.NewPathNameLength)
   562  
   563  	buf := new(bytes.Buffer)
   564  
   565  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   566  
   567  	for _, val := range fields {
   568  		_, _ = buf.Write([]byte(val))
   569  		_ = buf.WriteByte(0)
   570  	}
   571  
   572  	return buf.Bytes(), nil
   573  }
   574  
   575  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   576  func (r *RenameFileRequest) UnmarshalBinary(data []byte) error {
   577  	buf := bytes.NewBuffer(data)
   578  
   579  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   580  	if err != nil {
   581  		return err
   582  	}
   583  
   584  	fields := []struct {
   585  		len uint32
   586  		val *string
   587  	}{
   588  		{r.Body.OldPathNameLength, &r.OldPathName},
   589  		{r.Body.NewPathNameLength, &r.NewPathName},
   590  	}
   591  
   592  	for _, field := range fields {
   593  		field.len++ // NOTE: NULL byte is not included in the length fields on the wire
   594  
   595  		x := buf.Next(int(field.len))
   596  		*field.val = string(bytes.TrimRight(x, "\x00"))
   597  	}
   598  
   599  	return nil
   600  }
   601  
   602  type ListFilesRequest struct {
   603  	CommandRequestHeader
   604  
   605  	Body struct {
   606  		FileOptions         int32
   607  		GuestPathNameLength uint32
   608  		PatternLength       uint32
   609  		Index               int32
   610  		MaxResults          int32
   611  		Offset              uint64
   612  	}
   613  
   614  	GuestPathName string
   615  	Pattern       string
   616  }
   617  
   618  // MarshalBinary implements the encoding.BinaryMarshaler interface
   619  func (r *ListFilesRequest) MarshalBinary() ([]byte, error) {
   620  	var fields []string
   621  
   622  	add := func(s string, l *uint32) {
   623  		if n := len(s); n != 0 {
   624  			*l = uint32(n) + 1
   625  			fields = append(fields, s)
   626  		}
   627  	}
   628  
   629  	add(r.GuestPathName, &r.Body.GuestPathNameLength)
   630  	add(r.Pattern, &r.Body.PatternLength)
   631  
   632  	buf := new(bytes.Buffer)
   633  
   634  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   635  
   636  	for _, val := range fields {
   637  		_, _ = buf.Write([]byte(val))
   638  		_ = buf.WriteByte(0)
   639  	}
   640  
   641  	return buf.Bytes(), nil
   642  }
   643  
   644  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   645  func (r *ListFilesRequest) UnmarshalBinary(data []byte) error {
   646  	buf := bytes.NewBuffer(data)
   647  
   648  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   649  	if err != nil {
   650  		return err
   651  	}
   652  
   653  	fields := []struct {
   654  		len uint32
   655  		val *string
   656  	}{
   657  		{r.Body.GuestPathNameLength, &r.GuestPathName},
   658  		{r.Body.PatternLength, &r.Pattern},
   659  	}
   660  
   661  	for _, field := range fields {
   662  		if field.len == 0 {
   663  			continue
   664  		}
   665  
   666  		x := buf.Next(int(field.len))
   667  		*field.val = string(bytes.TrimRight(x, "\x00"))
   668  	}
   669  
   670  	return nil
   671  }
   672  
   673  type SetGuestFileAttributesRequest struct {
   674  	CommandRequestHeader
   675  
   676  	Body struct {
   677  		FileOptions         int32
   678  		AccessTime          int64
   679  		ModificationTime    int64
   680  		OwnerID             int32
   681  		GroupID             int32
   682  		Permissions         int32
   683  		Hidden              bool
   684  		ReadOnly            bool
   685  		GuestPathNameLength uint32
   686  	}
   687  
   688  	GuestPathName string
   689  }
   690  
   691  // MarshalBinary implements the encoding.BinaryMarshaler interface
   692  func (r *SetGuestFileAttributesRequest) MarshalBinary() ([]byte, error) {
   693  	buf := new(bytes.Buffer)
   694  
   695  	r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
   696  
   697  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   698  
   699  	_, _ = buf.WriteString(r.GuestPathName)
   700  	_ = buf.WriteByte(0)
   701  
   702  	return buf.Bytes(), nil
   703  }
   704  
   705  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   706  func (r *SetGuestFileAttributesRequest) UnmarshalBinary(data []byte) error {
   707  	buf := bytes.NewBuffer(data)
   708  
   709  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   710  	if err != nil {
   711  		return err
   712  	}
   713  
   714  	name := buf.Next(int(r.Body.GuestPathNameLength))
   715  	r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
   716  
   717  	return nil
   718  }
   719  
   720  func (r *SetGuestFileAttributesRequest) IsSet(opt int32) bool {
   721  	return r.Body.FileOptions&opt == opt
   722  }
   723  
   724  type CommandHgfsSendPacket struct {
   725  	CommandRequestHeader
   726  
   727  	Body struct {
   728  		PacketSize uint32
   729  		Timeout    int32
   730  	}
   731  
   732  	Packet []byte
   733  }
   734  
   735  // MarshalBinary implements the encoding.BinaryMarshaler interface
   736  func (r *CommandHgfsSendPacket) MarshalBinary() ([]byte, error) {
   737  	buf := new(bytes.Buffer)
   738  
   739  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   740  
   741  	_, _ = buf.Write(r.Packet)
   742  
   743  	return buf.Bytes(), nil
   744  }
   745  
   746  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   747  func (r *CommandHgfsSendPacket) UnmarshalBinary(data []byte) error {
   748  	buf := bytes.NewBuffer(data)
   749  
   750  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   751  	if err != nil {
   752  		return err
   753  	}
   754  
   755  	r.Packet = buf.Next(int(r.Body.PacketSize))
   756  
   757  	return nil
   758  }
   759  
   760  type InitiateFileTransferToGuestRequest struct {
   761  	CommandRequestHeader
   762  
   763  	Body struct {
   764  		Options             int32
   765  		GuestPathNameLength uint32
   766  		Overwrite           bool
   767  	}
   768  
   769  	GuestPathName string
   770  }
   771  
   772  // MarshalBinary implements the encoding.BinaryMarshaler interface
   773  func (r *InitiateFileTransferToGuestRequest) MarshalBinary() ([]byte, error) {
   774  	buf := new(bytes.Buffer)
   775  
   776  	r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
   777  
   778  	_ = binary.Write(buf, binary.LittleEndian, &r.Body)
   779  
   780  	_, _ = buf.WriteString(r.GuestPathName)
   781  	_ = buf.WriteByte(0)
   782  
   783  	return buf.Bytes(), nil
   784  }
   785  
   786  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   787  func (r *InitiateFileTransferToGuestRequest) UnmarshalBinary(data []byte) error {
   788  	buf := bytes.NewBuffer(data)
   789  
   790  	err := binary.Read(buf, binary.LittleEndian, &r.Body)
   791  	if err != nil {
   792  		return err
   793  	}
   794  
   795  	name := buf.Next(int(r.Body.GuestPathNameLength))
   796  	r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
   797  
   798  	return nil
   799  }
   800  
   801  type UserCredentialNamePassword struct {
   802  	Body struct {
   803  		NameLength     uint32
   804  		PasswordLength uint32
   805  	}
   806  
   807  	Name     string
   808  	Password string
   809  }
   810  
   811  func (c *UserCredentialNamePassword) UnmarshalBinary(data []byte) error {
   812  	buf := bytes.NewBuffer(bytes.TrimRight(data, "\x00"))
   813  
   814  	err := binary.Read(buf, binary.LittleEndian, &c.Body)
   815  	if err != nil {
   816  		return err
   817  	}
   818  
   819  	str, err := base64.StdEncoding.DecodeString(buf.String())
   820  	if err != nil {
   821  		return err
   822  	}
   823  
   824  	c.Name = string(str[0:c.Body.NameLength])
   825  	c.Password = string(str[c.Body.NameLength+1 : len(str)-1])
   826  
   827  	return nil
   828  }
   829  
   830  func (c *UserCredentialNamePassword) MarshalBinary() ([]byte, error) {
   831  	buf := new(bytes.Buffer)
   832  
   833  	c.Body.NameLength = uint32(len(c.Name))
   834  	c.Body.PasswordLength = uint32(len(c.Password))
   835  
   836  	_ = binary.Write(buf, binary.LittleEndian, &c.Body)
   837  
   838  	src := append([]byte(c.Name+"\x00"), []byte(c.Password+"\x00")...)
   839  
   840  	enc := base64.StdEncoding
   841  	pwd := make([]byte, enc.EncodedLen(len(src)))
   842  	enc.Encode(pwd, src)
   843  	_, _ = buf.Write(pwd)
   844  	_ = buf.WriteByte(0)
   845  
   846  	return buf.Bytes(), nil
   847  }