diff --git a/decode.go b/decode.go index 7142a94..1a4098f 100644 --- a/decode.go +++ b/decode.go @@ -10,6 +10,7 @@ import ( "io" "log" "reflect" + "regexp" "strconv" "strings" ) @@ -46,27 +47,21 @@ func (d *Decoder) loadVMXMap() error { for d.scanner.Scan() { line := d.scanner.Text() - // Ignore comments and empty lines - if strings.HasPrefix(line, "#") || strings.TrimSpace(line) == "" { + re := regexp.MustCompile(`^(?P[^#]\S+) ?= ?"(?P.+)"$`) + match := re.FindStringSubmatch(line) + if match == nil { continue } - parts := strings.Split(line, "=") - if len(parts) != 2 { - errors = appendErrors(errors, fmt.Errorf("Invalid line: %s ", line)) - } - - key := strings.TrimSpace(parts[0]) - value := strings.TrimSpace(parts[1]) - - unquotedVal, err := strconv.Unquote(value) - if err != nil { - unquotedVal = value - //errors = appendErrors(errors, fmt.Errorf("Error unquoting vmx value %s: %v.", value, err)) + groups := make(map[string]string) + for i, name := range re.SubexpNames() { + if i != 0 && name != "" { + groups[name] = match[i] + } } - key = strings.ToLower(key) - d.vmx[key] = unquotedVal + key := strings.ToLower(groups["key"]) + d.vmx[key] = groups["value"] } if err := d.scanner.Err(); err != nil { diff --git a/decode_test.go b/decode_test.go index 0d54550..4b2d44e 100644 --- a/decode_test.go +++ b/decode_test.go @@ -36,4 +36,9 @@ func TestUnmarshal(t *testing.T) { assert(t, len(vm2.SCSIDevices) == 2, fmt.Sprintf("%d != %d", len(vm2.SCSIDevices), 2)) assert(t, vm2.SCSIDevices[0].VMXID != "", fmt.Sprintf("VMXID should not be empty: ->%s<-", vm2.SCSIDevices[0].VMXID)) ok(t, err) + + data, err = ioutil.ReadFile(filepath.Join(".", "fixtures", "c.vmx")) + vm3 := new(VirtualMachine) + err = Unmarshal([]byte(data), vm3) + ok(t, err) } diff --git a/fixtures/c.vmx b/fixtures/c.vmx new file mode 100644 index 0000000..b7b5549 --- /dev/null +++ b/fixtures/c.vmx @@ -0,0 +1,99 @@ +.encoding = "UTF-8" +bios.bootorder = "hdd,cdrom" +checkpoint.vmstate = "" +cleanshutdown = "TRUE" +config.version = "8" +displayname = "generic-ubuntu1804-vmware" +ehci.pcislotnumber = "-1" +ehci.present = "FALSE" +extendedconfigfile = "generic-ubuntu1804-vmware.vmxf" +floppy0.present = "FALSE" +guestos = "ubuntu-64" +guestos.detailed.data = "bitness='64' distroName='Ubuntu' distroVersion='18.04' familyName='Linux' kernelVersion='4.15.0-76-generic' prettyName='Ubuntu 18.04.4 LTS'" +gui.fullscreenatpoweron = "FALSE" +gui.viewmodeatpoweron = "windowed" +hgfs.linkrootshare = "TRUE" +hgfs.maprootshare = "TRUE" +ide0:0.clientdevice = "TRUE" +ide0:0.devicetype = "cdrom-raw" +ide0:0.filename = "auto detect" +ide0:0.present = "TRUE" +isolation.tools.hgfs.disable = "FALSE" +memsize = "2048" +monitor.phys_bits_used = "42" +msg.autoanswer = "true" +numa.autosize.cookie = "20001" +numa.autosize.vcpu.maxpervirtualnode = "2" +numvcpus = "2" +nvme0.present = "FALSE" +nvram = "generic-ubuntu1804-vmware.nvram" +parallel0.autodetect = "FALSE" +parallel0.bidirectional = "" +parallel0.filename = "" +parallel0.present = "FALSE" +parallel0.startconnected = "FALSE" +pcibridge0.pcislotnumber = "17" +pcibridge0.present = "TRUE" +pcibridge4.functions = "8" +pcibridge4.pcislotnumber = "21" +pcibridge4.present = "TRUE" +pcibridge4.virtualdev = "pcieRootPort" +pcibridge5.functions = "8" +pcibridge5.pcislotnumber = "22" +pcibridge5.present = "TRUE" +pcibridge5.virtualdev = "pcieRootPort" +pcibridge6.functions = "8" +pcibridge6.pcislotnumber = "23" +pcibridge6.present = "TRUE" +pcibridge6.virtualdev = "pcieRootPort" +pcibridge7.functions = "8" +pcibridge7.pcislotnumber = "24" +pcibridge7.present = "TRUE" +pcibridge7.virtualdev = "pcieRootPort" +powertype.poweroff = "soft" +powertype.poweron = "soft" +powertype.reset = "soft" +powertype.suspend = "soft" +proxyapps.publishtohost = "FALSE" +remotedisplay.vnc.enabled = "FALSE" +remotedisplay.vnc.ip = "127.0.0.1" +remotedisplay.vnc.port = "5904" +replay.filename = "" +replay.supported = "FALSE" +sata0.present = "FALSE" +scsi0.pcislotnumber = "16" +scsi0.present = "TRUE" +scsi0.virtualdev = "lsilogic" +scsi0:0.filename = "generic-ubuntu1804-vmware.vmdk" +scsi0:0.present = "TRUE" +scsi0:0.redo = "" +serial0.autodetect = "FALSE" +serial0.filename = "" +serial0.filetype = "" +serial0.pipe.endpoint = "" +serial0.present = "FALSE" +serial0.startconnected = "FALSE" +serial0.trynorxloss = "" +serial0.yieldonmsrread = "" +softpoweroff = "FALSE" +sound.autodetect = "TRUE" +sound.filename = "-1" +sound.present = "FALSE" +sound.startconnected = "FALSE" +svga.guestbackedprimaryaware = "TRUE" +svga.vramsize = "134217728" +tools.synctime = "TRUE" +tools.upgrade.policy = "upgradeAtPowerCycle" +toolsinstallmanager.updatecounter = "1" +usb.pcislotnumber = "-1" +usb.present = "FALSE" +uuid.action = "create" +uuid.bios = "56 4d fc 04 54 ab 8e 06-3c c5 a6 4d f9 c8 bc 5a" +uuid.location = "56 4d fc 04 54 ab 8e 06-3c c5 a6 4d f9 c8 bc 5a" +virtualhw.productcompatibility = "hosted" +virtualhw.version = "12" +vmci0.id = "1861462628" +vmci0.pcislotnumber = "35" +vmci0.present = "TRUE" +vmotion.checkpointfbsize = "134217728" +vmotion.checkpointsvgaprimarysize = "134217728"