github.com/vmware/govmomi@v0.37.2/toolbox/vix/property.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/binary"
    22  	"errors"
    23  )
    24  
    25  // Property type enum as defined in open-vm-tools/lib/include/vix.h
    26  const (
    27  	_ = iota // ANY type not supported
    28  	vixPropertyTypeInt32
    29  	vixPropertyTypeString
    30  	vixPropertyTypeBool
    31  	_ // HANDLE type not supported
    32  	vixPropertyTypeInt64
    33  	vixPropertyTypeBlob
    34  )
    35  
    36  // Property ID enum as defined in open-vm-tools/lib/include/vixOpenSource.h
    37  const (
    38  	PropertyGuestToolsAPIOptions = 4501
    39  	PropertyGuestOsFamily        = 4502
    40  	PropertyGuestOsVersion       = 4503
    41  	PropertyGuestToolsProductNam = 4511
    42  	PropertyGuestToolsVersion    = 4500
    43  	PropertyGuestName            = 4505
    44  	PropertyGuestOsVersionShort  = 4520
    45  
    46  	PropertyGuestStartProgramEnabled            = 4540
    47  	PropertyGuestListProcessesEnabled           = 4541
    48  	PropertyGuestTerminateProcessEnabled        = 4542
    49  	PropertyGuestReadEnvironmentVariableEnabled = 4543
    50  
    51  	PropertyGuestMakeDirectoryEnabled                 = 4547
    52  	PropertyGuestDeleteFileEnabled                    = 4548
    53  	PropertyGuestDeleteDirectoryEnabled               = 4549
    54  	PropertyGuestMoveDirectoryEnabled                 = 4550
    55  	PropertyGuestMoveFileEnabled                      = 4551
    56  	PropertyGuestCreateTempFileEnabled                = 4552
    57  	PropertyGuestCreateTempDirectoryEnabled           = 4553
    58  	PropertyGuestListFilesEnabled                     = 4554
    59  	PropertyGuestChangeFileAttributesEnabled          = 4555
    60  	PropertyGuestInitiateFileTransferFromGuestEnabled = 4556
    61  	PropertyGuestInitiateFileTransferToGuestEnabled   = 4557
    62  )
    63  
    64  type Property struct {
    65  	header struct {
    66  		ID     int32
    67  		Kind   int32
    68  		Length int32
    69  	}
    70  
    71  	data struct {
    72  		Int32  int32
    73  		String string
    74  		Bool   uint8
    75  		Int64  int64
    76  		Blob   []byte
    77  	}
    78  }
    79  
    80  var int32Size int32
    81  
    82  func init() {
    83  	var i int32
    84  	int32Size = int32(binary.Size(&i))
    85  }
    86  
    87  type PropertyList []*Property
    88  
    89  func NewInt32Property(id int32, val int32) *Property {
    90  	p := new(Property)
    91  	p.header.ID = id
    92  	p.header.Kind = vixPropertyTypeInt32
    93  	p.header.Length = int32Size
    94  	p.data.Int32 = val
    95  	return p
    96  }
    97  
    98  func NewStringProperty(id int32, val string) *Property {
    99  	p := new(Property)
   100  	p.header.ID = id
   101  	p.header.Kind = vixPropertyTypeString
   102  	p.header.Length = int32(len(val) + 1)
   103  	p.data.String = val
   104  	return p
   105  }
   106  
   107  func NewBoolProperty(id int32, val bool) *Property {
   108  	p := new(Property)
   109  	p.header.ID = id
   110  	p.header.Kind = vixPropertyTypeBool
   111  	p.header.Length = 1
   112  	if val {
   113  		p.data.Bool = 1
   114  	}
   115  	return p
   116  }
   117  
   118  func NewInt64Property(id int32, val int64) *Property {
   119  	p := new(Property)
   120  	p.header.ID = id
   121  	p.header.Kind = vixPropertyTypeInt64
   122  	p.header.Length = int32Size * 2
   123  	p.data.Int64 = val
   124  	return p
   125  }
   126  
   127  func NewBlobProperty(id int32, val []byte) *Property {
   128  	p := new(Property)
   129  	p.header.ID = id
   130  	p.header.Kind = vixPropertyTypeBlob
   131  	p.header.Length = int32(len(val))
   132  	p.data.Blob = val
   133  	return p
   134  }
   135  
   136  // MarshalBinary implements the encoding.BinaryMarshaler interface
   137  func (p *Property) MarshalBinary() ([]byte, error) {
   138  	buf := new(bytes.Buffer)
   139  
   140  	// #nosec: Errors unhandled
   141  	_ = binary.Write(buf, binary.LittleEndian, &p.header)
   142  
   143  	switch p.header.Kind {
   144  	case vixPropertyTypeBool:
   145  		// #nosec: Errors unhandled
   146  		_ = binary.Write(buf, binary.LittleEndian, p.data.Bool)
   147  	case vixPropertyTypeInt32:
   148  		// #nosec: Errors unhandled
   149  		_ = binary.Write(buf, binary.LittleEndian, p.data.Int32)
   150  	case vixPropertyTypeInt64:
   151  		// #nosec: Errors unhandled
   152  		_ = binary.Write(buf, binary.LittleEndian, p.data.Int64)
   153  	case vixPropertyTypeString:
   154  		// #nosec: Errors unhandled
   155  		_, _ = buf.WriteString(p.data.String)
   156  		// #nosec: Errors unhandled
   157  		_ = buf.WriteByte(0)
   158  	case vixPropertyTypeBlob:
   159  		// #nosec: Errors unhandled
   160  		_, _ = buf.Write(p.data.Blob)
   161  	}
   162  
   163  	return buf.Bytes(), nil
   164  }
   165  
   166  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   167  func (p *Property) UnmarshalBinary(data []byte) error {
   168  	buf := bytes.NewBuffer(data)
   169  
   170  	err := binary.Read(buf, binary.LittleEndian, &p.header)
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	switch p.header.Kind {
   176  	case vixPropertyTypeBool:
   177  		return binary.Read(buf, binary.LittleEndian, &p.data.Bool)
   178  	case vixPropertyTypeInt32:
   179  		return binary.Read(buf, binary.LittleEndian, &p.data.Int32)
   180  	case vixPropertyTypeInt64:
   181  		return binary.Read(buf, binary.LittleEndian, &p.data.Int64)
   182  	case vixPropertyTypeString:
   183  		s := make([]byte, p.header.Length)
   184  		if _, err := buf.Read(s); err != nil {
   185  			return err
   186  		}
   187  
   188  		p.data.String = string(bytes.TrimRight(s, "\x00"))
   189  	case vixPropertyTypeBlob:
   190  		p.data.Blob = make([]byte, p.header.Length)
   191  		if _, err := buf.Read(p.data.Blob); err != nil {
   192  			return err
   193  		}
   194  	default:
   195  		return errors.New("VIX_E_UNRECOGNIZED_PROPERTY")
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
   202  func (l *PropertyList) UnmarshalBinary(data []byte) error {
   203  	headerSize := int32Size * 3
   204  
   205  	for {
   206  		p := new(Property)
   207  
   208  		err := p.UnmarshalBinary(data)
   209  		if err != nil {
   210  			return err
   211  		}
   212  
   213  		*l = append(*l, p)
   214  
   215  		offset := headerSize + p.header.Length
   216  		data = data[offset:]
   217  
   218  		if len(data) == 0 {
   219  			return nil
   220  		}
   221  	}
   222  }
   223  
   224  // MarshalBinary implements the encoding.BinaryMarshaler interface
   225  func (l *PropertyList) MarshalBinary() ([]byte, error) {
   226  	var buf bytes.Buffer
   227  
   228  	for _, p := range *l {
   229  		// #nosec: Errors unhandled
   230  		b, _ := p.MarshalBinary()
   231  		// #nosec: Errors unhandled
   232  		_, _ = buf.Write(b)
   233  	}
   234  
   235  	return buf.Bytes(), nil
   236  }